From 7d469b5d859c9ee02d2c37f84f0abafb9fd664ad Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 13 May 2025 15:31:13 +0100 Subject: [PATCH 1/8] chore(firestore-bigquery-export): bump script versions for release --- firestore-bigquery-export/scripts/gen-schema-view/package.json | 2 +- firestore-bigquery-export/scripts/import/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/firestore-bigquery-export/scripts/gen-schema-view/package.json b/firestore-bigquery-export/scripts/gen-schema-view/package.json index dd86dd739..52b4a1447 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/package.json +++ b/firestore-bigquery-export/scripts/gen-schema-view/package.json @@ -1,6 +1,6 @@ { "name": "@firebaseextensions/fs-bq-schema-views", - "version": "0.4.10", + "version": "0.4.11", "description": "Generate strongly-typed BigQuery Views based on raw JSON", "main": "./lib/index.js", "repository": { diff --git a/firestore-bigquery-export/scripts/import/package.json b/firestore-bigquery-export/scripts/import/package.json index 0a62c65f7..5f7122548 100644 --- a/firestore-bigquery-export/scripts/import/package.json +++ b/firestore-bigquery-export/scripts/import/package.json @@ -1,6 +1,6 @@ { "name": "@firebaseextensions/fs-bq-import-collection", - "version": "0.1.23", + "version": "0.1.24", "description": "Import a Firestore Collection into a BigQuery Changelog Table", "main": "./lib/index.js", "repository": { From 115d4f0201261d66a4d95f55aecd6c321a544cfc Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Tue, 13 May 2025 16:54:28 +0100 Subject: [PATCH 2/8] docs(firestore-send-email): add docs on dynamic SendGrid templates --- firestore-send-email/CHANGELOG.md | 4 ++++ firestore-send-email/POSTINSTALL.md | 23 +++++++++++++++++++++++ firestore-send-email/PREINSTALL.md | 25 ++++++++++++++++++++++++- firestore-send-email/README.md | 25 ++++++++++++++++++++++++- firestore-send-email/extension.yaml | 2 +- 5 files changed, 76 insertions(+), 3 deletions(-) diff --git a/firestore-send-email/CHANGELOG.md b/firestore-send-email/CHANGELOG.md index dc0c85e4b..4ab786219 100644 --- a/firestore-send-email/CHANGELOG.md +++ b/firestore-send-email/CHANGELOG.md @@ -1,3 +1,7 @@ +## Version 0.2.2 + +docs: add documentation on how to use dynamic templates with SendGrid + ## Version 0.2.1 fix: return info on sendgrid messages diff --git a/firestore-send-email/POSTINSTALL.md b/firestore-send-email/POSTINSTALL.md index 1c3d74fc9..5224adb98 100644 --- a/firestore-send-email/POSTINSTALL.md +++ b/firestore-send-email/POSTINSTALL.md @@ -61,6 +61,29 @@ Add this document to the Firestore mail collection to send categorized emails. For more details, see the [SendGrid Categories documentation](https://docs.sendgrid.com/ui/sending-email/categories). +#### Firestore-Send-Email: SendGrid Dynamic Templates + +When using SendGrid, you can use SendGrid Dynamic Templates to create and send templated emails. + +## Example JSON representation of Firestore document for a Dynamic Template: +```json +{ + "to": ["example@example.com"], + "sendGrid": { + "templateId": "d-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "dynamicTemplateData": { + "name": "John Doe", + "company": "Example Corp", + "position": "Developer" + } + } +} +``` + +Add this document to the Firestore mail collection to send an email using a SendGrid Dynamic Template. The `templateId` is required and should be your SendGrid Dynamic Template ID (always starts with 'd-'). The `dynamicTemplateData` object contains the variables that will be used in your template. + +For more details, see the [SendGrid Dynamic Templates documentation](https://docs.sendgrid.com/ui/sending-email/how-to-send-an-email-with-dynamic-templates). + #### Understanding SendGrid Email IDs When an email is sent successfully, the extension tracks two different IDs in the delivery information: diff --git a/firestore-send-email/PREINSTALL.md b/firestore-send-email/PREINSTALL.md index 1b459fddf..db67bafb1 100644 --- a/firestore-send-email/PREINSTALL.md +++ b/firestore-send-email/PREINSTALL.md @@ -39,6 +39,29 @@ Add this document to the Firestore mail collection to send categorized emails. For more details, see the [SendGrid Categories documentation](https://docs.sendgrid.com/ui/sending-email/categories). +#### Firestore-Send-Email: SendGrid Dynamic Templates + +When using SendGrid, you can use SendGrid Dynamic Templates to create and send templated emails. + +## Example JSON representation of Firestore document for a Dynamic Template: +```json +{ + "to": ["example@example.com"], + "sendGrid": { + "templateId": "d-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // SendGrid Dynamic Template ID always starts with 'd-' + "dynamicTemplateData": { + "name": "John Doe", + "company": "Example Corp", + "position": "Developer" + } + } +} +``` + +Add this document to the Firestore mail collection to send an email using a SendGrid Dynamic Template. The `templateId` is required and should be your SendGrid Dynamic Template ID (always starts with 'd-'). The `dynamicTemplateData` object contains the variables that will be used in your template. + +For more details, see the [SendGrid Dynamic Templates documentation](https://docs.sendgrid.com/ui/sending-email/how-to-send-an-email-with-dynamic-templates). + #### Setting Up OAuth2 Authentication This section will help you set up OAuth2 authentication for the extension, using GCP (Gmail) as an example. @@ -195,7 +218,7 @@ Detailed instructions for creating a TTL field can be found in the [Firestore TT #### Billing To install an extension, your project must be on the [Blaze (pay as you go) plan](https://firebase.google.com/pricing) -- This extension uses other Firebase and Google Cloud Platform services, which have associated charges if you exceed the service’s no-cost tier: +- This extension uses other Firebase and Google Cloud Platform services, which have associated charges if you exceed the service's no-cost tier: - Cloud Firestore - Cloud Functions (Node.js 10+ runtime. [See FAQs](https://firebase.google.com/support/faq#extensions-pricing)) diff --git a/firestore-send-email/README.md b/firestore-send-email/README.md index 711a1d6e6..b12c67c37 100644 --- a/firestore-send-email/README.md +++ b/firestore-send-email/README.md @@ -47,6 +47,29 @@ Add this document to the Firestore mail collection to send categorized emails. For more details, see the [SendGrid Categories documentation](https://docs.sendgrid.com/ui/sending-email/categories). +#### Firestore-Send-Email: SendGrid Dynamic Templates + +When using SendGrid, you can use SendGrid Dynamic Templates to create and send templated emails. + +## Example JSON representation of Firestore document for a Dynamic Template: +```json +{ + "to": ["example@example.com"], + "sendGrid": { + "templateId": "d-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", // SendGrid Dynamic Template ID always starts with 'd-' + "dynamicTemplateData": { + "name": "John Doe", + "company": "Example Corp", + "position": "Developer" + } + } +} +``` + +Add this document to the Firestore mail collection to send an email using a SendGrid Dynamic Template. The `templateId` is required and should be your SendGrid Dynamic Template ID (always starts with 'd-'). The `dynamicTemplateData` object contains the variables that will be used in your template. + +For more details, see the [SendGrid Dynamic Templates documentation](https://docs.sendgrid.com/ui/sending-email/how-to-send-an-email-with-dynamic-templates). + #### Setting Up OAuth2 Authentication This section will help you set up OAuth2 authentication for the extension, using GCP (Gmail) as an example. @@ -203,7 +226,7 @@ Detailed instructions for creating a TTL field can be found in the [Firestore TT #### Billing To install an extension, your project must be on the [Blaze (pay as you go) plan](https://firebase.google.com/pricing) -- This extension uses other Firebase and Google Cloud Platform services, which have associated charges if you exceed the service’s no-cost tier: +- This extension uses other Firebase and Google Cloud Platform services, which have associated charges if you exceed the service's no-cost tier: - Cloud Firestore - Cloud Functions (Node.js 10+ runtime. [See FAQs](https://firebase.google.com/support/faq#extensions-pricing)) diff --git a/firestore-send-email/extension.yaml b/firestore-send-email/extension.yaml index 591cef265..4b1f55161 100644 --- a/firestore-send-email/extension.yaml +++ b/firestore-send-email/extension.yaml @@ -13,7 +13,7 @@ # limitations under the License. name: firestore-send-email -version: 0.2.1 +version: 0.2.2 specVersion: v1beta displayName: Trigger Email from Firestore From ab45f26653cdc6f3ed0d8d92f5a45be497ca3603 Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Thu, 15 May 2025 12:56:55 +0100 Subject: [PATCH 3/8] fix(firestore-send-email): fix validation logic (#2420) * fix(firestore-send-email): fix validation logic * docs(firestore-send-email): add jsdoc comments --- .../functions/__tests__/validation.test.ts | 479 +++++++++++------- .../functions/src/validation.ts | 284 +++++++---- 2 files changed, 507 insertions(+), 256 deletions(-) diff --git a/firestore-send-email/functions/__tests__/validation.test.ts b/firestore-send-email/functions/__tests__/validation.test.ts index d18390a19..c0dc3e142 100644 --- a/firestore-send-email/functions/__tests__/validation.test.ts +++ b/firestore-send-email/functions/__tests__/validation.test.ts @@ -1,199 +1,338 @@ import { validatePayload, ValidationError } from "../src/validation"; describe("validatePayload", () => { - // Test valid standard message payload - it("should validate a standard message payload", () => { - const validPayload = { - to: "test@example.com", - message: { - subject: "Test Subject", - text: "Test message", - }, - }; - expect(() => validatePayload(validPayload)).not.toThrow(); - }); + describe("valid payloads", () => { + it("should validate a standard message payload", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); - // Test valid HTML message - it("should validate a message with HTML content", () => { - const validPayload = { - to: "test@example.com", - message: { - subject: "Test Subject", - html: "

Test message

", - }, - }; - expect(() => validatePayload(validPayload)).not.toThrow(); - }); + it("should validate a message with HTML content", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + html: "

Test message

", + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); - // Test valid SendGrid template - it("should validate a SendGrid template payload", () => { - const validPayload = { - to: "test@example.com", - sendGrid: { - templateId: "d-template-id", - dynamicTemplateData: { - name: "Test User", + it("should validate a SendGrid template payload", () => { + const validPayload = { + to: "test@example.com", + sendGrid: { + templateId: "d-template-id", + dynamicTemplateData: { + name: "Test User", + }, }, - }, - }; - expect(() => validatePayload(validPayload)).not.toThrow(); - }); + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); - // Test valid custom template - it("should validate a custom template payload", () => { - const validPayload = { - to: "test@example.com", - template: { - name: "welcome-email", - data: { - name: "Test User", + it("should validate a custom template payload", () => { + const validPayload = { + to: "test@example.com", + template: { + name: "welcome-email", + data: { + name: "Test User", + }, }, - }, - }; - expect(() => validatePayload(validPayload)).not.toThrow(); - }); + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); - // Test invalid message (missing text/html) - it("should throw ValidationError for message without text or html", () => { - const invalidPayload = { - to: "test@example.com", - message: { - subject: "Test Subject", - }, - }; - expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); - expect(() => validatePayload(invalidPayload)).toThrow( - "Invalid email configuration: At least one of 'text' or 'html' must be provided in message" - ); - }); + it("should validate multiple recipients", () => { + const validPayload = { + to: ["test1@example.com", "test2@example.com"], + cc: ["cc1@example.com"], + bcc: ["bcc1@example.com"], + message: { + subject: "Test Subject", + text: "Test message", + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); - // Test invalid SendGrid template (missing templateId) - it("should throw ValidationError for SendGrid template without templateId", () => { - const invalidPayload = { - to: "test@example.com", - sendGrid: { - dynamicTemplateData: { - name: "Test User", + it("should validate UID-based recipients", () => { + const validPayload = { + toUids: ["user1", "user2"], + ccUids: ["user3"], + bccUids: ["user4"], + message: { + subject: "Test Subject", + text: "Test message", }, - }, - }; - expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); - expect(() => validatePayload(invalidPayload)).toThrow( - "Invalid email configuration: Field 'sendGrid.templateId' must be a string" - ); - }); + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); - // Test invalid custom template (missing name) - it("should throw ValidationError for custom template without name", () => { - const invalidPayload = { - to: "test@example.com", - template: { - data: { - name: "Test User", + it("should validate payload with optional fields", () => { + const validPayload = { + to: "test@example.com", + from: "sender@example.com", + replyTo: "reply@example.com", + categories: ["category1", "category2"], + message: { + subject: "Test Subject", + text: "Test message", + attachments: [], }, - }, - }; - expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); - expect(() => validatePayload(invalidPayload)).toThrow( - "Invalid email configuration: Field 'template.name' must be a string" - ); - }); + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); - // Test missing recipients - it("should throw ValidationError when no recipients are provided", () => { - const invalidPayload = { - message: { - subject: "Test Subject", - text: "Test message", - }, - }; - expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); - expect(() => validatePayload(invalidPayload)).toThrow( - "Email must have at least one recipient" - ); - }); + it("should validate a template payload without html/text fields", () => { + const validPayload = { + to: "test@example.com", + template: { + name: "welcome-email", + data: { + name: "Test User", + }, + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); - // Test array of recipients - it("should validate multiple recipients", () => { - const validPayload = { - to: ["test1@example.com", "test2@example.com"], - cc: ["cc1@example.com"], - bcc: ["bcc1@example.com"], - message: { - subject: "Test Subject", - text: "Test message", - }, - }; - expect(() => validatePayload(validPayload)).not.toThrow(); - }); + it("should validate a template payload with message override", () => { + const validPayload = { + to: "test@example.com", + template: { + name: "welcome-email", + data: { + name: "Test User", + }, + }, + message: { + subject: "Custom Subject", + attachments: [], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); - // Test UID-based recipients - it("should validate UID-based recipients", () => { - const validPayload = { - toUids: ["user1", "user2"], - ccUids: ["user3"], - bccUids: ["user4"], - message: { - subject: "Test Subject", - text: "Test message", - }, - }; - expect(() => validatePayload(validPayload)).not.toThrow(); + it("should validate a template payload with empty data", () => { + const validPayload = { + to: "test@example.com", + template: { + name: "welcome-email", + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate template with message containing only subject", () => { + const validPayload = { + to: "test@example.com", + template: { + name: "welcome-email", + }, + message: { + subject: "Test Subject", + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate template with message containing optional fields", () => { + const validPayload = { + to: "test@example.com", + template: { + name: "welcome-email", + data: { name: "User" }, + }, + message: { + subject: "Test Subject", + attachments: [], + categories: ["category1"], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate template payload when message has no html or text", () => { + const validPayload = { + to: "test@example.com", + template: { + name: "welcome-email", + data: { userName: "John Doe" }, + }, + message: { + subject: "Welcome!", + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate template with completely empty message object", () => { + const validPayload = { + to: "test@example.com", + template: { + name: "welcome-email", + data: { userName: "John Doe" }, + }, + message: { + // Completely empty - template provides everything + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); }); - // Test optional fields - it("should validate payload with optional fields", () => { + it("should validate a SendGrid payload with only mailSettings", () => { const validPayload = { to: "test@example.com", - from: "sender@example.com", - replyTo: "reply@example.com", - categories: ["category1", "category2"], - message: { - subject: "Test Subject", - text: "Test message", - attachments: [], + sendGrid: { + mailSettings: { + sandboxMode: { + enable: true, + }, + }, }, }; expect(() => validatePayload(validPayload)).not.toThrow(); }); - // Test invalid field types - it("should throw ValidationError for invalid field types", () => { - const invalidPayload = { - to: 123, // should be string or array - message: { - subject: "Test Subject", - text: "Test message", - }, - }; - expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); - expect(() => validatePayload(invalidPayload)).toThrow( - "Invalid email configuration: Field 'to' must be either a string or an array of strings" - ); - }); + describe("invalid payloads", () => { + it("should throw ValidationError for message without text or html", () => { + const invalidPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid message configuration: At least one of 'text' or 'html' must be provided in message" + ); + }); - // Test missing message/template/sendGrid - it("should throw ValidationError when no message, template, or sendGrid is provided", () => { - const invalidPayload = { - to: "test@example.com", - }; - expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); - expect(() => validatePayload(invalidPayload)).toThrow( - "Email configuration must include either a 'message', 'template', or 'sendGrid' object" - ); - }); + it("should throw ValidationError for SendGrid template with dynamicTemplateData but no templateId", () => { + const invalidPayload = { + to: "test@example.com", + sendGrid: { + dynamicTemplateData: { + name: "Test User", + }, + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid sendGrid configuration: Field 'templateId' is required when 'dynamicTemplateData' is provided" + ); + }); - // Test missing subject - it("should throw ValidationError for message without subject", () => { - const invalidPayload = { - to: "test@example.com", - message: { - text: "Test message", - }, - }; - expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); - expect(() => validatePayload(invalidPayload)).toThrow( - "Invalid email configuration: Field 'message.subject' must be a string" - ); + it("should throw ValidationError for custom template without name", () => { + const invalidPayload = { + to: "test@example.com", + template: { + data: { + name: "Test User", + }, + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid template configuration: Field 'template.name' must be a string" + ); + }); + + it("should throw ValidationError when no recipients are provided", () => { + const invalidPayload = { + message: { + subject: "Test Subject", + text: "Test message", + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid email configuration: Email must have at least one recipient" + ); + }); + + it("should throw ValidationError for invalid field types", () => { + const invalidPayload = { + to: 123, + message: { + subject: "Test Subject", + text: "Test message", + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid email configuration: Field 'to' must be either a string or an array of strings" + ); + }); + + it("should throw ValidationError when no message, template, or sendGrid is provided", () => { + const invalidPayload = { + to: "test@example.com", + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid email configuration: Email configuration must include either a 'message', 'template', or 'sendGrid' object" + ); + }); + + it("should throw ValidationError for message without subject", () => { + const invalidPayload = { + to: "test@example.com", + message: { + text: "Test message", + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid message configuration: Field 'message.subject' must be a string" + ); + }); + + it("should throw ValidationError for template with invalid name type", () => { + const invalidPayload = { + to: "test@example.com", + template: { + name: 123, + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid template configuration: Field 'template.name' must be a string" + ); + }); + + it("should throw ValidationError for template with invalid type", () => { + const invalidPayload = { + to: "test@example.com", + template: 123, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid template configuration: Field 'template' must be a map" + ); + }); + + it("should throw ValidationError for template with invalid data type", () => { + const invalidPayload = { + to: "test@example.com", + template: { + name: "welcome-email", + data: "invalid-data", + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid template configuration: Field 'template.data' must be a map" + ); + }); }); }); diff --git a/firestore-send-email/functions/src/validation.ts b/firestore-send-email/functions/src/validation.ts index cbbafa336..65ba29d7a 100644 --- a/firestore-send-email/functions/src/validation.ts +++ b/firestore-send-email/functions/src/validation.ts @@ -1,7 +1,9 @@ import { z } from "zod"; import { logger } from "firebase-functions/v1"; -// Custom error class for validation errors +/** + * Custom error class for validation failures. + */ export class ValidationError extends Error { constructor(message: string) { super(message); @@ -9,50 +11,128 @@ export class ValidationError extends Error { } } -// Standard message schema (for non-template, non-SendGrid) -const standardMessageSchema = z - .object({ - subject: z.string(), - text: z.string().optional(), - html: z.string().optional(), - attachments: z.array(z.any()).optional(), - }) +/** + * Base schema for email message content. + */ +const baseMessageSchema = z.object({ + subject: z.string().optional(), + text: z.string().optional(), + html: z.string().optional(), + attachments: z.array(z.any()).optional(), +}); + +/** + * Schema for standard email messages requiring subject and text/html content. + */ +const standardMessageSchema = baseMessageSchema + .required({ subject: true }) .refine((data) => !!data.text || !!data.html, { message: "At least one of 'text' or 'html' must be provided in message", }); -// SendGrid template schema -const sendGridSchema = z.object({ - templateId: z.string(), - dynamicTemplateData: z.record(z.any()).optional(), - mailSettings: z.record(z.any()).optional(), -}); +/** + * Schema for template-based messages (subject and content optional). + */ +const templateMessageSchema = baseMessageSchema.optional(); + +/** + * Schema for SendGrid-specific configuration options. + */ +const sendGridSchema = z + .object({ + templateId: z.string().optional(), + dynamicTemplateData: z.record(z.any()).optional(), + mailSettings: z.record(z.any()).optional(), + }) + .refine( + (data) => { + return !data.dynamicTemplateData || data.templateId; + }, + { + message: + "Field 'templateId' is required when 'dynamicTemplateData' is provided", + path: ["templateId"], + } + ); -// Template schema +/** + * Schema for custom email templates. + */ const templateSchema = z.object({ - name: z.string(), + name: z.string().min(1, "Template name cannot be empty"), data: z.record(z.any()).optional(), }); -// Main payload schema -const payloadSchema = z.object({ - to: z.union([z.string(), z.array(z.string())]).optional(), - cc: z.union([z.string(), z.array(z.string())]).optional(), - bcc: z.union([z.string(), z.array(z.string())]).optional(), - toUids: z.array(z.string()).optional(), - ccUids: z.array(z.string()).optional(), - bccUids: z.array(z.string()).optional(), - from: z.string().optional(), - replyTo: z.string().optional(), - message: standardMessageSchema.optional(), - template: templateSchema.optional(), - sendGrid: sendGridSchema.optional(), - categories: z.array(z.string()).optional(), -}); +/** + * Schema for email recipients (single email or array of emails). + */ +const recipientSchema = z.union([ + z.string().email(), + z.array(z.string().email()), +]); + +/** + * Schema for arrays of UIDs. + */ +const uidArraySchema = z.array(z.string().min(1)); + +/** + * Main schema for the entire email payload. + */ +const payloadSchema = z + .object({ + to: recipientSchema.optional(), + cc: recipientSchema.optional(), + bcc: recipientSchema.optional(), + toUids: uidArraySchema.optional(), + ccUids: uidArraySchema.optional(), + bccUids: uidArraySchema.optional(), + from: z.string().email().optional(), + replyTo: z.string().email().optional(), + message: baseMessageSchema.optional(), + template: templateSchema.optional(), + sendGrid: sendGridSchema.optional(), + categories: z.array(z.string()).optional(), + }) + .refine( + (data) => { + const hasRecipients = [ + data.to, + data.cc, + data.bcc, + data.toUids, + data.ccUids, + data.bccUids, + ].some((field) => (Array.isArray(field) ? field.length > 0 : field)); -function formatZodError(error: z.ZodError): string { + return hasRecipients; + }, + { + message: "Email must have at least one recipient", + } + ) + .refine( + (data) => { + return !!(data.message || data.template || data.sendGrid); + }, + { + message: + "Email configuration must include either a 'message', 'template', or 'sendGrid' object", + } + ); + +/** + * Formats Zod validation errors into human-readable error messages. + * @param error - The Zod error to format + * @param context - The context or field name where the error occurred + * @returns A formatted error message string + */ +function formatZodError( + error: z.ZodError, + context: string = "email configuration" +): string { const issues = error.issues.map((issue) => { - const path = issue.path.join("."); + const path = issue.path.length > 0 ? issue.path.join(".") : context; switch (issue.code) { case "invalid_type": if (issue.expected === "string") { @@ -61,82 +141,114 @@ function formatZodError(error: z.ZodError): string { if (issue.expected === "array") { return `Field '${path}' must be an array`; } + if (issue.expected === "object") { + return `Field '${path}' must be a map`; + } return `Field '${path}' must be ${issue.expected}`; case "invalid_string": + if (issue.validation === "email") { + return `Field '${path}' must be a valid email address`; + } return `Field '${path}' is invalid`; case "too_small": + if (issue.minimum === 1) { + return `Field '${path}' cannot be empty`; + } return `Field '${path}' is required`; case "invalid_union": + if (path === "template") { + return `Field '${path}' must be a map with a 'name' field`; + } return `Field '${path}' must be either a string or an array of strings`; + case "custom": + return issue.message; default: return issue.message; } }); - return issues.join(". "); + return `Invalid ${context}: ${issues.join(". ")}`; +} + +/** + * Adjusts Zod error issues by adding a path prefix. + * @param error - The Zod error to adjust + * @param pathPrefix - The prefix to add to error paths + * @returns A new Zod error with adjusted paths + */ +function adjustZodErrorIssues( + error: z.ZodError, + pathPrefix: string[] +): z.ZodError { + const adjustedIssues = error.issues.map((issue) => ({ + ...issue, + path: [...pathPrefix, ...issue.path], + })); + return new z.ZodError(adjustedIssues); +} + +/** + * Validates a specific field using a Zod schema and throws a ValidationError on failure. + * @param fieldValue - The value to validate + * @param schema - The Zod schema to use for validation + * @param fieldName - The name of the field being validated + * @param context - The context for error messages + * @throws {ValidationError} When validation fails + */ +function validateField( + fieldValue: any, + schema: z.ZodSchema, + fieldName: string, + context: string +): void { + const result = schema.safeParse(fieldValue); + if (!result.success) { + const adjustedError = adjustZodErrorIssues(result.error, [fieldName]); + throw new ValidationError(formatZodError(adjustedError, context)); + } } +/** + * Validates an email payload against predefined schemas. + * Validates specific fields first (sendGrid, template, message) with context-specific error messages, + * then validates the entire payload structure. + * @param payload - The email payload to validate + * @throws {ValidationError} When validation fails + */ export function validatePayload(payload: any) { try { - // First validate the overall payload structure - const result = payloadSchema.safeParse(payload); - if (!result.success) { - throw new ValidationError( - `Invalid email configuration: ${formatZodError(result.error)}` + if (payload.sendGrid !== undefined) { + validateField( + payload.sendGrid, + sendGridSchema, + "sendGrid", + "sendGrid configuration" ); } - // If using SendGrid template, validate sendGrid object - if (payload.sendGrid) { - const sendGridResult = sendGridSchema.safeParse(payload.sendGrid); - if (!sendGridResult.success) { - throw new ValidationError( - `Invalid SendGrid configuration: ${formatZodError( - sendGridResult.error - )}` - ); - } - return; - } - - // If using custom template, validate template object - if (payload.template) { - const templateResult = templateSchema.safeParse(payload.template); - if (!templateResult.success) { - throw new ValidationError( - `Invalid template configuration: ${formatZodError( - templateResult.error - )}` - ); - } - return; - } - - // If not using templates, validate message object - if (!payload.message) { - throw new ValidationError( - "Email configuration must include either a 'message', 'template', or 'sendGrid' object" + if (payload.template !== undefined) { + validateField( + payload.template, + templateSchema, + "template", + "template configuration" ); } - const messageResult = standardMessageSchema.safeParse(payload.message); - if (!messageResult.success) { - throw new ValidationError( - `Invalid message configuration: ${formatZodError(messageResult.error)}` + if (payload.message && Object.keys(payload.message).length > 0) { + const messageSchema = payload.template + ? templateMessageSchema + : standardMessageSchema; + validateField( + payload.message, + messageSchema, + "message", + "message configuration" ); } - // Validate that there is at least one recipient - if ( - !payload.to?.length && - !payload.cc?.length && - !payload.bcc?.length && - !payload.toUids?.length && - !payload.ccUids?.length && - !payload.bccUids?.length - ) { - throw new ValidationError( - "Email must have at least one recipient (to, cc, bcc, toUids, ccUids, or bccUids)" - ); + const result = payloadSchema.safeParse(payload); + if (!result.success) { + throw new ValidationError(formatZodError(result.error)); } } catch (error) { if (error instanceof ValidationError) { From 092dd8f5267e477c5f8cca3d7c9cf073d0230c10 Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Thu, 15 May 2025 13:18:44 +0100 Subject: [PATCH 4/8] chore(firestore-send-email): bump CHANGELOG --- firestore-send-email/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/firestore-send-email/CHANGELOG.md b/firestore-send-email/CHANGELOG.md index 4ab786219..1491388c8 100644 --- a/firestore-send-email/CHANGELOG.md +++ b/firestore-send-email/CHANGELOG.md @@ -1,5 +1,7 @@ ## Version 0.2.2 +fix: fix validation of payloads + docs: add documentation on how to use dynamic templates with SendGrid ## Version 0.2.1 From 988d6b916c1a0930e54619780516e8f1930cab41 Mon Sep 17 00:00:00 2001 From: Jacob Cable <32874567+cabljac@users.noreply.github.com> Date: Fri, 16 May 2025 14:15:47 +0100 Subject: [PATCH 5/8] fix(firestore-send-email): preparePayload fix (#2423) * chore(firestore-send-email): bump CHANGELOG * fix(firestore-send-email): extract preparePayload for better dep injection * fix(firestore-send-email): fix preparePayload with template * chore(firestore-send-email): remove debug logs * fix(firestore-send-email): attachment validation * chore(firestore-send-email): add test coverage script * fix(firestore-send-email): nullable message fields --- .../functions/__tests__/e2e/sendgrid.test.ts | 145 ++++++ .../__tests__/prepare-payload.test.ts | 442 ++++++++++++++++++ .../functions/__tests__/validation.test.ts | 273 +++++++++++ firestore-send-email/functions/jest.config.js | 7 + firestore-send-email/functions/package.json | 2 + firestore-send-email/functions/src/index.ts | 150 +----- .../functions/src/prepare-payload.ts | 197 ++++++++ .../functions/src/validation.ts | 56 ++- 8 files changed, 1123 insertions(+), 149 deletions(-) create mode 100644 firestore-send-email/functions/__tests__/e2e/sendgrid.test.ts create mode 100644 firestore-send-email/functions/__tests__/prepare-payload.test.ts create mode 100644 firestore-send-email/functions/src/prepare-payload.ts diff --git a/firestore-send-email/functions/__tests__/e2e/sendgrid.test.ts b/firestore-send-email/functions/__tests__/e2e/sendgrid.test.ts new file mode 100644 index 000000000..815b13d42 --- /dev/null +++ b/firestore-send-email/functions/__tests__/e2e/sendgrid.test.ts @@ -0,0 +1,145 @@ +// This test suite assumes local emulator is running the extension, with the following config: + +// AUTH_TYPE=UsernamePassword +// DATABASE=(default) +// DATABASE_REGION=us-east1 +// DEFAULT_FROM= +// MAIL_COLLECTION=emailCollection +// OAUTH_PORT=465 +// SMTP_CONNECTION_URI=smtps://apikey@smtp.sendgrid.net:465 +// TEMPLATES_COLLECTION=emailTemplates +// TTL_EXPIRE_TYPE=never +// TTL_EXPIRE_VALUE=1 + +// set the TEST_EMAIL environment variable to the recipient email address for the test +const TEST_EMAIL = process.env.TEST_EMAIL || "test@example.com"; + +// and that the sendgrid api key is set as a secret for the emulator in a .secret.local file + +import * as admin from "firebase-admin"; + +// Test data constants +const TEST_TEMPLATE = { + name: "test_template", + subject: "Test Subject", + text: `Hello {{userName}}, + +Thank you for your order: +{{orderText}} + +Your order will be processed by {{doctorName}}. + +Business Hours: +{{openingHours}} + +Address: +{{address}} + +Best regards, +The Team`, + html: ` + + + +

Hello {{userName}},

+

Thank you for your order: {{orderText}}

+

Your order will be processed by {{doctorName}}.

+

Business Hours: {{openingHours}}

+

Address: {{address}}

+

Best regards,
The Team

+ +`, +}; + +const TEST_TEMPLATE_DATA = { + address: "123 Test Street, Test City", + doctorName: "Dr. Test", + openingHours: "Mon-Fri: 9:00-17:00", + orderText: "Test order items", + userName: "Test User", +}; + +const TEST_COLLECTIONS = ["emailCollection", "emailTemplates"] as const; + +// Skip the entire suite if E2E_SENDGRID is not set to true +(process.env.E2E_SENDGRID === "true" ? describe : describe.skip)( + "SendGrid E2E Tests", + () => { + beforeAll(() => { + // Initialize with emulator settings + admin.initializeApp({ + projectId: "dev-extensions-testing", + databaseURL: "http://localhost:8080?ns=dev-extensions-testing", + }); + + // Point Firestore to the emulator + process.env.FIRESTORE_EMULATOR_HOST = "localhost:8080"; + }); + + beforeEach(async () => { + // Clear all data from the emulator + const db = admin.firestore(); + + for (const collection of TEST_COLLECTIONS) { + const snapshot = await db.collection(collection).get(); + const batch = db.batch(); + + snapshot.docs.forEach((doc) => { + batch.delete(doc.ref); + }); + + await batch.commit(); + } + + // Create the email template + await db.collection("emailTemplates").doc(TEST_TEMPLATE.name).set({ + subject: TEST_TEMPLATE.subject, + text: TEST_TEMPLATE.text, + html: TEST_TEMPLATE.html, + }); + }); + + test("should process a template-based email document", async () => { + const db = admin.firestore(); + + const testData = { + message: { + attachments: [], + html: null, + text: null, + subject: TEST_TEMPLATE.subject, + }, + template: { + data: TEST_TEMPLATE_DATA, + name: TEST_TEMPLATE.name, + }, + to: TEST_EMAIL, + }; + + // Write the document to the emulator + const docRef = db.collection("emailCollection").doc("test-doc"); + await docRef.set(testData); + + // Wait a bit for the function to process + await new Promise((resolve) => setTimeout(resolve, 2000)); + + // Verify the document was updated + const doc = await docRef.get(); + const updatedData = doc.data(); + + // Assert the delivery state was updated to SUCCESS + console.log("updatedData", updatedData); + expect(updatedData?.delivery.state).toBe("SUCCESS"); + expect(updatedData?.delivery.attempts).toBe(1); + expect(updatedData?.delivery.endTime).toBeDefined(); + expect(updatedData?.delivery.error).toBeNull(); + + // Verify SendGrid specific info + expect(updatedData?.delivery.info).toBeDefined(); + expect(updatedData?.delivery.info?.messageId).toBeDefined(); + expect(updatedData?.delivery.info?.accepted).toContain(TEST_EMAIL); + expect(updatedData?.delivery.info?.rejected).toEqual([]); + expect(updatedData?.delivery.info?.pending).toEqual([]); + }); + } +); diff --git a/firestore-send-email/functions/__tests__/prepare-payload.test.ts b/firestore-send-email/functions/__tests__/prepare-payload.test.ts new file mode 100644 index 000000000..c9a7be394 --- /dev/null +++ b/firestore-send-email/functions/__tests__/prepare-payload.test.ts @@ -0,0 +1,442 @@ +import { preparePayload, setDependencies } from "../src/prepare-payload"; + +class MockTemplates { + async render(name: string, data: any) { + switch (name) { + case "html-only-template": + return { + html: "

Template HTML

", + subject: "Template Subject", + }; + case "text-only-template": + return { + text: "Template text content", + subject: "Template Subject", + }; + case "both-html-text-template": + return { + html: "

Template HTML

", + text: "Template text content", + subject: "Template Subject", + }; + case "template-with-attachments": + return { + html: "

Template HTML

", + subject: "Template Subject", + attachments: [{ filename: "template.pdf" }], + }; + case "template-with-data": + return { + html: `

Hello ${data.name}

`, + subject: `Subject for ${data.name}`, + }; + case "template-with-null-values": + return { + html: null, + text: null, + subject: "Template Subject", + }; + case "template-with-empty-strings": + return { + html: "", + text: "", + subject: "Template Subject", + }; + case "template-with-undefined-values": + return { + html: undefined, + text: undefined, + subject: "Template Subject", + }; + default: + return {}; + } + } +} + +describe("preparePayload Template Merging", () => { + beforeEach(() => { + jest.clearAllMocks(); + // We stub db.getAll here but it won't be called unless toUids/ccUids/bccUids are used + setDependencies({ getAll: jest.fn() }, new MockTemplates()); + }); + + it("should throw error when there is no message and no template", async () => { + const payload = { + to: "test@example.com", + }; + + await expect(preparePayload(payload)).rejects.toThrow( + "Invalid email configuration: Email configuration must include either a 'message', 'template', or 'sendGrid' object" + ); + }); + + it("should", async () => { + const payload = { + to: "test@example.com", + template: { + name: "text-only-template", + data: {}, + }, + }; + + const result = await preparePayload(payload); + + console.log(result); + + expect(result.message.text).toBe("Template text content"); + expect(result.message.html).toBeUndefined(); + expect(result.message.subject).toBe("Template Subject"); + }); + + it("should preserve existing HTML content when template only provides text", async () => { + const payload = { + to: "test@example.com", + template: { + name: "text-only-template", + data: {}, + }, + message: { + html: "

Original HTML content

", + subject: "Original Subject", + }, + }; + + const result = await preparePayload(payload); + + expect(result.message.html).toBe("

Original HTML content

"); // Should preserve original HTML + expect(result.message.text).toBe("Template text content"); + expect(result.message.subject).toBe("Template Subject"); + }); + + it("should prioritize template HTML over message text when both exist", async () => { + const payload = { + to: "test@example.com", + template: { + name: "both-html-text-template", + data: {}, + }, + message: { + text: "Original text content", + }, + }; + + const result = await preparePayload(payload); + + expect(result.message.html).toBe("

Template HTML

"); + expect(result.message.text).toBe("Template text content"); + }); + + it("should handle attachment merging correctly", async () => { + const payload = { + to: "test@example.com", + template: { + name: "template-with-attachments", + data: {}, + }, + message: { + attachments: [{ filename: "original.doc" }], + }, + }; + + const result = await preparePayload(payload); + + expect(result.message.attachments).toEqual([{ filename: "template.pdf" }]); + }); + + it("should gracefully handle template with no content", async () => { + const payload = { + to: "test@example.com", + template: { + name: "empty-template", + data: {}, + }, + message: { + html: "

Original HTML content

", + subject: "Original Subject", + }, + }; + + const result = await preparePayload(payload); + + expect(result.message.html).toBe("

Original HTML content

"); + expect(result.message.subject).toBe("Original Subject"); + expect(result.message.attachments).toEqual([]); + }); + + it("should merge template and message content correctly", async () => { + const payload = { + to: "test@example.com", + template: { + name: "html-only-template", + data: {}, + }, + message: { + text: "Original text content", + subject: "Original Subject", + }, + attachments: [{ filename: "original.doc" }], + }; + + const result = await preparePayload(payload); + + expect(result.message.html).toBe("

Template HTML

"); + expect(result.message.text).toBe("Original text content"); // Should preserve original text + expect(result.message.subject).toBe("Template Subject"); + }); + + it("should handle template data correctly", async () => { + const payload = { + to: "test@example.com", + template: { + name: "template-with-data", + data: { name: "John" }, + }, + }; + + const result = await preparePayload(payload); + + expect(result.message.html).toBe("

Hello John

"); + expect(result.message.subject).toBe("Subject for John"); + }); + + it("should handle string recipient addresses", async () => { + const payload = { + to: "test@example.com", + cc: "cc@example.com", + bcc: "bcc@example.com", + message: { + subject: "Test Subject", + html: "

Test HTML content

", + }, + }; + + const result = await preparePayload(payload); + + expect(result.to).toEqual(["test@example.com"]); + expect(result.cc).toEqual(["cc@example.com"]); + expect(result.bcc).toEqual(["bcc@example.com"]); + }); + + it("should handle array recipient addresses", async () => { + const payload = { + to: ["test1@example.com", "test2@example.com"], + cc: ["cc1@example.com", "cc2@example.com"], + bcc: ["bcc1@example.com", "bcc2@example.com"], + message: { + subject: "Test Subject", + html: "

Test HTML content

", + }, + }; + + const result = await preparePayload(payload); + + expect(result.to).toEqual(["test1@example.com", "test2@example.com"]); + expect(result.cc).toEqual(["cc1@example.com", "cc2@example.com"]); + expect(result.bcc).toEqual(["bcc1@example.com", "bcc2@example.com"]); + }); + + it("should handle message without template", async () => { + const payload = { + to: "test@example.com", + message: { + html: "

Direct HTML content

", + subject: "Direct Subject", + }, + }; + + const result = await preparePayload(payload); + + expect(result.message.html).toBe("

Direct HTML content

"); + expect(result.message.subject).toBe("Direct Subject"); + }); + + it("should handle empty message object", async () => { + const payload = { + to: "test@example.com", + message: {}, + }; + + const result = await preparePayload(payload); + + expect(result.message).toEqual({}); + }); + + it("should handle template with null values", async () => { + const payload = { + to: "test@example.com", + template: { + name: "template-with-null-values", + data: {}, + }, + }; + + const result = await preparePayload(payload); + + // Changed: null values should be omitted entirely + expect(result.message.html).toBeUndefined(); + expect(result.message.text).toBeUndefined(); + expect(result.message.subject).toBe("Template Subject"); + // Verify properties don't exist at all + expect("html" in result.message).toBe(false); + expect("text" in result.message).toBe(false); + }); + + // NEW TEST: Test for null values not overwriting existing content + it("should not overwrite existing content when template has null values", async () => { + const payload = { + to: "test@example.com", + template: { + name: "template-with-null-values", + data: {}, + }, + message: { + html: "

Original HTML

", + text: "Original text", + subject: "Original Subject", + }, + }; + + const result = await preparePayload(payload); + + // null values should not overwrite existing content - they should be omitted + expect(result.message.html).toBe("

Original HTML

"); + expect(result.message.text).toBe("Original text"); + expect(result.message.subject).toBe("Template Subject"); + }); + + // NEW TEST: Test for empty string values being preserved + it("should preserve empty string values from template", async () => { + const payload = { + to: "test@example.com", + template: { + name: "template-with-empty-strings", + data: {}, + }, + message: { + html: "

Original HTML

", + text: "Original text", + subject: "Original Subject", + }, + }; + + const result = await preparePayload(payload); + + // Empty strings should overwrite existing content + expect(result.message.html).toBe(""); + expect(result.message.text).toBe(""); + expect(result.message.subject).toBe("Template Subject"); + }); + + // NEW TEST: Test for undefined values preserving existing content + it("should preserve existing content when template has undefined values", async () => { + const payload = { + to: "test@example.com", + template: { + name: "template-with-undefined-values", + data: {}, + }, + message: { + html: "

Original HTML

", + text: "Original text", + subject: "Original Subject", + }, + }; + + const result = await preparePayload(payload); + + // undefined values should preserve existing content + expect(result.message.html).toBe("

Original HTML

"); + expect(result.message.text).toBe("Original text"); + expect(result.message.subject).toBe("Template Subject"); + }); + + it("should handle incorrectly formatted attachments object", async () => { + const payload = { + to: "tester@gmx.at", + template: { + name: "med_order_reply_greimel", + data: { + address: "Halbenrain 140 Graz", + doctorName: "Dr. Andreas", + openingHours: "Mo., Mi., Fr. 8:00-12:00Di., Do. 10:30-15:30", + orderText: "Some stuff i need", + userName: "Pfeiler ", + name: "med_order_reply_greimel", + }, + }, + message: { + attachments: [ + { + html: null, + text: null, + }, + ], + subject: "Bestellbestätigung", + }, + }; + + const result = await preparePayload(payload); + + // Should convert attachments to an empty array since the format is incorrect + expect(result.message.attachments).toEqual([]); + expect(result.message.subject).toBe("Bestellbestätigung"); + expect(result.to).toEqual(["tester@gmx.at"]); + }); + + describe("attachment validation", () => { + it("should handle non-array attachments", async () => { + const payload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test text", + attachments: "not-an-array", + }, + }; + + await expect(preparePayload(payload)).rejects.toThrow(); + }); + + it("should handle null attachments", async () => { + const payload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test text", + attachments: null, + }, + }; + + await expect(preparePayload(payload)).rejects.toThrow(); + }); + + it("should handle undefined attachments", async () => { + const payload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test text", + attachments: undefined, + }, + }; + + const result = await preparePayload(payload); + expect(result.message.attachments).toBeUndefined(); + }); + + it("should handle empty attachments array", async () => { + const payload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test text", + attachments: [], + }, + }; + + const result = await preparePayload(payload); + expect(result.message.attachments).toEqual([]); + }); + }); +}); diff --git a/firestore-send-email/functions/__tests__/validation.test.ts b/firestore-send-email/functions/__tests__/validation.test.ts index c0dc3e142..cedff391f 100644 --- a/firestore-send-email/functions/__tests__/validation.test.ts +++ b/firestore-send-email/functions/__tests__/validation.test.ts @@ -187,6 +187,17 @@ describe("validatePayload", () => { }; expect(() => validatePayload(validPayload)).not.toThrow(); }); + + it("should validate template without message object", () => { + const validPayload = { + to: "test@example.com", + template: { + name: "EGFMB64MzmVz0Or75ctL", + data: { userName: "cabljac", name: "jacob" }, + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); }); it("should validate a SendGrid payload with only mailSettings", () => { @@ -335,4 +346,266 @@ describe("validatePayload", () => { ); }); }); + + describe("attachment validation", () => { + describe("valid attachments", () => { + it("should validate plain text attachment", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + filename: "hello.txt", + content: "Hello world!", + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate binary buffer attachment", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + filename: "buffer.txt", + content: Buffer.from("Hello world!", "utf8"), + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate local file attachment", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + filename: "report.pdf", + path: "/absolute/path/to/report.pdf", + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate attachment with implicit filename", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + path: "/absolute/path/to/image.png", + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate attachment with custom content type", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + filename: "data.bin", + content: Buffer.from("deadbeef", "hex"), + contentType: "application/octet-stream", + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate remote file attachment", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + filename: "license.txt", + href: "https://raw.githubusercontent.com/nodemailer/nodemailer/master/LICENSE", + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate base64 encoded attachment", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + filename: "photo.jpg", + content: "/9j/4AAQSkZJRgABAQAAAQABAAD…", + encoding: "base64", + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate data URI attachment", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + path: "data:text/plain;base64,SGVsbG8gd29ybGQ=", + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate pre-built MIME node attachment", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + raw: [ + "Content-Type: text/plain; charset=utf-8", + 'Content-Disposition: attachment; filename="greeting.txt"', + "", + "Hello world!", + ].join("\r\n"), + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate embedded image attachment", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + html: '

Nodemailer logo

', + attachments: [ + { + filename: "logo.png", + path: "./assets/logo.png", + cid: "logo@nodemailer", + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + + it("should validate multiple attachments", () => { + const validPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + filename: "file1.txt", + content: "Content 1", + }, + { + filename: "file2.txt", + content: "Content 2", + }, + ], + }, + }; + expect(() => validatePayload(validPayload)).not.toThrow(); + }); + }); + + describe("invalid attachments", () => { + it("should throw error for invalid httpHeaders type", () => { + const invalidPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + filename: "test.txt", + href: "https://example.com", + httpHeaders: "not-an-object", + }, + ], + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid message configuration: Field 'message.attachments.0.httpHeaders' must be a map" + ); + }); + + it("should throw error for invalid headers type", () => { + const invalidPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: [ + { + filename: "test.txt", + content: "test", + headers: "not-an-object", + }, + ], + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid message configuration: Field 'message.attachments.0.headers' must be a map" + ); + }); + + it("should throw error for non-array attachments", () => { + const invalidPayload = { + to: "test@example.com", + message: { + subject: "Test Subject", + text: "Test message", + attachments: { + filename: "test.txt", + content: "test", + }, + }, + }; + expect(() => validatePayload(invalidPayload)).toThrow(ValidationError); + expect(() => validatePayload(invalidPayload)).toThrow( + "Invalid message configuration: Field 'message.attachments' must be an array" + ); + }); + }); + }); }); diff --git a/firestore-send-email/functions/jest.config.js b/firestore-send-email/functions/jest.config.js index 6ead6a89f..d9dc12340 100644 --- a/firestore-send-email/functions/jest.config.js +++ b/firestore-send-email/functions/jest.config.js @@ -17,6 +17,13 @@ module.exports = { setupFiles: ["/__tests__/jest.setup.ts"], testMatch: ["**/__tests__/**/*.test.ts"], testEnvironment: "node", + collectCoverageFrom: [ + "src/**/*.{js,ts}", + "!src/**/*.d.ts", + "!**/__tests__/**", + ], + coverageDirectory: "coverage", + coverageReporters: ["text", "lcov", "html"], moduleNameMapper: { "firebase-admin/app": "/node_modules/firebase-admin/lib/app", "firebase-admin/eventarc": diff --git a/firestore-send-email/functions/package.json b/firestore-send-email/functions/package.json index e9f93091b..4180a2fa2 100644 --- a/firestore-send-email/functions/package.json +++ b/firestore-send-email/functions/package.json @@ -13,6 +13,8 @@ "testIfEmulatorRunning": "wait-on tcp:4001 && jest", "test:local": "concurrently --kill-others \"npm run local:emulator\" \"npm run testIfEmulatorRunning\"", "test:watch": "concurrently \"npm run local:emulator\" \"jest --watch\"", + "test:coverage": "concurrently --kill-others \"npm run local:emulator\" \"wait-on tcp:4001 && jest --coverage\"", + "test:e2e:sendgrid": "E2E_SENDGRID=true jest __tests__/e2e/sendgrid.test.ts", "generate-readme": "firebase ext:info .. --markdown > ../README.md" }, "keywords": [], diff --git a/firestore-send-email/functions/src/index.ts b/firestore-send-email/functions/src/index.ts index 112ea1889..2af1518a6 100644 --- a/firestore-send-email/functions/src/index.ts +++ b/firestore-send-email/functions/src/index.ts @@ -22,7 +22,6 @@ import { DocumentSnapshot, DocumentReference, getFirestore, - DocumentData, } from "firebase-admin/firestore"; import { onDocumentWritten } from "firebase-functions/v2/firestore"; import * as functions from "firebase-functions"; @@ -35,7 +34,7 @@ import { Delivery, QueuePayload, ExtendedSendMailOptions } from "./types"; import { isSendGrid, setSmtpCredentials } from "./helpers"; import * as events from "./events"; import { SendGridTransport } from "./nodemailer-sendgrid"; -import { validatePayload } from "./validation"; +import { preparePayload, setDependencies } from "./prepare-payload"; logs.init(); @@ -66,6 +65,9 @@ async function initialize() { templates = new Templates(db.collection(config.templatesCollection)); } + // Set dependencies for preparePayload + setDependencies(db, templates); + /** setup events */ events.setupEventChannel(); } @@ -124,150 +126,6 @@ function getExpireAt(startTime: Timestamp) { return Timestamp.fromDate(now); } -async function preparePayload(payload: DocumentData): Promise { - // Validate the payload before processing - validatePayload(payload); - - const { template } = payload; - - if (templates && template) { - if (!template.name) { - throw new Error(`Template object is missing a 'name' parameter.`); - } - - const templateRender = await templates.render(template.name, template.data); - - const mergeMessage = payload.message || {}; - - const attachments = templateRender.attachments - ? templateRender.attachments - : mergeMessage.attachments; - - payload.message = Object.assign(mergeMessage, templateRender, { - attachments: attachments || [], - }); - } - - let to: string[] = []; - let cc: string[] = []; - let bcc: string[] = []; - - if (typeof payload.to === "string") { - to = [payload.to]; - } else if (payload.to) { - validateFieldArray("to", payload.to); - to = to.concat(payload.to); - } - - if (typeof payload.cc === "string") { - cc = [payload.cc]; - } else if (payload.cc) { - validateFieldArray("cc", payload.cc); - cc = cc.concat(payload.cc); - } - - if (typeof payload.bcc === "string") { - bcc = [payload.bcc]; - } else if (payload.bcc) { - validateFieldArray("bcc", payload.bcc); - bcc = bcc.concat(payload.bcc); - } - - if (!payload.toUids && !payload.ccUids && !payload.bccUids) { - payload.to = to; - payload.cc = cc; - payload.bcc = bcc; - - return payload; - } - - if (!config.usersCollection) { - throw new Error("Must specify a users collection to send using uids."); - } - - let uids: string[] = []; - - if (payload.toUids) { - validateFieldArray("toUids", payload.toUids); - uids = uids.concat(payload.toUids); - } - - if (payload.ccUids) { - validateFieldArray("ccUids", payload.ccUids); - uids = uids.concat(payload.ccUids); - } - - if (payload.bccUids) { - validateFieldArray("bccUids", payload.bccUids); - uids = uids.concat(payload.bccUids); - } - - const toFetch: Record = {}; - uids.forEach((uid) => (toFetch[uid] = null)); - - const documents = await db.getAll( - ...Object.keys(toFetch).map((uid) => - db.collection(config.usersCollection).doc(uid) - ), - { - fieldMask: ["email"], - } - ); - - const missingUids: string[] = []; - - documents.forEach((documentSnapshot) => { - if (documentSnapshot.exists) { - const email = documentSnapshot.get("email"); - - if (email) { - toFetch[documentSnapshot.id] = email; - } else { - missingUids.push(documentSnapshot.id); - } - } else { - missingUids.push(documentSnapshot.id); - } - }); - - logs.missingUids(missingUids); - - if (payload.toUids) { - payload.toUids.forEach((uid) => { - const email = toFetch[uid]; - if (email) { - to.push(email); - } - }); - } - - payload.to = to; - - if (payload.ccUids) { - payload.ccUids.forEach((uid) => { - const email = toFetch[uid]; - if (email) { - cc.push(email); - } - }); - } - - payload.cc = cc; - - if (payload.bccUids) { - payload.bccUids.forEach((uid) => { - const email = toFetch[uid]; - if (email) { - bcc.push(email); - } - }); - } - - payload.bcc = bcc; - - return payload; -} - async function deliver(ref: DocumentReference): Promise { // Fetch the Firestore document const snapshot = await ref.get(); diff --git a/firestore-send-email/functions/src/prepare-payload.ts b/firestore-send-email/functions/src/prepare-payload.ts new file mode 100644 index 000000000..5574c732d --- /dev/null +++ b/firestore-send-email/functions/src/prepare-payload.ts @@ -0,0 +1,197 @@ +import { DocumentData } from "firebase-admin/firestore"; +import { + validatePayload, + attachmentSchema, + attachmentsSchema, +} from "./validation"; +import * as logs from "./logs"; +import config from "./config"; +import { z } from "zod"; + +let db: any; +let templates: any; + +export function setDependencies(database: any, templatesInstance: any) { + db = database; + templates = templatesInstance; +} + +function validateFieldArray(field: string, array?: string[]) { + if (!Array.isArray(array)) { + throw new Error(`Invalid field "${field}". Expected an array of strings.`); + } + + if (array.find((item) => typeof item !== "string")) { + throw new Error(`Invalid field "${field}". Expected an array of strings.`); + } +} + +export async function preparePayload( + payload: DocumentData +): Promise { + validatePayload(payload); + + const { template } = payload; + + if (templates && template) { + if (!template.name) { + throw new Error(`Template object is missing a 'name' parameter.`); + } + + const templateRender = await templates.render(template.name, template.data); + const mergeMessage = payload.message || {}; + + let attachments = attachmentsSchema.parse( + templateRender.attachments + ? templateRender.attachments + : mergeMessage.attachments + ); + + const handleTemplateValue = (value: any) => { + if (value === null) { + return undefined; + } + if (value === "") { + return ""; + } + if (value === undefined) { + return undefined; + } + return value || undefined; + }; + + const templateContent = { + subject: handleTemplateValue(templateRender.subject), + html: handleTemplateValue(templateRender.html), + text: handleTemplateValue(templateRender.text), + amp: handleTemplateValue(templateRender.amp), + attachments: attachments || [], + }; + + Object.keys(templateContent).forEach((key) => { + if (templateContent[key] === undefined) { + delete templateContent[key]; + } + }); + + payload.message = Object.assign(mergeMessage, templateContent); + } + + let to: string[] = []; + let cc: string[] = []; + let bcc: string[] = []; + + if (typeof payload.to === "string") { + to = [payload.to]; + } else if (payload.to) { + validateFieldArray("to", payload.to); + to = to.concat(payload.to); + } + + if (typeof payload.cc === "string") { + cc = [payload.cc]; + } else if (payload.cc) { + validateFieldArray("cc", payload.cc); + cc = cc.concat(payload.cc); + } + + if (typeof payload.bcc === "string") { + bcc = [payload.bcc]; + } else if (payload.bcc) { + validateFieldArray("bcc", payload.bcc); + bcc = bcc.concat(payload.bcc); + } + + if (!payload.toUids && !payload.ccUids && !payload.bccUids) { + payload.to = to; + payload.cc = cc; + payload.bcc = bcc; + return payload; + } + + if (!config.usersCollection) { + throw new Error("Must specify a users collection to send using uids."); + } + + let uids: string[] = []; + + if (payload.toUids) { + validateFieldArray("toUids", payload.toUids); + uids = uids.concat(payload.toUids); + } + + if (payload.ccUids) { + validateFieldArray("ccUids", payload.ccUids); + uids = uids.concat(payload.ccUids); + } + + if (payload.bccUids) { + validateFieldArray("bccUids", payload.bccUids); + uids = uids.concat(payload.bccUids); + } + + const toFetch: Record = {}; + uids.forEach((uid) => (toFetch[uid] = null)); + + const documents = await db.getAll( + ...Object.keys(toFetch).map((uid) => + db.collection(config.usersCollection).doc(uid) + ), + { + fieldMask: ["email"], + } + ); + + const missingUids: string[] = []; + + documents.forEach((documentSnapshot) => { + if (documentSnapshot.exists) { + const email = documentSnapshot.get("email"); + + if (email) { + toFetch[documentSnapshot.id] = email; + } else { + missingUids.push(documentSnapshot.id); + } + } else { + missingUids.push(documentSnapshot.id); + } + }); + + logs.missingUids(missingUids); + + if (payload.toUids) { + payload.toUids.forEach((uid) => { + const email = toFetch[uid]; + if (email) { + to.push(email); + } + }); + } + + payload.to = to; + + if (payload.ccUids) { + payload.ccUids.forEach((uid) => { + const email = toFetch[uid]; + if (email) { + cc.push(email); + } + }); + } + + payload.cc = cc; + + if (payload.bccUids) { + payload.bccUids.forEach((uid) => { + const email = toFetch[uid]; + if (email) { + bcc.push(email); + } + }); + } + + payload.bcc = bcc; + + return payload; +} diff --git a/firestore-send-email/functions/src/validation.ts b/firestore-send-email/functions/src/validation.ts index 65ba29d7a..6b8b8af03 100644 --- a/firestore-send-email/functions/src/validation.ts +++ b/firestore-send-email/functions/src/validation.ts @@ -11,14 +11,64 @@ export class ValidationError extends Error { } } +/** + * Schema for email attachments + */ +export const attachmentSchema = z + .object({ + filename: z.string().nullable().optional(), + content: z + .union([z.string(), z.instanceof(Buffer), z.any()]) + .nullable() + .optional(), // Stream type is handled as any + path: z.string().nullable().optional(), + href: z.string().nullable().optional(), + httpHeaders: z.record(z.string()).nullable().optional(), + contentType: z.string().nullable().optional(), + contentDisposition: z.string().nullable().optional(), + cid: z.string().nullable().optional(), + encoding: z.string().nullable().optional(), + headers: z.record(z.string()).nullable().optional(), + raw: z.string().nullable().optional(), + }) + .passthrough() + .transform((data) => { + // Only keep properties that are defined in the schema + const validKeys = [ + "filename", + "content", + "path", + "href", + "httpHeaders", + "contentType", + "contentDisposition", + "cid", + "encoding", + "headers", + "raw", + ]; + return Object.fromEntries( + Object.entries(data).filter(([key]) => validKeys.includes(key)) + ); + }); + +export const attachmentsSchema = z + .array(attachmentSchema) + .optional() + .transform((attachments) => + attachments + ? attachments.filter((attachment) => Object.keys(attachment).length > 0) + : undefined + ); + /** * Base schema for email message content. */ const baseMessageSchema = z.object({ subject: z.string().optional(), - text: z.string().optional(), - html: z.string().optional(), - attachments: z.array(z.any()).optional(), + text: z.string().nullable().optional(), + html: z.string().nullable().optional(), + attachments: attachmentsSchema, }); /** From 282426faec8b9ea7163544516243fa32985b4476 Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Fri, 16 May 2025 14:33:34 +0100 Subject: [PATCH 6/8] chore(firestore-send-email): regen package lock --- .../functions/package-lock.json | 1909 ++++++++--------- 1 file changed, 904 insertions(+), 1005 deletions(-) diff --git a/firestore-send-email/functions/package-lock.json b/firestore-send-email/functions/package-lock.json index 9754fb1c8..94e91b416 100644 --- a/firestore-send-email/functions/package-lock.json +++ b/firestore-send-email/functions/package-lock.json @@ -32,57 +32,57 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.2.tgz", + "integrity": "sha512-TUtMJYRPyUb/9aU8f3K0mjmjf6M9N5Woshn2CS6nqJSeJtTtQcpLUXjGt9vbF8ZGff0El99sWkLgzwW3VXnxZQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz", - "integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.1.tgz", + "integrity": "sha512-IaaGWsQqfsQWVLqMn9OB92MNN7zukfVA4s7KKAI0KfrrDsZ0yhi5uV4baBuLuN7n3vsZpwP8asPPcVwApxvjBQ==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.24.4", - "@babel/parser": "^7.24.4", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.1", - "@babel/types": "^7.24.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helpers": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -97,147 +97,83 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", - "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "node_modules/@babel/core/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" + "ms": "^2.1.3" }, "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" + "node": ">=6.0" }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "node_modules/@babel/generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.1.tgz", + "integrity": "sha512-UnJfnIpc/+JO0/+KRVQNGU+y5taA5vCbwN8+azkX6beii/ZF+enZJSOKo11ZSzGJjlNfJHfQtmQT8H+9TXPG2w==", "dev": true, "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@babel/parser": "^7.27.1", + "@babel/types": "^7.27.1", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, "dependencies": { - "@babel/types": "^7.22.5" + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "dependencies": { - "@babel/types": "^7.24.0" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz", - "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.1.tgz", + "integrity": "sha512-9yHn519/8KvTU5BjTVEEeIM3w9/2yXNKoD82JifINImhpKkARMJKPP59kLo+BafpdN5zgNeIcS4jsGDmd3l58g==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -247,85 +183,61 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", - "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", - "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.1.tgz", + "integrity": "sha512-FCvFTm0sWV8Fxhpp2McP5/W53GPllQ9QeQ7SiqGWjMf/LVG07lFa5+pgK05IRhVwtvafT22KF+ZSnM9I545CvQ==", "dev": true, "dependencies": { - "@babel/template": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", - "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.2.tgz", + "integrity": "sha512-QYLs8299NA7WM/bZAdp+CviYYkVoYXlDW2rzliy3chxd1PQjej7JORuMJDJXJUb9g0TT+B99EwaVLKmX+sPXWw==", "dev": true, "dependencies": { - "@babel/types": "^7.27.0" + "@babel/types": "^7.27.1" }, "bin": { "parser": "bin/babel-parser.js" @@ -370,6 +282,36 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-import-meta": { "version": "7.10.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", @@ -395,12 +337,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz", - "integrity": "sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -481,6 +423,21 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-top-level-await": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", @@ -497,12 +454,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz", - "integrity": "sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -511,34 +468,40 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.1.tgz", + "integrity": "sha512-1x3D2xEk2fRo3PAhwQwu5UubzgiVWSXTBfWpVd2Mx2AzRqJuDJCsgaDVZ7HB5iGzDW1Hl1sWN2mFyKjmR9uAog==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", - "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.27.0", - "@babel/types": "^7.27.0" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz", - "integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.1", - "@babel/generator": "^7.24.1", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.24.1", - "@babel/types": "^7.24.0", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.1.tgz", + "integrity": "sha512-ZCYtZciz1IWJB4U61UPu4KEaqyfj+r5T1Q5mqPo+IBpcG9kHv30Z0aD8LXPgC1trYa6rK0orRyAhqUgk4MjmEg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.1", + "@babel/parser": "^7.27.1", + "@babel/template": "^7.27.1", + "@babel/types": "^7.27.1", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -546,14 +509,37 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, "node_modules/@babel/types": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", - "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", + "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -586,11 +572,11 @@ "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==" }, "node_modules/@firebase/component": { - "version": "0.6.13", - "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.13.tgz", - "integrity": "sha512-I/Eg1NpAtZ8AAfq8mpdfXnuUpcLxIDdCDtTzWSh+FXnp/9eCKJ3SNbOCKrUCyhLzNa2SiPJYruei0sxVjaOTeg==", + "version": "0.6.16", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.6.16.tgz", + "integrity": "sha512-whx+e3pgC3J9O6t4LOB8jiLk3tpWtnXaQ+xt/ys/4IGUPRI+nnWooVdtWrEnMga/gT03ug9SdEAEJLl6I1BIlg==", "dependencies": { - "@firebase/util": "1.11.0", + "@firebase/util": "1.11.3", "tslib": "^2.1.0" }, "engines": { @@ -598,15 +584,15 @@ } }, "node_modules/@firebase/database": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.14.tgz", - "integrity": "sha512-9nxYtkHAG02/Nh2Ssms1T4BbWPPjiwohCvkHDUl4hNxnki1kPgsLo5xe9kXNzbacOStmVys+RUXvwzynQSKmUQ==", + "version": "1.0.17", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.0.17.tgz", + "integrity": "sha512-CUUsegGubS90/QkZ4sO84SgoJlnYOCaArVl6CG8aTSuTJoEAoD8elVwR02aPM80m0GOFM6NBT7B+ayK7jeVmMA==", "dependencies": { "@firebase/app-check-interop-types": "0.3.3", "@firebase/auth-interop-types": "0.2.4", - "@firebase/component": "0.6.13", + "@firebase/component": "0.6.16", "@firebase/logger": "0.4.4", - "@firebase/util": "1.11.0", + "@firebase/util": "1.11.3", "faye-websocket": "0.11.4", "tslib": "^2.1.0" }, @@ -615,15 +601,15 @@ } }, "node_modules/@firebase/database-compat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.5.tgz", - "integrity": "sha512-CNf1UbvWh6qIaSf4sn6sx2DTDz/em/D7QxULH1LTxxDQHr9+CeYGvlAqrKnk4ZH0P0eIHyQFQU7RwkUJI0B9gQ==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.0.8.tgz", + "integrity": "sha512-GsopZGu8SefAUHtdh+1HL10TcpuBmXCz7RRJ1iPP9sbkF0vWHu5eYpkqKzaZ687EyS0SG03o2rno7JIwm1hbYQ==", "dependencies": { - "@firebase/component": "0.6.13", - "@firebase/database": "1.0.14", - "@firebase/database-types": "1.0.10", + "@firebase/component": "0.6.16", + "@firebase/database": "1.0.17", + "@firebase/database-types": "1.0.13", "@firebase/logger": "0.4.4", - "@firebase/util": "1.11.0", + "@firebase/util": "1.11.3", "tslib": "^2.1.0" }, "engines": { @@ -631,12 +617,12 @@ } }, "node_modules/@firebase/database-types": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.10.tgz", - "integrity": "sha512-mH6RC1E9/Pv8jf1/p+M8YFTX+iu+iHDN89hecvyO7wHrI4R1V0TXjxOHvX3nLJN1sfh0CWG6CHZ0VlrSmK/cwg==", + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.13.tgz", + "integrity": "sha512-HoMVmHNLNEmSe55XMKXYbfAaie21h++G7gxhIttj330yPlW+RgG00CLedpmQvaqfEHEvh+6eUjddtJ/ezm1x2w==", "dependencies": { "@firebase/app-types": "0.9.3", - "@firebase/util": "1.11.0" + "@firebase/util": "1.11.3" } }, "node_modules/@firebase/logger": { @@ -651,9 +637,9 @@ } }, "node_modules/@firebase/util": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.11.0.tgz", - "integrity": "sha512-PzSrhIr++KI6y4P6C/IdgBNMkEx0Ex6554/cYd0Hm+ovyFSJtJXqb/3OSIdnBoa2cpwZT1/GW56EmRc5qEc5fQ==", + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.11.3.tgz", + "integrity": "sha512-4wYnOV9FpwdCq3rHQOCrdx4AQBUbfH1p2DhWGQxlQ+D3Xl/wSxc/HttcyPN4NNFiynxoNCFGWQH/zdhRfxP1Zg==", "hasInstallScript": true, "dependencies": { "tslib": "^2.1.0" @@ -663,9 +649,9 @@ } }, "node_modules/@google-cloud/firestore": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.0.tgz", - "integrity": "sha512-88uZ+jLsp1aVMj7gh3EKYH1aulTAMFAp8sH/v5a9w8q8iqSG27RiWLoxSAFr/XocZ9hGiWH1kEnBw+zl3xAgNA==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@google-cloud/firestore/-/firestore-7.11.1.tgz", + "integrity": "sha512-ZxOdH8Wr01hBDvKCQfMWqwUcfNcN3JY19k1LtS1fTFhEyorYPLsbWN+VxIRL46pOYGHTPkU3Or5HbT/SLQM5nA==", "optional": true, "dependencies": { "@opentelemetry/api": "^1.3.0", @@ -877,21 +863,6 @@ } } }, - "node_modules/@jest/core/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, "node_modules/@jest/environment": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", @@ -1007,48 +978,6 @@ } } }, - "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -1131,12 +1060,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/transform/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, "node_modules/@jest/types": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", @@ -1155,22 +1078,23 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "engines": { "node": ">=6.0.0" @@ -1186,9 +1110,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { @@ -1275,13 +1199,12 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@sendgrid/client": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.4.tgz", - "integrity": "sha512-VxZoQ82MpxmjSXLR3ZAE2OWxvQIW2k2G24UeRPr/SYX8HqWLV/8UBN15T2WmjjnEb5XSmFImTJOKDzzSeKr9YQ==", - "license": "MIT", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.5.tgz", + "integrity": "sha512-Jqt8aAuGIpWGa15ZorTWI46q9gbaIdQFA21HIPQQl60rCjzAko75l3D1z7EyjFrNr4MfQ0StusivWh8Rjh10Cg==", "dependencies": { "@sendgrid/helpers": "^8.0.0", - "axios": "^1.7.4" + "axios": "^1.8.2" }, "engines": { "node": ">=12.*" @@ -1291,7 +1214,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz", "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==", - "license": "MIT", "dependencies": { "deepmerge": "^4.2.2" }, @@ -1300,12 +1222,11 @@ } }, "node_modules/@sendgrid/mail": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.4.tgz", - "integrity": "sha512-MUpIZykD9ARie8LElYCqbcBhGGMaA/E6I7fEcG7Hc2An26QJyLtwOaKQ3taGp8xO8BICPJrSKuYV4bDeAJKFGQ==", - "license": "MIT", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.5.tgz", + "integrity": "sha512-W+YuMnkVs4+HA/bgfto4VHKcPKLc7NiZ50/NH2pzO6UHCCFuq8/GNB98YJlLEr/ESDyzAaDr7lVE7hoBwFTT3Q==", "dependencies": { - "@sendgrid/client": "^8.1.4", + "@sendgrid/client": "^8.1.5", "@sendgrid/helpers": "^8.0.0" }, "engines": { @@ -1313,9 +1234,9 @@ } }, "node_modules/@sideway/address": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", - "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", "dependencies": { "@hapi/hoek": "^9.0.0" } @@ -1377,9 +1298,9 @@ } }, "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", "dev": true, "dependencies": { "@babel/types": "^7.0.0" @@ -1396,9 +1317,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz", - "integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==", + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" @@ -1428,9 +1349,9 @@ } }, "node_modules/@types/cors": { - "version": "2.8.13", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.13.tgz", - "integrity": "sha512-RG8AStHlUiV5ysZQKq97copd2UmVYw3/pRMLefISZ3S1hK104Cwm7iLQ3fTKx+lsUH2CE8FlLaYeEA2LSeqYUA==", + "version": "2.8.18", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.18.tgz", + "integrity": "sha512-nX3d0sxJW41CqQvfOzVG1NCTXfFDrDWIghCZncpHeWlVFd81zxB/DLhg7avFg6eHLCRX7ckBmoIIcqa++upvJA==", "dependencies": { "@types/node": "*" } @@ -1482,15 +1403,15 @@ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" }, "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", "dev": true }, "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", "dev": true, "dependencies": { "@types/istanbul-lib-coverage": "*" @@ -1525,9 +1446,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.14.191", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", - "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==", + "version": "4.17.16", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.16.tgz", + "integrity": "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==", "dev": true }, "node_modules/@types/long": { @@ -1547,17 +1468,17 @@ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" }, "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "version": "20.17.47", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.47.tgz", + "integrity": "sha512-3dLX0Upo1v7RvUimvxLeXqwrfyKxUINk0EAM83swP2mlSUcwV73sZy8XhNz8bcZ3VbsfQyC/y6jRdL5tgCNpDQ==", "dependencies": { - "undici-types": "~5.26.4" + "undici-types": "~6.19.2" } }, "node_modules/@types/nodemailer": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.7.tgz", - "integrity": "sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg==", + "version": "6.4.17", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.17.tgz", + "integrity": "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==", "dependencies": { "@types/node": "*" } @@ -1572,14 +1493,14 @@ } }, "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==" }, "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" }, "node_modules/@types/request": { "version": "2.48.12", @@ -1641,18 +1562,18 @@ "optional": true }, "node_modules/@types/yargs": { - "version": "17.0.32", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", - "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "21.0.0", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", - "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, "node_modules/abort-controller": { @@ -1739,6 +1660,15 @@ "node": ">= 8" } }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -1768,9 +1698,9 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, "node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.9.0.tgz", + "integrity": "sha512-re4CqKTJaURpzbLHtIi6XpDv20/CnpXOtjRY5/CU32L8gU8ek9UIivcfvSWvmKEngmVbrUtPpdDwWDWL7DNHvg==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -1830,15 +1760,6 @@ "node": ">=8" } }, - "node_modules/babel-plugin-istanbul/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/babel-plugin-jest-hoist": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", @@ -1855,23 +1776,26 @@ } }, "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", "dev": true, "dependencies": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-top-level-await": "^7.8.3" + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -1937,7 +1861,6 @@ "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", - "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -1957,27 +1880,20 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/body-parser/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { - "ms": "2.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, - "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -1986,9 +1902,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.24.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.5.tgz", + "integrity": "sha512-FDToo4Wo82hIdgc1CQ+NQD0hEhmpPjrZ3hiUgwgOG6IuTdlpr8jdjyG24P6cNP1yJpTLzS5OcGgSw0xmDU1/Tw==", "dev": true, "funding": [ { @@ -2005,10 +1921,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001716", + "electron-to-chromium": "^1.5.149", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -2053,16 +1969,14 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", - "license": "MIT", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -2072,13 +1986,12 @@ } }, "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", - "license": "MIT", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -2106,9 +2019,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001610", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001610.tgz", - "integrity": "sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==", + "version": "1.0.30001718", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001718.tgz", + "integrity": "sha512-AflseV1ahcSunK53NfEs9gFWgOEmzr0f+kaMFA4xiLZlr9Hzt7HxcSpIFcnNCUkz6R6dWKa54rUz3HUmI3nVcw==", "dev": true, "funding": [ { @@ -2141,6 +2054,18 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", @@ -2159,10 +2084,25 @@ "node": ">= 0.8.0" } }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, "node_modules/cjs-module-lexer": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", - "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", "dev": true }, "node_modules/cliui": { @@ -2256,21 +2196,6 @@ "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/concurrently/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -2286,16 +2211,20 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", "engines": { "node": ">= 0.6" } }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/cookie": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2343,7 +2272,6 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, - "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -2354,10 +2282,13 @@ } }, "node_modules/date-fns": { - "version": "2.29.3", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", - "integrity": "sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==", + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", "dev": true, + "dependencies": { + "@babel/runtime": "^7.21.0" + }, "engines": { "node": ">=0.11" }, @@ -2367,25 +2298,17 @@ } }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "ms": "2.0.0" } }, "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", "dev": true, "peerDependencies": { "babel-plugin-macros": "^3.1.0" @@ -2397,9 +2320,9 @@ } }, "node_modules/deepmerge": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", - "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "engines": { "node": ">=0.10.0" } @@ -2416,7 +2339,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -2425,7 +2347,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", - "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -2453,7 +2374,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -2486,13 +2406,12 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", - "license": "MIT" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.736", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.736.tgz", - "integrity": "sha512-Rer6wc3ynLelKNM4lOCg7/zPQj8tPOCB2hzD32PX9wd3hgRRi9MxEbmkFCokzcEhRVMiOVLjnL9ig9cefJ+6+Q==", + "version": "1.5.155", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.155.tgz", + "integrity": "sha512-ps5KcGGmwL8VaeJlvlDlu4fORQpv3+GIcF5I3f9tUKUlJ/wsysh6HU8P5L1XWRYeXfA0oJd4PyM8ds8zTFf6Ng==", "dev": true }, "node_modules/emittery": { @@ -2517,7 +2436,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -2544,7 +2462,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "license": "MIT", "engines": { "node": ">= 0.4" } @@ -2553,16 +2470,14 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "license": "MIT", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "dependencies": { "es-errors": "^1.3.0" }, @@ -2574,7 +2489,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "optional": true, "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -2586,9 +2500,9 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "devOptional": true, "engines": { "node": ">=6" @@ -2597,8 +2511,7 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", - "license": "MIT" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" }, "node_modules/escape-string-regexp": { "version": "2.0.0", @@ -2626,7 +2539,6 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -2640,6 +2552,29 @@ "node": ">=6" } }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -2669,7 +2604,6 @@ "version": "4.21.2", "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", - "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", @@ -2711,19 +2645,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/express/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2792,7 +2713,6 @@ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, - "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2804,7 +2724,6 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", - "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~2.0.0", @@ -2818,21 +2737,6 @@ "node": ">= 0.8" } }, - "node_modules/finalhandler/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -2847,9 +2751,9 @@ } }, "node_modules/firebase-admin": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.2.0.tgz", - "integrity": "sha512-qQBTKo0QWCDaWwISry989pr8YfZSSk00rNCKaucjOgltEm3cCYzEe4rODqBd1uUwma+Iu5jtAzg89Nfsjr3fGg==", + "version": "13.4.0", + "resolved": "https://registry.npmjs.org/firebase-admin/-/firebase-admin-13.4.0.tgz", + "integrity": "sha512-Y8DcyKK+4pl4B93ooiy1G8qvdyRMkcNFfBSh+8rbVcw4cW8dgG0VXCCTp5NUwub8sn9vSPsOwpb9tE2OuFmcfQ==", "dependencies": { "@fastify/busboy": "^3.0.0", "@firebase/database-compat": "^2.0.0", @@ -2871,9 +2775,9 @@ } }, "node_modules/firebase-admin/node_modules/@types/node": { - "version": "22.14.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", - "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", + "version": "22.15.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.18.tgz", + "integrity": "sha512-v1DKRfUdyW+jJhZNEI1PYy29S2YRxMV5AOO/x/SjKmW0acCIOqmbj6Haf9eHAhsPmrhlHSxEhv/1WszcLWV4cg==", "dependencies": { "undici-types": "~6.21.0" } @@ -2922,9 +2826,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", @@ -2941,12 +2845,13 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" }, "engines": { @@ -2965,7 +2870,6 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -3062,21 +2966,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", - "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", - "license": "MIT", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "dunder-proto": "^1.0.0", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "math-intrinsics": "^1.0.0" + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3094,6 +2997,50 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -3120,9 +3067,9 @@ } }, "node_modules/google-gax": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.6.0.tgz", - "integrity": "sha512-zKKLeLfcYBVOzzM48Brtn4EQkKcTli9w6c1ilzFK2NbJvcd4ATD8/XqFExImvE/W5IwMlKKwa5qqVufji3ioNQ==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/google-gax/-/google-gax-4.6.1.tgz", + "integrity": "sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ==", "optional": true, "dependencies": { "@grpc/grpc-js": "^1.10.9", @@ -3167,7 +3114,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3176,9 +3122,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/gtoken": { @@ -3194,12 +3140,12 @@ } }, "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -3213,18 +3159,6 @@ "uglify-js": "^3.1.4" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -3238,7 +3172,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3250,7 +3183,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "optional": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -3265,7 +3197,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -3299,7 +3230,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -3342,6 +3272,29 @@ "node": ">= 6.0.0" } }, + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "optional": true + }, "node_modules/https-proxy-agent": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", @@ -3354,6 +3307,27 @@ "node": ">= 14" } }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -3367,7 +3341,6 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -3376,9 +3349,9 @@ } }, "node_modules/import-local": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", - "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "dependencies": { "pkg-dir": "^4.2.0", @@ -3407,6 +3380,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "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.", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3437,12 +3411,15 @@ "dev": true }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3471,7 +3448,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -3491,8 +3467,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" + "dev": true }, "node_modules/istanbul-lib-coverage": { "version": "3.2.2", @@ -3504,9 +3479,9 @@ } }, "node_modules/istanbul-lib-instrument": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.2.tgz", - "integrity": "sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "dependencies": { "@babel/core": "^7.23.9", @@ -3519,6 +3494,18 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/istanbul-lib-report": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", @@ -3533,6 +3520,18 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/istanbul-lib-source-maps": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", @@ -3547,6 +3546,29 @@ "node": ">=10" } }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, "node_modules/istanbul-reports": { "version": "3.1.7", "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", @@ -3600,53 +3622,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-changed-files/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/jest-changed-files/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-changed-files/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/jest-circus": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", @@ -3756,63 +3731,6 @@ } } }, - "node_modules/jest-config/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/jest-config/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-config/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-config/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -4093,48 +4011,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-runtime/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/jest-snapshot": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", @@ -4166,6 +4042,18 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -4183,21 +4071,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-util/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, "node_modules/jest-validate": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", @@ -4261,29 +4134,14 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/joi": { - "version": "17.11.0", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.11.0.tgz", - "integrity": "sha512-NgB+lZLNoqISVy1rZocE9PZI36bL/77ie924Ri43yEvi9GUUMPeyVIr8KdFTMUlby1p0PBYMk9spIxEUQYqrJQ==", + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", "dependencies": { - "@hapi/hoek": "^9.0.0", - "@hapi/topo": "^5.0.0", - "@sideway/address": "^4.1.3", + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } @@ -4315,25 +4173,16 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/js-yaml/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, "node_modules/json-bigint": { @@ -4363,14 +4212,20 @@ } }, "node_modules/jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", "dependencies": { "jws": "^3.2.2", - "lodash": "^4.17.21", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", "ms": "^2.1.1", - "semver": "^7.3.8" + "semver": "^7.5.4" }, "engines": { "node": ">=12", @@ -4378,11 +4233,11 @@ } }, "node_modules/jsonwebtoken/node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", "dependencies": { - "buffer-equal-constant-time": "1.0.1", + "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } @@ -4396,12 +4251,28 @@ "safe-buffer": "^5.0.1" } }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jwa": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", - "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz", + "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==", "dependencies": { - "buffer-equal-constant-time": "1.0.1", + "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } @@ -4422,6 +4293,27 @@ "node": ">=14" } }, + "node_modules/jwks-rsa/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/jwks-rsa/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/jws": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", @@ -4497,26 +4389,59 @@ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, "node_modules/long": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", - "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==" }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "yallist": "^3.0.2" } }, "node_modules/lru-memoizer": { @@ -4528,6 +4453,22 @@ "lru-cache": "6.0.0" } }, + "node_modules/lru-memoizer/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru-memoizer/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -4543,6 +4484,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -4562,7 +4515,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", "engines": { "node": ">= 0.4" } @@ -4571,7 +4523,6 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -4580,7 +4531,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", - "license": "MIT", "funding": { "url": "https://github.com/sponsors/sindresorhus" } @@ -4604,7 +4554,6 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, - "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -4653,6 +4602,17 @@ "node": ">=6" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -4693,10 +4653,16 @@ } } }, - "node_modules/ms": { + "node_modules/mocked-env/node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -4751,15 +4717,15 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true }, "node_modules/nodemailer": { - "version": "6.9.13", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.13.tgz", - "integrity": "sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==", + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.1.tgz", + "integrity": "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==", "engines": { "node": ">=6.0.0" } @@ -4773,6 +4739,18 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4791,10 +4769,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", - "license": "MIT", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "engines": { "node": ">= 0.4" }, @@ -4806,7 +4783,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", - "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -4910,7 +4886,6 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -4937,7 +4912,6 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -4951,13 +4925,12 @@ "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", - "license": "MIT" + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "node_modules/picomatch": { @@ -4973,9 +4946,9 @@ } }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", "dev": true, "engines": { "node": ">= 6" @@ -5045,9 +5018,9 @@ } }, "node_modules/protobufjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.0.tgz", - "integrity": "sha512-Z2E/kOY1QjoMlCytmexzYfDm/w5fKAiRwpSzGtdnXW1zC88Z2yXazHHrOtwCzn+7wSxyE8PYM4rvVcMphF9sOA==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.2.tgz", + "integrity": "sha512-f2ls6rpO6G153Cy+o2XQ+Y0sARLOZ17+OGVLHrc3VUKcLHYKEKWbkSujdBWQXM7gKn5NTfp0XnRPZn1MIu8n9w==", "hasInstallScript": true, "dependencies": { "@protobufjs/aspromise": "^1.1.2", @@ -5084,10 +5057,10 @@ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" }, - "node_modules/punycode": { + "node_modules/punycode.js": { "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "engines": { "node": ">=6" } @@ -5112,7 +5085,6 @@ "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.6" }, @@ -5133,7 +5105,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5142,7 +5113,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -5154,9 +5124,9 @@ } }, "node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", "dev": true }, "node_modules/readable-stream": { @@ -5183,18 +5153,21 @@ } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5221,9 +5194,9 @@ } }, "node_modules/resolve.exports": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", - "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", "dev": true, "engines": { "node": ">=10" @@ -5256,6 +5229,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dependencies": { "glob": "^7.1.3" }, @@ -5263,49 +5237,10 @@ "rimraf": "bin.js" } }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "dependencies": { "tslib": "^2.1.0" } @@ -5335,24 +5270,18 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/send": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", - "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -5372,26 +5301,10 @@ "node": ">= 0.8.0" } }, - "node_modules/send/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/send/node_modules/debug/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, "node_modules/send/node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -5400,7 +5313,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "license": "MIT", "bin": { "mime": "cli.js" }, @@ -5411,14 +5323,12 @@ "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", - "license": "MIT", "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", @@ -5432,15 +5342,13 @@ "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", - "license": "ISC" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -5453,16 +5361,18 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shell-quote": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.0.tgz", - "integrity": "sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", + "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", "dev": true, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -5471,7 +5381,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", @@ -5490,7 +5399,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" @@ -5506,7 +5414,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -5524,7 +5431,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "license": "MIT", "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", @@ -5561,19 +5467,27 @@ } }, "node_modules/smtp-server": { - "version": "3.13.4", - "resolved": "https://registry.npmjs.org/smtp-server/-/smtp-server-3.13.4.tgz", - "integrity": "sha512-BbElv5UP+HgPtCZtcRW35N/GFoc4DzPkrbSMLioXsrVMmQT1mMBoO0k+egl264hxWaWczoVvadSPY2pLUINFXg==", + "version": "3.13.6", + "resolved": "https://registry.npmjs.org/smtp-server/-/smtp-server-3.13.6.tgz", + "integrity": "sha512-dqbSPKn3PCq3Gp5hxBM99u7PET7cQSAWrauhtArJbc+zrf5xNEOjm9+Ob3lySySrRoIEvNE0dz+w2H/xWFJNRw==", "dependencies": { "base32.js": "0.1.0", "ipv6-normalize": "1.0.1", - "nodemailer": "6.9.13", - "punycode": "2.3.1" + "nodemailer": "6.9.15", + "punycode.js": "2.3.1" }, "engines": { "node": ">=12.0.0" } }, + "node_modules/smtp-server/node_modules/nodemailer": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", + "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -5593,9 +5507,9 @@ } }, "node_modules/spawn-command": { - "version": "0.0.2-1", - "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", - "integrity": "sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==", + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2.tgz", + "integrity": "sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==", "dev": true }, "node_modules/sprintf-js": { @@ -5620,7 +5534,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "license": "MIT", "engines": { "node": ">= 0.8" } @@ -5737,15 +5650,18 @@ "optional": true }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { "has-flag": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -5788,6 +5704,23 @@ "node": ">= 6.0.0" } }, + "node_modules/teeny-request/node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "optional": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, "node_modules/teeny-request/node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -5801,6 +5734,12 @@ "node": ">= 6" } }, + "node_modules/teeny-request/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "optional": true + }, "node_modules/teeny-request/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -5828,48 +5767,6 @@ "node": ">=8" } }, - "node_modules/test-exclude/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/test-exclude/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -5881,7 +5778,6 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -5893,7 +5789,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "license": "MIT", "engines": { "node": ">=0.6" } @@ -5955,10 +5850,22 @@ } } }, + "node_modules/ts-jest/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" }, "node_modules/type-detect": { "version": "4.0.8", @@ -5985,7 +5892,6 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -6007,9 +5913,9 @@ } }, "node_modules/uglify-js": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", - "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -6019,23 +5925,22 @@ } }, "node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", - "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "funding": [ { @@ -6052,8 +5957,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -6089,9 +5994,9 @@ } }, "node_modules/v8-to-istanbul": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", - "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", @@ -6102,12 +6007,6 @@ "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", @@ -6183,7 +6082,6 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, - "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -6244,9 +6142,10 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yargs": { "version": "17.7.2", From be0b4cb194f1ad5bbb39486b931495272586c66b Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Fri, 16 May 2025 14:44:11 +0100 Subject: [PATCH 7/8] chore(firestore-bigquery-export): regen package locks --- .../scripts/gen-schema-view/package-lock.json | 4 ++-- firestore-bigquery-export/scripts/import/package-lock.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/firestore-bigquery-export/scripts/gen-schema-view/package-lock.json b/firestore-bigquery-export/scripts/gen-schema-view/package-lock.json index 7374ea4f8..a221ced25 100644 --- a/firestore-bigquery-export/scripts/gen-schema-view/package-lock.json +++ b/firestore-bigquery-export/scripts/gen-schema-view/package-lock.json @@ -1,12 +1,12 @@ { "name": "@firebaseextensions/fs-bq-schema-views", - "version": "0.4.10", + "version": "0.4.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@firebaseextensions/fs-bq-schema-views", - "version": "0.4.10", + "version": "0.4.11", "license": "Apache-2.0", "dependencies": { "@firebaseextensions/firestore-bigquery-change-tracker": "^1.1.40", diff --git a/firestore-bigquery-export/scripts/import/package-lock.json b/firestore-bigquery-export/scripts/import/package-lock.json index 8403f7b7f..42dcb2973 100644 --- a/firestore-bigquery-export/scripts/import/package-lock.json +++ b/firestore-bigquery-export/scripts/import/package-lock.json @@ -1,12 +1,12 @@ { "name": "@firebaseextensions/fs-bq-import-collection", - "version": "0.1.23", + "version": "0.1.24", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@firebaseextensions/fs-bq-import-collection", - "version": "0.1.23", + "version": "0.1.24", "license": "Apache-2.0", "dependencies": { "@firebaseextensions/firestore-bigquery-change-tracker": "^1.1.40", From 509247b52ef4e2a56e9d8de44a52fc2214540532 Mon Sep 17 00:00:00 2001 From: Jacob Cable Date: Fri, 16 May 2025 16:43:29 +0100 Subject: [PATCH 8/8] chore(*): trigger kokoro --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8107f00b2..6fce1b15f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Firebase Extensions -This repository contains the source for Firebase Extensions. Created and tested by Firebase, these official Firebase extensions are reliable and secure. To learn more about Firebase Extensions, including how to install them in your Firebase projects, visit the [Firebase documentation](https://firebase.google.com/docs/extensions). +This repository contains the source for Firebase Extensions. Created and tested by Firebase, these official Firebase extensions are reliable and secure. + +To learn more about Firebase Extensions, including how to install them in your Firebase projects, visit the [Firebase documentation](https://firebase.google.com/docs/extensions). Each directory in this repo contains the source code for the extension and a README to explain how the extension works, including information about the APIs enabled, resources created, and the access granted to the extension.