From 7db7cad18f38dc973e0c74557fa2a67728d7f83f Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 13 Mar 2025 02:30:45 +0100 Subject: [PATCH 01/34] build(pre-commit): fixing eslint for windows --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3c8fc60..e7618f7 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ }, "lint-staged": { "package.json": "finepack", - "*.{js,ts,jsx,tsx}": "eslint --cache --fix . || true", + "*.{js,ts,jsx,tsx}": "(eslint --cache --fix .) || true", "*.{js,ts,jsx,tsx,json,css,md}": "prettier --write" }, "type": "module" From 4750b3baf9d0e8c118e58c6c1b2b02603097075c Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 13 Mar 2025 02:42:21 +0100 Subject: [PATCH 02/34] revert(pre-commit)!: slapping windows specific linting back in As it seems I did not fix the eslint not throwing, so I need to temporarily put the call to cmd back in until further investigation Refs: 5304933 Format: text/plain Milestone: none BREAKING-CHANGE: calling the windows command line cmd will probably make the pre-commit hook not work on non-windows systems --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e7618f7..707d176 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ }, "lint-staged": { "package.json": "finepack", - "*.{js,ts,jsx,tsx}": "(eslint --cache --fix .) || true", + "*.{js,ts,jsx,tsx}": "cmd /c eslint --cache --fix . || exit 0", "*.{js,ts,jsx,tsx,json,css,md}": "prettier --write" }, "type": "module" From 09645c30e61131ba20a3c6b2b594337a4e4feb33 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 13 Mar 2025 02:45:11 +0100 Subject: [PATCH 03/34] build(tsconfig): specify include globs to /src/**/* Previous glob was `**/*` Format: text/markdown Milestone: none --- tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 9ed2a61..fb41ac3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,6 +27,6 @@ "~/*": ["./src/*"] } }, - "include": ["**/*.ts", "**/*.tsx", "**/*.cjs", "**/*.js"], - "exclude": ["node_modules", "docs", "dist"] + "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.cjs", "src/**/*.js"], + "exclude": ["node_modules/**/*", "docs/**/*", "dist/**/*"] } From ac239fd090643263b42576bf058dbe77a24c9a1c Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 13 Mar 2025 02:46:01 +0100 Subject: [PATCH 04/34] feat: sends message Message sending is not yet feature complete Missing: - attachments - priority 2 -> retry & expire Format: text/markdown Milestone: minor --- src/index.ts | 269 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 163 insertions(+), 106 deletions(-) diff --git a/src/index.ts b/src/index.ts index 777ada8..fa6da79 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,111 +1,168 @@ -import { z } from "zod"; +import https from "node:https"; +import { URLSearchParams } from "node:url"; -const messageSchema = z.object({ - /** - * The message to send. - */ - message: z.string(), - /** - * The title of the message. - */ - title: z.string().optional(), - /** - * The URL to open when the notification is clicked. - */ - url: z - .object({ - /** - * The URL itself. - */ - url: z.string(), - /** - * The title of the URL to be displayed. - */ - title: z.string().optional(), - }) - .optional(), - priority: z - .object({ - level: z.number().default(0), - retry: z.number().optional(), - expire: z.number().optional(), - callback: z.string().optional(), - }) - .optional(), - sound: z.string().optional(), - timestamp: z.date().optional(), - html: z.boolean().default(false), - attachment: z - .object({ - data: z.string().or(z.instanceof(File)), - type: z.string(), - }) - .optional(), - users: z.array( - z.object({ - name: z.string(), - token: z.string(), - devices: z.array(z.string()), - }), - ), - appToken: z.string(), -}); +export interface PushoverMessage { + message: string; + title?: string; + link?: { + url: string; + title?: string; + }; + priority?: -2 | -1 | 0 | 1 | 2; + sound?: string; + timestamp?: number; + html?: 0 | 1; + monospace?: 0 | 1; + ttl?: number; +} -export type PushoverMessage = z.infer; +export interface PushoverResponse { + status: number; + request: string; + errors?: string[]; +} -export type Pushover = { - // ################################# - // # Helpers # - // ################################# - - /** - * Get all available sounds. - */ - getSounds: () => { sounds: string[] }; - - /** - * Get all available devices for a user. - */ - getDevices: (userToken: string) => { devices: string[] }; - - // ################################# - // # Sending # - // ################################# - - /** - * Send the notification. - */ - send: () => void; - - // ################################# - // # Options # - // ################################# - withMessage: (message: string) => Pushover; - withTitle: (title: string) => Pushover; - withUrl: (url: { url: string; title: string }) => Pushover; - withPriority: (priority: { - level: number; - retry?: number; - expire?: number; - callback?: string; - }) => Pushover; - withSound: (sound: string) => Pushover; - withTimestamp: (timestamp: number) => Pushover; - withHtml: (enable: boolean) => Pushover; - withAttachment: (attachment: File) => Pushover; - withBase64Attachment: (attachment: { - data: string; - type: string; - }) => Pushover; - addUsers: (users: User[]) => Pushover; -}; - -export type User = { - name: string; +export interface PushoverConfig { token: string; - devices: string[]; -}; + defaultUser?: string; +} -console.log( - "this is indented obnoxiously far and has no semi at the end. (testing previous commits", -); +export interface SendOptions { + recipients?: string | string[]; + device?: string | string[]; + verbose?: boolean; +} + +export class Pushover { + private token: string; + private defaultUser?: string; + private apiUrl = "https://api.pushover.net/1/messages.json"; + + constructor(config: PushoverConfig) { + this.token = config.token; + this.defaultUser = config.defaultUser; + } + + /** + * Send a notification to one or multiple recipients + */ + public async send( + message: PushoverMessage, + options: SendOptions = {}, + ): Promise { + const recipients = this.getRecipients(options); + + if (recipients.length === 0) { + throw new Error( + "No recipients specified. Provide recipients in options or set a defaultUser.", + ); + } + + if (options.verbose) { + console.log("Verbose mode enabled. Logging message and options:"); + console.log(message); + console.log(options); + console.log("----------------------"); + console.log("Sending message..."); + } + + const promises = recipients.map((recipient) => + this.sendToSingleRecipient(message, recipient, options.device), + ); + + const results = await Promise.all(promises); + + // Combine results + const combinedResponse: PushoverResponse[] = results.map( + (result) => result, + ); + + return combinedResponse; + } + + private getRecipients(options: SendOptions): string[] { + const { recipients } = options; + + if (recipients) { + return Array.isArray(recipients) ? recipients : [recipients]; + } + + return this.defaultUser ? [this.defaultUser] : []; + } + + private async sendToSingleRecipient( + message: PushoverMessage, + user: string, + device?: string | string[], + ): Promise { + const params = new URLSearchParams(); + + // Add token and user + params.append("token", this.token); + params.append("user", user); + + // Add message properties + Object.entries(message).forEach(([key, value]) => { + if (value !== undefined) { + if (key === "link") { + if (typeof value === "string") { + params.append("url", value); + return; + } + params.append("url", value.url); + if (value.title) { + params.append("url_title", value.title); + } + return; + } + params.append(key, value.toString()); + } + }); + + // Add device if specified + if (device) { + if (Array.isArray(device)) { + params.append("device", device.join(",")); + } else { + params.append("device", device); + } + } + + return this.makeRequest(params); + } + + private makeRequest(params: URLSearchParams): Promise { + return new Promise((resolve, reject) => { + const options = { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }; + + const req = https.request(this.apiUrl, options, (res) => { + let data = ""; + + res.on("data", (chunk) => { + data += chunk; + }); + + res.on("end", () => { + try { + const response = JSON.parse(data) as PushoverResponse; + resolve(response); + } catch (error) { + reject(new Error(`Failed to parse response: ${data}`)); + } + }); + }); + + req.on("error", (error) => { + reject(error); + }); + + req.write(params.toString()); + req.end(); + }); + } +} From f48bd35319e7ca36efb8124691441dbca6a130f9 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 13 Mar 2025 02:53:53 +0100 Subject: [PATCH 05/34] fix: log request error to console --- src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.ts b/src/index.ts index fa6da79..60a70ef 100644 --- a/src/index.ts +++ b/src/index.ts @@ -152,6 +152,7 @@ export class Pushover { const response = JSON.parse(data) as PushoverResponse; resolve(response); } catch (error) { + console.error(error); reject(new Error(`Failed to parse response: ${data}`)); } }); From d520d52da8d1fb25bac8b6a7feaece7e275cb949 Mon Sep 17 00:00:00 2001 From: "Alix von Schirp @ BootMedia Media Production" Date: Fri, 14 Mar 2025 20:52:19 +0100 Subject: [PATCH 06/34] feat: Adds typechecking via zod for message --- src/index.ts | 155 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 126 insertions(+), 29 deletions(-) diff --git a/src/index.ts b/src/index.ts index 60a70ef..bad3809 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,20 +1,106 @@ import https from "node:https"; import { URLSearchParams } from "node:url"; +import { z } from "zod"; -export interface PushoverMessage { - message: string; - title?: string; - link?: { - url: string; - title?: string; - }; - priority?: -2 | -1 | 0 | 1 | 2; - sound?: string; - timestamp?: number; - html?: 0 | 1; - monospace?: 0 | 1; - ttl?: number; -} +const MessageSchema = z + .object({ + /** + * The message sent to the user. + */ + message: z.string().min(3), + /** + * An optional title. + */ + title: z.string().optional(), + /** + * A link attached to the message. + * Can be either the link or an object containing the link and an optional title. + */ + link: z + .string() + .url() + .or( + z.object({ + /** + * The url of the link + */ + url: z.string().url(), + /** + * The title displayed as the link + */ + title: z.string().optional(), + }), + ) + .optional(), + /** + * Sets notification setting for the message. + * + * -2: Message only, no notification. May increment notification bubble. + * -1: Silent notification + * 0: default notification + * 1: ignores user's quiet hours. + * 2: requires acknowledgement + */ + priority: z + .union([ + z.literal(-2), + z.literal(-1), + z.literal(0), + z.literal(1), + z.literal(2), + ]) + .default(0), + emergencyOpts: z + .object({ + repeat: z.number().min(30), + expire: z.number().max(10800), + callback: z.string().url().optional(), + tags: z.string().array().optional(), + }) + .optional(), + sound: z.string().optional(), + timestamp: z.number().optional(), + html: z.boolean().default(false), + monospace: z.boolean().default(false), + ttl: z.number().optional(), + }) + .refine( + (data) => { + if (data.priority == 2 && !data.emergencyOpts) return false; + return true; + }, + { + path: ["priority", "emergencyOpts"], + message: "If priority is set to 2, emergencyOpts must be included.", + }, + ) + .refine( + (data) => { + if (data.html && data.monospace) return false; + return true; + }, + { + path: ["html", "monospace"], + message: "html and monospace are mutually exclusive.", + }, + ); + +export type PushoverMessage = z.infer; + +// export interface PushoverMessage { +// message: string; +// title?: string; +// link?: { +// url: string; +// title?: string; +// } | string; +// priority: -2 | -1 | 0 | 1 | 2; +// sound?: string; +// timestamp?: number; +// html: boolean; +// monospace: boolean; +// ttl?: number; +// } export interface PushoverResponse { status: number; @@ -52,6 +138,8 @@ export class Pushover { ): Promise { const recipients = this.getRecipients(options); + console.log(MessageSchema.parse(message)); + if (recipients.length === 0) { throw new Error( "No recipients specified. Provide recipients in options or set a defaultUser.", @@ -102,22 +190,31 @@ export class Pushover { params.append("user", user); // Add message properties - Object.entries(message).forEach(([key, value]) => { - if (value !== undefined) { - if (key === "link") { - if (typeof value === "string") { - params.append("url", value); - return; - } - params.append("url", value.url); - if (value.title) { - params.append("url_title", value.title); - } - return; - } - params.append(key, value.toString()); + params.append("message", message.message); + if (message.title) params.append("title", message.title); + params.append("priority", "" + message.priority); + if (message.priority === 2 && message.emergencyOpts) { + params.append("repeat", String(message.emergencyOpts.repeat)); + params.append("expire", String(message.emergencyOpts.expire)); + if (message.emergencyOpts.callback) + params.append("callback", message.emergencyOpts.callback); + if (message.emergencyOpts.tags) + params.append("tags", message.emergencyOpts.tags.join()); + } + if (message.link) { + if (typeof message.link === "string") { + params.append("url", message.link); + } else { + params.append("url", message.link.url); + if (message.link.title) params.append("title", message.link.title); } - }); + } + if (message.html) params.append("html", "1"); + if (message.monospace) params.append("monospace", "1"); + if (message.sound) params.append("sound", message.sound); + if (message.timestamp) + params.append("timestamp", String(message.timestamp)); + if (message.ttl) params.append("ttl", String(message.ttl)); // Add device if specified if (device) { From e5a3e04e0c997568bb202b6358bede68113959f4 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Tue, 15 Apr 2025 10:55:19 +0200 Subject: [PATCH 07/34] build(tsconfig): Updates config, adds build:watch script - Build files now include sourcemaps and declarations - No longer compiles non-ts files - package.json includes build:watch script Signed-off-by: Alix von Schirp --- package.json | 3 ++- tsconfig.json | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 707d176..5b72583 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ }, "scripts": { "build": "tsc", + "build:watch": "tsc --watch", "check": "pnpm lint && pnpm typecheck", "docs:generate": "typedoc", "format:check": "prettier --check .", @@ -68,4 +69,4 @@ "*.{js,ts,jsx,tsx,json,css,md}": "prettier --write" }, "type": "module" -} +} diff --git a/tsconfig.json b/tsconfig.json index fb41ac3..6c4a667 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "esModuleInterop": true, "skipLibCheck": true, "target": "es2022", + "sourceMap": true, "allowJs": true, "resolveJsonModule": true, "moduleDetection": "force", @@ -20,6 +21,7 @@ "moduleResolution": "node", "incremental": true, "outDir": "dist", + "declaration": true, /* Path Aliases */ "baseUrl": "./src", @@ -27,6 +29,6 @@ "~/*": ["./src/*"] } }, - "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.cjs", "src/**/*.js"], + "include": ["src/**/*.ts", "src/**/*.tsx"], "exclude": ["node_modules/**/*", "docs/**/*", "dist/**/*"] } From a72a2c335809145498ae663f388f9b7cf7823cfa Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Tue, 15 Apr 2025 11:15:41 +0200 Subject: [PATCH 08/34] ci(pre-commit): Pre-commit hook now should no longer block commits Added eslint-plugin-only-warn to suppress errors Signed-off-by: Alix von Schirp --- eslint.config.mjs | 6 ++++++ package.json | 3 ++- pnpm-lock.yaml | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index af6150b..c99bc9f 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -2,6 +2,7 @@ import globals from "globals"; import pluginJs from "@eslint/js"; import tseslint from "typescript-eslint"; import eslintConfigPrettier from "eslint-config-prettier"; +import onlyWarn from "eslint-plugin-only-warn"; /** @type {import('eslint').Linter.Config[]} */ export default [ @@ -11,4 +12,9 @@ export default [ pluginJs.configs.recommended, ...tseslint.configs.recommended, eslintConfigPrettier, + { + plugins: { + onlyWarn, + }, + }, ]; diff --git a/package.json b/package.json index 5b72583..a5ff346 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@types/node": "^22.13.10", "eslint": "^9.22.0", "eslint-config-prettier": "^10.1.1", + "eslint-plugin-only-warn": "^1.1.0", "finepack": "^2.12.7", "globals": "^16.0.0", "husky": "^9.1.7", @@ -65,7 +66,7 @@ }, "lint-staged": { "package.json": "finepack", - "*.{js,ts,jsx,tsx}": "cmd /c eslint --cache --fix . || exit 0", + "*.{js,ts,jsx,tsx}": "eslint --cache --fix .", "*.{js,ts,jsx,tsx,json,css,md}": "prettier --write" }, "type": "module" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c4dc941..3b4d3da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,6 +27,9 @@ importers: eslint-config-prettier: specifier: ^10.1.1 version: 10.1.1(eslint@9.22.0) + eslint-plugin-only-warn: + specifier: ^1.1.0 + version: 1.1.0 finepack: specifier: ^2.12.7 version: 2.12.7 @@ -413,6 +416,10 @@ packages: peerDependencies: eslint: '>=7.0.0' + eslint-plugin-only-warn@1.1.0: + resolution: {integrity: sha512-2tktqUAT+Q3hCAU0iSf4xAN1k9zOpjK5WO8104mB0rT/dGhOa09582HN5HlbxNbPRZ0THV7nLGvzugcNOSjzfA==} + engines: {node: '>=6'} + eslint-scope@8.3.0: resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1532,6 +1539,8 @@ snapshots: dependencies: eslint: 9.22.0 + eslint-plugin-only-warn@1.1.0: {} + eslint-scope@8.3.0: dependencies: esrecurse: 4.3.0 From 2106734b887862593c6c3941f8998260efd58a77 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Tue, 15 Apr 2025 11:20:01 +0200 Subject: [PATCH 09/34] feat: sending messages is now feature complete including zod schema validation Signed-off-by: Alix von Schirp --- package.json | 3 + src/Pushover.ts | 251 +++++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 267 +----------------------------------------------- 3 files changed, 257 insertions(+), 264 deletions(-) create mode 100644 src/Pushover.ts diff --git a/package.json b/package.json index a5ff346..dd21597 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,9 @@ "typescript": "^5.5.3", "typescript-eslint": "^8.26.0" }, + "files": [ + "dist/**/*.{js,ts,map}" + ], "scripts": { "build": "tsc", "build:watch": "tsc --watch", diff --git a/src/Pushover.ts b/src/Pushover.ts new file mode 100644 index 0000000..ace51c7 --- /dev/null +++ b/src/Pushover.ts @@ -0,0 +1,251 @@ +import https from "node:https"; +import { URLSearchParams } from "node:url"; +import { z } from "zod"; + +const MessageSchema = z + .object({ + /** + * The message sent to the user. + */ + message: z.string().min(3), + /** + * An optional title. + */ + title: z.string().optional(), + /** + * A link attached to the message. + * Can be either the link or an object containing the link and an optional title. + */ + link: z + .string() + .url() + .or( + z.object({ + /** + * The url of the link + */ + url: z.string().url(), + /** + * The title displayed as the link + */ + title: z.string().optional(), + }), + ) + .optional(), + /** + * Sets notification setting for the message. + * + * -2: Message only, no notification. May increment notification bubble. + * -1: Silent notification + * 0: default notification + * 1: ignores user's quiet hours. + * 2: requires acknowledgement + */ + priority: z + .union([ + z.literal(-2), + z.literal(-1), + z.literal(0), + z.literal(1), + z.literal(2), + ]) + .default(0), + emergencyOpts: z + .object({ + repeat: z.number().min(30), + expire: z.number().max(10800), + callback: z.string().url().optional(), + tags: z.string().array().optional(), + }) + .optional(), + sound: z.string().optional(), + timestamp: z.number().optional(), + html: z.boolean().default(false), + monospace: z.boolean().default(false), + ttl: z.number().optional(), + }) + .refine( + (data) => { + if (data.priority == 2 && !data.emergencyOpts) return false; + return true; + }, + { + path: ["priority", "emergencyOpts"], + message: "If priority is set to 2, emergencyOpts must be included.", + }, + ) + .refine( + (data) => { + if (data.html && data.monospace) return false; + return true; + }, + { + path: ["html", "monospace"], + message: "html and monospace are mutually exclusive.", + }, + ); + +export type PushoverMessage = z.infer; + +export interface PushoverResponse { + status: number; + request: string; + errors?: string[]; +} + +export interface PushoverConfig { + token: string; + defaultUser?: string; +} + +export interface SendOptions { + recipients?: string | string[]; + device?: string | string[]; + verbose?: boolean; +} + +export class Pushover { + private token: string; + private defaultUser?: string; + private apiUrl = "https://api.pushover.net/1/messages.json"; + + constructor(config: PushoverConfig) { + this.token = config.token; + this.defaultUser = config.defaultUser; + } + + /** + * Send a notification to one or multiple recipients + */ + public async send( + message: PushoverMessage, + options: SendOptions = {}, + ): Promise { + const recipients = this.getRecipients(options); + + console.log(MessageSchema.parse(message)); + + if (recipients.length === 0) { + throw new Error( + "No recipients specified. Provide recipients in options or set a defaultUser.", + ); + } + + if (options.verbose) { + console.log("Verbose mode enabled. Logging message and options:"); + console.log(message); + console.log(options); + console.log("----------------------"); + console.log("Sending message..."); + } + + const promises = recipients.map((recipient) => + this.sendToSingleRecipient(message, recipient, options.device), + ); + + const results = await Promise.all(promises); + + // Combine results + const combinedResponse: PushoverResponse[] = results.map( + (result) => result, + ); + + return combinedResponse; + } + + private getRecipients(options: SendOptions): string[] { + const { recipients } = options; + + if (recipients) { + return Array.isArray(recipients) ? recipients : [recipients]; + } + + return this.defaultUser ? [this.defaultUser] : []; + } + + private async sendToSingleRecipient( + message: PushoverMessage, + user: string, + device?: string | string[], + ): Promise { + const params = new URLSearchParams(); + + // Add token and user + params.append("token", this.token); + params.append("user", user); + + // Add message properties + params.append("message", message.message); + if (message.title) params.append("title", message.title); + params.append("priority", "" + message.priority); + if (message.priority === 2 && message.emergencyOpts) { + params.append("repeat", String(message.emergencyOpts.repeat)); + params.append("expire", String(message.emergencyOpts.expire)); + if (message.emergencyOpts.callback) + params.append("callback", message.emergencyOpts.callback); + if (message.emergencyOpts.tags) + params.append("tags", message.emergencyOpts.tags.join()); + } + if (message.link) { + if (typeof message.link === "string") { + params.append("url", message.link); + } else { + params.append("url", message.link.url); + if (message.link.title) params.append("title", message.link.title); + } + } + if (message.html) params.append("html", "1"); + if (message.monospace) params.append("monospace", "1"); + if (message.sound) params.append("sound", message.sound); + if (message.timestamp) + params.append("timestamp", String(message.timestamp)); + if (message.ttl) params.append("ttl", String(message.ttl)); + + // Add device if specified + if (device) { + if (Array.isArray(device)) { + params.append("device", device.join(",")); + } else { + params.append("device", device); + } + } + + return this.makeRequest(params); + } + + private makeRequest(params: URLSearchParams): Promise { + return new Promise((resolve, reject) => { + const options = { + method: "POST", + headers: { + "Content-Type": "application/x-www-form-urlencoded", + }, + }; + + const req = https.request(this.apiUrl, options, (res) => { + let data = ""; + + res.on("data", (chunk) => { + data += chunk; + }); + + res.on("end", () => { + try { + const response = JSON.parse(data) as PushoverResponse; + resolve(response); + } catch (error) { + console.error(error); + reject(new Error(`Failed to parse response: ${data}`)); + } + }); + }); + + req.on("error", (error) => { + reject(error); + }); + + req.write(params.toString()); + req.end(); + }); + } +} diff --git a/src/index.ts b/src/index.ts index bad3809..54d4896 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,266 +1,5 @@ -import https from "node:https"; -import { URLSearchParams } from "node:url"; -import { z } from "zod"; +import { Pushover } from "./Pushover"; -const MessageSchema = z - .object({ - /** - * The message sent to the user. - */ - message: z.string().min(3), - /** - * An optional title. - */ - title: z.string().optional(), - /** - * A link attached to the message. - * Can be either the link or an object containing the link and an optional title. - */ - link: z - .string() - .url() - .or( - z.object({ - /** - * The url of the link - */ - url: z.string().url(), - /** - * The title displayed as the link - */ - title: z.string().optional(), - }), - ) - .optional(), - /** - * Sets notification setting for the message. - * - * -2: Message only, no notification. May increment notification bubble. - * -1: Silent notification - * 0: default notification - * 1: ignores user's quiet hours. - * 2: requires acknowledgement - */ - priority: z - .union([ - z.literal(-2), - z.literal(-1), - z.literal(0), - z.literal(1), - z.literal(2), - ]) - .default(0), - emergencyOpts: z - .object({ - repeat: z.number().min(30), - expire: z.number().max(10800), - callback: z.string().url().optional(), - tags: z.string().array().optional(), - }) - .optional(), - sound: z.string().optional(), - timestamp: z.number().optional(), - html: z.boolean().default(false), - monospace: z.boolean().default(false), - ttl: z.number().optional(), - }) - .refine( - (data) => { - if (data.priority == 2 && !data.emergencyOpts) return false; - return true; - }, - { - path: ["priority", "emergencyOpts"], - message: "If priority is set to 2, emergencyOpts must be included.", - }, - ) - .refine( - (data) => { - if (data.html && data.monospace) return false; - return true; - }, - { - path: ["html", "monospace"], - message: "html and monospace are mutually exclusive.", - }, - ); +export default Pushover; -export type PushoverMessage = z.infer; - -// export interface PushoverMessage { -// message: string; -// title?: string; -// link?: { -// url: string; -// title?: string; -// } | string; -// priority: -2 | -1 | 0 | 1 | 2; -// sound?: string; -// timestamp?: number; -// html: boolean; -// monospace: boolean; -// ttl?: number; -// } - -export interface PushoverResponse { - status: number; - request: string; - errors?: string[]; -} - -export interface PushoverConfig { - token: string; - defaultUser?: string; -} - -export interface SendOptions { - recipients?: string | string[]; - device?: string | string[]; - verbose?: boolean; -} - -export class Pushover { - private token: string; - private defaultUser?: string; - private apiUrl = "https://api.pushover.net/1/messages.json"; - - constructor(config: PushoverConfig) { - this.token = config.token; - this.defaultUser = config.defaultUser; - } - - /** - * Send a notification to one or multiple recipients - */ - public async send( - message: PushoverMessage, - options: SendOptions = {}, - ): Promise { - const recipients = this.getRecipients(options); - - console.log(MessageSchema.parse(message)); - - if (recipients.length === 0) { - throw new Error( - "No recipients specified. Provide recipients in options or set a defaultUser.", - ); - } - - if (options.verbose) { - console.log("Verbose mode enabled. Logging message and options:"); - console.log(message); - console.log(options); - console.log("----------------------"); - console.log("Sending message..."); - } - - const promises = recipients.map((recipient) => - this.sendToSingleRecipient(message, recipient, options.device), - ); - - const results = await Promise.all(promises); - - // Combine results - const combinedResponse: PushoverResponse[] = results.map( - (result) => result, - ); - - return combinedResponse; - } - - private getRecipients(options: SendOptions): string[] { - const { recipients } = options; - - if (recipients) { - return Array.isArray(recipients) ? recipients : [recipients]; - } - - return this.defaultUser ? [this.defaultUser] : []; - } - - private async sendToSingleRecipient( - message: PushoverMessage, - user: string, - device?: string | string[], - ): Promise { - const params = new URLSearchParams(); - - // Add token and user - params.append("token", this.token); - params.append("user", user); - - // Add message properties - params.append("message", message.message); - if (message.title) params.append("title", message.title); - params.append("priority", "" + message.priority); - if (message.priority === 2 && message.emergencyOpts) { - params.append("repeat", String(message.emergencyOpts.repeat)); - params.append("expire", String(message.emergencyOpts.expire)); - if (message.emergencyOpts.callback) - params.append("callback", message.emergencyOpts.callback); - if (message.emergencyOpts.tags) - params.append("tags", message.emergencyOpts.tags.join()); - } - if (message.link) { - if (typeof message.link === "string") { - params.append("url", message.link); - } else { - params.append("url", message.link.url); - if (message.link.title) params.append("title", message.link.title); - } - } - if (message.html) params.append("html", "1"); - if (message.monospace) params.append("monospace", "1"); - if (message.sound) params.append("sound", message.sound); - if (message.timestamp) - params.append("timestamp", String(message.timestamp)); - if (message.ttl) params.append("ttl", String(message.ttl)); - - // Add device if specified - if (device) { - if (Array.isArray(device)) { - params.append("device", device.join(",")); - } else { - params.append("device", device); - } - } - - return this.makeRequest(params); - } - - private makeRequest(params: URLSearchParams): Promise { - return new Promise((resolve, reject) => { - const options = { - method: "POST", - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, - }; - - const req = https.request(this.apiUrl, options, (res) => { - let data = ""; - - res.on("data", (chunk) => { - data += chunk; - }); - - res.on("end", () => { - try { - const response = JSON.parse(data) as PushoverResponse; - resolve(response); - } catch (error) { - console.error(error); - reject(new Error(`Failed to parse response: ${data}`)); - } - }); - }); - - req.on("error", (error) => { - reject(error); - }); - - req.write(params.toString()); - req.end(); - }); - } -} +Object.assign(module.exports, Pushover); From 6a8cf528e36b5c35e02c98eacb02638084a78623 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Tue, 15 Apr 2025 11:22:21 +0200 Subject: [PATCH 10/34] build(tests): Adds jest to run tests Milestone: none Signed-off-by: Alix von Schirp --- jest.config.js | 7 + package.json | 4 + pnpm-lock.yaml | 2243 +++++++++++++++++++++++++++++++++++++++++++ tests/index.spec.ts | 11 + 4 files changed, 2265 insertions(+) create mode 100644 jest.config.js create mode 100644 tests/index.spec.ts diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..e6904cc --- /dev/null +++ b/jest.config.js @@ -0,0 +1,7 @@ +/** @type {import('ts-jest').JestConfigWithTsJest} **/ +export default { + testEnvironment: "node", + transform: { + "^.+\.tsx?$": ["ts-jest", {}], + }, +}; diff --git a/package.json b/package.json index dd21597..4c6695b 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "devDependencies": { "@eslint/js": "^9.22.0", "@shipgirl/typedoc-plugin-versions": "^0.3.0", + "@types/jest": "^29.5.14", "@types/node": "^22.13.10", "eslint": "^9.22.0", "eslint-config-prettier": "^10.1.1", @@ -36,8 +37,10 @@ "finepack": "^2.12.7", "globals": "^16.0.0", "husky": "^9.1.7", + "jest": "^29.7.0", "lint-staged": "^15.4.3", "prettier": "3.5.3", + "ts-jest": "^29.2.6", "typedoc": "^0.27.9", "typedoc-github-theme": "^0.2.1", "typedoc-plugin-coverage": "^3.4.1", @@ -60,6 +63,7 @@ "format:check": "prettier --check .", "lint": "eslint --cache .", "prepare": "husky", + "test": "jest", "typecheck": "tsc --noEmit" }, "private": true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3b4d3da..29677f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,6 +18,9 @@ importers: '@shipgirl/typedoc-plugin-versions': specifier: ^0.3.0 version: 0.3.0(typedoc@0.27.9(typescript@5.8.2)) + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 '@types/node': specifier: ^22.13.10 version: 22.13.10 @@ -39,12 +42,18 @@ importers: husky: specifier: ^9.1.7 version: 9.1.7 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@22.13.10) lint-staged: specifier: ^15.4.3 version: 15.4.3 prettier: specifier: 3.5.3 version: 3.5.3 + ts-jest: + specifier: ^29.2.6 + version: 29.3.2(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) typedoc: specifier: ^0.27.9 version: 0.27.9(typescript@5.8.2) @@ -78,6 +87,171 @@ importers: packages: + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.10': + resolution: {integrity: sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.27.0': + resolution: {integrity: sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.0': + resolution: {integrity: sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.27.0': + resolution: {integrity: sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.27.0': + resolution: {integrity: sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.27.0': + resolution: {integrity: sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.27.0': + resolution: {integrity: sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.27.0': + resolution: {integrity: sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@eslint-community/eslint-utils@4.4.1': resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -139,6 +313,98 @@ packages: resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} engines: {node: '>=18.18'} + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@29.7.0': + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/core@29.7.0': + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/environment@29.7.0': + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect-utils@29.7.0': + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/expect@29.7.0': + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/fake-timers@29.7.0': + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/globals@29.7.0': + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/reporters@29.7.0': + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/source-map@29.6.3': + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-result@29.7.0': + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/test-sequencer@29.7.0': + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/transform@29.7.0': + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -166,21 +432,66 @@ packages: peerDependencies: typedoc: '>=0.26.0 <0.28.0' + '@sinclair/typebox@0.27.8': + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@10.3.0': + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.7': + resolution: {integrity: sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==} + '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} '@types/node@22.13.10': resolution: {integrity: sha512-I6LPUvlRH+O6VRUqYOcMudhaIdUVWfsjnZavnsraHvpBwaEyMN29ry+0UVJhImYL16xsscu0aske3yA+uPOWfw==} + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + '@typescript-eslint/eslint-plugin@8.26.0': resolution: {integrity: sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -254,6 +565,10 @@ packages: ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + ansi-escapes@7.0.0: resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} engines: {node: '>=18'} @@ -262,6 +577,10 @@ packages: resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} engines: {node: '>=0.10.0'} + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + ansi-regex@6.1.0: resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} engines: {node: '>=12'} @@ -278,10 +597,21 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -289,6 +619,34 @@ packages: resolution: {integrity: sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==} engines: {node: '>=0.10.0'} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + babel-jest@29.7.0: + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@29.6.3: + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -302,6 +660,21 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bs-logger@0.2.6: + resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} + engines: {node: '>= 6'} + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -314,6 +687,17 @@ packages: resolution: {integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==} engines: {node: '>=0.10.0'} + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001713: + resolution: {integrity: sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==} + chalk@0.4.0: resolution: {integrity: sha512-sQfYDlfv2DGVtjdoQqxS0cEZDroyG8h6TamA6rvxwlrU5BaSLDx9xhatBYl2pxZ7gmpNaPFVwBtdGdu5rQ+tYQ==} engines: {node: '>=0.8.0'} @@ -334,6 +718,17 @@ packages: resolution: {integrity: sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cjs-module-lexer@1.4.3: + resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + cli-cursor@5.0.0: resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} engines: {node: '>=18'} @@ -342,11 +737,22 @@ packages: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} engines: {node: '>=18'} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + coffeescript@2.7.0: resolution: {integrity: sha512-hzWp6TUE2d/jCcN67LrW1eh5b/rSDKQK6oD6VMLlggYVUUFexgTH9z3dNYihzX4RMhze5FTUsUmOXViJKFQR/A==} engines: {node: '>=6'} hasBin: true + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -364,6 +770,14 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + create-jest@29.7.0: + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -385,12 +799,47 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.137: + resolution: {integrity: sha512-/QSJaU2JyIuTbbABAo/crOs+SuAZLS+fVVS10PVrIT9hrRkmZl8Hb0xPSkKRUUWHQtYzXHpQUW3Dy5hwMzGZkA==} + + emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + emoji-regex@10.4.0: resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -402,10 +851,18 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} @@ -446,6 +903,11 @@ packages: resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.6.0: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} @@ -465,6 +927,10 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + execa@8.0.1: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} @@ -477,6 +943,14 @@ packages: resolution: {integrity: sha512-+ujBig9GaRXyOhu3IyWyFt58gL1dbA3yd291FerR6Zrea5cCNfpboiXNuvggfmWWOiOqGIpaqW2Q8t0nAXdehQ==} engines: {node: '>= 0.10.0', npm: '>= 1.4.0'} + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -493,10 +967,16 @@ packages: fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -505,6 +985,10 @@ packages: resolution: {integrity: sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==} engines: {node: '>=0.10.0'} + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} @@ -528,17 +1012,41 @@ packages: resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} engines: {node: '>=14.14'} + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.3.0: resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} engines: {node: '>=18'} + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + get-stdin@4.0.1: resolution: {integrity: sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==} engines: {node: '>=0.10.0'} + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} @@ -551,6 +1059,14 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -588,6 +1104,13 @@ packages: resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==} engines: {node: ^16.14.0 || >=18.0.0} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + human-signals@5.0.0: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} @@ -605,6 +1128,11 @@ packages: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -613,6 +1141,13 @@ packages: resolution: {integrity: sha512-aqwDFWSgSgfRaEwao5lg5KEcVd/2a+D1rvoG7NdilmYz0NwRk6StWpWdz/Hpk34MKPpx7s8XxUqimfcQK6gGlg==} engines: {node: '>=0.10.0'} + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -628,6 +1163,10 @@ packages: resolution: {integrity: sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==} engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-fullwidth-code-point@4.0.0: resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} engines: {node: '>=12'} @@ -636,6 +1175,10 @@ packages: resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} engines: {node: '>=18'} + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -648,6 +1191,10 @@ packages: resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} engines: {node: '>=8'} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + is-stream@3.0.0: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -658,10 +1205,180 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@6.0.3: + resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} + engines: {node: '>=10'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + + jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-cli@29.7.0: + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@29.7.0: + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + + jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest@29.7.0: + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -669,12 +1386,20 @@ packages: resolution: {integrity: sha512-/4ARarHlSuFbRgWzftpWUjsBGSjkCAkhcl8tf5/YCToMumioFMmxSNjsEYwk9fH8OLjiWD0Rv3u5zdOq8ZlMWQ==} engines: {node: '>= 0.10.0', npm: '>= 1.4.0'} + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} @@ -690,6 +1415,14 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -698,6 +1431,9 @@ packages: resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} engines: {node: '>=14'} + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} @@ -714,6 +1450,10 @@ packages: resolution: {integrity: sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A==} engines: {node: '>=0.10.0'} + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} @@ -724,6 +1464,9 @@ packages: lodash.defaults@4.0.1: resolution: {integrity: sha512-wD18hjhvkjhKqECL3fpTLochfdi6c9HsczeBF25W6wncvhCTfDJwA3E62UwBeioZQnvWeXoy+ifU7nzTq1j+Bg==} + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -754,9 +1497,22 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lunr@2.3.9: resolution: {integrity: sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==} + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + map-obj@1.0.1: resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} engines: {node: '>=0.10.0'} @@ -783,6 +1539,10 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} @@ -794,6 +1554,10 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + minimatch@9.0.5: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} @@ -811,6 +1575,12 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + nomnom@1.8.1: resolution: {integrity: sha512-5s0JxqhDx9/rksG2BTMVN1enjWSvPidpoSgViZU4ZXULyTe+7jxcCRLB6f42Z0l1xYJpleCBtSyY6Lwg3uu5CQ==} deprecated: Package no longer supported. Contact support@npmjs.com for more info. @@ -822,6 +1592,14 @@ packages: resolution: {integrity: sha512-V6gygoYb/5EmNI+MEGrWkC+e6+Rr7mTmfHrxDbLzxQogBkgzo76rkok0Am6thgSF7Mv2nLOajAJj5vDJZEFn7g==} engines: {node: ^16.14.0 || >=18.0.0} + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -830,6 +1608,13 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} @@ -842,14 +1627,26 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -858,6 +1655,10 @@ packages: resolution: {integrity: sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==} engines: {node: '>=0.10.0'} + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + parse-ms@2.1.0: resolution: {integrity: sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==} engines: {node: '>=6'} @@ -870,6 +1671,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -885,6 +1690,9 @@ packages: resolution: {integrity: sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg==} engines: {node: '>=0.10.0'} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -906,6 +1714,14 @@ packages: resolution: {integrity: sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==} engines: {node: '>=0.10.0'} + pirates@4.0.7: + resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -915,10 +1731,18 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + pretty-ms@6.0.1: resolution: {integrity: sha512-ke4njoVmlotekHlHyCZ3wI/c5AMT8peuHs8rKJqekj/oR5G8lND2dVpicFlUz5cbZgE290vvkMuDwfj/OcW1kw==} engines: {node: '>=10'} + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} @@ -927,9 +1751,15 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + read-pkg-up@1.0.1: resolution: {integrity: sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A==} engines: {node: '>=0.10.0'} @@ -946,10 +1776,26 @@ packages: resolution: {integrity: sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A==} engines: {node: '>=0.10.0'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve.exports@2.0.3: + resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} + engines: {node: '>=10'} + resolve@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} @@ -973,6 +1819,10 @@ packages: resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + semver@7.7.1: resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} engines: {node: '>=10'} @@ -993,6 +1843,13 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + slice-ansi@5.0.0: resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} engines: {node: '>=12'} @@ -1012,6 +1869,13 @@ packages: resolution: {integrity: sha512-aUYIEU/UviqPgc8mHR6IW1EGxkAXpeRETYcrzg8cLAvUPZcpAlleSXHV2mY7G12GphSH6Gzv+4MMVSSkbdteHg==} engines: {node: '>=8'} + source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + spdx-correct@3.2.0: resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} @@ -1024,10 +1888,25 @@ packages: spdx-license-ids@3.0.21: resolution: {integrity: sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg==} + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + string-width@7.2.0: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} @@ -1041,6 +1920,10 @@ packages: resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} engines: {node: '>=0.10.0'} + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + strip-ansi@7.1.0: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} @@ -1049,6 +1932,14 @@ packages: resolution: {integrity: sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==} engines: {node: '>=0.10.0'} + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + strip-final-newline@3.0.0: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} @@ -1070,10 +1961,21 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1088,6 +1990,30 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-jest@29.3.2: + resolution: {integrity: sha512-bJJkrWc6PjFVz5g2DGCNUo8z7oFEYaz1xP1NpeDU7KNLMWPpEyV8Chbpkn8xjzgRDpQhnGMyvyldoL7h8JXyug==} + engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@babel/core': '>=7.0.0-beta.0 <8' + '@jest/transform': ^29.0.0 + '@jest/types': ^29.0.0 + babel-jest: ^29.0.0 + esbuild: '*' + jest: ^29.0.0 + typescript: '>=4.3 <6' + peerDependenciesMeta: + '@babel/core': + optional: true + '@jest/transform': + optional: true + '@jest/types': + optional: true + babel-jest: + optional: true + esbuild: + optional: true + tsml@1.0.1: resolution: {integrity: sha512-3KmepnH9SUsoOVtg013CRrL7c+AK7ECaquAsJdvu4288EDJuraqBlP4PDXT/rLEJ9YDn4jqLAzRJsnFPx+V6lg==} deprecated: no longer maintained @@ -1096,6 +2022,18 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@4.39.1: + resolution: {integrity: sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==} + engines: {node: '>=16'} + typedoc-github-theme@0.2.1: resolution: {integrity: sha512-pOgsS9CVAOO3JxQ1V0ocDkrPCULpoWg1OzRmn/mOlyG+vEYwUAp5DAoKrGECdNIomycxcisc8ovcMX0nHDgWTA==} engines: {node: '>=18.0.0'} @@ -1165,12 +2103,25 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -1180,15 +2131,41 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + wrap-ansi@9.0.0: resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} engines: {node: '>=18'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yaml@2.7.0: resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} engines: {node: '>= 14'} hasBin: true + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -1198,6 +2175,198 @@ packages: snapshots: + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.26.8': {} + + '@babel/core@7.26.10': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.27.0 + '@babel/helper-compilation-targets': 7.27.0 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.10) + '@babel/helpers': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + convert-source-map: 2.0.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.27.0': + dependencies: + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.27.0': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.27.0 + '@babel/types': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.27.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.26.5': {} + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helpers@7.27.0': + dependencies: + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 + + '@babel/parser@7.27.0': + dependencies: + '@babel/types': 7.27.0 + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.10)': + dependencies: + '@babel/core': 7.26.10 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/template@7.27.0': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + + '@babel/traverse@7.27.0': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.27.0 + '@babel/parser': 7.27.0 + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.27.0': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@bcoe/v8-coverage@0.2.3': {} + '@eslint-community/eslint-utils@4.4.1(eslint@9.22.0)': dependencies: eslint: 9.22.0 @@ -1261,6 +2430,195 @@ snapshots: '@humanwhocodes/retry@0.4.2': {} + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + + '@jest/core@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@22.13.10) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/environment@29.7.0': + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + jest-mock: 29.7.0 + + '@jest/expect-utils@29.7.0': + dependencies: + jest-get-type: 29.6.3 + + '@jest/expect@29.7.0': + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/fake-timers@29.7.0': + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 22.13.10 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + '@jest/globals@29.7.0': + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + + '@jest/reporters@29.7.0': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + '@types/node': 22.13.10 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.3 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.3.0 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.8 + + '@jest/source-map@29.6.3': + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + callsites: 3.1.0 + graceful-fs: 4.2.11 + + '@jest/test-result@29.7.0': + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@29.7.0': + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + + '@jest/transform@29.7.0': + dependencies: + '@babel/core': 7.26.10 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.25 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.8 + pirates: 4.0.7 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.13.10 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -1291,20 +2649,78 @@ snapshots: semver: 7.7.1 typedoc: 0.27.9(typescript@5.8.2) + '@sinclair/typebox@0.27.8': {} + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@10.3.0': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.7 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.27.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.27.0 + '@babel/types': 7.27.0 + + '@types/babel__traverse@7.20.7': + dependencies: + '@babel/types': 7.27.0 + '@types/estree@1.0.6': {} + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 22.13.10 + '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.3 + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/jest@29.5.14': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + '@types/json-schema@7.0.15': {} '@types/node@22.13.10': dependencies: undici-types: 6.20.0 + '@types/stack-utils@2.0.3': {} + '@types/unist@3.0.3': {} + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + '@typescript-eslint/eslint-plugin@8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.22.0)(typescript@5.8.2))(eslint@9.22.0)(typescript@5.8.2)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -1408,12 +2824,18 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + ansi-escapes@7.0.0: dependencies: environment: 1.1.0 ansi-regex@2.1.1: {} + ansi-regex@5.0.1: {} + ansi-regex@6.1.0: {} ansi-styles@1.0.0: {} @@ -1424,12 +2846,80 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.1: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + argparse@2.0.1: {} array-find-index@1.0.2: {} + async@3.2.6: {} + + babel-jest@29.7.0(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.26.10) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.26.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@29.6.3: + dependencies: + '@babel/template': 7.27.0 + '@babel/types': 7.27.0 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.7 + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.10) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.10) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.10) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.10) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.10) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.10) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.10) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.10) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.10) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.10) + + babel-preset-jest@29.6.3(@babel/core@7.26.10): + dependencies: + '@babel/core': 7.26.10 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) + balanced-match@1.0.2: {} brace-expansion@1.1.11: @@ -1445,6 +2935,23 @@ snapshots: dependencies: fill-range: 7.1.1 + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001713 + electron-to-chromium: 1.5.137 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + + bs-logger@0.2.6: + dependencies: + fast-json-stable-stringify: 2.1.0 + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + callsites@3.1.0: {} camelcase-keys@2.1.0: @@ -1454,6 +2961,12 @@ snapshots: camelcase@2.1.1: {} + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001713: {} + chalk@0.4.0: dependencies: ansi-styles: 1.0.0 @@ -1480,6 +2993,12 @@ snapshots: chalk@5.4.1: {} + char-regex@1.0.2: {} + + ci-info@3.9.0: {} + + cjs-module-lexer@1.4.3: {} + cli-cursor@5.0.0: dependencies: restore-cursor: 5.1.0 @@ -1489,8 +3008,18 @@ snapshots: slice-ansi: 5.0.0 string-width: 7.2.0 + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + co@4.6.0: {} + coffeescript@2.7.0: {} + collect-v8-coverage@1.0.2: {} + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -1503,6 +3032,23 @@ snapshots: concat-map@0.0.1: {} + convert-source-map@2.0.0: {} + + create-jest@29.7.0(@types/node@22.13.10): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@22.13.10) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -1519,10 +3065,28 @@ snapshots: decamelize@1.2.0: {} + dedent@1.5.3: {} + deep-is@0.1.4: {} + deepmerge@4.3.1: {} + + detect-newline@3.1.0: {} + + diff-sequences@29.6.3: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-to-chromium@1.5.137: {} + + emittery@0.13.1: {} + emoji-regex@10.4.0: {} + emoji-regex@8.0.0: {} + entities@4.5.0: {} environment@1.1.0: {} @@ -1531,8 +3095,12 @@ snapshots: dependencies: is-arrayish: 0.2.1 + escalade@3.2.0: {} + escape-string-regexp@1.0.5: {} + escape-string-regexp@2.0.0: {} + escape-string-regexp@4.0.0: {} eslint-config-prettier@10.1.1(eslint@9.22.0): @@ -1596,6 +3164,8 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.14.1) eslint-visitor-keys: 4.2.0 + esprima@4.0.1: {} + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -1610,6 +3180,18 @@ snapshots: eventemitter3@5.0.1: {} + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + execa@8.0.1: dependencies: cross-spawn: 7.0.6 @@ -1630,6 +3212,16 @@ snapshots: existential@1.0.3: {} + exit@0.1.2: {} + + expect@29.7.0: + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + fast-deep-equal@3.1.3: {} fast-glob@3.3.3: @@ -1648,10 +3240,18 @@ snapshots: dependencies: reusify: 1.1.0 + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -1661,6 +3261,11 @@ snapshots: path-exists: 2.1.0 pinkie-promise: 2.0.1 + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + find-up@5.0.0: dependencies: locate-path: 6.0.0 @@ -1700,12 +3305,25 @@ snapshots: jsonfile: 6.1.0 universalify: 2.0.1 + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + function-bind@1.1.2: {} + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + get-east-asian-width@1.3.0: {} + get-package-type@0.1.0: {} + get-stdin@4.0.1: {} + get-stream@6.0.1: {} + get-stream@8.0.1: {} glob-parent@5.1.2: @@ -1716,6 +3334,17 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + globals@11.12.0: {} + globals@14.0.0: {} globals@16.0.0: {} @@ -1742,6 +3371,10 @@ snapshots: dependencies: lru-cache: 10.4.3 + html-escaper@2.0.2: {} + + human-signals@2.1.0: {} + human-signals@5.0.0: {} husky@9.1.7: {} @@ -1753,12 +3386,24 @@ snapshots: parent-module: 1.0.1 resolve-from: 4.0.0 + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + imurmurhash@0.1.4: {} indent-string@2.1.0: dependencies: repeating: 2.0.1 + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.4: {} + is-arrayish@0.2.1: {} is-core-module@2.16.1: @@ -1769,12 +3414,16 @@ snapshots: is-finite@1.1.0: {} + is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@4.0.0: {} is-fullwidth-code-point@5.0.0: dependencies: get-east-asian-width: 1.3.0 + is-generator-fn@2.1.0: {} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -1783,24 +3432,395 @@ snapshots: is-plain-obj@2.1.0: {} + is-stream@2.0.1: {} + is-stream@3.0.0: {} is-utf8@0.2.1: {} isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.26.10 + '@babel/parser': 7.27.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-instrument@6.0.3: + dependencies: + '@babel/core': 7.26.10 + '@babel/parser': 7.27.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + + jest-changed-files@29.7.0: + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + + jest-circus@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.3 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-cli@29.7.0(@types/node@22.13.10): + dependencies: + '@jest/core': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@22.13.10) + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@22.13.10) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-config@29.7.0(@types/node@22.13.10): + dependencies: + '@babel/core': 7.26.10 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.26.10) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 22.13.10 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-diff@29.7.0: + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-docblock@29.7.0: + dependencies: + detect-newline: 3.1.0 + + jest-each@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + + jest-environment-node@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + jest-mock: 29.7.0 + jest-util: 29.7.0 + + jest-get-type@29.6.3: {} + + jest-haste-map@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.13.10 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-leak-detector@29.7.0: + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-matcher-utils@29.7.0: + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + + jest-message-util@29.7.0: + dependencies: + '@babel/code-frame': 7.26.2 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + jest-util: 29.7.0 + + jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + optionalDependencies: + jest-resolve: 29.7.0 + + jest-regex-util@29.6.3: {} + + jest-resolve-dependencies@29.7.0: + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + + jest-resolve@29.7.0: + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.10 + resolve.exports: 2.0.3 + slash: 3.0.0 + + jest-runner@29.7.0: + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + + jest-runtime@29.7.0: + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + cjs-module-lexer: 1.4.3 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-snapshot@29.7.0: + dependencies: + '@babel/core': 7.26.10 + '@babel/generator': 7.27.0 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.10) + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.10) + '@babel/types': 7.27.0 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.10) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + jest-util@29.7.0: + dependencies: + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jest-watcher@29.7.0: + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.13.10 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + + jest-worker@29.7.0: + dependencies: + '@types/node': 22.13.10 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@29.7.0(@types/node@22.13.10): + dependencies: + '@jest/core': 29.7.0 + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0(@types/node@22.13.10) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + js-yaml@4.1.0: dependencies: argparse: 2.0.1 + jsesc@3.1.0: {} + json-buffer@3.0.1: {} json-is-equal@1.0.0: {} + json-parse-even-better-errors@2.3.1: {} + json-schema-traverse@0.4.1: {} json-stable-stringify-without-jsonify@1.0.1: {} + json5@2.2.3: {} + jsonfile@6.1.0: dependencies: universalify: 2.0.1 @@ -1818,6 +3838,10 @@ snapshots: kind-of@6.0.3: {} + kleur@3.0.3: {} + + leven@3.1.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -1825,6 +3849,8 @@ snapshots: lilconfig@3.1.3: {} + lines-and-columns@1.2.4: {} + linkify-it@5.0.0: dependencies: uc.micro: 2.1.0 @@ -1861,6 +3887,10 @@ snapshots: pinkie-promise: 2.0.1 strip-bom: 2.0.0 + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + locate-path@6.0.0: dependencies: p-locate: 5.0.0 @@ -1872,6 +3902,8 @@ snapshots: lodash.assigninwith: 4.2.0 lodash.rest: 4.0.5 + lodash.memoize@4.1.2: {} + lodash.merge@4.6.2: {} lodash.omit@4.5.0: {} @@ -1902,8 +3934,22 @@ snapshots: lru-cache@10.4.3: {} + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + lunr@2.3.9: {} + make-dir@4.0.0: + dependencies: + semver: 7.7.1 + + make-error@1.3.6: {} + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + map-obj@1.0.1: {} markdown-it@14.1.0: @@ -1939,6 +3985,8 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mimic-fn@2.1.0: {} + mimic-fn@4.0.0: {} mimic-function@5.0.1: {} @@ -1947,6 +3995,10 @@ snapshots: dependencies: brace-expansion: 1.1.11 + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 @@ -1959,6 +4011,10 @@ snapshots: natural-compare@1.4.0: {} + node-int64@0.4.0: {} + + node-releases@2.0.19: {} + nomnom@1.8.1: dependencies: chalk: 0.4.0 @@ -1977,12 +4033,26 @@ snapshots: semver: 7.7.1 validate-npm-package-license: 3.0.4 + normalize-path@3.0.0: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 object-assign@4.1.1: {} + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + onetime@6.0.0: dependencies: mimic-fn: 4.0.0 @@ -2000,14 +4070,24 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + p-limit@3.1.0: dependencies: yocto-queue: 0.1.0 + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + p-locate@5.0.0: dependencies: p-limit: 3.1.0 + p-try@2.2.0: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -2016,6 +4096,13 @@ snapshots: dependencies: error-ex: 1.3.2 + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + parse-ms@2.1.0: {} path-exists@2.1.0: @@ -2024,6 +4111,8 @@ snapshots: path-exists@4.0.0: {} + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -2036,6 +4125,8 @@ snapshots: pify: 2.3.0 pinkie-promise: 2.0.1 + picocolors@1.1.1: {} + picomatch@2.3.1: {} pidtree@0.6.0: {} @@ -2048,20 +4139,41 @@ snapshots: pinkie@2.0.4: {} + pirates@4.0.7: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + prelude-ls@1.2.1: {} prettier@3.5.3: {} + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + pretty-ms@6.0.1: dependencies: parse-ms: 2.1.0 + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + punycode.js@2.3.1: {} punycode@2.3.1: {} + pure-rand@6.1.0: {} + queue-microtask@1.2.3: {} + react-is@18.3.1: {} + read-pkg-up@1.0.1: dependencies: find-up: 1.1.2 @@ -2082,8 +4194,18 @@ snapshots: dependencies: is-finite: 1.1.0 + require-directory@2.1.1: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + resolve-from@4.0.0: {} + resolve-from@5.0.0: {} + + resolve.exports@2.0.3: {} + resolve@1.22.10: dependencies: is-core-module: 2.16.1 @@ -2105,6 +4227,8 @@ snapshots: semver@5.7.2: {} + semver@6.3.1: {} + semver@7.7.1: {} shebang-command@2.0.0: @@ -2117,6 +4241,10 @@ snapshots: signal-exit@4.1.0: {} + sisteransi@1.0.5: {} + + slash@3.0.0: {} + slice-ansi@5.0.0: dependencies: ansi-styles: 6.2.1 @@ -2138,6 +4266,13 @@ snapshots: dependencies: is-plain-obj: 2.1.0 + source-map-support@0.5.13: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + spdx-correct@3.2.0: dependencies: spdx-expression-parse: 3.0.1 @@ -2152,8 +4287,25 @@ snapshots: spdx-license-ids@3.0.21: {} + sprintf-js@1.0.3: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + string-argv@0.3.2: {} + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + string-width@7.2.0: dependencies: emoji-regex: 10.4.0 @@ -2166,6 +4318,10 @@ snapshots: dependencies: ansi-regex: 2.1.1 + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + strip-ansi@7.1.0: dependencies: ansi-regex: 6.1.0 @@ -2174,6 +4330,10 @@ snapshots: dependencies: is-utf8: 0.2.1 + strip-bom@4.0.0: {} + + strip-final-newline@2.0.0: {} + strip-final-newline@3.0.0: {} strip-indent@1.0.1: @@ -2188,8 +4348,20 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + tmpl@1.0.5: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -2200,12 +4372,38 @@ snapshots: dependencies: typescript: 5.8.2 + ts-jest@29.3.2(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2): + dependencies: + bs-logger: 0.2.6 + ejs: 3.1.10 + fast-json-stable-stringify: 2.1.0 + jest: 29.7.0(@types/node@22.13.10) + jest-util: 29.7.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.7.1 + type-fest: 4.39.1 + typescript: 5.8.2 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.26.10 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.26.10) + tsml@1.0.1: {} type-check@0.4.0: dependencies: prelude-ls: 1.2.1 + type-detect@4.0.8: {} + + type-fest@0.21.3: {} + + type-fest@4.39.1: {} + typedoc-github-theme@0.2.1(typedoc@0.27.9(typescript@5.8.2)): dependencies: typedoc: 0.27.9(typescript@5.8.2) @@ -2263,29 +4461,74 @@ snapshots: universalify@2.0.1: {} + update-browserslist-db@1.1.3(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 spdx-expression-parse: 3.0.1 + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + which@2.0.2: dependencies: isexe: 2.0.0 word-wrap@1.2.5: {} + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 string-width: 7.2.0 strip-ansi: 7.1.0 + wrappy@1.0.2: {} + + write-file-atomic@4.0.2: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + + y18n@5.0.8: {} + + yallist@3.1.1: {} + yaml@2.7.0: {} + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yocto-queue@0.1.0: {} zod@3.24.2: {} diff --git a/tests/index.spec.ts b/tests/index.spec.ts new file mode 100644 index 0000000..dec99c0 --- /dev/null +++ b/tests/index.spec.ts @@ -0,0 +1,11 @@ +import Pushover from "../src"; + +test("Pushover is exported", () => { + expect(Pushover).toBeDefined(); + expect(Pushover).toBeInstanceOf(Object); +}); + +test("Pushover has expected functions", () => { + expect(Pushover).toHaveProperty("prototype.constructor"); + expect(Pushover).toHaveProperty("prototype.send"); +}); From 52b11eeffb19d83ed8af111474537413e985aeaa Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Tue, 15 Apr 2025 15:24:12 +0200 Subject: [PATCH 11/34] feat: Adds user validation via api Validates user and if specified device Signed-off-by: Alix von Schirp --- src/Pushover.ts | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/Pushover.ts b/src/Pushover.ts index ace51c7..e2937c3 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -87,12 +87,20 @@ const MessageSchema = z export type PushoverMessage = z.infer; -export interface PushoverResponse { +interface PushoverResponse { status: number; +} + +export interface PushoverMessageResponse extends PushoverResponse { request: string; errors?: string[]; } +export interface PushoverValidationResponse extends PushoverResponse { + devices?: string[]; + licenses?: string[]; +} + export interface PushoverConfig { token: string; defaultUser?: string; @@ -104,10 +112,15 @@ export interface SendOptions { verbose?: boolean; } +export interface ValidateOptions { + user?: string; + deviceName?: string; +} + export class Pushover { private token: string; private defaultUser?: string; - private apiUrl = "https://api.pushover.net/1/messages.json"; + private apiUrl = "https://api.pushover.net/1/"; constructor(config: PushoverConfig) { this.token = config.token; @@ -210,10 +223,13 @@ export class Pushover { } } - return this.makeRequest(params); + return this.makeRequest("messages.json", params); } - private makeRequest(params: URLSearchParams): Promise { + private makeRequest( + url: string, + params: URLSearchParams, + ): Promise { return new Promise((resolve, reject) => { const options = { method: "POST", @@ -222,7 +238,7 @@ export class Pushover { }, }; - const req = https.request(this.apiUrl, options, (res) => { + const req = https.request(this.apiUrl + url, options, (res) => { let data = ""; res.on("data", (chunk) => { @@ -232,7 +248,11 @@ export class Pushover { res.on("end", () => { try { const response = JSON.parse(data) as PushoverResponse; - resolve(response); + if (url === "messages.json") + resolve(response as PushoverMessageResponse); + else if (url == "users/validate.json") + resolve(response as PushoverValidationResponse); + else resolve(response); } catch (error) { console.error(error); reject(new Error(`Failed to parse response: ${data}`)); @@ -248,4 +268,19 @@ export class Pushover { req.end(); }); } + + /** + * Validate a user and device. + * + * If only user is provided, it will validate the user and return. + */ + validate(options: ValidateOptions): Promise { + const params = new URLSearchParams(); + + params.append("token", this.token); + params.append("user", options.user ?? this.defaultUser ?? ""); + if (options.deviceName) params.append("device", options.deviceName); + + return this.makeRequest("users/validate.json", params); + } } From 65524da6dc97c9d4a6b74a7f223256535f3472c4 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Tue, 15 Apr 2025 16:12:42 +0200 Subject: [PATCH 12/34] chore(package.json): add types Signed-off-by: Alix von Schirp --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 4c6695b..cc51084 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "description": "A client for Pushover, a service for sending notifications. Written in TypeScript. Supports sending to multiple users.", "homepage": "https://cis-oss.github.io/pushover", "version": "0.0.1", + "types": "dist/index.d.ts", "main": "dist/index.js", "author": { "email": "hi@b00tload.space", From 2007e906a4f9febeed2ef3f7614c8d6a1c32f3e7 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 17 Apr 2025 02:05:50 +0200 Subject: [PATCH 13/34] fix: removes module.exports Signed-off-by: Alix von Schirp --- src/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 54d4896..ce44630 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,3 @@ import { Pushover } from "./Pushover"; export default Pushover; - -Object.assign(module.exports, Pushover); From b09b0bcdae96fb58bd976940ab3c5e47e3e6af35 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 17 Apr 2025 02:09:46 +0200 Subject: [PATCH 14/34] refactor: recipient handling removes default user, changes recipient to optionally include device Also fixes url_title replacing message title Signed-off-by: Alix von Schirp --- src/Pushover.ts | 106 +++++++++++++++++------------------------------- 1 file changed, 37 insertions(+), 69 deletions(-) diff --git a/src/Pushover.ts b/src/Pushover.ts index e2937c3..d82267c 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -52,7 +52,7 @@ const MessageSchema = z .default(0), emergencyOpts: z .object({ - repeat: z.number().min(30), + retry: z.number().min(30), expire: z.number().max(10800), callback: z.string().url().optional(), tags: z.string().array().optional(), @@ -60,8 +60,8 @@ const MessageSchema = z .optional(), sound: z.string().optional(), timestamp: z.number().optional(), - html: z.boolean().default(false), - monospace: z.boolean().default(false), + html: z.boolean().optional(), + monospace: z.boolean().optional(), ttl: z.number().optional(), }) .refine( @@ -76,8 +76,7 @@ const MessageSchema = z ) .refine( (data) => { - if (data.html && data.monospace) return false; - return true; + return !(data.html && data.monospace); }, { path: ["html", "monospace"], @@ -101,30 +100,27 @@ export interface PushoverValidationResponse extends PushoverResponse { licenses?: string[]; } -export interface PushoverConfig { - token: string; - defaultUser?: string; -} - export interface SendOptions { - recipients?: string | string[]; - device?: string | string[]; + recipients: PushoverUser[]; verbose?: boolean; } +export interface PushoverUser { + id: string; + devices?: string[]; +} + export interface ValidateOptions { - user?: string; + user: string; deviceName?: string; } export class Pushover { private token: string; - private defaultUser?: string; private apiUrl = "https://api.pushover.net/1/"; - constructor(config: PushoverConfig) { - this.token = config.token; - this.defaultUser = config.defaultUser; + constructor(token: string) { + this.token = token; } /** @@ -132,67 +128,48 @@ export class Pushover { */ public async send( message: PushoverMessage, - options: SendOptions = {}, + options: SendOptions, ): Promise { - const recipients = this.getRecipients(options); + return new Promise((resolve, reject) => { + console.log(MessageSchema.parse(message)); - console.log(MessageSchema.parse(message)); + if (options.recipients.length === 0) { + reject("No recipients specified."); + } - if (recipients.length === 0) { - throw new Error( - "No recipients specified. Provide recipients in options or set a defaultUser.", + if (options.verbose) { + console.log("Verbose mode enabled. Logging message and options:"); + console.log(message); + console.log(options); + console.log("----------------------"); + console.log("Sending message..."); + } + + const promises = options.recipients.map((recipient) => + this.sendToSingleRecipient(message, recipient), ); - } - if (options.verbose) { - console.log("Verbose mode enabled. Logging message and options:"); - console.log(message); - console.log(options); - console.log("----------------------"); - console.log("Sending message..."); - } - - const promises = recipients.map((recipient) => - this.sendToSingleRecipient(message, recipient, options.device), - ); - - const results = await Promise.all(promises); - - // Combine results - const combinedResponse: PushoverResponse[] = results.map( - (result) => result, - ); - - return combinedResponse; - } - - private getRecipients(options: SendOptions): string[] { - const { recipients } = options; - - if (recipients) { - return Array.isArray(recipients) ? recipients : [recipients]; - } - - return this.defaultUser ? [this.defaultUser] : []; + resolve(Promise.all(promises)); + }); } private async sendToSingleRecipient( message: PushoverMessage, - user: string, - device?: string | string[], + user: PushoverUser, ): Promise { const params = new URLSearchParams(); // Add token and user params.append("token", this.token); - params.append("user", user); + params.append("user", user.id); + params.append("device", user.devices?.join(",") ?? ""); // Add message properties params.append("message", message.message); if (message.title) params.append("title", message.title); params.append("priority", "" + message.priority); if (message.priority === 2 && message.emergencyOpts) { - params.append("repeat", String(message.emergencyOpts.repeat)); + params.append("retry", String(message.emergencyOpts.retry)); params.append("expire", String(message.emergencyOpts.expire)); if (message.emergencyOpts.callback) params.append("callback", message.emergencyOpts.callback); @@ -204,7 +181,7 @@ export class Pushover { params.append("url", message.link); } else { params.append("url", message.link.url); - if (message.link.title) params.append("title", message.link.title); + if (message.link.title) params.append("url_title", message.link.title); } } if (message.html) params.append("html", "1"); @@ -214,15 +191,6 @@ export class Pushover { params.append("timestamp", String(message.timestamp)); if (message.ttl) params.append("ttl", String(message.ttl)); - // Add device if specified - if (device) { - if (Array.isArray(device)) { - params.append("device", device.join(",")); - } else { - params.append("device", device); - } - } - return this.makeRequest("messages.json", params); } @@ -278,7 +246,7 @@ export class Pushover { const params = new URLSearchParams(); params.append("token", this.token); - params.append("user", options.user ?? this.defaultUser ?? ""); + params.append("user", options.user ?? ""); if (options.deviceName) params.append("device", options.deviceName); return this.makeRequest("users/validate.json", params); From 64829441e509831d9e2e2592d4d50aa53659ecf2 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 17 Apr 2025 02:48:19 +0200 Subject: [PATCH 15/34] build(package.json): adds tsx to test functionality using ts files Signed-off-by: Alix von Schirp --- package.json | 1 + pnpm-lock.yaml | 434 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 419 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index cc51084..be9de5a 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "lint-staged": "^15.4.3", "prettier": "3.5.3", "ts-jest": "^29.2.6", + "tsx": "^4.19.3", "typedoc": "^0.27.9", "typedoc-github-theme": "^0.2.1", "typedoc-plugin-coverage": "^3.4.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29677f9..5ec8e13 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,7 +44,7 @@ importers: version: 9.1.7 jest: specifier: ^29.7.0 - version: 29.7.0(@types/node@22.13.10) + version: 29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)) lint-staged: specifier: ^15.4.3 version: 15.4.3 @@ -53,7 +53,10 @@ importers: version: 3.5.3 ts-jest: specifier: ^29.2.6 - version: 29.3.2(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2) + version: 29.3.2(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)))(typescript@5.8.2) + tsx: + specifier: ^4.19.3 + version: 4.19.3 typedoc: specifier: ^0.27.9 version: 0.27.9(typescript@5.8.2) @@ -252,6 +255,160 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@cspotcode/source-map-support@0.8.1': + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + + '@esbuild/aix-ppc64@0.25.2': + resolution: {integrity: sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.2': + resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.2': + resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.2': + resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.2': + resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.2': + resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.2': + resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.2': + resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.2': + resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.2': + resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.2': + resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.2': + resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.2': + resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.2': + resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.2': + resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.2': + resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.2': + resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.2': + resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.2': + resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.2': + resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.2': + resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.2': + resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.2': + resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.2': + resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.2': + resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.1': resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -405,6 +562,9 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -441,6 +601,18 @@ packages: '@sinonjs/fake-timers@10.3.0': resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -557,6 +729,10 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.4: + resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} + engines: {node: '>=0.4.0'} + acorn@8.14.1: resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} engines: {node: '>=0.4.0'} @@ -609,6 +785,9 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -778,6 +957,9 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} hasBin: true + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -822,6 +1004,10 @@ packages: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} @@ -851,6 +1037,11 @@ packages: error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + esbuild@0.25.2: + resolution: {integrity: sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -1051,6 +1242,9 @@ packages: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} + get-tsconfig@4.10.0: + resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1792,6 +1986,9 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve.exports@2.0.3: resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} engines: {node: '>=10'} @@ -2014,10 +2211,29 @@ packages: esbuild: optional: true + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + tsml@1.0.1: resolution: {integrity: sha512-3KmepnH9SUsoOVtg013CRrL7c+AK7ECaquAsJdvu4288EDJuraqBlP4PDXT/rLEJ9YDn4jqLAzRJsnFPx+V6lg==} deprecated: no longer maintained + tsx@4.19.3: + resolution: {integrity: sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==} + engines: {node: '>=18.0.0'} + hasBin: true + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -2112,6 +2328,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + v8-to-istanbul@9.3.0: resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} engines: {node: '>=10.12.0'} @@ -2166,6 +2385,10 @@ packages: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} @@ -2367,6 +2590,86 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + optional: true + + '@esbuild/aix-ppc64@0.25.2': + optional: true + + '@esbuild/android-arm64@0.25.2': + optional: true + + '@esbuild/android-arm@0.25.2': + optional: true + + '@esbuild/android-x64@0.25.2': + optional: true + + '@esbuild/darwin-arm64@0.25.2': + optional: true + + '@esbuild/darwin-x64@0.25.2': + optional: true + + '@esbuild/freebsd-arm64@0.25.2': + optional: true + + '@esbuild/freebsd-x64@0.25.2': + optional: true + + '@esbuild/linux-arm64@0.25.2': + optional: true + + '@esbuild/linux-arm@0.25.2': + optional: true + + '@esbuild/linux-ia32@0.25.2': + optional: true + + '@esbuild/linux-loong64@0.25.2': + optional: true + + '@esbuild/linux-mips64el@0.25.2': + optional: true + + '@esbuild/linux-ppc64@0.25.2': + optional: true + + '@esbuild/linux-riscv64@0.25.2': + optional: true + + '@esbuild/linux-s390x@0.25.2': + optional: true + + '@esbuild/linux-x64@0.25.2': + optional: true + + '@esbuild/netbsd-arm64@0.25.2': + optional: true + + '@esbuild/netbsd-x64@0.25.2': + optional: true + + '@esbuild/openbsd-arm64@0.25.2': + optional: true + + '@esbuild/openbsd-x64@0.25.2': + optional: true + + '@esbuild/sunos-x64@0.25.2': + optional: true + + '@esbuild/win32-arm64@0.25.2': + optional: true + + '@esbuild/win32-ia32@0.25.2': + optional: true + + '@esbuild/win32-x64@0.25.2': + optional: true + '@eslint-community/eslint-utils@4.4.1(eslint@9.22.0)': dependencies: eslint: 9.22.0 @@ -2449,7 +2752,7 @@ snapshots: jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 @@ -2463,7 +2766,7 @@ snapshots: exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.13.10) + jest-config: 29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -2619,6 +2922,12 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.9': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + optional: true + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2659,6 +2968,18 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 + '@tsconfig/node10@1.0.11': + optional: true + + '@tsconfig/node12@1.0.11': + optional: true + + '@tsconfig/node14@1.0.3': + optional: true + + '@tsconfig/node16@1.0.4': + optional: true + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.27.0 @@ -2815,6 +3136,11 @@ snapshots: dependencies: acorn: 8.14.1 + acorn-walk@8.3.4: + dependencies: + acorn: 8.14.1 + optional: true + acorn@8.14.1: {} ajv@6.12.6: @@ -2855,6 +3181,9 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + arg@4.1.3: + optional: true + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 @@ -3034,13 +3363,13 @@ snapshots: convert-source-map@2.0.0: {} - create-jest@29.7.0(@types/node@22.13.10): + create-jest@29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.13.10) + jest-config: 29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -3049,6 +3378,9 @@ snapshots: - supports-color - ts-node + create-require@1.1.1: + optional: true + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -3075,6 +3407,9 @@ snapshots: diff-sequences@29.6.3: {} + diff@4.0.2: + optional: true + ejs@3.1.10: dependencies: jake: 10.9.2 @@ -3095,6 +3430,34 @@ snapshots: dependencies: is-arrayish: 0.2.1 + esbuild@0.25.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.2 + '@esbuild/android-arm': 0.25.2 + '@esbuild/android-arm64': 0.25.2 + '@esbuild/android-x64': 0.25.2 + '@esbuild/darwin-arm64': 0.25.2 + '@esbuild/darwin-x64': 0.25.2 + '@esbuild/freebsd-arm64': 0.25.2 + '@esbuild/freebsd-x64': 0.25.2 + '@esbuild/linux-arm': 0.25.2 + '@esbuild/linux-arm64': 0.25.2 + '@esbuild/linux-ia32': 0.25.2 + '@esbuild/linux-loong64': 0.25.2 + '@esbuild/linux-mips64el': 0.25.2 + '@esbuild/linux-ppc64': 0.25.2 + '@esbuild/linux-riscv64': 0.25.2 + '@esbuild/linux-s390x': 0.25.2 + '@esbuild/linux-x64': 0.25.2 + '@esbuild/netbsd-arm64': 0.25.2 + '@esbuild/netbsd-x64': 0.25.2 + '@esbuild/openbsd-arm64': 0.25.2 + '@esbuild/openbsd-x64': 0.25.2 + '@esbuild/sunos-x64': 0.25.2 + '@esbuild/win32-arm64': 0.25.2 + '@esbuild/win32-ia32': 0.25.2 + '@esbuild/win32-x64': 0.25.2 + escalade@3.2.0: {} escape-string-regexp@1.0.5: {} @@ -3326,6 +3689,10 @@ snapshots: get-stream@8.0.1: {} + get-tsconfig@4.10.0: + dependencies: + resolve-pkg-maps: 1.0.0 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -3520,16 +3887,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@22.13.10): + jest-cli@29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)): dependencies: - '@jest/core': 29.7.0 + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.13.10) + create-jest: 29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@22.13.10) + jest-config: 29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -3539,7 +3906,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@22.13.10): + jest-config@29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)): dependencies: '@babel/core': 7.26.10 '@jest/test-sequencer': 29.7.0 @@ -3565,6 +3932,7 @@ snapshots: strip-json-comments: 3.1.1 optionalDependencies: '@types/node': 22.13.10 + ts-node: 10.9.2(@types/node@22.13.10)(typescript@5.8.2) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -3784,12 +4152,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@22.13.10): + jest@29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)): dependencies: - '@jest/core': 29.7.0 + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@22.13.10) + jest-cli: 29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -4204,6 +4572,8 @@ snapshots: resolve-from@5.0.0: {} + resolve-pkg-maps@1.0.0: {} + resolve.exports@2.0.3: {} resolve@1.22.10: @@ -4372,12 +4742,12 @@ snapshots: dependencies: typescript: 5.8.2 - ts-jest@29.3.2(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10))(typescript@5.8.2): + ts-jest@29.3.2(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)))(typescript@5.8.2): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.13.10) + jest: 29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -4392,8 +4762,34 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.26.10) + ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.11 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.13.10 + acorn: 8.14.1 + acorn-walk: 8.3.4 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.8.2 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optional: true + tsml@1.0.1: {} + tsx@4.19.3: + dependencies: + esbuild: 0.25.2 + get-tsconfig: 4.10.0 + optionalDependencies: + fsevents: 2.3.3 + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -4471,6 +4867,9 @@ snapshots: dependencies: punycode: 2.3.1 + v8-compile-cache-lib@3.0.1: + optional: true + v8-to-istanbul@9.3.0: dependencies: '@jridgewell/trace-mapping': 0.3.25 @@ -4529,6 +4928,9 @@ snapshots: y18n: 5.0.8 yargs-parser: 21.1.1 + yn@3.1.1: + optional: true + yocto-queue@0.1.0: {} zod@3.24.2: {} From f9385c9cf0fa37dcad1803ef385f0e02a4283643 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 17 Apr 2025 02:52:57 +0200 Subject: [PATCH 16/34] feat: Add receipt checking and retry cancellation Signed-off-by: Alix von Schirp --- src/Pushover.ts | 63 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/src/Pushover.ts b/src/Pushover.ts index d82267c..0532e2f 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -88,11 +88,12 @@ export type PushoverMessage = z.infer; interface PushoverResponse { status: number; + request: string; } export interface PushoverMessageResponse extends PushoverResponse { - request: string; errors?: string[]; + receipt?: string; } export interface PushoverValidationResponse extends PushoverResponse { @@ -100,6 +101,22 @@ export interface PushoverValidationResponse extends PushoverResponse { licenses?: string[]; } +export interface PushoverReceiptResponse extends PushoverResponse { + acknowledged: boolean; + acknowledged_at: number; + acknowledged_by: string; + acknowledged_by_device: string; + last_delivered_at: number; + expired: boolean; + expired_at: number; + called_back: boolean; + called_back_at: number; +} + +export interface PushoverTagCancellationResponse extends PushoverResponse { + canceled: number; +} + export interface SendOptions { recipients: PushoverUser[]; verbose?: boolean; @@ -129,10 +146,8 @@ export class Pushover { public async send( message: PushoverMessage, options: SendOptions, - ): Promise { + ): Promise { return new Promise((resolve, reject) => { - console.log(MessageSchema.parse(message)); - if (options.recipients.length === 0) { reject("No recipients specified."); } @@ -156,7 +171,7 @@ export class Pushover { private async sendToSingleRecipient( message: PushoverMessage, user: PushoverUser, - ): Promise { + ): Promise { const params = new URLSearchParams(); // Add token and user @@ -191,16 +206,17 @@ export class Pushover { params.append("timestamp", String(message.timestamp)); if (message.ttl) params.append("ttl", String(message.ttl)); - return this.makeRequest("messages.json", params); + return this.makeRequest("messages.json", "POST", params); } private makeRequest( url: string, + method: "POST" | "GET", params: URLSearchParams, ): Promise { return new Promise((resolve, reject) => { const options = { - method: "POST", + method: method, headers: { "Content-Type": "application/x-www-form-urlencoded", }, @@ -216,11 +232,7 @@ export class Pushover { res.on("end", () => { try { const response = JSON.parse(data) as PushoverResponse; - if (url === "messages.json") - resolve(response as PushoverMessageResponse); - else if (url == "users/validate.json") - resolve(response as PushoverValidationResponse); - else resolve(response); + resolve(response); } catch (error) { console.error(error); reject(new Error(`Failed to parse response: ${data}`)); @@ -249,6 +261,31 @@ export class Pushover { params.append("user", options.user ?? ""); if (options.deviceName) params.append("device", options.deviceName); - return this.makeRequest("users/validate.json", params); + return this.makeRequest("users/validate.json", "POST", params); + } + + checkReceipt(receipt: string): Promise { + const params = new URLSearchParams(); + return this.makeRequest( + `receipts/${receipt}.json?token=${this.token}`, + "GET", + params, + ) as Promise; + } + + cancelRetries(receipt: string): Promise { + const params = new URLSearchParams(); + params.append("token", this.token); + return this.makeRequest(`receipts/${receipt}/cancel.json`, "POST", params); + } + + cancelRetriesByTag(tag: string): Promise { + const params = new URLSearchParams(); + params.append("token", this.token); + return this.makeRequest( + `receipts/cancel_by_tag/${tag}.json`, + "POST", + params, + ) as Promise; } } From 5cfbc8d4413bdf9d5f453506c5797a7715588af7 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 17 Apr 2025 03:51:55 +0200 Subject: [PATCH 17/34] refactor: Split out zod input and output type Signed-off-by: Alix von Schirp --- src/Pushover.ts | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/Pushover.ts b/src/Pushover.ts index 0532e2f..8d91341 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -60,8 +60,8 @@ const MessageSchema = z .optional(), sound: z.string().optional(), timestamp: z.number().optional(), - html: z.boolean().optional(), - monospace: z.boolean().optional(), + html: z.boolean().optional().default(false), + monospace: z.boolean().optional().default(false), ttl: z.number().optional(), }) .refine( @@ -84,7 +84,9 @@ const MessageSchema = z }, ); -export type PushoverMessage = z.infer; +export type PushoverMessage = z.input; + +type PushoverMessageParsed = z.output; interface PushoverResponse { status: number; @@ -152,16 +154,27 @@ export class Pushover { reject("No recipients specified."); } + const { + success, + error, + data: parsedMessage, + } = MessageSchema.safeParse(message); + + if (!success) { + reject(`Message validation failed: ${error}`); + return; + } + if (options.verbose) { console.log("Verbose mode enabled. Logging message and options:"); - console.log(message); + console.log(parsedMessage); console.log(options); console.log("----------------------"); console.log("Sending message..."); } const promises = options.recipients.map((recipient) => - this.sendToSingleRecipient(message, recipient), + this.sendToSingleRecipient(parsedMessage, recipient), ); resolve(Promise.all(promises)); @@ -169,7 +182,7 @@ export class Pushover { } private async sendToSingleRecipient( - message: PushoverMessage, + message: PushoverMessageParsed, user: PushoverUser, ): Promise { const params = new URLSearchParams(); From 15beebf196608ff299f0b23c1995e0c296b9b0b6 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 17 Apr 2025 04:42:04 +0200 Subject: [PATCH 18/34] docs: Documented methods Signed-off-by: Alix von Schirp --- src/Pushover.ts | 496 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 439 insertions(+), 57 deletions(-) diff --git a/src/Pushover.ts b/src/Pushover.ts index 8d91341..a22c841 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -2,19 +2,25 @@ import https from "node:https"; import { URLSearchParams } from "node:url"; import { z } from "zod"; +/** + * @internal + * Defines the internal Zod schema for validating Pushover message payloads. + * This ensures messages conform to the Pushover API requirements before sending. + * Includes validation rules for required fields, formats, and conditional requirements. + */ const MessageSchema = z .object({ /** - * The message sent to the user. + * The message content sent to the user. Must be at least 3 characters long. */ message: z.string().min(3), /** - * An optional title. + * An optional title for the message. */ title: z.string().optional(), /** - * A link attached to the message. - * Can be either the link or an object containing the link and an optional title. + * An optional link attached to the message. + * Can be either a simple URL string or an object containing the URL and an optional display title. */ link: z .string() @@ -22,24 +28,25 @@ const MessageSchema = z .or( z.object({ /** - * The url of the link + * The URL of the link. */ url: z.string().url(), /** - * The title displayed as the link + * The title displayed for the link. */ title: z.string().optional(), }), ) .optional(), /** - * Sets notification setting for the message. + * Sets the notification priority for the message. + * Defaults to 0 (normal priority). * - * -2: Message only, no notification. May increment notification bubble. - * -1: Silent notification - * 0: default notification - * 1: ignores user's quiet hours. - * 2: requires acknowledgement + * - -2: Message only, no notification sound/vibration. May increment the notification bubble. + * - -1: Silent notification (no sound/vibration). + * - 0: Default notification behavior. + * - 1: High priority, ignores user's quiet hours. + * - 2: Emergency priority, requires acknowledgement. Requires `emergencyOpts`. */ priority: z .union([ @@ -49,101 +56,296 @@ const MessageSchema = z z.literal(1), z.literal(2), ]) + .optional() .default(0), + /** + * Emergency priority options, required when `priority` is 2. + */ emergencyOpts: z .object({ + /** + * Specifies how often (in seconds) the Pushover servers will send the same notification to the user. + * Minimum value is 30 seconds. + */ retry: z.number().min(30), + /** + * Specifies how long (in seconds) the notification will continue to be resent. + * Maximum value is 10800 seconds (3 hours). + */ expire: z.number().max(10800), + /** + * An optional callback URL that Pushover servers will send a request to when the notification has been acknowledged. + */ callback: z.string().url().optional(), + /** + * Optional tags for emergency notifications. Helps with cancelling retries. + */ tags: z.string().array().optional(), }) .optional(), + /** + * The name of one of the predefined Pushover sounds or a custom sound uploaded by the user to be played for the notification. + */ sound: z.string().optional(), + /** + * An optional Unix timestamp representing the message's date and time to display to the user, rather than the time Pushover received it. + */ timestamp: z.number().optional(), + /** + * If set to true, the message content will be treated as HTML. + * Mutually exclusive with `monospace`. + */ html: z.boolean().optional().default(false), + /** + * If set to true, the message content will be displayed using a monospace font. + * Mutually exclusive with `html`. + */ monospace: z.boolean().optional().default(false), + /** + * Time To Live in seconds. Specifies how long the message will be kept until disappearing. + */ ttl: z.number().optional(), }) + /** + * Validation rule: Ensures that if the priority is set to 2 (emergency), + * the `emergencyOpts` object must be provided. + */ .refine( (data) => { - if (data.priority == 2 && !data.emergencyOpts) return false; - return true; + // If priority is 2, emergencyOpts must exist. + return !(data.priority === 2 && !data.emergencyOpts); }, { - path: ["priority", "emergencyOpts"], + path: ["priority", "emergencyOpts"], // Path related to the error message: "If priority is set to 2, emergencyOpts must be included.", }, ) + /** + * Validation rule: Ensures that `html` and `monospace` formatting options + * are mutually exclusive and cannot be enabled simultaneously. + */ .refine( (data) => { + // Cannot have both html and monospace set to true. return !(data.html && data.monospace); }, { - path: ["html", "monospace"], + path: ["html", "monospace"], // Path related to the error message: "html and monospace are mutually exclusive.", }, ); +/** + * Defines the structure for a Pushover message object used when calling the `send` method. + * + * This type represents the complete set of parameters you can provide for a + * Pushover notification. It includes the required `message` field and various + * optional fields to customize the notification's appearance, behavior, priority, + * sound, and delivery options. + * + * Refer to the official Pushover API documentation for detailed explanations of each field. + * Note the specific constraints: + * - `emergencyOpts` must be provided if `priority` is set to `2`. + * - `html` and `monospace` formatting options cannot be used together. + * + * @example + * ```typescript + * import type { PushoverMessage } from '@cis-oss/pushover'; + * + * const standardMessage: PushoverMessage = { + * message: "Deployment successful!", + * title: "Server Update", + * priority: 1, // High priority + * sound: "pushover", + * link: { + * url: "https://example.com/deployment/status", + * title: "View Status" + * } + * }; + * + * const emergencyMessage: PushoverMessage = { + * message: "System critical: Service down!", + * priority: 2, + * emergencyOpts: { + * retry: 60, // Retry every 60 seconds + * expire: 3600 // Expire after 1 hour + * tags: ["critical", "infra"] + * }, + * }; + * ``` + */ export type PushoverMessage = z.input; type PushoverMessageParsed = z.output; +/** + * Base interface for all Pushover API responses + */ interface PushoverResponse { - status: number; + /** Indicates the status of the request. `1` for success, `0` for failure. */ + status: 0 | 1; + /** A unique identifier for the API request, generated by Pushover. */ request: string; + /** An array of error messages if the request failed (`status` is `0`). */ + errors?: string[]; } +/** + * Represents the response received after successfully sending a Pushover message. + */ export interface PushoverMessageResponse extends PushoverResponse { - errors?: string[]; + /** + * A receipt ID, returned only for messages sent with emergency priority (`priority: 2`). + * This ID can be used to check the acknowledgement status or cancel retries. + */ receipt?: string; } +/** + * Represents the response received after validating a user or user/device combination. + */ export interface PushoverValidationResponse extends PushoverResponse { + /** A list of the user's registered device names, returned on successful validation. */ devices?: string[]; + /** A list of the user's Pushover license types (e.g., 'Android', 'iOS', 'Desktop'). */ licenses?: string[]; } +/** + * Represents the response received when checking the status of an emergency message receipt. + */ export interface PushoverReceiptResponse extends PushoverResponse { + /** `true` if the emergency notification has been acknowledged by the user, `false` otherwise. */ acknowledged: boolean; + /** A Unix timestamp indicating when the notification was acknowledged. `0` if not acknowledged. */ acknowledged_at: number; + /** The user key of the user who first acknowledged the notification. Empty if not acknowledged. */ acknowledged_by: string; + /** The name of the device that first acknowledged the notification. Empty if not acknowledged. */ acknowledged_by_device: string; + /** A Unix timestamp indicating the last time the notification was delivered (due to retries). `0` if not delivered. */ last_delivered_at: number; + /** `true` if the notification has expired without acknowledgement, `false` otherwise. */ expired: boolean; + /** A Unix timestamp indicating when the notification expired. `0` if not expired. */ expired_at: number; + /** `true` if the optional callback URL was successfully contacted, `false` otherwise. */ called_back: boolean; + /** A Unix timestamp indicating when the callback URL was contacted. `0` if not called back. */ called_back_at: number; } +/** + * Represents the response received when cancelling emergency message retries by tag. + */ export interface PushoverTagCancellationResponse extends PushoverResponse { + /** The number of emergency message retries that were successfully cancelled for the given tag. */ canceled: number; } +/** + * Defines the options for the `send` method, primarily specifying the recipients. + */ export interface SendOptions { - recipients: PushoverUser[]; + /** An array of `PushoverRecipient` objects, each specifying a user/group and optional devices. */ + recipients: PushoverRecipient[]; + /** If true, enables verbose logging to the console during the send operation. Defaults to false. */ verbose?: boolean; } -export interface PushoverUser { +/** + * Defines the options for the `validate` method. + */ +export interface ValidateOptions { + /** The Pushover user key to validate. */ + user: string; + /** An optional device name to validate along with the user key. */ + deviceName?: string; + /** If true, enables verbose logging to the console during the send operation. Defaults to false. */ + verbose?: boolean; +} + +/** + * Represents a single Pushover recipient, which can be a user or a group. + */ +export interface PushoverRecipient { + /** The Pushover user key or group key. */ id: string; + /** An optional array of specific device names belonging to the user to send the notification to. If omitted, sends to all user's devices. */ devices?: string[]; } -export interface ValidateOptions { - user: string; - deviceName?: string; -} - +/** + * Main class for interacting with the Pushover API (v1). + * Provides methods for sending notifications, validating users/devices, + * and managing emergency priority messages. + * + * @param token - Your Pushover application's API token. + * + * @example + * ```typescript + * import { Pushover } from '@cis-oss/pushover'; + * + * // Initialize the client + * const pushover = new Pushover('YOUR_APP_API_TOKEN'); + * + * // Define recipients + * const recipients = [{ id: 'USER_KEY_1' }, {id: 'USER_KEY_2', devices: ['DEVICE_1', 'DEVICE_2']}, { id: 'GROUP_KEY_1' }]; + * + * // Send a basic message + * const responses = pushover.send({ + * message: "Hello from the library!", + * title: "Test Message" + * }, { recipients }); + * + * responses.then((responses) => { + * console.log('Messages sent:', responses); + * }).catch( (error) => { + * console.error('Failed to send messages:', error); + * }) + * ``` + */ export class Pushover { private token: string; private apiUrl = "https://api.pushover.net/1/"; + /** + * Creates an instance of the Pushover client. + * @param token - Your Pushover application's API token. Found on your Pushover dashboard. + */ constructor(token: string) { this.token = token; } /** - * Send a notification to one or multiple recipients + * Sends a Pushover notification to one or more recipients. + * + * @param message - A `PushoverMessage` object containing the notification details. + * @param options - A `SendOptions` object specifying the recipients and optional settings. + * @returns A Promise resolving to an array of `PushoverMessageResponse` objects, one for each recipient. + * Rejects if message validation fails or if there's a fundamental issue sending to all recipients. + * Individual recipient failures are indicated within their respective response objects (`status: 0`). + * + * @example + * ```typescript + * // Send a message to a specific user and device + * const userRecipient: PushoverRecipient = { id: "user-key", devices: ["phone"] }; + * await pushover.send({ message: "Targeted message" }, { recipients: [userRecipient] }); + * + * // Send an emergency priority message and handle the receipt + * const responses = pushover.send({ + * message: "Emergency alert!", + * priority: 2, + * emergencyOpts: { retry: 30, expire: 3600 } + * }, { recipients: [userRecipient] }); + * + * responses.then((responses) => { + * console.log(`Emergency message sent. Receipts: ${responses.map((response) => response.receipt).join(", ")}`); + * // Store the receipt to check status or cancel later + * }).catch((error) => { + * console.error("Failed to send emergency message:", error); + * }); + * ``` */ public async send( message: PushoverMessage, @@ -151,7 +353,7 @@ export class Pushover { ): Promise { return new Promise((resolve, reject) => { if (options.recipients.length === 0) { - reject("No recipients specified."); + reject(new Error("No recipients specified.")); } const { @@ -161,7 +363,7 @@ export class Pushover { } = MessageSchema.safeParse(message); if (!success) { - reject(`Message validation failed: ${error}`); + reject(new Error(`Message validation failed: ${error}`)); return; } @@ -174,23 +376,37 @@ export class Pushover { } const promises = options.recipients.map((recipient) => - this.sendToSingleRecipient(parsedMessage, recipient), + this.sendToSingleRecipient( + parsedMessage, + recipient, + options.verbose ?? false, + ), ); resolve(Promise.all(promises)); }); } + /** + * @internal + * Sends the validated message payload to a single recipient. + * + * @param message - The validated PushoverMessage object. + * @param recipient - The PushoverRecipient object. + * @param verbose - Optional flag for logging. + * @returns A Promise resolving to the PushoverMessageResponse. + */ private async sendToSingleRecipient( message: PushoverMessageParsed, - user: PushoverUser, + recipient: PushoverRecipient, + verbose?: boolean, ): Promise { const params = new URLSearchParams(); // Add token and user params.append("token", this.token); - params.append("user", user.id); - params.append("device", user.devices?.join(",") ?? ""); + params.append("user", recipient.id); + params.append("device", recipient.devices?.join(",") ?? ""); // Add message properties params.append("message", message.message); @@ -219,53 +435,144 @@ export class Pushover { params.append("timestamp", String(message.timestamp)); if (message.ttl) params.append("ttl", String(message.ttl)); - return this.makeRequest("messages.json", "POST", params); + return this.makeRequest( + "messages.json", + "POST", + params, + verbose ?? false, + ); } - private makeRequest( - url: string, + /** + * @internal + * Makes an HTTPS request to the Pushover API. + * + * @param endpoint - The API endpoint path (e.g., "messages.json"). + * @param method - The HTTP method ("POST" or "GET"). + * @param params - URLSearchParams for POST body or query string. + * @param verbose - Optional flag for logging request/response details. + * @returns A Promise resolving to the parsed JSON response. + */ + private makeRequest( + endpoint: string, method: "POST" | "GET", params: URLSearchParams, - ): Promise { + verbose?: boolean, + ): Promise { return new Promise((resolve, reject) => { - const options = { + const url = this.apiUrl + endpoint; + let requestBody: string | null = null; + let requestUrl = url; + + const options: https.RequestOptions = { method: method, - headers: { - "Content-Type": "application/x-www-form-urlencoded", - }, + headers: {}, }; - const req = https.request(this.apiUrl + url, options, (res) => { + if (method === "POST") { + requestBody = params.toString(); + options.headers!["Content-Type"] = "application/x-www-form-urlencoded"; + options.headers!["Content-Length"] = Buffer.byteLength(requestBody); + } else { + // Append params to URL for GET requests + const queryString = params.toString(); + if (queryString) { + requestUrl += "?" + queryString; + } + } + + if (verbose) { + console.log(`Making ${method} request to ${requestUrl}`); + if (requestBody) { + console.log("Request Body:", requestBody); + } + } + + const req = https.request(requestUrl, options, (res) => { let data = ""; + res.setEncoding("utf8"); // Ensure correct encoding res.on("data", (chunk) => { data += chunk; }); res.on("end", () => { + if (verbose) { + console.log("Received response status:", res.statusCode); + console.log("Received response headers:", res.headers); + console.log( + `Received response body (length: ${data.length}: ${data}`, + ); + } try { - const response = JSON.parse(data) as PushoverResponse; + // Handle potential empty responses or non-JSON responses gracefully + if (!data) { + // Reject promise on empty response + reject( + new Error( + `Request failed with status ${res.statusCode} and empty response.`, + ), + ); + return; + } + + const response = JSON.parse(data) as T; + // Basic check for expected structure + if ( + typeof response.status === "undefined" || + typeof response.request === "undefined" + ) { + reject(new Error(`Invalid response structure received: ${data}`)); + return; + } + resolve(response); } catch (error) { - console.error(error); - reject(new Error(`Failed to parse response: ${data}`)); + if (verbose) console.error("Failed to parse JSON response:", error); + reject( + new Error(`Failed to parse API response. Raw data: ${data}`), + ); } }); }); req.on("error", (error) => { - reject(error); + if (verbose) + console.error(`HTTPS request error to ${endpoint}:`, error); + reject(new Error(`API request failed: ${error.message}`)); }); - req.write(params.toString()); + if (method === "POST" && requestBody) { + req.write(requestBody); + } + req.end(); }); } /** - * Validate a user and device. + * Validates a Pushover user key and optionally a specific device name associated with that user. + * Useful for verifying recipient details before sending messages. * - * If only user is provided, it will validate the user and return. + * @param options - A `ValidateOptions` object containing the `user` key and optional `deviceName`. + * @returns A Promise resolving to a `PushoverValidationResponse` object. + * Check the `status` field (1 for valid, 0 for invalid) and `errors` for details on failure. + * On success, `devices` and `licenses` may be populated. + * + * @example + * ```typescript + * // Validate a user key + * const validation = await pushover.validate({ user: "user-key" }); + * if (validation.status === 1) { + * console.log("User is valid. Devices:", validation.devices, ", Licenses:", validation.licenses); + * } else { + * console.error("Validation failed:", validation.errors); + * } + * + * // Validate a user and device + * const deviceValidation = await pushover.validate({ user: "user-key", deviceName: "phone" }); + * console.log("Device validation status:", deviceValidation.status); + * ``` */ validate(options: ValidateOptions): Promise { const params = new URLSearchParams(); @@ -274,31 +581,106 @@ export class Pushover { params.append("user", options.user ?? ""); if (options.deviceName) params.append("device", options.deviceName); - return this.makeRequest("users/validate.json", "POST", params); + return this.makeRequest( + "users/validate.json", + "POST", + params, + options.verbose ?? false, + ); } - checkReceipt(receipt: string): Promise { + /** + * Checks the status of an emergency priority message using its receipt ID. + * Allows querying whether the message has been acknowledged, expired, or if the callback was triggered. + * + * @param receipt - The receipt ID obtained from the `PushoverMessageResponse` when sending an emergency message. + * @param verbose - Optional flag for logging. + * @returns A Promise resolving to a `PushoverReceiptResponse` object containing the status details. + * + * @example + * ```typescript + * const receiptId = "RECEIPT_ID_FROM_SEND_RESPONSE"; + * const status = await pushover.checkReceipt(receiptId); + * if (status.status === 1) { + * console.log(`Acknowledged: ${status.acknowledged} by ${status.acknowledged_by}`); + * console.log(`Expired: ${status.expired}`); + * } else { + * console.error("Failed to check receipt:", status.errors); + * } + * ``` + */ + checkReceipt( + receipt: string, + verbose?: boolean, + ): Promise { const params = new URLSearchParams(); - return this.makeRequest( + return this.makeRequest( `receipts/${receipt}.json?token=${this.token}`, "GET", params, - ) as Promise; + verbose ?? false, + ); } - cancelRetries(receipt: string): Promise { + /** + * Cancels the retries for an emergency priority message that has not yet been acknowledged. + * + * @param receipt - The receipt ID of the emergency message whose retries should be cancelled. + * @param verbose - Optional flag for logging. + * @returns A Promise resolving to a basic `PushoverResponse`. Check `status` for success (1) or failure (0). + * + * @example + * ```typescript + * const receiptId = "RECEIPT_ID_TO_CANCEL"; + * const cancelResponse = await pushover.cancelRetries(receiptId); + * if (cancelResponse.status === 1) { + * console.log("Successfully cancelled retries for receipt:", receiptId); + * } else { + * console.error("Failed to cancel retries:", cancelResponse.errors); + * } + * ``` + */ + cancelRetries(receipt: string, verbose?: boolean): Promise { const params = new URLSearchParams(); params.append("token", this.token); - return this.makeRequest(`receipts/${receipt}/cancel.json`, "POST", params); + return this.makeRequest( + `receipts/${receipt}/cancel.json`, + "POST", + params, + verbose ?? false, + ); } - cancelRetriesByTag(tag: string): Promise { + /** + * Cancels the retries for all emergency priority messages associated with a specific tag + * that have not yet been acknowledged. + * + * @param tag - The tag associated with the emergency messages (set in `emergencyOpts.tags` during send). + * @param verbose - Optional flag for logging. + * @returns A Promise resolving to a `PushoverTagCancellationResponse` indicating the number of messages cancelled. + * + * @example + * ```typescript + * const tagName = "critical-db-alert"; + * const cancelByTagResponse = await pushover.cancelRetriesByTag(tagName); + * if (cancelByTagResponse.status === 1) { + * console.log(`Successfully cancelled ${cancelByTagResponse.canceled} messages with tag: ${tagName}`); + * } else { + * console.error("Failed to cancel by tag:", cancelByTagResponse.errors); + * } + * ``` + */ + cancelRetriesByTag( + tag: string, + verbose?: boolean, + ): Promise { const params = new URLSearchParams(); params.append("token", this.token); - return this.makeRequest( + return this.makeRequest( `receipts/cancel_by_tag/${tag}.json`, "POST", params, - ) as Promise; + verbose ?? false, + ); } } From 6d2743e7e840d815aea671d22aa24781164bfe22 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 17 Apr 2025 04:54:51 +0200 Subject: [PATCH 19/34] feat: exports types Signed-off-by: Alix von Schirp --- src/index.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/index.ts b/src/index.ts index ce44630..41289e7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,25 @@ import { Pushover } from "./Pushover"; +import type { + PushoverRecipient, + PushoverMessage, + PushoverMessageResponse, + PushoverValidationResponse, + PushoverReceiptResponse, + PushoverTagCancellationResponse, + ValidateOptions, + SendOptions, +} from "./Pushover"; + export default Pushover; + +export type { + PushoverRecipient, + PushoverMessage, + PushoverMessageResponse, + PushoverValidationResponse, + PushoverReceiptResponse, + PushoverTagCancellationResponse, + ValidateOptions, + SendOptions, +}; From 609e6dc50794803755d4f9749cb6f3e7b623d115 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 17 Apr 2025 04:57:54 +0200 Subject: [PATCH 20/34] build(tsconfig.json): sets strictNullChecks to true This is needed by TypeDoc Signed-off-by: Alix von Schirp --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index 6c4a667..12e6dfc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,7 @@ /* Strictness */ "strict": true, + "strictNullChecks": true, "noUncheckedIndexedAccess": true, "checkJs": true, From 37fdebdcab3fe3ac424b4cb68cd94e1cf828d0cf Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Thu, 17 Apr 2025 05:24:42 +0200 Subject: [PATCH 21/34] chore(package.json): added packageManager field Signed-off-by: Alix von Schirp --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index be9de5a..e2fe2e3 100644 --- a/package.json +++ b/package.json @@ -78,5 +78,6 @@ "*.{js,ts,jsx,tsx}": "eslint --cache --fix .", "*.{js,ts,jsx,tsx,json,css,md}": "prettier --write" }, + "packageManager": "pnpm@10.6.5", "type": "module" } From 143796f8178f87c3ba0bc9cbc94aac6e2a6f8407 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sat, 30 Aug 2025 20:30:46 +0200 Subject: [PATCH 22/34] ci(pre-commit): fix hook t user pnpm instead of npm Signed-off-by: Alix von Schirp --- .husky/pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 2312dc5..5ee7abd 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1 @@ -npx lint-staged +pnpm exec lint-staged From 8d711af84d546c9fd1290964763682d01be17da4 Mon Sep 17 00:00:00 2001 From: Alix von Schirp <15247003+B00tLoad@users.noreply.github.com> Date: Sat, 30 Aug 2025 21:43:34 +0200 Subject: [PATCH 23/34] style: add missing brackets in template Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Pushover.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Pushover.ts b/src/Pushover.ts index a22c841..5c3971d 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -500,8 +500,7 @@ export class Pushover { if (verbose) { console.log("Received response status:", res.statusCode); console.log("Received response headers:", res.headers); - console.log( - `Received response body (length: ${data.length}: ${data}`, + `Received response body (length: ${data.length}): ${data}`, ); } try { From 9b88ae87cc86dd05216f8ac5c78d74ab8d908e60 Mon Sep 17 00:00:00 2001 From: Alix von Schirp <15247003+B00tLoad@users.noreply.github.com> Date: Sat, 30 Aug 2025 21:46:40 +0200 Subject: [PATCH 24/34] fix(user-validation): remove nullish coalescing operator Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/Pushover.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Pushover.ts b/src/Pushover.ts index 5c3971d..a92ff62 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -577,7 +577,7 @@ export class Pushover { const params = new URLSearchParams(); params.append("token", this.token); - params.append("user", options.user ?? ""); + params.append("user", options.user); if (options.deviceName) params.append("device", options.deviceName); return this.makeRequest( From 5e4645097a7328b60642da99a4adf43e25b00316 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sat, 30 Aug 2025 22:02:16 +0200 Subject: [PATCH 25/34] fix: fix syntax errors introduced by copilot in previous commit Refs: 8d711af84d546c9fd1290964763682d01be17da4 --- src/Pushover.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Pushover.ts b/src/Pushover.ts index a92ff62..4b2b7b6 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -500,6 +500,7 @@ export class Pushover { if (verbose) { console.log("Received response status:", res.statusCode); console.log("Received response headers:", res.headers); + console.log( `Received response body (length: ${data.length}): ${data}`, ); } From 4f6015a0c250e31ee87054476a1db8aed5eb2d6c Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sat, 30 Aug 2025 22:26:39 +0200 Subject: [PATCH 26/34] docs(Message): added missing comma --- src/Pushover.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Pushover.ts b/src/Pushover.ts index 4b2b7b6..9b71dfc 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -168,7 +168,7 @@ const MessageSchema = z * priority: 2, * emergencyOpts: { * retry: 60, // Retry every 60 seconds - * expire: 3600 // Expire after 1 hour + * expire: 3600, // Expire after 1 hour * tags: ["critical", "infra"] * }, * }; From 85663272c42deac51ad7b0370d0d4cba4e07c033 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sat, 30 Aug 2025 22:27:24 +0200 Subject: [PATCH 27/34] fix(send): added missing return --- src/Pushover.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Pushover.ts b/src/Pushover.ts index 9b71dfc..d11117e 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -354,6 +354,7 @@ export class Pushover { return new Promise((resolve, reject) => { if (options.recipients.length === 0) { reject(new Error("No recipients specified.")); + return; } const { From d66c54d25de7a0efda40df7aa4e19e832baeb9e8 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sun, 31 Aug 2025 00:19:29 +0200 Subject: [PATCH 28/34] docs: reformat code examples to follow prettier styling --- src/Pushover.ts | 85 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 27 deletions(-) diff --git a/src/Pushover.ts b/src/Pushover.ts index d11117e..ffb9ff7 100644 --- a/src/Pushover.ts +++ b/src/Pushover.ts @@ -284,25 +284,34 @@ export interface PushoverRecipient { * * @example * ```typescript - * import { Pushover } from '@cis-oss/pushover'; + * import { Pushover } from "@cis-oss/pushover"; * * // Initialize the client - * const pushover = new Pushover('YOUR_APP_API_TOKEN'); + * const pushover = new Pushover("YOUR_APP_API_TOKEN"); * * // Define recipients - * const recipients = [{ id: 'USER_KEY_1' }, {id: 'USER_KEY_2', devices: ['DEVICE_1', 'DEVICE_2']}, { id: 'GROUP_KEY_1' }]; + * const recipients = [ + * { id: "USER_KEY_1" }, + * { id: "USER_KEY_2", devices: ["DEVICE_1", "DEVICE_2"] }, + * { id: "GROUP_KEY_1" }, + * ]; * * // Send a basic message - * const responses = pushover.send({ + * const responses = pushover.send( + * { * message: "Hello from the library!", - * title: "Test Message" - * }, { recipients }); + * title: "Test Message", + * }, + * { recipients }, + * ); * - * responses.then((responses) => { - * console.log('Messages sent:', responses); - * }).catch( (error) => { - * console.error('Failed to send messages:', error); - * }) + * responses + * .then((responses) => { + * console.log("Messages sent:", responses); + * }) + * .catch((error) => { + * console.error("Failed to send messages:", error); + * }); * ``` */ export class Pushover { @@ -330,21 +339,31 @@ export class Pushover { * ```typescript * // Send a message to a specific user and device * const userRecipient: PushoverRecipient = { id: "user-key", devices: ["phone"] }; - * await pushover.send({ message: "Targeted message" }, { recipients: [userRecipient] }); + * await pushover.send( + * { message: "Targeted message" }, + * { recipients: [userRecipient] }, + * ); * * // Send an emergency priority message and handle the receipt - * const responses = pushover.send({ - * message: "Emergency alert!", - * priority: 2, - * emergencyOpts: { retry: 30, expire: 3600 } - * }, { recipients: [userRecipient] }); + * const responses = pushover.send( + * { + * message: "Emergency alert!", + * priority: 2, + * emergencyOpts: { retry: 30, expire: 3600 }, + * }, + * { recipients: [userRecipient] }, + * ); * - * responses.then((responses) => { - * console.log(`Emergency message sent. Receipts: ${responses.map((response) => response.receipt).join(", ")}`); - * // Store the receipt to check status or cancel later - * }).catch((error) => { - * console.error("Failed to send emergency message:", error); - * }); + * responses + * .then((responses) => { + * console.log( + * `Emergency message sent. Receipts: ${responses.map((response) => response.receipt).join(", ")}`, + * ); + * // Store the receipt to check status or cancel later + * }) + * .catch((error) => { + * console.error("Failed to send emergency message:", error); + * }); * ``` */ public async send( @@ -565,13 +584,21 @@ export class Pushover { * // Validate a user key * const validation = await pushover.validate({ user: "user-key" }); * if (validation.status === 1) { - * console.log("User is valid. Devices:", validation.devices, ", Licenses:", validation.licenses); + * console.log( + * "User is valid. Devices:", + * validation.devices, + * ", Licenses:", + * validation.licenses, + * ); * } else { * console.error("Validation failed:", validation.errors); * } * * // Validate a user and device - * const deviceValidation = await pushover.validate({ user: "user-key", deviceName: "phone" }); + * const deviceValidation = await pushover.validate({ + * user: "user-key", + * deviceName: "phone", + * }); * console.log("Device validation status:", deviceValidation.status); * ``` */ @@ -603,7 +630,9 @@ export class Pushover { * const receiptId = "RECEIPT_ID_FROM_SEND_RESPONSE"; * const status = await pushover.checkReceipt(receiptId); * if (status.status === 1) { - * console.log(`Acknowledged: ${status.acknowledged} by ${status.acknowledged_by}`); + * console.log( + * `Acknowledged: ${status.acknowledged} by ${status.acknowledged_by}`, + * ); * console.log(`Expired: ${status.expired}`); * } else { * console.error("Failed to check receipt:", status.errors); @@ -665,7 +694,9 @@ export class Pushover { * const tagName = "critical-db-alert"; * const cancelByTagResponse = await pushover.cancelRetriesByTag(tagName); * if (cancelByTagResponse.status === 1) { - * console.log(`Successfully cancelled ${cancelByTagResponse.canceled} messages with tag: ${tagName}`); + * console.log( + * `Successfully cancelled ${cancelByTagResponse.canceled} messages with tag: ${tagName}`, + * ); * } else { * console.error("Failed to cancel by tag:", cancelByTagResponse.errors); * } From 98cd99e27ab6c01c21355f079593157040178455 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sun, 31 Aug 2025 14:15:10 +0200 Subject: [PATCH 29/34] chore(package.json): split main files between dev and release --- package.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e2fe2e3..2ccd881 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,7 @@ "description": "A client for Pushover, a service for sending notifications. Written in TypeScript. Supports sending to multiple users.", "homepage": "https://cis-oss.github.io/pushover", "version": "0.0.1", - "types": "dist/index.d.ts", - "main": "dist/index.js", + "main": "src/index.ts", "author": { "email": "hi@b00tload.space", "name": "Alix von Schirp", @@ -79,5 +78,9 @@ "*.{js,ts,jsx,tsx,json,css,md}": "prettier --write" }, "packageManager": "pnpm@10.6.5", + "publishConfig": { + "main": "dist/index.js", + "types": "dist/index.d.ts" + }, "type": "module" } From 93716ba3f8cc01fa27f18d4d248b47bc84fe0b06 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sun, 31 Aug 2025 14:24:06 +0200 Subject: [PATCH 30/34] build(devDependencies): add shx --- package.json | 1 + pnpm-lock.yaml | 147 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+) diff --git a/package.json b/package.json index 2ccd881..9e933ce 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "jest": "^29.7.0", "lint-staged": "^15.4.3", "prettier": "3.5.3", + "shx": "^0.4.0", "ts-jest": "^29.2.6", "tsx": "^4.19.3", "typedoc": "^0.27.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5ec8e13..e30e403 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -51,6 +51,9 @@ importers: prettier: specifier: 3.5.3 version: 3.5.3 + shx: + specifier: ^0.4.0 + version: 0.4.0 ts-jest: specifier: ^29.2.6 version: 29.3.2(@babel/core@7.26.10)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.10))(jest@29.7.0(@types/node@22.13.10)(ts-node@10.9.2(@types/node@22.13.10)(typescript@5.8.2)))(typescript@5.8.2) @@ -960,6 +963,10 @@ packages: create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-spawn@6.0.6: + resolution: {integrity: sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==} + engines: {node: '>=4.8'} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -1026,6 +1033,9 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -1118,6 +1128,10 @@ packages: eventemitter3@5.0.1: resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + execa@1.0.0: + resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} + engines: {node: '>=6'} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -1234,6 +1248,10 @@ packages: resolution: {integrity: sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==} engines: {node: '>=0.10.0'} + get-stream@4.1.0: + resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} + engines: {node: '>=6'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -1342,6 +1360,10 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -1385,6 +1407,10 @@ packages: resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} engines: {node: '>=8'} + is-stream@1.1.0: + resolution: {integrity: sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==} + engines: {node: '>=0.10.0'} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -1769,6 +1795,9 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + nice-try@1.0.5: + resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} @@ -1790,6 +1819,10 @@ packages: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + npm-run-path@2.0.2: + resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} + engines: {node: '>=4'} + npm-run-path@4.0.1: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} @@ -1821,6 +1854,10 @@ packages: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -1869,6 +1906,10 @@ packages: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} + path-key@2.0.1: + resolution: {integrity: sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==} + engines: {node: '>=4'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1937,6 +1978,9 @@ packages: resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} engines: {node: '>= 6'} + pump@3.0.3: + resolution: {integrity: sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==} + punycode.js@2.3.1: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} @@ -1962,6 +2006,10 @@ packages: resolution: {integrity: sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ==} engines: {node: '>=0.10.0'} + rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + redent@1.0.0: resolution: {integrity: sha512-qtW5hKzGQZqKoh6JNSD+4lfitfPKGz42e6QwiRmPM5mmKtR0N41AbJRYu0xJi7nhOJ4WDgRkKvAk6tw4WIwR4g==} engines: {node: '>=0.10.0'} @@ -2025,14 +2073,32 @@ packages: engines: {node: '>=10'} hasBin: true + shebang-command@1.2.0: + resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} + engines: {node: '>=0.10.0'} + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} + shebang-regex@1.0.0: + resolution: {integrity: sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==} + engines: {node: '>=0.10.0'} + shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shelljs@0.9.2: + resolution: {integrity: sha512-S3I64fEiKgTZzKCC46zT/Ib9meqofLrQVbpSswtjFfAVDW+AZ54WTnAM/3/yENoxz/V1Cy6u3kiiEbQ4DNphvw==} + engines: {node: '>=18'} + hasBin: true + + shx@0.4.0: + resolution: {integrity: sha512-Z0KixSIlGPpijKgcH6oCMCbltPImvaKy0sGH8AkLRXw1KyzpKtaCTizP2xen+hNDqVF4xxgvA0KXSb9o4Q6hnA==} + engines: {node: '>=18'} + hasBin: true + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -2133,6 +2199,10 @@ packages: resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} engines: {node: '>=8'} + strip-eof@1.0.0: + resolution: {integrity: sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==} + engines: {node: '>=0.10.0'} + strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} @@ -2341,6 +2411,10 @@ packages: walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -3381,6 +3455,14 @@ snapshots: create-require@1.1.1: optional: true + cross-spawn@6.0.6: + dependencies: + nice-try: 1.0.5 + path-key: 2.0.1 + semver: 5.7.2 + shebang-command: 1.2.0 + which: 1.3.1 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 @@ -3422,6 +3504,10 @@ snapshots: emoji-regex@8.0.0: {} + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + entities@4.5.0: {} environment@1.1.0: {} @@ -3543,6 +3629,16 @@ snapshots: eventemitter3@5.0.1: {} + execa@1.0.0: + dependencies: + cross-spawn: 6.0.6 + get-stream: 4.1.0 + is-stream: 1.1.0 + npm-run-path: 2.0.2 + p-finally: 1.0.0 + signal-exit: 3.0.7 + strip-eof: 1.0.0 + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -3685,6 +3781,10 @@ snapshots: get-stdin@4.0.1: {} + get-stream@4.1.0: + dependencies: + pump: 3.0.3 + get-stream@6.0.1: {} get-stream@8.0.1: {} @@ -3771,6 +3871,8 @@ snapshots: inherits@2.0.4: {} + interpret@1.4.0: {} + is-arrayish@0.2.1: {} is-core-module@2.16.1: @@ -3799,6 +3901,8 @@ snapshots: is-plain-obj@2.1.0: {} + is-stream@1.1.0: {} + is-stream@2.0.1: {} is-stream@3.0.0: {} @@ -4379,6 +4483,8 @@ snapshots: natural-compare@1.4.0: {} + nice-try@1.0.5: {} + node-int64@0.4.0: {} node-releases@2.0.19: {} @@ -4403,6 +4509,10 @@ snapshots: normalize-path@3.0.0: {} + npm-run-path@2.0.2: + dependencies: + path-key: 2.0.1 + npm-run-path@4.0.1: dependencies: path-key: 3.1.1 @@ -4438,6 +4548,8 @@ snapshots: type-check: 0.4.0 word-wrap: 1.2.5 + p-finally@1.0.0: {} + p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -4481,6 +4593,8 @@ snapshots: path-is-absolute@1.0.1: {} + path-key@2.0.1: {} + path-key@3.1.1: {} path-key@4.0.0: {} @@ -4532,6 +4646,11 @@ snapshots: kleur: 3.0.3 sisteransi: 1.0.5 + pump@3.0.3: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + punycode.js@2.3.1: {} punycode@2.3.1: {} @@ -4553,6 +4672,10 @@ snapshots: normalize-package-data: 2.5.0 path-type: 1.1.0 + rechoir@0.6.2: + dependencies: + resolve: 1.22.10 + redent@1.0.0: dependencies: indent-string: 2.1.0 @@ -4601,12 +4724,30 @@ snapshots: semver@7.7.1: {} + shebang-command@1.2.0: + dependencies: + shebang-regex: 1.0.0 + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 + shebang-regex@1.0.0: {} + shebang-regex@3.0.0: {} + shelljs@0.9.2: + dependencies: + execa: 1.0.0 + fast-glob: 3.3.3 + interpret: 1.4.0 + rechoir: 0.6.2 + + shx@0.4.0: + dependencies: + minimist: 1.2.8 + shelljs: 0.9.2 + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -4702,6 +4843,8 @@ snapshots: strip-bom@4.0.0: {} + strip-eof@1.0.0: {} + strip-final-newline@2.0.0: {} strip-final-newline@3.0.0: {} @@ -4885,6 +5028,10 @@ snapshots: dependencies: makeerror: 1.0.12 + which@1.3.1: + dependencies: + isexe: 2.0.0 + which@2.0.2: dependencies: isexe: 2.0.0 From 1ea099ff98be2c4330d1fb7f0b73e53b751330d3 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sun, 31 Aug 2025 14:29:21 +0200 Subject: [PATCH 31/34] chore(package.json): script cleanup and addition of preRelease script --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9e933ce..aef4cd1 100644 --- a/package.json +++ b/package.json @@ -60,11 +60,13 @@ "scripts": { "build": "tsc", "build:watch": "tsc --watch", - "check": "pnpm lint && pnpm typecheck", + "check": "pnpm run lint && pnpm run typecheck", + "clean": "shx rm -rf dist/", "docs:generate": "typedoc", "format:check": "prettier --check .", "lint": "eslint --cache .", "prepare": "husky", + "prepublishOnly": "pnpm run clean && pnpm run build", "test": "jest", "typecheck": "tsc --noEmit" }, From 61ac47fd052de1ca471cbf8241ef8ecca546faa1 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sun, 31 Aug 2025 14:30:00 +0200 Subject: [PATCH 32/34] chore(package.json): add maintainers --- package.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/package.json b/package.json index aef4cd1..800249f 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,18 @@ "*.{js,ts,jsx,tsx}": "eslint --cache --fix .", "*.{js,ts,jsx,tsx,json,css,md}": "prettier --write" }, + "maintainers": [ + { + "name": "Alix von Schirp", + "email": "hi@b00tload.space", + "url": "https://b00tload.space" + }, + { + "name": "Ole", + "email": "jateute123@gmail.com", + "url": "https://github.com/jateute" + } + ], "packageManager": "pnpm@10.6.5", "publishConfig": { "main": "dist/index.js", From 421821f1ee7a4d19f9a0cd3f1fc87df4a9a9edba Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Sun, 31 Aug 2025 23:51:48 +0200 Subject: [PATCH 33/34] docs(README): Add ReadMe file --- README.md | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1f0e753..750ac1a 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,48 @@ # CIS Pushover Client +![GitHub License](https://img.shields.io/github/license/cis-oss/pushover) +![NPM Version](https://img.shields.io/npm/v/%40cis-oss%2Fpushover) +![npm bundle size (scoped)](https://img.shields.io/bundlephobia/min/cis-oss/pushover?label=bundle%20size) + A client for Pushover, a service for sending notifications. Typesafe. Supports sending the same message to multiple users. ## Installation -⚠️ This package is **not yet published** to npm. - ```bash pnpm add @cis-oss/pushover ``` +
+Or using npm + ```bash npm install @cis-oss/pushover ``` +
+ +
+Or use our meta-packages + ```bash -yarn add @cis-oss/pushover +pnpm add @cis-oss/notify ``` ```bash -bun add @cis-oss/pushover +pnpm add @cis-oss/notify-push ``` + +
+ +# Documentation + +Documentation can be found at [https://cis-oss.github.io/pushover](https://cis-oss.github.io/pushover). + +# Contributing + +Contributions are welcome! Please see [CONTRIBUTING.md](https://github.com/cis-oss/.github/blob/main/CONTRIBUTING.md) for details. + +Please make sure to read our [Code of Conduct](https://github.com/cis-oss/.github/blob/main/CODE_OF_CONDUCT.md) and [Support Policy](https://github.com/cis-oss/.github/blob/main/SUPPORT.md). + +Disclose security issues responsibly by following our [Security Policy](https://github.com/cis-oss/.github/blob/main/SECURITY.md). From c1c8eda3b280c07d749cfe420e919eff5693d876 Mon Sep 17 00:00:00 2001 From: Alix von Schirp Date: Mon, 1 Sep 2025 00:15:35 +0200 Subject: [PATCH 34/34] release(v0.1.0): set version string, remove private: true --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index 800249f..2bbc87f 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@cis-oss/pushover", "description": "A client for Pushover, a service for sending notifications. Written in TypeScript. Supports sending to multiple users.", "homepage": "https://cis-oss.github.io/pushover", - "version": "0.0.1", + "version": "0.1.0", "main": "src/index.ts", "author": { "email": "hi@b00tload.space", @@ -70,7 +70,6 @@ "test": "jest", "typecheck": "tsc --noEmit" }, - "private": true, "license": "MIT", "husky": { "shell": "bash"