diff --git a/components/CollectiveAddress.js b/components/CollectiveAddress.js index 5fa5557e..504f2c7c 100644 --- a/components/CollectiveAddress.js +++ b/components/CollectiveAddress.js @@ -1,17 +1,15 @@ import React from 'react'; import PropTypes from 'prop-types'; import { get } from 'lodash'; -import countries from 'i18n-iso-countries'; -import countriesEN from 'i18n-iso-countries/langs/en.json'; -countries.registerLocale(countriesEN); +import { getCountryName } from '../lib/i18n'; /** * Pretty render a location (multiline) */ const CollectiveAddress = ({ collective, fallBackOnHostAddress }) => { const countryISO = get(collective, 'location.country'); - const country = countryISO && (countries.getName(countryISO, 'en') || countryISO); + const country = countryISO && (getCountryName(countryISO) || countryISO); let address = get(collective, 'location.address'); if (!address && fallBackOnHostAddress) { address = get(collective, 'host.location.address'); diff --git a/lib/i18n.ts b/lib/i18n.ts new file mode 100644 index 00000000..a85e2252 --- /dev/null +++ b/lib/i18n.ts @@ -0,0 +1,8 @@ +import countries from 'i18n-iso-countries'; +import countriesEN from 'i18n-iso-countries/langs/en.json'; + +countries.registerLocale(countriesEN); + +export const getCountryName = (code: string) => { + return countries.getName(code, 'en'); +}; diff --git a/lib/math.ts b/lib/math.ts new file mode 100644 index 00000000..93a29e59 --- /dev/null +++ b/lib/math.ts @@ -0,0 +1,19 @@ +import { clamp } from 'lodash'; + +/** + * Generates a scaling function from transforming a number from one range to another. + * @param range1 The original range. + * @param range2 The target range. + * @returns A function that takes a number from range1 and returns the equivalent in range2. + * + * @example + */ +export function scaleValue( + value: number, + [initialMin, initialMax]: [number, number], + [targetMin, targetMax]: [number, number], + shouldClamp = false, +) { + const result = ((value - initialMin) * (targetMax - targetMin)) / (initialMax - initialMin) + targetMin; + return shouldClamp ? clamp(result, targetMin, targetMax) : result; +} diff --git a/lib/pdf-lib-utils.ts b/lib/pdf-lib-utils.ts new file mode 100644 index 00000000..111d2400 --- /dev/null +++ b/lib/pdf-lib-utils.ts @@ -0,0 +1,261 @@ +import fs from 'fs'; +import { get, isNil } from 'lodash'; +import { scaleValue } from './math'; +import fontkit from 'pdf-fontkit'; +import { PDFDocument, PDFField, PDFFont, PDFForm, PDFHexString, PDFTextField, TextAlignment } from 'pdf-lib'; +import { allCharsValid } from './string-utils'; + +const SIGNATURE_FONT_BYTES = fs.readFileSync('resources/fonts/JustMeAgainDownHere-Regular.ttf'); + +export const logAllFieldsFromPDFForm = (pdfForm) => { + for (const field of pdfForm.getFields()) { + if (field.constructor.name === 'PDFTextField') { + console.log(`${field.constructor.name}: ${field.getName()}`); + } else { + console.log(`${field.constructor.name}: ${field.getName()}`); + } + } +}; + +const truncateMiddle = (str, limit) => { + if (!limit) { + return str; + } else if (str.length <= limit) { + return str; + } else { + limit -= 1; // For the ellipsis + const frontChars = Math.ceil(limit / 2); + const backChars = Math.floor(limit / 2); + return `${str.slice(0, frontChars)}…${str.slice(-backChars)}`; + } +}; + +/** + * A development helper that makes it easy to identify all fields in a PDF form by filling them with + * their own names. + */ +export const fillAllFieldsFromPDFFormWithPath = (pdfForm) => { + for (const field of pdfForm.getFields()) { + if (field.constructor.name === 'PDFTextField') { + const maxLength = field.getMaxLength(); + field.setText(truncateMiddle(field.getName(), maxLength)); + } + } +}; + +/** + * Gets the font size for the signature. The longer the text, the smaller the font. + */ +const getSignatureSize = (text: string): number => { + const maxTextLength = 60; // This is not the real max length (as defined in `components/dashboard/sections/tax-information/common.ts`), but the length that corresponds to the minimum font size. + return scaleValue(maxTextLength - text.length, [0, maxTextLength], [4, 26], true); +}; + +/** + * Generate a signature at the specified position. + */ +export const addSignature = async (pdfDoc: PDFDocument, signerFullName, { page = 0, x, y, fallbackFont }) => { + pdfDoc.registerFontkit(fontkit); + let signatureFont = await pdfDoc.embedFont(SIGNATURE_FONT_BYTES, { subset: true }); + let size = getSignatureSize(signerFullName); + + // Handle unsupported characters in signature + const supportedChars = new Set(signatureFont.getCharacterSet()); + if (!allCharsValid(signerFullName, supportedChars)) { + if (allCharsValid(signerFullName, new Set(fallbackFont.getCharacterSet()))) { + signatureFont = fallbackFont; + size = size * 0.7; // Fallback font is bigger + } else { + // Replace unsupported characters with a question mark + for (let i = 0; i < signerFullName.length; i++) { + if (!supportedChars.has(signerFullName.charCodeAt(i))) { + signerFullName = `${signerFullName.slice(0, i)}?${signerFullName.slice(i + 1)}`; + } + } + } + } + + const pdfPage = pdfDoc.getPage(page); + pdfPage.drawText(signerFullName, { x, y, font: signatureFont, size }); +}; + +type FieldTypeCombo = { + type: 'combo'; + values: Record; + if?: (value, allValues) => boolean; + transform?: (value, allValues) => string; +}; + +type AdvancedPDFFieldDefinition = { + formPath: string; + if?: (value, allValues) => boolean; + transform?: (value, allValues) => string; +}; + +type FieldTypeSplitText = { + type: 'split-text'; + if?: (value, allValues) => boolean; + transform?: (value, allValues) => string; + fields: Array<{ + formPath: string; + maxLength: number | 'auto'; + }>; +}; + +type FieldTypeNested = { + type: 'nested'; + if?: (value, allValues) => boolean; + fields: Record; +}; + +type FieldTypeMulti = { + type: 'multi'; + if?: (value, allValues) => boolean; + fields: PDFFieldDefinition[]; +}; + +function isFieldTypeCombo(field: PDFFieldDefinition): field is FieldTypeCombo { + return (field as FieldTypeCombo).type === 'combo'; +} + +function isFieldTypeSplitText(field: PDFFieldDefinition): field is FieldTypeSplitText { + return (field as FieldTypeSplitText).type === 'split-text'; +} + +function isFieldTypeNested(field: PDFFieldDefinition): field is FieldTypeNested { + return (field as FieldTypeNested).type === 'nested'; +} + +function isFieldTypeMulti(field: PDFFieldDefinition): field is FieldTypeMulti { + return (field as FieldTypeMulti).type === 'multi'; +} + +function isTextFormField(field: PDFField): field is PDFTextField { + return field.constructor.name === 'PDFTextField'; +} + +export type PDFFieldDefinition = + /** The simplest type possible: just provide the path to the field in the PDF form. Works with text inputs and checkboxes. */ + | string + /** Adds the ability to pass a transformer */ + | AdvancedPDFFieldDefinition + /** For multi-checkboxes where only one should be checked */ + | FieldTypeCombo + | FieldTypeSplitText + | FieldTypeNested + | FieldTypeMulti; + +/** + * After setting the value for a text field, PDF-Lib updates its appearance (updateAppearances) using the + * default font, Helvetica. This causes the text to be rendered in Helvetica, even if a custom font was set before, which + * can lead to crashes when the text contains characters not supported by Helvetica (e.g. Korean characters). + * + * This function sets the content of a text field using a custom font, mostly by re-implementing the setText method without marking the field as dirty (which would trigger the updateAppearances method). + * If no font is provided, this function will simply call the original setText method. + * + * See https://github.com/Hopding/pdf-lib/issues/205 + */ +function setTextFieldContentWithFont(textField: PDFTextField, content: string, font: PDFFont = null) { + if (!font) { + textField.setText(content); + } else { + textField.disableRichFormatting(); + textField.acroField.setValue(PDFHexString.fromText(content)); + textField.updateAppearances(font); + } +} + +function fillValueForField( + form: PDFForm, + field: PDFFieldDefinition, + value: unknown, + allValues: Values, + font: PDFFont = null, +) { + // Simple field with just the path + if (typeof field === 'string') { + const formField = form.getField(field); + if (isTextFormField(formField)) { + if (value) { + formField.setAlignment(TextAlignment.Left); + setTextFieldContentWithFont(formField, value.toString().trim(), font); + } + } else if (formField.constructor.name === 'PDFCheckBox') { + if (value) { + form.getCheckBox(field).check(); + } + } + return; + } + + // All rich fields support conditional rendering + if (field.if && !field.if(value, allValues)) { + return; + } + + // Render the field + if (isFieldTypeNested(field)) { + for (const [key, nestedField] of Object.entries(field.fields)) { + fillValueForField(form, nestedField, get(value, key), allValues, font); + } + } else if (isFieldTypeMulti(field)) { + for (const subField of field.fields) { + fillValueForField(form, subField, value, allValues, font); + } + } else if (isFieldTypeCombo(field)) { + const transform = field.transform || ((v) => v); + const checkbox = field.values[transform(value, allValues)]; + if (checkbox) { + form.getCheckBox(checkbox).check(); + } + } else if (isFieldTypeSplitText(field)) { + const transformedValue = field.transform ? field.transform(value, allValues) : value; + if (!isNil(transformedValue) && transformedValue !== '') { + let start = 0; + field.fields.forEach(({ formPath, maxLength }) => { + const subField = form.getTextField(formPath); + const end = start + (maxLength === 'auto' ? subField.getMaxLength() : maxLength); + const content = transformedValue.toString().slice(start, end).trim(); + setTextFieldContentWithFont(subField, content, font); + start = end; + }); + } + } else { + const formPath = field.formPath; + const transform = field.transform || ((v) => v); + const transformedValue = transform(value, allValues); + if (transformedValue) { + const formField = form.getTextField(formPath); + formField.setAlignment(TextAlignment.Left); + const content = transformedValue.toString().trim(); + setTextFieldContentWithFont(formField, content, font); + } + } +} + +export function fillPDFFormFromValues( + form: PDFForm, + values: Values, + fields: Partial>, + font: PDFFont, +): void { + for (const [key, fieldDefinitions] of Object.entries(fields)) { + const fieldDefinitionsArray = Array.isArray(fieldDefinitions) ? fieldDefinitions : [fieldDefinitions]; + fieldDefinitionsArray.forEach((field) => { + const value = values[key]; + fillValueForField(form, field, value, values, font); + }); + } +} + +export function flattenForm(form: PDFForm, { useFallbackReadonly = false } = {}): void { + if (!useFallbackReadonly) { + form.flatten(); + } else { + // PDF lib crashes when it tries to flatten W8 (see https://github.com/Hopding/pdf-lib/issues/1347). We manually + // mark all fields as read-only instead. + for (const field of form.getFields()) { + field.enableReadOnly(); + } + } +} diff --git a/lib/string-utils.ts b/lib/string-utils.ts new file mode 100644 index 00000000..4b083c0e --- /dev/null +++ b/lib/string-utils.ts @@ -0,0 +1,11 @@ +/** + * Check if all characters in a string are included in a set of valid characters. + */ +export function allCharsValid(str: string, validChars: Set) { + for (let i = 0; i < str.length; i++) { + if (!validChars.has(str.charCodeAt(i))) { + return false; + } + } + return true; +} diff --git a/lib/tax-forms/frontend-types.ts b/lib/tax-forms/frontend-types.ts new file mode 100644 index 00000000..2cc7877e --- /dev/null +++ b/lib/tax-forms/frontend-types.ts @@ -0,0 +1,240 @@ +// This file is auto-generated by opencollective-frontend/scripts/export-tax-form-types.ts + +export enum TaxFormType { + W9 = 'W9', + W8_BEN = 'W8_BEN', + W8_BEN_E = 'W8_BEN_E', +} + +export enum SubmitterType { + Individual = 'Individual', + Business = 'Business', +} + +export enum FederalTaxClassification { + Individual = 'Individual', + C_Corporation = 'C_Corporation', + S_Corporation = 'S_Corporation', + Partnership = 'Partnership', + TrustEstate = 'TrustEstate', + LimitedLiabilityCompany = 'LimitedLiabilityCompany', + Other = 'Other', +} + +export enum Chapter3Status { + Corporation = 'Corporation', + Partnership = 'Partnership', + SimpleTrust = 'SimpleTrust', + TaxExemptOrganization = 'TaxExemptOrganization', + ComplexTrust = 'ComplexTrust', + ForeignGovernmentControlledEntity = 'ForeignGovernmentControlledEntity', + CentralBankOfIssue = 'CentralBankOfIssue', + PrivateFoundation = 'PrivateFoundation', + Estate = 'Estate', + ForeignGovernmentIntegralPart = 'ForeignGovernmentIntegralPart', + GrantorTrust = 'GrantorTrust', + DisregardedEntity = 'DisregardedEntity', + InternationalOrganization = 'InternationalOrganization', +} + +export enum TypeOfLimitationOnBenefitsProvisions { + Government = 'Government', + TaxExemptPensionTrustOrPensionFund = 'TaxExemptPensionTrustOrPensionFund', + OtherTaxExemptOrganization = 'OtherTaxExemptOrganization', + PubliclyTradedCorporation = 'PubliclyTradedCorporation', + SubsidiaryOfAPubliclyTradedCorporation = 'SubsidiaryOfAPubliclyTradedCorporation', + CompanyThatMeetsTheOwnershipAndBaseErosionTest = 'CompanyThatMeetsTheOwnershipAndBaseErosionTest', + CompanyThatMeetsTheDerivativeBenefitsTest = 'CompanyThatMeetsTheDerivativeBenefitsTest', + CompanyWithAnItemOfIncomeThatMeetsActiveTradeOrBusinessTest = 'CompanyWithAnItemOfIncomeThatMeetsActiveTradeOrBusinessTest', + FavorableDiscretionaryDeterminationByTheUSCompetentAuthorityReceived = 'FavorableDiscretionaryDeterminationByTheUSCompetentAuthorityReceived', + NoLOBArticleInTreaty = 'NoLOBArticleInTreaty', + Other = 'Other', +} + +export enum NFFEStatus { + ActiveNFFE = 'ActiveNFFE', + PassiveNFFE = 'PassiveNFFE', + NonProfitOrganization = 'NonProfitOrganization', +} + +export type TaxFormNameValues = { firstName?: string; middleName?: string; lastName?: string }; + +export type TaxFormLocationValues = { + country?: string; + structured?: { address1?: string; address2?: string; city?: string; zone?: string; postalCode?: string }; +}; + +export type BaseFormValues = { + isUSPersonOrEntity?: boolean; + submitterType?: SubmitterType; + formType?: TaxFormType; + email?: string; + signer?: { firstName?: string; middleName?: string; lastName?: string }; + isSigned?: boolean; +}; + +export type W9TaxFormValues = { + isUSPersonOrEntity?: boolean; + submitterType?: SubmitterType; + formType?: TaxFormType; + email?: string; + signer?: { firstName?: string; middleName?: string; lastName?: string }; + isSigned?: boolean; + businessName?: string; + federalTaxClassificationDetails?: string; + exemptPayeeCode?: string; + fatcaExemptionCode?: string; + taxIdNumberType?: 'SSN' | 'EIN'; + taxIdNumber?: string; + accountNumbers?: string; + federalTaxClassification?: FederalTaxClassification; + hasConfirmedTOS?: boolean; + location?: { + country?: string; + structured?: { address1?: string; address2?: string; city?: string; zone?: string; postalCode?: string }; + }; +}; + +export type W8BenTaxFormValues = ({ + isUSPersonOrEntity?: boolean; + submitterType?: SubmitterType; + formType?: TaxFormType; + email?: string; + signer?: { firstName?: string; middleName?: string; lastName?: string }; + isSigned?: boolean; + beneficialOwner?: { firstName?: string; middleName?: string; lastName?: string }; + taxpayerIdentificationNumberTypeUS?: 'SSN' | 'ITIN'; + taxpayerIdentificationNumberUS?: string; + taxpayerIdentificationNumberForeign?: string; + dateOfBirth?: string; + countryOfCitizenship?: string; + residenceAddress?: { + country?: string; + structured?: { address1?: string; address2?: string; city?: string; zone?: string; postalCode?: string }; + }; + mailingAddress?: { + country?: string; + structured?: { address1?: string; address2?: string; city?: string; zone?: string; postalCode?: string }; + }; + hasConfirmedTOS?: boolean; + claimsSpecialRatesAndConditions?: boolean; + isSignerTheBeneficialOwner?: boolean; + certifiesResidentCountry?: boolean; + hasTaxTreatySpecialRatesAndConditions?: boolean; + claimsArticleAndParagraph?: string; + claimsRate?: number; + claimsIncomeType?: string; + claimsExplanation?: string; + signerCapacity?: string; +} & (( + | { claimsSpecialRatesAndConditions?: false } + | { + claimsSpecialRatesAndConditions?: true; + hasTaxTreatySpecialRatesAndConditions?: boolean; + certifiesResidentCountry?: boolean; + } +) & + ( + | { hasTaxTreatySpecialRatesAndConditions?: false } + | { + hasTaxTreatySpecialRatesAndConditions?: true; + claimsArticleAndParagraph?: string; + claimsRate?: number; + claimsIncomeType?: string; + claimsExplanation?: string; + } + ))) & + ({ isSignerTheBeneficialOwner?: true } | { isSignerTheBeneficialOwner?: false; signerCapacity?: string }); + +export type W8BenETaxFormValues = ((({ + isUSPersonOrEntity?: boolean; + submitterType?: SubmitterType; + formType?: TaxFormType; + email?: string; + signer?: { firstName?: string; middleName?: string; lastName?: string }; + isSigned?: boolean; + businessName?: string; + businessCountryOfIncorporationOrOrganization?: string; + businessAddress?: { + country?: string; + structured?: { address1?: string; address2?: string; city?: string; zone?: string; postalCode?: string }; + }; + businessMailingAddress?: { + country?: string; + structured?: { address1?: string; address2?: string; city?: string; zone?: string; postalCode?: string }; + }; + disregardedBusinessName?: string; + chapter3Status?: Chapter3Status; + hasCapacityToSign?: boolean; + certifyStatus?: boolean; + taxpayerIdentificationNumberForeign?: string; + taxpayerIdentificationNumberUS?: string; + giin?: string; + reference?: string; + hasConfirmedTOS?: boolean; + isHybridEntity?: boolean; + claimsSpecialRatesAndConditions?: boolean; + nffeStatus?: NFFEStatus; + certifyDerivesIncome?: boolean; + typeOfLimitationOnBenefitsProvisions?: TypeOfLimitationOnBenefitsProvisions; + typeOfLimitationOnBenefitsProvisionsOther?: string; + certifyBeneficialOwnerCountry?: boolean; + certifyForeignCorporation?: boolean; + claimsArticleAndParagraph?: string; + claimsRate?: number; + claimsIncomeType?: string; + claimsExplanation?: string; + usOwners?: { + name?: string; + address?: { + country?: string; + structured?: { address1?: string; address2?: string; city?: string; zone?: string; postalCode?: string }; + }; + tin?: string; + }[]; +} & ( + | { nffeStatus?: NFFEStatus.ActiveNFFE } + | { nffeStatus?: NFFEStatus.NonProfitOrganization } + | { + nffeStatus?: NFFEStatus.PassiveNFFE; + entityHasNoUSOwners?: boolean; + usOwners?: { + name?: string; + address?: { + country?: string; + structured?: { address1?: string; address2?: string; city?: string; zone?: string; postalCode?: string }; + }; + tin?: string; + }[]; + } +)) & + ( + | { isHybridEntity?: boolean } + | { + isHybridEntity?: boolean; + certifyBeneficialOwnerCountry?: boolean; + certifyDerivesIncome?: boolean; + certifyForeignCorporation?: boolean; + claimsSpecialRatesAndConditions?: boolean; + } + )) & + ( + | { certifyDerivesIncome?: boolean } + | { certifyDerivesIncome?: boolean } + | { + certifyDerivesIncome?: boolean; + typeOfLimitationOnBenefitsProvisions?: TypeOfLimitationOnBenefitsProvisions; + typeOfLimitationOnBenefitsProvisionsOther?: string; + } + )) & + ( + | { claimsSpecialRatesAndConditions?: boolean } + | { claimsSpecialRatesAndConditions?: boolean } + | { + claimsSpecialRatesAndConditions?: boolean; + claimsArticleAndParagraph?: string; + claimsRate?: number; + claimsIncomeType?: string; + claimsExplanation?: string; + } + ); diff --git a/lib/tax-forms/index.ts b/lib/tax-forms/index.ts new file mode 100644 index 00000000..ce6ea59f --- /dev/null +++ b/lib/tax-forms/index.ts @@ -0,0 +1,35 @@ +import fs from 'fs'; +import { fillW9TaxForm } from './w9'; +import { fillW8BenTaxForm } from './w8-ben'; +import { PDFDocument, PDFFont } from 'pdf-lib'; +import { fillW8BenETaxForm } from './w8-ben-e'; + +type TaxFormType = 'W9' | 'W8_BEN' | 'W8_BEN_E'; + +/** + * Defines all the forms available. + */ +export const TAX_FORMS: Record< + TaxFormType, + { + bytes: Uint8Array; + fillPDF: (pdfDoc: PDFDocument, values: Record, font: PDFFont) => Promise; + } +> = { + W9: { + bytes: fs.readFileSync('resources/tax-forms/fw9.pdf'), + fillPDF: fillW9TaxForm, + }, + W8_BEN: { + bytes: fs.readFileSync('resources/tax-forms/fw8ben.pdf'), + fillPDF: fillW8BenTaxForm, + }, + W8_BEN_E: { + bytes: fs.readFileSync('resources/tax-forms/fw8bene.pdf'), + fillPDF: fillW8BenETaxForm, + }, +} as const; + +export const isValidTaxFormType = (formType: string): formType is keyof typeof TAX_FORMS => { + return formType in TAX_FORMS; +}; diff --git a/lib/tax-forms/utils.ts b/lib/tax-forms/utils.ts new file mode 100644 index 00000000..beb1156e --- /dev/null +++ b/lib/tax-forms/utils.ts @@ -0,0 +1,3 @@ +export const getFullName = ({ firstName = undefined, middleName = undefined, lastName = undefined }): string => { + return [firstName, middleName, lastName].filter(Boolean).join(' '); +}; diff --git a/lib/tax-forms/w8-ben-e.ts b/lib/tax-forms/w8-ben-e.ts new file mode 100644 index 00000000..74866d75 --- /dev/null +++ b/lib/tax-forms/w8-ben-e.ts @@ -0,0 +1,149 @@ +import moment from 'moment'; +import { addSignature, fillPDFFormFromValues, PDFFieldDefinition } from '../pdf-lib-utils'; +import { PDFDocument, PDFFont } from 'pdf-lib'; +import { getFullName } from './utils'; +import { isNil } from 'lodash'; +import { W8BenETaxFormValues } from './frontend-types'; +import { getCountryName } from '../i18n'; + +const W8BenEFieldsDefinition: Partial> = { + businessName: 'topmostSubform[0].Page1[0].f1_1[0]', + disregardedBusinessName: 'topmostSubform[0].Page1[0].f1_3[0]', + businessCountryOfIncorporationOrOrganization: { + formPath: 'topmostSubform[0].Page1[0].f1_2[0]', + transform: getCountryName, + }, + chapter3Status: { + type: 'combo', + values: { + Corporation: 'topmostSubform[0].Page1[0].c1_1[0]', + Partnership: 'topmostSubform[0].Page1[0].c1_1[1]', + SimpleTrust: 'topmostSubform[0].Page1[0].c1_1[2]', + TaxExemptOrganization: 'topmostSubform[0].Page1[0].c1_1[3]', + ComplexTrust: 'topmostSubform[0].Page1[0].c1_1[4]', + ForeignGovernmentControlledEntity: 'topmostSubform[0].Page1[0].c1_1[5]', + CentralBankOfIssue: 'topmostSubform[0].Page1[0].c1_1[6]', + PrivateFoundation: 'topmostSubform[0].Page1[0].c1_1[7]', + Estate: 'topmostSubform[0].Page1[0].c1_1[8]', + ForeignGovernmentIntegralPart: 'topmostSubform[0].Page1[0].c1_1[9]', + GrantorTrust: 'topmostSubform[0].Page1[0].c1_1[10]', + DisregardedEntity: 'topmostSubform[0].Page1[0].c1_1[11]', + InternationalOrganization: 'topmostSubform[0].Page1[0].c1_1[12]', + }, + }, + isHybridEntity: { + type: 'combo', + transform: (value) => (isNil(value) ? null : value ? 'yes' : 'no'), + values: { + yes: 'topmostSubform[0].Page1[0].c1_2[0]', + no: 'topmostSubform[0].Page1[0].c1_2[1]', + }, + }, + certifyDerivesIncome: 'topmostSubform[0].Page2[0].c2_4[0]', + typeOfLimitationOnBenefitsProvisions: { + type: 'combo', + values: { + Government: 'topmostSubform[0].Page2[0].CheckboxesLine14b_ReadOrder[0].c2_5[0]', + TaxExemptPensionTrustOrPensionFund: 'topmostSubform[0].Page2[0].CheckboxesLine14b_ReadOrder[0].c2_5[1]', + OtherTaxExemptOrganization: 'topmostSubform[0].Page2[0].CheckboxesLine14b_ReadOrder[0].c2_5[2]', + PubliclyTradedCorporation: 'topmostSubform[0].Page2[0].CheckboxesLine14b_ReadOrder[0].c2_5[3]', + SubsidiaryOfAPubliclyTradedCorporation: 'topmostSubform[0].Page2[0].CheckboxesLine14b_ReadOrder[0].c2_5[4]', + CompanyThatMeetsTheOwnershipAndBaseErosionTest: 'topmostSubform[0].Page2[0].c2_5[0]', + CompanyThatMeetsTheDerivativeBenefitsTest: 'topmostSubform[0].Page2[0].c2_5[1]', + CompanyWithAnItemOfIncomeThatMeetsActiveTradeOrBusinessTest: 'topmostSubform[0].Page2[0].c2_5[2]', + FavorableDiscretionaryDeterminationByTheUSCompetentAuthorityReceived: 'topmostSubform[0].Page2[0].c2_5[3]', + NoLOBArticleInTreaty: 'topmostSubform[0].Page2[0].c2_5[4]', + Other: 'topmostSubform[0].Page2[0].c2_5[5]', + }, + }, + typeOfLimitationOnBenefitsProvisionsOther: 'topmostSubform[0].Page2[0].f2_10[0]', + certifyBeneficialOwnerCountry: 'topmostSubform[0].Page2[0].c2_3[0]', + taxpayerIdentificationNumberUS: 'topmostSubform[0].Page2[0].f2_1[0]', + taxpayerIdentificationNumberForeign: 'topmostSubform[0].Page2[0].Line9b_ReadOrder[0].f2_3[0]', + claimsArticleAndParagraph: { + formPath: 'topmostSubform[0].Page2[0].f2_11[0]', + if: (value, values) => values.claimsSpecialRatesAndConditions, + }, + claimsRate: { + formPath: 'topmostSubform[0].Page2[0].f2_12[0]', + if: (value, values) => values.claimsSpecialRatesAndConditions, + }, + claimsIncomeType: { + formPath: 'topmostSubform[0].Page2[0].f2_13[0]', + if: (value, values) => values.claimsSpecialRatesAndConditions, + }, + claimsExplanation: { + type: 'split-text', + fields: [ + { formPath: 'topmostSubform[0].Page2[0].f2_14[0]', maxLength: 18 }, + { formPath: 'topmostSubform[0].Page2[0].f2_15[0]', maxLength: 120 }, + { formPath: 'topmostSubform[0].Page2[0].f2_16[0]', maxLength: 120 }, + ], + }, + businessAddress: { + type: 'multi', + fields: [ + { + formPath: 'topmostSubform[0].Page1[0].f1_6[0]', + transform: (value: W8BenETaxFormValues['businessAddress']) => getCountryName(value?.country), + }, + { + formPath: 'topmostSubform[0].Page1[0].f1_4[0]', + transform: (value: W8BenETaxFormValues['businessAddress']) => + [value?.structured?.address1, value?.structured?.address2].filter(Boolean).join(', '), + }, + { + formPath: 'topmostSubform[0].Page1[0].f1_5[0]', + transform: (value: W8BenETaxFormValues['businessAddress']) => + [value?.structured?.city, value?.structured?.zone, value?.structured?.postalCode].filter(Boolean).join(', '), + }, + ], + }, + businessMailingAddress: { + type: 'multi', + fields: [ + { + formPath: 'topmostSubform[0].Page1[0].f1_9[0]', + transform: (value: W8BenETaxFormValues['businessMailingAddress']) => getCountryName(value?.country), + }, + { + formPath: 'topmostSubform[0].Page1[0].f1_7[0]', + transform: (value: W8BenETaxFormValues['businessMailingAddress']) => + [value?.structured?.address1, value?.structured?.address2].filter(Boolean).join(', '), + }, + { + formPath: 'topmostSubform[0].Page1[0].f1_8[0]', + transform: (value: W8BenETaxFormValues['businessMailingAddress']) => + [value?.structured?.city, value?.structured?.zone, value?.structured?.postalCode].filter(Boolean).join(', '), + }, + ], + }, + reference: 'topmostSubform[0].Page2[0].f2_4[0]', + giin: 'topmostSubform[0].Page2[0].Line9a_ReadOrder[0].f2_2[0]', + usOwners: 'topmostSubform[0].Page8[0].Table_Part29[0].BodyRow1[0].f8_3[0]', + signer: { + formPath: 'topmostSubform[0].Page8[0].f8_31[0]', + transform: getFullName, + }, +} as const; + +export const fillW8BenETaxForm = async (pdfDoc: PDFDocument, values: W8BenETaxFormValues, font: PDFFont) => { + const form = pdfDoc.getForm(); + const signerFullName = getFullName(values.signer); + + // Fill form + fillPDFFormFromValues(form, values, W8BenEFieldsDefinition, font); + + // Add date & signature + form.getTextField('topmostSubform[0].Page8[0].f8_32[0]').setText(moment().format('MM/DD/YYYY')); + if (values.isSigned) { + const [signatureWidget] = form.getField('topmostSubform[0].Page8[0].f8_30[0]').acroField.getWidgets(); + const signaturePosition = signatureWidget.getRectangle(); + await addSignature(pdfDoc, signerFullName, { + page: 7, + x: signaturePosition.x, + y: signaturePosition.y, + fallbackFont: font, + }); + } +}; diff --git a/lib/tax-forms/w8-ben.ts b/lib/tax-forms/w8-ben.ts new file mode 100644 index 00000000..199cec0b --- /dev/null +++ b/lib/tax-forms/w8-ben.ts @@ -0,0 +1,120 @@ +import moment from 'moment'; +import { addSignature, fillPDFFormFromValues, PDFFieldDefinition } from '../pdf-lib-utils'; +import { PDFDocument, PDFFont } from 'pdf-lib'; +import { getFullName } from './utils'; +import { W8BenTaxFormValues } from './frontend-types'; +import { getCountryName } from '../i18n'; + +const W8BenFieldsDefinition: Partial> = { + beneficialOwner: { formPath: 'topmostSubform[0].Page1[0].f_1[0]', transform: getFullName }, + countryOfCitizenship: { + type: 'multi', + fields: [ + { formPath: 'topmostSubform[0].Page1[0].f_2[0]', transform: getCountryName }, + { + formPath: 'topmostSubform[0].Page1[0].f_13[0]', + transform: getCountryName, + if: (value, values) => values.claimsSpecialRatesAndConditions && values.certifiesResidentCountry, + }, + ], + }, + residenceAddress: { + type: 'multi', + fields: [ + { + formPath: 'topmostSubform[0].Page1[0].f_5[0]', + transform: (value) => getCountryName(value?.country), + }, + { + formPath: 'topmostSubform[0].Page1[0].f_3[0]', + transform: (value: W8BenTaxFormValues['residenceAddress']) => + [value?.structured?.address1, value?.structured?.address2].filter(Boolean).join(', '), + }, + { + formPath: 'topmostSubform[0].Page1[0].f_4[0]', + transform: (value: W8BenTaxFormValues['residenceAddress']) => + [value?.structured?.city, value?.structured?.zone, value?.structured?.postalCode].filter(Boolean).join(', '), + }, + ], + }, + mailingAddress: { + type: 'multi', + fields: [ + { + formPath: 'topmostSubform[0].Page1[0].f_8[0]', + transform: (value) => getCountryName(value?.country), + }, + { + formPath: 'topmostSubform[0].Page1[0].f_6[0]', + transform: (value: W8BenTaxFormValues['mailingAddress']) => + [value?.structured?.address1, value?.structured?.address2].filter(Boolean).join(', '), + }, + { + formPath: 'topmostSubform[0].Page1[0].f_7[0]', + transform: (value: W8BenTaxFormValues['mailingAddress']) => + [value?.structured?.city, value?.structured?.zone, value?.structured?.postalCode].filter(Boolean).join(', '), + }, + ], + }, + dateOfBirth: { + formPath: 'topmostSubform[0].Page1[0].f_12[0]', + transform: (value: string) => (value ? moment(value).format('MM/DD/YYYY') : ''), + }, + taxpayerIdentificationNumberForeign: 'topmostSubform[0].Page1[0].f_10[0]', + taxpayerIdentificationNumberUS: { + formPath: 'topmostSubform[0].Page1[0].f_9[0]', + transform: (value: string) => value.replaceAll('-', ''), + }, + claimsArticleAndParagraph: { + formPath: 'topmostSubform[0].Page1[0].f_14[0]', + if: (value, values) => values.hasTaxTreatySpecialRatesAndConditions && values.claimsSpecialRatesAndConditions, + }, + claimsRate: { + formPath: 'topmostSubform[0].Page1[0].f_15[0]', + if: (value, values) => values.hasTaxTreatySpecialRatesAndConditions && values.claimsSpecialRatesAndConditions, + }, + claimsIncomeType: { + formPath: 'topmostSubform[0].Page1[0].f_16[0]', + if: (value, values) => values.hasTaxTreatySpecialRatesAndConditions && values.claimsSpecialRatesAndConditions, + }, + claimsExplanation: { + type: 'split-text', + if: (value, values) => values.hasTaxTreatySpecialRatesAndConditions && values.claimsSpecialRatesAndConditions, + fields: [ + { formPath: 'topmostSubform[0].Page1[0].f_17[0]', maxLength: 11 }, + { formPath: 'topmostSubform[0].Page1[0].f_18[0]', maxLength: 120 }, + ], + }, + signer: { + type: 'multi', + if: (value, values) => values.isSignerTheBeneficialOwner || values.signerCapacity, + fields: [ + 'topmostSubform[0].Page1[0].c1_02[0]', + { + formPath: 'topmostSubform[0].Page1[0].f_21[0]', + transform: (value, values) => + values.isSignerTheBeneficialOwner ? getFullName(values.beneficialOwner) : getFullName(value), + }, + ], + }, +}; + +export const fillW8BenTaxForm = async (pdfDoc: PDFDocument, values: W8BenTaxFormValues, font: PDFFont) => { + const form = pdfDoc.getForm(); + const signerFullName = getFullName(values.signer); + + fillPDFFormFromValues(form, values, W8BenFieldsDefinition, font); + + // Add date & signature + form.getTextField('topmostSubform[0].Page1[0].Date[0]').setText(moment().format('MM/DD/YYYY')); + if (values.isSigned) { + const [signatureWidget] = form.getField('topmostSubform[0].Page1[0].f_20[0]').acroField.getWidgets(); + const signaturePosition = signatureWidget.getRectangle(); + await addSignature(pdfDoc, signerFullName, { + page: 0, + x: signaturePosition.x, + y: signaturePosition.y, + fallbackFont: font, + }); + } +}; diff --git a/lib/tax-forms/w9.ts b/lib/tax-forms/w9.ts new file mode 100644 index 00000000..3a37faec --- /dev/null +++ b/lib/tax-forms/w9.ts @@ -0,0 +1,84 @@ +import moment from 'moment'; +import { PDFDocument, PDFFont } from 'pdf-lib'; +import { addSignature, fillPDFFormFromValues, PDFFieldDefinition } from '../pdf-lib-utils'; +import { getFullName } from './utils'; +import { W9TaxFormValues } from './frontend-types'; + +const W9FieldsDefinition: Partial> = { + signer: { formPath: 'topmostSubform[0].Page1[0].f1_1[0]', transform: getFullName }, + businessName: 'topmostSubform[0].Page1[0].f1_2[0]', + accountNumbers: 'topmostSubform[0].Page1[0].f1_10[0]', + exemptPayeeCode: 'topmostSubform[0].Page1[0].Exemptions[0].f1_5[0]', + fatcaExemptionCode: 'topmostSubform[0].Page1[0].Exemptions[0].f1_6[0]', + federalTaxClassification: { + type: 'combo', + values: { + Individual: 'topmostSubform[0].Page1[0].FederalClassification[0].c1_1[0]', + C_Corporation: 'topmostSubform[0].Page1[0].FederalClassification[0].c1_1[1]', + S_Corporation: 'topmostSubform[0].Page1[0].FederalClassification[0].c1_1[2]', + Partnership: 'topmostSubform[0].Page1[0].FederalClassification[0].c1_1[3]', + TrustEstate: 'topmostSubform[0].Page1[0].FederalClassification[0].c1_1[4]', + LimitedLiabilityCompany: 'topmostSubform[0].Page1[0].FederalClassification[0].c1_1[5]', + Other: 'topmostSubform[0].Page1[0].FederalClassification[0].c1_1[6]', + }, + }, + federalTaxClassificationDetails: { + formPath: 'topmostSubform[0].Page1[0].FederalClassification[0].f1_4[0]', + if: (value, values) => values.federalTaxClassification === 'Other', + }, + taxIdNumber: { + type: 'multi', + fields: [ + { + type: 'split-text', + if: (value, values) => values.taxIdNumberType === 'SSN', + transform: (value) => value && value.replace(/-/g, '').trim(), + fields: [ + { formPath: 'topmostSubform[0].Page1[0].SSN[0].f1_11[0]', maxLength: 3 }, + { formPath: 'topmostSubform[0].Page1[0].SSN[0].f1_12[0]', maxLength: 2 }, + { formPath: 'topmostSubform[0].Page1[0].SSN[0].f1_13[0]', maxLength: 4 }, + ], + }, + { + type: 'split-text', + if: (value, values) => values.taxIdNumberType === 'EIN', + transform: (value) => value && value.replace(/-/g, '').trim(), + fields: [ + { formPath: 'topmostSubform[0].Page1[0].EmployerID[0].f1_14[0]', maxLength: 2 }, + { formPath: 'topmostSubform[0].Page1[0].EmployerID[0].f1_15[0]', maxLength: 7 }, + ], + }, + ], + }, + location: { + type: 'multi', + fields: [ + { + formPath: 'topmostSubform[0].Page1[0].Address[0].f1_7[0]', + transform: (value: W9TaxFormValues['location']) => + [value?.structured?.address1, value?.structured?.address2].filter(Boolean).join(', '), + }, + { + formPath: 'topmostSubform[0].Page1[0].Address[0].f1_8[0]', + transform: (value: W9TaxFormValues['location']) => + [value?.structured?.city, value?.structured?.zone, value?.structured?.postalCode].filter(Boolean).join(', '), + }, + ], + }, +}; + +export const fillW9TaxForm = async (pdfDoc: PDFDocument, values: W9TaxFormValues, font: PDFFont) => { + const form = pdfDoc.getForm(); + const signerFullName = getFullName(values.signer); + + fillPDFFormFromValues(form, values, W9FieldsDefinition, font); + + // W9 don't have a dedicated date field, so we add it manually + const firstPage = pdfDoc.getPage(0); + firstPage.drawText(moment().format('MM/DD/YYYY'), { x: 420, y: 235, size: 10, font }); + + // Add date & signature + if (values.isSigned) { + await addSignature(pdfDoc, signerFullName, { x: 140, y: 235, fallbackFont: font }); + } +}; diff --git a/next-env.d.ts b/next-env.d.ts index ec2e2c31..2532e77a 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,4 +1,4 @@ -// / +/// // NOTE: This file should not be edited // see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/next.config.js b/next.config.js index 5ece849a..3c063999 100644 --- a/next.config.js +++ b/next.config.js @@ -18,6 +18,14 @@ const nextConfig = { API_KEY: process.env.API_KEY, LOG_LEVEL: process.env.LOG_LEVEL, }, + rewrites: async () => { + return [ + { + source: '/tax-form/:filename', + destination: '/api/tax-form/:filename', + }, + ]; + }, webpack: (config) => { // See https://styled-components.com/docs/faqs#how-can-i-fix-issues-when-using-npm-link-or-yarn-link config.resolve.alias['styled-components'] = path.join(__dirname, 'node_modules/styled-components'); diff --git a/package-lock.json b/package-lock.json index 966a4d55..e08252cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,8 @@ "next": "^12.3.4", "next-transpile-modules": "9.1.0", "node-fetch": "2.7.0", + "pdf-fontkit": "1.8.9", + "pdf-lib": "1.17.1", "prop-types": "15.8.1", "qrcode.react": "3.1.0", "react": "18.2.0", @@ -32,8 +34,9 @@ "styled-system": "5.1.5" }, "devDependencies": { - "@babel/core": "^7.14.8", + "@babel/core": "^7.24.0", "@babel/eslint-parser": "^7.11.0", + "@babel/node": "^7.23.9", "@babel/preset-typescript": "^7.23.3", "@types/node": "^20.11.24", "@types/react": "^18.2.61", @@ -135,9 +138,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz", - "integrity": "sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" @@ -147,33 +150,33 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", - "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", - "integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz", + "integrity": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-compilation-targets": "^7.21.4", - "@babel/helper-module-transforms": "^7.21.2", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.4", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.4", - "@babel/types": "^7.21.4", - "convert-source-map": "^1.7.0", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@babel/helper-compilation-targets": "^7.23.6", + "@babel/helper-module-transforms": "^7.23.3", + "@babel/helpers": "^7.24.0", + "@babel/parser": "^7.24.0", + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.0", + "@babel/types": "^7.24.0", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.2", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -183,6 +186,11 @@ "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==" + }, "node_modules/@babel/eslint-parser": { "version": "7.21.3", "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.21.3.tgz", @@ -202,11 +210,11 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", - "integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", + "version": "7.23.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz", + "integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==", "dependencies": { - "@babel/types": "^7.21.4", + "@babel/types": "^7.23.6", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -227,13 +235,13 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "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==", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@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" }, @@ -424,21 +432,21 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.0.tgz", + "integrity": "sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==", "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.24.0", + "@babel/traverse": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" @@ -457,10 +465,33 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/node": { + "version": "7.23.9", + "resolved": "https://registry.npmjs.org/@babel/node/-/node-7.23.9.tgz", + "integrity": "sha512-/d4ju/POwlGIJlZ+NqWH1qu61wt6ZlTZZZutrK2MOSdaH1JCh726nLw/GSvAjG+LTY6CO9SsB8uWcttnFKm6yg==", + "dev": true, + "dependencies": { + "@babel/register": "^7.23.7", + "commander": "^4.0.1", + "core-js": "^3.30.2", + "node-environment-flags": "^1.0.5", + "regenerator-runtime": "^0.14.0", + "v8flags": "^3.1.1" + }, + "bin": { + "babel-node": "bin/babel-node.js" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/parser": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.4.tgz", - "integrity": "sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.0.tgz", + "integrity": "sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==", "bin": { "parser": "bin/babel-parser.js" }, @@ -698,6 +729,25 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/register": { + "version": "7.23.7", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.23.7.tgz", + "integrity": "sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==", + "dev": true, + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/runtime": { "version": "7.23.9", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.9.tgz", @@ -709,38 +759,33 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime/node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", - "integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", - "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.21.4", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.21.4", - "@babel/types": "^7.21.4", - "debug": "^4.1.0", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.0.tgz", + "integrity": "sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==", + "dependencies": { + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.6", + "@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.0", + "@babel/types": "^7.24.0", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { @@ -748,9 +793,9 @@ } }, "node_modules/@babel/types": { - "version": "7.23.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.4.tgz", - "integrity": "sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", @@ -2917,6 +2962,22 @@ } } }, + "node_modules/@pdf-lib/standard-fonts": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz", + "integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==", + "dependencies": { + "pako": "^1.0.6" + } + }, + "node_modules/@pdf-lib/upng": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz", + "integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==", + "dependencies": { + "pako": "^1.0.10" + } + }, "node_modules/@popperjs/core": { "version": "2.11.8", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", @@ -4718,13 +4779,16 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4794,6 +4858,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array.prototype.reduce": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.6.tgz", + "integrity": "sha512-UW+Mz8LG/sPSU8jRDCjVr6J/ZKAGpHfwrZ6kWTG5qCxIEiXdVshqGnu5vEZA8S1y6X4aCSbQZ0/EEsfvEvBiSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array.prototype.tosorted": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", @@ -4807,6 +4890,28 @@ "get-intrinsic": "^1.1.3" } }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/asap": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", @@ -4846,10 +4951,13 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -5180,9 +5288,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "funding": [ { "type": "opencollective", @@ -5198,9 +5306,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -5279,13 +5387,19 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5317,9 +5431,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001564", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001564.tgz", - "integrity": "sha512-DqAOf+rhof+6GVx1y+xzbFPeOumfQnhYzVnZD6LAXijR77yPtm9mfOcqOnT3mpnJiZVT+kwLAFnRlZcIz+c6bg==", + "version": "1.0.30001591", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz", + "integrity": "sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==", "funding": [ { "type": "opencollective", @@ -5725,6 +5839,32 @@ "node": ">=0.8" } }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-deep/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/clsx": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.0.tgz", @@ -5794,6 +5934,15 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/commitizen": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.3.0.tgz", @@ -5824,6 +5973,12 @@ "node": ">= 12" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -6202,12 +6357,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -6403,9 +6576,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.593", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.593.tgz", - "integrity": "sha512-c7+Hhj87zWmdpmjDONbvNKNo24tvmD4mjal1+qqTYTrlF0/sNpAcDlU0Ki84ftA/5yj3BF2QhSGEC0Rky6larg==" + "version": "1.4.689", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.689.tgz", + "integrity": "sha512-GatzRKnGPS1go29ep25reM94xxd1Wj8ritU0yRhCJ/tr1Bg8gKnm6R9O/yPOhGQBoLMZ9ezfrpghNaTw97C/PQ==" }, "node_modules/emittery": { "version": "0.13.1", @@ -6466,45 +6639,52 @@ } }, "node_modules/es-abstract": { - "version": "1.21.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", - "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "version": "1.22.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", + "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.0", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.1", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.0", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.5", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -6513,6 +6693,33 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", + "dev": true + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-module-lexer": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", @@ -6521,14 +6728,14 @@ "peer": true }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -7537,6 +7744,20 @@ "node": ">=8" } }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/find-node-modules": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz", @@ -7666,20 +7887,23 @@ "dev": true }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -7715,14 +7939,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7758,13 +7987,14 @@ } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -8048,21 +8278,21 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, "engines": { "node": ">= 0.4" @@ -8084,12 +8314,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -8120,6 +8350,18 @@ "node": ">=0.10.0" } }, + "node_modules/hasown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.1.tgz", + "integrity": "sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -8538,13 +8780,13 @@ } }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -8571,14 +8813,16 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8704,9 +8948,9 @@ } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -8773,12 +9017,15 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8827,16 +9074,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -8890,12 +9133,27 @@ "node": ">=0.10.0" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "devOptional": true }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -10905,6 +11163,15 @@ "integrity": "sha512-IG6nm0+QtAMdXt9KvbgbGdvY50RSrw+U4sGZg+KlrSKPJEwVE5JVoI3d7RWfSMdBQneRheeAOj3lIjX5VL/9RQ==", "optional": true }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/klaw": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", @@ -11159,6 +11426,28 @@ "react": "^16.5.1 || ^17.0.0 || ^18.0.0" } }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -11493,6 +11782,25 @@ "node": ">= 10" } }, + "node_modules/node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/node-environment-flags/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -11519,9 +11827,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -11562,9 +11870,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -11580,13 +11888,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -11628,6 +11936,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.7.tgz", + "integrity": "sha512-PrJz0C2xJ58FNn11XV2lr4Jt5Gzl94qpy9Lu0JlfEj14z88sqbSBJCBEzdlNUCzY2gburhbrwOZ5BHCmuNUy0g==", + "dev": true, + "dependencies": { + "array.prototype.reduce": "^1.0.6", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "safe-array-concat": "^1.0.0" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object.hasown": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", @@ -11862,6 +12189,11 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -11944,6 +12276,30 @@ "node": ">=8" } }, + "node_modules/pdf-fontkit": { + "version": "1.8.9", + "resolved": "https://registry.npmjs.org/pdf-fontkit/-/pdf-fontkit-1.8.9.tgz", + "integrity": "sha512-TTq+umfhlFjUuQYOq6dCKT/wLslCrX4zVr5gqrIvrGHfo+vJ3ETapZTb4YLOCErohX7pF+HxlXSZuiToSRhNmA==", + "dependencies": { + "pako": "^1.0.6" + } + }, + "node_modules/pdf-lib": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.17.1.tgz", + "integrity": "sha512-V/mpyJAoTsN4cnP31vc0wfNA1+p20evqqnap0KLoRUN0Yk/p3wN52DOEsL4oBFcLdb76hlpKPtzJIgo67j/XLw==", + "dependencies": { + "@pdf-lib/standard-fonts": "^1.0.0", + "@pdf-lib/upng": "^1.0.1", + "pako": "^1.0.11", + "tslib": "^1.11.1" + } + }, + "node_modules/pdf-lib/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -12025,6 +12381,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pinkie": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", @@ -12047,14 +12412,87 @@ } }, "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.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, "engines": { "node": ">= 6" } }, + "node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-dir/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, "node_modules/polished": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", @@ -12066,6 +12504,15 @@ "node": ">=10" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postcss": { "version": "8.4.14", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", @@ -12529,15 +12976,21 @@ "node": ">= 6" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -12860,6 +13313,24 @@ "tslib": "^2.1.0" } }, + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -12881,15 +13352,18 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13007,11 +13481,55 @@ "randombytes": "^2.1.0" } }, + "node_modules/set-function-length": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.1.tgz", + "integrity": "sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.2", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", @@ -13103,7 +13621,6 @@ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, - "peer": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -13234,14 +13751,14 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "engines": { "node": ">= 0.4" @@ -13251,28 +13768,28 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -13814,15 +14331,74 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.5.tgz", + "integrity": "sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -14079,6 +14655,18 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/v8flags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/validator": { "version": "13.11.0", "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", @@ -14243,17 +14831,16 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.14.tgz", + "integrity": "sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.6", + "call-bind": "^1.0.5", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.1" }, "engines": { "node": ">= 0.4" diff --git a/package.json b/package.json index 51d07ffa..522bcdb8 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,8 @@ "next": "^12.3.4", "next-transpile-modules": "9.1.0", "node-fetch": "2.7.0", + "pdf-fontkit": "1.8.9", + "pdf-lib": "1.17.1", "prop-types": "15.8.1", "qrcode.react": "3.1.0", "react": "18.2.0", @@ -51,11 +53,13 @@ "prettier:check": "npm run prettier -- --check", "prettier:write": "npm run prettier -- --write", "depcheck": "npx depcheck", - "type:check": "tsc" + "type:check": "tsc", + "script": "babel-node --extensions .js,.ts,.tsx -- $@" }, "devDependencies": { - "@babel/core": "^7.14.8", + "@babel/core": "^7.24.0", "@babel/eslint-parser": "^7.11.0", + "@babel/node": "^7.23.9", "@babel/preset-typescript": "^7.23.3", "@types/node": "^20.11.24", "@types/react": "^18.2.61", diff --git a/pages/_document.js b/pages/_document.js index 771c45af..8657b5f1 100644 --- a/pages/_document.js +++ b/pages/_document.js @@ -110,6 +110,7 @@ export default class Document extends NextJSDocument { { pageFormat: query.pageFormat || 'A4' }, ); + res.setHeader('cache-control', 'no-cache'); res.setHeader('Content-disposition', `inline; filename="${get(ctx, 'query.filename', 'result.pdf')}"`); res.setHeader('Content-Type', 'application/pdf'); res.end(buffer); diff --git a/pages/api/tax-form/[filename].ts b/pages/api/tax-form/[filename].ts new file mode 100644 index 00000000..3eb14dc4 --- /dev/null +++ b/pages/api/tax-form/[filename].ts @@ -0,0 +1,80 @@ +import { PDFDocument, StandardFonts } from 'pdf-lib'; +import fs from 'fs'; +import fontkit from 'pdf-fontkit'; +import { TAX_FORMS, isValidTaxFormType } from '../../../lib/tax-forms'; +import { getFullName } from '../../../lib/tax-forms/utils'; +import { flattenForm } from '../../../lib/pdf-lib-utils'; +import { allCharsValid } from '../../../lib/string-utils'; + +const MAIN_FONT_BYTES = fs.readFileSync('resources/fonts/NanumGothic-Regular.ttf'); + +export default async function handler(req, res) { + // Get values from query + const { formType: rawFormType, values: base64Values, isFinal } = req.query; + const formType = rawFormType?.toUpperCase(); + if (!formType) { + res.status(400).send('Missing form type'); + return; + } else if (!isValidTaxFormType(formType)) { + res.status(400).send('Invalid form type'); + return; + } + + // Load file + const formDefinition = TAX_FORMS[formType]; + const pdfDoc = await PDFDocument.load(formDefinition.bytes); + + // Parse values + const rawValues = Buffer.from(base64Values, 'base64').toString() || '{}'; + let values; + try { + values = JSON.parse(rawValues); + } catch (e) { + res.status(400).send('Invalid values'); + return; + } + + // Set metadata + const signerFullName = getFullName(values.signer); + const entityName = values.businessName || signerFullName; + pdfDoc.setTitle(`${formType} Form - ${entityName}`); + pdfDoc.setSubject(`${formType} Form`); + pdfDoc.setAuthor(signerFullName || ''); + pdfDoc.setCreator('Open Collective'); + pdfDoc.setCreationDate(new Date()); + pdfDoc.setModificationDate(new Date()); + pdfDoc.setKeywords([formType]); + + // Add custom font to support unicode characters if needed + const defaultFont = await pdfDoc.embedStandardFont(StandardFonts.Helvetica); + let customFont = undefined; + try { + const defaultCharacterSet = new Set(defaultFont.getCharacterSet()); + if (!allCharsValid(rawValues, defaultCharacterSet)) { + pdfDoc.registerFontkit(fontkit); + customFont = await pdfDoc.embedFont(MAIN_FONT_BYTES, { subset: true }); + } + } catch (e) { + res.status(500).send('Failed to embed font'); + return; + } + + // Fill form + await formDefinition.fillPDF(pdfDoc, values, customFont); + + // If final, flatten the form and attach raw data + if (isFinal && ['true', '1'].includes(isFinal.toLowerCase())) { + flattenForm(pdfDoc.getForm(), { useFallbackReadonly: formType !== 'W9' }); + const valueBase64 = Buffer.from(JSON.stringify(values)).toString('base64'); + await pdfDoc.attach(valueBase64, 'raw-data.json', { + mimeType: 'application/json', + description: 'Raw form data', + }); + } + + // Return file + const pdfBytes = await pdfDoc.save(); + res.setHeader('Content-Type', 'application/pdf'); + res.setHeader('Access-Control-Allow-Origin', '*'); // TODO + res.send(Buffer.from(pdfBytes)); +} diff --git a/.fonts/Inter-Black.otf b/resources/fonts/Inter-Black.otf similarity index 100% rename from .fonts/Inter-Black.otf rename to resources/fonts/Inter-Black.otf diff --git a/.fonts/Inter-BlackItalic.otf b/resources/fonts/Inter-BlackItalic.otf similarity index 100% rename from .fonts/Inter-BlackItalic.otf rename to resources/fonts/Inter-BlackItalic.otf diff --git a/.fonts/Inter-Bold.otf b/resources/fonts/Inter-Bold.otf similarity index 100% rename from .fonts/Inter-Bold.otf rename to resources/fonts/Inter-Bold.otf diff --git a/.fonts/Inter-BoldItalic.otf b/resources/fonts/Inter-BoldItalic.otf similarity index 100% rename from .fonts/Inter-BoldItalic.otf rename to resources/fonts/Inter-BoldItalic.otf diff --git a/.fonts/Inter-ExtraBold.otf b/resources/fonts/Inter-ExtraBold.otf similarity index 100% rename from .fonts/Inter-ExtraBold.otf rename to resources/fonts/Inter-ExtraBold.otf diff --git a/.fonts/Inter-ExtraBoldItalic.otf b/resources/fonts/Inter-ExtraBoldItalic.otf similarity index 100% rename from .fonts/Inter-ExtraBoldItalic.otf rename to resources/fonts/Inter-ExtraBoldItalic.otf diff --git a/.fonts/Inter-ExtraLight.otf b/resources/fonts/Inter-ExtraLight.otf similarity index 100% rename from .fonts/Inter-ExtraLight.otf rename to resources/fonts/Inter-ExtraLight.otf diff --git a/.fonts/Inter-ExtraLightItalic.otf b/resources/fonts/Inter-ExtraLightItalic.otf similarity index 100% rename from .fonts/Inter-ExtraLightItalic.otf rename to resources/fonts/Inter-ExtraLightItalic.otf diff --git a/.fonts/Inter-Italic.otf b/resources/fonts/Inter-Italic.otf similarity index 100% rename from .fonts/Inter-Italic.otf rename to resources/fonts/Inter-Italic.otf diff --git a/.fonts/Inter-Light.otf b/resources/fonts/Inter-Light.otf similarity index 100% rename from .fonts/Inter-Light.otf rename to resources/fonts/Inter-Light.otf diff --git a/.fonts/Inter-LightItalic.otf b/resources/fonts/Inter-LightItalic.otf similarity index 100% rename from .fonts/Inter-LightItalic.otf rename to resources/fonts/Inter-LightItalic.otf diff --git a/.fonts/Inter-Medium.otf b/resources/fonts/Inter-Medium.otf similarity index 100% rename from .fonts/Inter-Medium.otf rename to resources/fonts/Inter-Medium.otf diff --git a/.fonts/Inter-MediumItalic.otf b/resources/fonts/Inter-MediumItalic.otf similarity index 100% rename from .fonts/Inter-MediumItalic.otf rename to resources/fonts/Inter-MediumItalic.otf diff --git a/.fonts/Inter-Regular.otf b/resources/fonts/Inter-Regular.otf similarity index 100% rename from .fonts/Inter-Regular.otf rename to resources/fonts/Inter-Regular.otf diff --git a/.fonts/Inter-SemiBold.otf b/resources/fonts/Inter-SemiBold.otf similarity index 100% rename from .fonts/Inter-SemiBold.otf rename to resources/fonts/Inter-SemiBold.otf diff --git a/.fonts/Inter-SemiBoldItalic.otf b/resources/fonts/Inter-SemiBoldItalic.otf similarity index 100% rename from .fonts/Inter-SemiBoldItalic.otf rename to resources/fonts/Inter-SemiBoldItalic.otf diff --git a/.fonts/Inter-Thin.otf b/resources/fonts/Inter-Thin.otf similarity index 100% rename from .fonts/Inter-Thin.otf rename to resources/fonts/Inter-Thin.otf diff --git a/.fonts/Inter-ThinItalic.otf b/resources/fonts/Inter-ThinItalic.otf similarity index 100% rename from .fonts/Inter-ThinItalic.otf rename to resources/fonts/Inter-ThinItalic.otf diff --git a/.fonts/Inter-V.otf b/resources/fonts/Inter-V.otf similarity index 100% rename from .fonts/Inter-V.otf rename to resources/fonts/Inter-V.otf diff --git a/resources/fonts/JustMeAgainDownHere-Regular.ttf b/resources/fonts/JustMeAgainDownHere-Regular.ttf new file mode 100644 index 00000000..bd6f48c2 Binary files /dev/null and b/resources/fonts/JustMeAgainDownHere-Regular.ttf differ diff --git a/resources/fonts/NanumGothic-Regular.ttf b/resources/fonts/NanumGothic-Regular.ttf new file mode 100644 index 00000000..6e4dd874 Binary files /dev/null and b/resources/fonts/NanumGothic-Regular.ttf differ diff --git a/.fonts/REAME.md b/resources/fonts/REAME.md similarity index 100% rename from .fonts/REAME.md rename to resources/fonts/REAME.md diff --git a/resources/tax-forms/fw8ben.pdf b/resources/tax-forms/fw8ben.pdf new file mode 100644 index 00000000..210eb21d Binary files /dev/null and b/resources/tax-forms/fw8ben.pdf differ diff --git a/resources/tax-forms/fw8bene.pdf b/resources/tax-forms/fw8bene.pdf new file mode 100644 index 00000000..7eb4fadf Binary files /dev/null and b/resources/tax-forms/fw8bene.pdf differ diff --git a/resources/tax-forms/fw9.pdf b/resources/tax-forms/fw9.pdf new file mode 100644 index 00000000..50a3a466 Binary files /dev/null and b/resources/tax-forms/fw9.pdf differ diff --git a/scripts/remove-xfa-form-data.sh b/scripts/remove-xfa-form-data.sh new file mode 100755 index 00000000..20125066 --- /dev/null +++ b/scripts/remove-xfa-form-data.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# ---------------------------------------------------------- +# Removes XFA form data from a PDF file. +# ---------------------------------------------------------- + +pdftk "$1" output "$1_fixed" drop_xfa +mv "$1_fixed" "$1"