diff --git a/functions/assets/fonts/Code25I.ttf b/functions/assets/fonts/Code25I.ttf new file mode 100644 index 0000000..f1f9bdb Binary files /dev/null and b/functions/assets/fonts/Code25I.ttf differ diff --git a/functions/assets/fonts/Times New Roman Bold Italic.ttf b/functions/assets/fonts/Times New Roman Bold Italic.ttf new file mode 100644 index 0000000..47e8580 Binary files /dev/null and b/functions/assets/fonts/Times New Roman Bold Italic.ttf differ diff --git a/functions/assets/fonts/Times New Roman Bold.ttf b/functions/assets/fonts/Times New Roman Bold.ttf new file mode 100644 index 0000000..578542c Binary files /dev/null and b/functions/assets/fonts/Times New Roman Bold.ttf differ diff --git a/functions/assets/fonts/Times New Roman Italic.ttf b/functions/assets/fonts/Times New Roman Italic.ttf new file mode 100644 index 0000000..eff3616 Binary files /dev/null and b/functions/assets/fonts/Times New Roman Italic.ttf differ diff --git a/functions/assets/fonts/Times New Roman.ttf b/functions/assets/fonts/Times New Roman.ttf new file mode 100644 index 0000000..d7969c3 Binary files /dev/null and b/functions/assets/fonts/Times New Roman.ttf differ diff --git a/functions/assets/images/banrisul.png b/functions/assets/images/banrisul.png new file mode 100644 index 0000000..1b9e299 Binary files /dev/null and b/functions/assets/images/banrisul.png differ diff --git a/functions/ecom.config.js b/functions/ecom.config.js index 6f2c232..03cda84 100644 --- a/functions/ecom.config.js +++ b/functions/ecom.config.js @@ -34,13 +34,13 @@ const app = { * Triggered when listing payments, must return available payment methods. * Start editing `routes/ecom/modules/list-payments.js` */ - // list_payments: { enabled: true }, + list_payments: { enabled: true }, /** * Triggered when order is being closed, must create payment transaction and return info. * Start editing `routes/ecom/modules/create-transaction.js` */ - // create_transaction: { enabled: true }, + create_transaction: { enabled: true }, }, /** @@ -82,7 +82,7 @@ const app = { // 'DELETE', // Delete customers ], orders: [ - // 'GET', // List/read orders with public and private fields + 'GET', // List/read orders with public and private fields // 'POST', // Create orders // 'PATCH', // Edit orders // 'PUT', // Overwrite orders @@ -106,7 +106,7 @@ const app = { ], 'orders/payments_history': [ // 'GET', // List/read order payments history events - // 'POST', // Create payments history entry with new status + 'POST', // Create payments history entry with new status // 'DELETE', // Delete payments history entry ], @@ -138,37 +138,174 @@ const app = { }, admin_settings: { - /** - * JSON schema based fields to be configured by merchant and saved to app `data` / `hidden_data`, such as: - - webhook_uri: { - schema: { - type: 'string', - maxLength: 255, - format: 'uri', - title: 'Notifications URI', - description: 'Unique notifications URI available on your Custom App dashboard' - }, - hide: true - }, - token: { - schema: { - type: 'string', - maxLength: 50, - title: 'App token' - }, - hide: true - }, - opt_in: { - schema: { - type: 'boolean', - default: false, - title: 'Some config option' - }, - hide: false - }, - - */ + client_id: { + schema: { + type: 'string', + maxLength: 255, + title: 'Client Id', + // description: '' + }, + hide: true + }, + client_secret: { + schema: { + type: 'string', + maxLength: 255, + title: 'Client Secret', + // description: '' + }, + hide: true + }, + beneficiary_code: { + schema: { + type: 'string', + maxLength: 13, + title: 'Código beneficiário', + description: 'Seu código de beneficiário no Banrisul (13 dígitos)' + }, + hide: true + }, + is_homologation: { + schema: { + type: 'boolean', + title: 'Ambiente de Homologação', + description: 'Habilitar ambiente para Homologação', + default: false + }, + hide: false + }, + days_to_expiry: { + schema:{ + type: 'integer', + minimum: 1, + maximum: 999, + default: 7, + title: 'Dias corridos até o vencimento', + description: 'Representa diferença de dias entre a data da requisição e a data de vencimento' + }, + hide: false + }, + fees: { + schema: { + type: 'object', + required: [ + 'value' + ], + title: 'Juros', + description: 'Juros a ser aplicado nos boletos após vencimento', + additionalProperties: false, + properties: { + type: { + type: 'string', + enum: [ + 'percentual', + 'fixo', + 'isento' + ], + default: 'isento', + title: 'Tipo de juros', + description: 'Se fixo valor diário, se percentual taxa mensal' + }, + value: { + type: 'number', + minimum: 0, + maximum: 99999999, + title: 'Valor do juros', + description: 'Valor percentual ou fixo a ser acrescentado, dependendo to tipo configurado' + } + } + }, + hide: false + }, + tax: { + schema: { + type: 'object', + required: [ + 'value' + ], + title: 'Multa', + description: 'Multa a ser aplicada nos boletos após vencimento', + additionalProperties: false, + properties: { + disable: { + type: 'boolean', + default: true, + title: 'Desabilitar multa' + }, + type: { + type: 'string', + enum: [ + 'percentual', + 'fixa' + ], + default: 'percentual', + title: 'Tipo de multa', + description: 'Multa com valor percentual ou fixo' + }, + value: { + type: 'number', + minimum: 0, + maximum: 99999999, + title: 'Valor da multa', + description: 'Valor percentual ou fixo a ser acrescentado, dependendo to tipo configurado' + } + } + }, + hide: false + }, + discount: { + schema: { + type: 'object', + required: [ + 'value' + ], + title: 'Desconto', + additionalProperties: false, + properties: { + disable: { + type: 'boolean', + default: false, + title: 'Desabilitar desconto' + }, + apply_at: { + type: 'string', + enum: [ + 'total', + 'subtotal', + 'freight' + ], + default: 'subtotal', + title: 'Aplicar desconto em', + description: 'Em qual valor o desconto deverá ser aplicado no checkout' + }, + min_amount: { + type: 'integer', + minimum: 1, + maximum: 999999999, + title: 'Pedido mínimo', + description: 'Montante mínimo para aplicar o desconto' + }, + type: { + type: 'string', + enum: [ + 'percentage', + 'fixed' + ], + default: 'percentage', + title: 'Tipo de desconto', + description: 'Desconto com valor percentual ou fixo' + }, + value: { + type: 'number', + minimum: 0, + maximum: 99999999, + title: 'Valor do desconto', + description: 'Valor percentual ou fixo a ser descontado, dependendo to tipo configurado' + } + } + }, + hide: false + } } } diff --git a/functions/lib/banrisul/auth/create-access.js b/functions/lib/banrisul/auth/create-access.js new file mode 100644 index 0000000..dd7cd98 --- /dev/null +++ b/functions/lib/banrisul/auth/create-access.js @@ -0,0 +1,54 @@ +const createAxios = require('./create-axios') +const getOAuth = require('./get-token') + +module.exports = function (clientId, clientSecret, storeId, firestoreColl = 'banrisul_auth') { + const self = this + + let documentRef + // const hashLogin = Buffer.from(`${galaxpayId}:${galaxpayHash}`).toString('base64') + + if (firestoreColl) { + documentRef = require('firebase-admin') + .firestore() + .doc(`${firestoreColl}/${storeId}`) + } + + this.preparing = new Promise((resolve, reject) => { + const authenticate = (accessToken, documentRef) => { + self.axios = createAxios(accessToken) + self.documentRef = documentRef + if (documentRef) { + documentRef + .set({ accessToken }, { merge: true }) + .catch(console.error) + } + resolve(self) + } + + const handleAuth = () => { + console.log('> Banrisul Auth02 ', storeId) + getOAuth(clientId, clientSecret) + .then((accessToken) => { + console.log(`>> s:${storeId} token => ${accessToken}`) + authenticate(accessToken, documentRef) + }) + .catch(reject) + } + + if (documentRef) { + documentRef.get() + .then((documentSnapshot) => { + if (documentSnapshot.exists && + Date.now() - documentSnapshot.updateTime.toDate().getTime() <= 59 * 60 * 1000 // access token expires in 60 minutes + ) { + authenticate(documentSnapshot.get('accessToken'), documentRef) + } else { + handleAuth() + } + }) + .catch(console.error) + } else { + handleAuth() + } + }) +} diff --git a/functions/lib/banrisul/auth/create-axios.js b/functions/lib/banrisul/auth/create-axios.js new file mode 100644 index 0000000..bd5cce2 --- /dev/null +++ b/functions/lib/banrisul/auth/create-axios.js @@ -0,0 +1,18 @@ +const axios = require('axios') +module.exports = (accessToken, isGetToken) => { + const isSandbox = true + + const headers = { + 'Content-Type': 'application/json' + } + + if (accessToken) { + console.log('> token ', accessToken) + headers.Authorization = `Bearer ${accessToken}` + } + + return axios.create({ + baseURL: `https://api${isSandbox ? 'dev' : ''}.banrisul.com.br${isGetToken ? '' : '/cobranca/v1'}`, + headers + }) +} diff --git a/functions/lib/banrisul/auth/get-token.js b/functions/lib/banrisul/auth/get-token.js new file mode 100644 index 0000000..c9a2112 --- /dev/null +++ b/functions/lib/banrisul/auth/get-token.js @@ -0,0 +1,35 @@ +const axios = require('./create-axios') +const qs = require('qs') + +module.exports = (clientId, clientSecret) => new Promise((resolve, reject) => { + const banrisulAxios = axios(null, true) + + const request = async (isRetry) => { + try { + const headers = { + 'content-type': 'application/x-www-form-urlencoded', + Authorization: `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}` + } + + const body = { + grant_type: 'client_credentials', + scope: 'boletos' + } + + const { data: { access_token: token } } = await banrisulAxios.post( + '/auth/oauth/v2/token', + qs.stringify(body), + { headers } + ) + + resolve(token) + } catch (err) { + if (!isRetry && err.response && err.response.status >= 429) { + setTimeout(() => request(true), 7000) + } + reject(err) + } + } + + request() +}) diff --git a/functions/lib/banrisul/calculate-our-number.js b/functions/lib/banrisul/calculate-our-number.js new file mode 100644 index 0000000..9894b47 --- /dev/null +++ b/functions/lib/banrisul/calculate-our-number.js @@ -0,0 +1,51 @@ +const mod10 = (number) => { + const stringNumber = (`${number}`.padStart(8, '0')) + .split('') + .map(sNumber => { + return parseInt(sNumber, 10) + }) + let mod10 = 0 + let isWeight1 = false + for (let i = stringNumber.length - 1; i >= 0; i--) { + let result = stringNumber[i] * (isWeight1 ? 1 : 2) + if (result > 9) { + result -= 9 + } + mod10 += result + isWeight1 = !isWeight1 + } + return 10 - (mod10 % 10) +} + +const mod11 = (number, mod10) => { + const calcRest = (dv) => { + const stringNumber = (`${number}${dv}`.padStart(9, '0')) + .split('') + .map(sNumber => { + return parseInt(sNumber, 10) + }) + let mod11 = 0 + let weight = 2 + for (let i = stringNumber.length - 1; i >= 0; i--) { + const result = stringNumber[i] * weight + mod11 += result + weight = weight === 7 ? 2 : weight + 1 + } + return mod11 % 11 + } + let rest = calcRest(mod10) + if (rest === 1) { + rest = calcRest(mod10 === 9 ? 0 : mod10 + 1) + } + + return 11 - rest +} + +const ourNumber = (number) => { + const dvMod10 = mod10(number) + const dvMod11 = mod11(number, dvMod10) + + return `${number}${dvMod10}${dvMod11}`.padStart(10, '0') +} + +module.exports = ourNumber diff --git a/functions/lib/banrisul/check-billet.js b/functions/lib/banrisul/check-billet.js new file mode 100644 index 0000000..65c5cc0 --- /dev/null +++ b/functions/lib/banrisul/check-billet.js @@ -0,0 +1,126 @@ +const Banrisul = require('./auth/create-access') +const getAppData = require('../store-api/get-app-data') + +const parseStatus = { + A: 'pending', + B: 'voided', + D: 'voided', + L: 'paid', + R: 'refunded', + T: 'pending', + P: 'pending' +} + +module.exports = async (admin, appSdk) => { + try { + /* + A = Ativo + B = Baixado por pagamento // Cancelado + D = Baixado por devolução // Cancelado + L = Liquidado // PAGO + R = Reembolsado + T = Transferido para CL + P = Protestado + */ + const collectionBillet = admin.firestore().collection('billets') + admin.firestore().collection('ecomplus_app_auth').get() + .then(async (docsRef) => { + const storeIds = [] + const apps = docsRef?.docs?.map((doc) => { + return { + ...doc.data(), + id: doc.id + } + }) + + for (let i = 0; i < apps.length; i++) { + const app = apps[i] + const storeId = app.store_id + console.log('>> StoreId: ', storeId) + + const docsBillets = (await collectionBillet.where('storeId', '==', storeId).get()) + ?.docs?.map((doc) => { + return { + ...doc.data(), + orderId: doc.id, + refDoc: doc.ref + } + }) + + if (!storeIds.includes(storeId)) { + storeIds.push(storeId) + const auth = await appSdk.getAuth(storeId) + const appData = await getAppData({ appSdk, storeId, auth }) + const banrisul = new Banrisul(appData.client_id, appData.client_secret, storeId) + + await banrisul.preparing + const barisulAxios = banrisul.axios + + for (let j = 0; j < docsBillets.length; j++) { + try { + const { titulo, orderId, refDoc } = docsBillets[j] + const idBoleto = titulo.nosso_numero + console.log('>> orderId: ', orderId, ' nosso numero', idBoleto) + + const { data: billet } = await barisulAxios.get( + `/boletos/${idBoleto}`, + { + headers: { + 'bergs-beneficiario': appData.beneficiary_code + } + } + ) + + console.log('> billet ', JSON.stringify(billet)) + + const status = parseStatus[billet?.titulo?.situacao_banrisul] || 'pending' + const parseDate = { + voided: billet?.titulo?.data_baixa, + paid: billet?.titulo?.data_pagamento, + refunded: billet?.titulo?.data_reembolso, + pending: Date.now() + } + + console.log('> status ', status, ' date: ', parseDate[status]) + + if (orderId) { + const { response: { data: order } } = (await appSdk.apiRequest(storeId, `/orders/${orderId}.json`, 'GET', null, auth)) + + if (order && order.financial_status.current !== status) { + console.log('>> Update status ', status) + let transactionId + if (order.transactions && order.transactions[0]) { + transactionId = order.transactions[0]._id + } + const body = { + date_time: new Date(parseDate[status]).toISOString(), + status, + notification_code: `time:${new Date().toISOString()};`, + flags: ['Banrisul'] + } + + if (transactionId) { + body.transaction_id = transactionId + } + + await appSdk.apiRequest(storeId, `orders/${order._id}/payments_history.json`, 'POST', body, auth) + } + + if (status !== 'pending') { + console.log('Removing Billet') + await refDoc.delete() + } + } + } catch (error) { + console.error(error) + } + } + } else { + console.log(`Already executed in the store #${storeId}`) + } + } + }) + } catch (error) { + console.error(error) + } +} diff --git a/functions/lib/banrisul/payload-to-billet.js b/functions/lib/banrisul/payload-to-billet.js new file mode 100644 index 0000000..432fd2e --- /dev/null +++ b/functions/lib/banrisul/payload-to-billet.js @@ -0,0 +1,121 @@ +const parseAddress = to => ({ + city: to.city, + state: to.province, + stateCode: to.province_code, + country: to.country_code ? to.country_code.toUpperCaseCase() : 'BR', + zipCode: to.zip, + number: `${String(to.number) || 's/n'}`, + street: `${to.street}`, + borough: `${to.borough}`, + complement: to.complement || '' +}) + +const createBodyToBillet = (appData, params, ourNumber) => { + const { amount, buyer, to } = params + const { + fees, // Juros + tax // Multa + } = appData + + const isHomologation = appData.is_homologation + const daysToExpiry = appData.days_to_expiry + + const createdAt = new Date() + const dayExpiry = new Date(createdAt.getTime() + daysToExpiry * 24 * 60 * 60 * 1000) + /* + especie + + 02 = Duplicata Mercantil + 04 = Duplicata de Serviço + 31 = Cartão de Crédito + 32 = Boleto de Proposta + 99 = Outros + */ + + const titulo = { + data_emissao: createdAt.toISOString().split('T')[0], + data_vencimento: dayExpiry.toISOString().split('T')[0], + especie: '99', + instrucoes: {}, + pag_parcial: { + autoriza: 1, + codigo: 3 + }, + valor_nominal: (amount.total).toFixed(2), + // nosso_numero: ourNumber, + seu_numero: Date.now().toString() + } + + /* + Códigos Juros + 1 = Valor por dia + 2 = Taxa mensal + 3 = Isento + */ + + let codeFees = 3 + if (fees.type && fees.type !== 'isento') { + codeFees = fees.type === 'percentual' ? 2 : 1 + } + + Object.assign(titulo.instrucoes, { + juros: { + codigo: codeFees + } + }) + + switch (fees.type) { + case 'percentual': + titulo.instrucoes.juros.taxa = (fees.value || 0) + break + case 'fixo': + titulo.instrucoes.juros.valor = (fees.value || 0) + break + default: + break + } + + /* + Códigos Multa + 1 = Valor Fixo + 2 = Percentual + */ + + if (tax && !tax.disable && tax.value) { + Object.assign(titulo.instrucoes, { + multa: { + codigo: tax.type === 'fixa' ? 1 : 2 + } + }) + + switch (tax.type) { + case 'percentual': + titulo.instrucoes.multa.taxa = (tax.value || 0) + break + case 'fixa': + titulo.instrucoes.multa.valor = (tax.value || 0) + break + default: + break + } + } + + const address = to && to.street ? parseAddress(to) : parseAddress(params.billing_address) + + const pagador = { + aceite: 'A', + cep: address.zipCode, + cidade: (address.city).toUpperCase(), + cpf_cnpj: buyer.doc_number, + endereco: `${address.street}, ${address.number} Complemento: ${address.complement}`.toUpperCase(), + nome: (buyer.fullname).toUpperCase(), + tipo_pessoa: buyer.registry_type.toUpperCase() === 'P' ? 'F' : 'J', + uf: (address.stateCode).toUpperCase() + } + + Object.assign(titulo, { pagador }) + + return { ambiente: isHomologation ? 'T' : 'P', titulo } +} + +module.exports = createBodyToBillet diff --git a/functions/lib/billet/billet-test.js b/functions/lib/billet/billet-test.js new file mode 100644 index 0000000..ef6ede6 --- /dev/null +++ b/functions/lib/billet/billet-test.js @@ -0,0 +1,142 @@ +const billet = { + retorno: '49', + titulo: { + beneficiario: { + codigo: '5731168866247', + cpf_cnpj: '76209196126', + nome: 'uÍiÀI', + nome_fantasia: 'ÀÃ%ÔGÀkÁzmyau`OPYoáT?v9_ÉÚÍ3;fÂUyÀ=h7~XSzÓyqF4Q.#vN', + tipo_pessoa: 'J' + }, + codigo_barras: '55283391686229690574349498672515103287485996', + data_emissao: '5655-12-02', + data_vencimento: '4348-09-31', + especie: '02', + instrucoes: { + juros: { + codigo: 2, + data: '6324-10-31', + taxa: '-271.8', + valor: '-578496171676.03' + }, + abatimento: { + valor: '1111268606.51' + }, + baixa: { + codigo: 1, + prazo: 36 + }, + desconto: { + codigo: 5, + data: '7772-11-07', + taxa: '-7.08', + valor: '-682677.95' + }, + multa: { + codigo: 2, + data: '1689-03-06', + taxa: '0753.4', + valor: '679.05' + }, + protesto: { + codigo: 1, + prazo: 2 + } + }, + linha_digitavel: '77269815406457311243003537544386312277562531949', + nosso_numero: '8513805687', + pag_parcial: { + autoriza: 1, + codigo: 1, + percentual_max: '-2.82', + percentual_min: '-898.0', + quantidade: 90, + tipo: 1, + valor_max: '819279703429.29', + valor_min: '150673382.60' + }, + pagador: { + aceite: 'N', + cep: '65514150', + cidade: '`hzvú`NY', + cpf_cnpj: '85417382064', + endereco: 'ú_1vánÁ:_ôLÂgoÇu#+;d\\êUãÚÃcáocçwyd#', + nome: '0vâç9À# G \\k81hXO#êàÍ2p', + tipo_pessoa: 'F', + uf: 'HU' + }, + seu_numero: '.T5$s-ZyCj', + valor_nominal: '-49231204.08', + carteira: 5, + hibrido: { + autoriza: 'S', + copia_cola: "pSx@k`{MccaQkm$i2`0*xNY[*1=K4|RfL'm_LBx4~IN,obW$2l0Q%SFY|IC2b*;n7R'}?SAH~ .Kx/[:%A#qOjTe7U!cdu,hsoBf077gxC=x2L5LW\\}XSEhu1k D?J8@)mq5'LP~4;@S1#EBW5/VGtE:BafwCESU#L~9tu", + location: "_;D.zb$A_RX'P_i+a5F9Rx!Nd9jfme_X+{G5},3VDLUtG2U?1]0)Z(i'qSR", + situacao: 'N', + txid: '930072925297634867722746857370174' + }, + id_titulo_empresa: 'Jm1QdffG4ATmT9vc6MdnFED', + mensagens: [ + { + linha: 1, + texto: 'ÜlA?}?ÁLX=aõfVoaálBUÜK3Q_' + } + ], + operacoes: { + custas_cartorio: '-593529996407.27', + data_baixa: '6031-06-01', + data_credito: '5076-12-08', + data_pagamento: '4015-02-26', + data_reembolso: '7973-08-31', + ressarcimento_cartorio: '-06858.22', + tarifa_aponte_cartorio: '-5772142.19', + tarifa_baixa_liquidacao: '-631558390.13', + tarifa_interbancaria: '2786404686.91', + tarifa_manutencao_mensal: '5784.51', + tarifa_registro: '976691950.11', + tarifa_sustacao: '-984300.69', + tarifas_diversas: '-968.81', + valor_abatimento_utilizado: '2.07', + valor_cobrado: '9047821.85', + valor_creditado_debitado: '7722975.40', + valor_desconto_utilizado: '1660661.71', + valor_iof: '-5800.18', + valor_juros_pago: '65918831.20', + valor_juros_recebido: '-06161021419.64', + valor_multa_recebido: '2.49', + valor_pagamento: '-8974290.59', + valor_reembolso: '3980.25' + }, + rateio: { + beneficiarios: [ + { + codigo: '0341947597124', + cpf_cnpj: '96722574999', + nome: "IÔ0b;W:JBÜÀç#POzú\\mrf5'Õ=SÚ+EJ=wÁiqLTSDrws|zOXU'Í+ÂêwbÊ$çX!h", + nome_fantasia: 's7útÉ]é#17Â+Ua', + parcela: 5, + percentual: '190.037', + tipo_pessoa: 'J', + valor: '-3.67' + } + ], + codigo: 2, + tipo_valor: 2 + }, + situacao_banrisul: 'T', + situacao_cip: 'A', + situacao_pagamento: 4, + valor_iof: '-38.70' + } +} + +/* +const testGerate = () => { + console.log('>> Gerate') + const gerate = require('./gerate-billet') + gerate(billet.titulo) +} +testGerate() +// */ + +module.exports = billet diff --git a/functions/lib/billet/gerate-billet.js b/functions/lib/billet/gerate-billet.js new file mode 100644 index 0000000..c4c4da6 --- /dev/null +++ b/functions/lib/billet/gerate-billet.js @@ -0,0 +1,52 @@ +const Pdf = require('pdfkit') +const layoutPDF = require('./utils/layout-pdf') +const descriptionsPDF = require('./utils/descriptions-pdf') +const { join } = require('path') + +/* + REF.: + https://github.com/Romulosanttos/gerar-boletos +*/ + +const generateBilletBanking = (billet, isSandbox) => new Promise((resolve, reject) => { + try { + const dirAssets = join(process.cwd(), '/assets') + const dirFonts = join(dirAssets, '/fonts') + + const pdf = new Pdf({ + size: [595.44, 881.68] + }) + + const timesNewRoman = join(dirFonts, 'Times New Roman.ttf') + const timesNewRomanBold = join(dirFonts, 'Times New Roman Bold.ttf') + const code25I = join(dirFonts, 'Code25I.ttf') + + const chunks = [] + pdf.on('data', (buffer) => { + chunks.push(buffer) + }) + + pdf.on('end', () => { + resolve(Buffer.concat(chunks)) + }) + + pdf.registerFont('normal', timesNewRoman) + pdf.registerFont('bold', timesNewRomanBold) + pdf.registerFont('barCode', code25I) + + /* + const fs = require('fs') + const dirFile = join(dirAssets, '/tmp/billet.pdf') + pdf.pipe(fs.createWriteStream(dirFile)) + // */ + + layoutPDF(pdf) + descriptionsPDF(pdf, billet, isSandbox) + + pdf.end() + } catch (err) { + reject(err) + } +}) + +module.exports = generateBilletBanking diff --git a/functions/lib/billet/utils/descriptions-pdf.js b/functions/lib/billet/utils/descriptions-pdf.js new file mode 100644 index 0000000..728d474 --- /dev/null +++ b/functions/lib/billet/utils/descriptions-pdf.js @@ -0,0 +1,271 @@ +const { + spaceCol, + colStart, + line +} = require('./dimensions') + +const parseEspecie = { + '02': 'DM', + '04': 'DS', + 31: 'CC', + 32: 'BDP', + 99: 'DV' +} + +const addText = ( + pdf, + fontType, + fontSize, + text, + posX, + posY, + width, + align = 'left' +) => { + pdf + .font(fontType || 'normal') + .fontSize(fontSize) + .text(text, posX, posY, + { + lineBreak: false, + width, + align + } + ) +} +const titles = { + instrucoes: 'Instruções de responsabilidade do BENEFICIÁRIO', + dataDocumento: 'Data Documento', + nomeDoPagador: 'Nome do Cliente', + agenciaECodigoDoBeneficiario: 'Agência / Código do Beneficiário', + nossoNumero: 'Nosso Número', + especie: 'Espécie', + especieDoDocumento: 'Espécie Doc.', + quantidade: 'Quantidade', + numeroDoDocumento: 'Nº do Documento', + dataDeProcessamento: 'Data Processamento', + valorDoDocumento: '(=) Valor do Documento', + valor: 'Valor', + carteira: 'Carteira', + moraMulta: '(+) Mora / Multa', + localDoPagamento: 'Local do Pagamento' +} + +const handleDate = (date) => { + const newDate = date.split('-') + return `${newDate[2]}/${newDate[1]}/${newDate[0]}` +} + +const handleInstructions = (instructions, dayExpiry, pdf, posCol, lastLine, withCol) => { + const { + juros, + desconto, + multa, + protesto + } = instructions + + let hasInterest = false + let text = '' + + if (juros && (juros.codigo !== 3)) { + text = `APLICAR JUROS DE ${juros.codigo === 2 ? `${(juros.taxa).replace('.', ',')}% AO MÊS` : `R$${(juros.valor).replace('.', ',')} AO DIA`} ` + hasInterest = true + } + if (multa) { + text += `${hasInterest ? 'E' : 'APLICAR'} MULTA DE ${multa.codigo === 2 ? `${(multa.taxa).replace('.', ',')}%` : `R$${(multa.valor).replace('.', ',')}`} AO DIA` + } + text = text.length ? `${text} após o vencimento` : '' + addText(pdf, 'normal', 8, text?.toUpperCase(), posCol, line(lastLine + 6, -2, 'write'), withCol * 5) + + if (desconto) { + let textDiscount = '' + textDiscount = `APLICAR DESCONTO DE ${desconto.codigo === 2 ? `${(desconto.taxa).replace('.', ',')}%` : `R$${(desconto.valor).replace('.', ',')}`} até` + textDiscount = dayExpiry === desconto.data ? `${textDiscount} o vencimento` : `${textDiscount} dia ${handleDate(dayExpiry)}` + addText(pdf, 'normal', 8, textDiscount?.toUpperCase(), posCol, line(lastLine + 7, 10, 'write'), withCol * 5) + } + + if (protesto && protesto.codigo !== 3) { + const textProtest = `protestar em ${protesto.prazo} dias após o vencimento` + addText(pdf, 'normal', 8, textProtest?.toUpperCase(), posCol, line(lastLine + 7, -2, 'write'), withCol * 5) + } +} + +const handleDigitableLine = (digitableLine) => { + const arrayDigitableLine = digitableLine.split('') + return arrayDigitableLine.reduce((accumulator, digit, index) => { + let rule = '' + if (index === 5 || index === 15 || index === 26) { + rule = '.' + } else if (index === 10 || index === 21 || index === 32 || index === 33) { + rule = ' ' + } + return accumulator + rule + digit + }, '') +} + +const handlePayer = (payer, pdf, posCol, lastLine, withCol) => { + addText(pdf, 'bold', 5, 'PAGADOR', posCol, line(lastLine + 11, 8, 'write'), withCol / 2) + let textLine1 = payer.nome + const arrayDocNumber = payer.cpf_cnpj?.split('') + if (payer.tipo_pessoa === 'J') { + textLine1 += ' CNPJ: ' + textLine1 += arrayDocNumber.reduce((accumulator, digit, index) => { + let rule = '' + if (index === 2 || index === 5) { + rule = '.' + } else if (index === 8) { + rule = '/' + } else if (index === 12) { + rule = '-' + } + return accumulator + rule + digit + }, '') + } else { + textLine1 += ' CPF: ' + textLine1 += arrayDocNumber.reduce((accumulator, digit, index) => { + let rule = '' + if (index === 3 || index === 6) { + rule = '.' + } else if (index === 9) { + rule = '-' + } + return accumulator + rule + digit + }, '') + } + + addText(pdf, 'normal', 9, textLine1, posCol + (withCol / 2), line(lastLine + 11, 8, 'write'), withCol * 4) + addText(pdf, 'normal', 9, payer.endereco || '', posCol, line(lastLine + 11, -2, 'write'), withCol * 5) + + const textLine2 = `${payer.cidade || ''} - ${payer.uf || ''} CEP: ${payer.cep || ''}` + addText(pdf, 'normal', 9, textLine2, posCol, line(lastLine + 11, -14, 'write'), withCol * 5) +} + +const handleCodeBar = (text) => { + // REF: + // https://github.com/Romulosanttos/gerar-boletos/blob/master/lib/boleto/gerador-de-boleto.js#L624 + if (text.length % 2 !== 0) { + throw new Error('Text must have an even number of characters') + } + const start = String.fromCharCode(201) + const stop = String.fromCharCode(202) + + return text.match(/.{2}/g) + .reduce((accumulator, part) => { + const value = parseInt(part, 10) + let ascii + + if (value >= 0 && value <= 93) { + ascii = value + 33 + } + + if (value >= 94 && value <= 99) { + ascii = value + 101 + } + + return accumulator + String.fromCharCode(ascii) + }, start) + stop +} + +const renderPdf = (pdf, lastLine, billet, isReceipt, isSandbox) => { + const posX = colStart + 90 + const withCol = spaceCol - 20 + const posCol = colStart + 5 + const beneficiario = billet?.beneficiario + const pagador = billet?.pagador + + addText(pdf, 'bold', 18, '041-8', posX + 10, line(lastLine + 1, 7, 'write'), withCol, 'center') + + if (isReceipt) { + addText(pdf, 'normal', 8, 'SAC BANRISUL: 0800-646-1515 OUVIDORIA BANRISUL: 0800-644-2200', posX + withCol * 1.5, line(lastLine + 1, 7, 'write'), withCol * 1.5) + addText(pdf, 'bold', 10, 'RECIBO PAGADOR', posX + (3.5 * withCol), line(lastLine + 1, 7, 'write'), withCol) + } else { + addText(pdf, 'bold', 12, handleDigitableLine(billet.linha_digitavel), posX + withCol, line(lastLine + 1, 2, 'write'), withCol * 3.5, 'right') + } + + // row 1 + addText(pdf, 'bold', 5, titles.localDoPagamento.toLocaleUpperCase(), colStart + 5, line(lastLine + 2, 8, 'write'), withCol + 30) + addText(pdf, null, 9, 'PAGÁVEL PREFERENCIALMENTE NA REDE INTEGRADA BANRISUL', colStart + 5, line(lastLine + 2, -2, 'write'), withCol * 3, 'center') + addText(pdf, 'bold', 5, 'VENCIMENTO', posX + (withCol * 3.5), line(lastLine + 2, 8, 'write'), withCol) + addText(pdf, 'normal', 9, billet.data_vencimento && handleDate(billet.data_vencimento), posX + (withCol * 3.5), line(lastLine + 2, -2, 'write'), withCol, 'right') + + // row 2 + addText(pdf, 'bold', 5, 'BENEFICIÁRIO', posCol, line(lastLine + 3, 8, 'write'), withCol * 3) + // Beneficiário nome + addText(pdf, null, 9, (beneficiario?.nome_fantasia || beneficiario?.nome), colStart + 5, line(lastLine + 3, -2, 'write'), withCol * 4) + addText(pdf, 'bold', 5, titles.agenciaECodigoDoBeneficiario?.toUpperCase(), posX + (withCol * 3.5), line(lastLine + 3, 8, 'write'), withCol) + // Código + addText(pdf, 'normal', 9, beneficiario?.codigo, posX + (withCol * 3.5), line(lastLine + 3, -2, 'write'), withCol, 'right') + // + + // row 3 + addText(pdf, 'bold', 5, titles.dataDocumento?.toUpperCase(), posCol, line(lastLine + 4, 8, 'write'), withCol + 30) + // data emissao + addText(pdf, 'normal', 9, billet.data_emissao && handleDate(billet.data_emissao), posCol, line(lastLine + 4, -2, 'write'), withCol + 30) + // seu numero + addText(pdf, 'bold', 5, titles.numeroDoDocumento?.toUpperCase(), posCol + withCol, line(lastLine + 4, 8, 'write'), withCol) + addText(pdf, 'normal', 9, billet.seu_numero, posCol + withCol, line(lastLine + 4, -2, 'write'), withCol) + + addText(pdf, 'bold', 5, titles.especieDoDocumento?.toUpperCase(), posCol + (2 * withCol), line(lastLine + 4, 8, 'write'), withCol) + addText(pdf, 'normal', 9, parseEspecie[billet.especie || 99], posCol + (2 * withCol), line(lastLine + 4, -2, 'write'), withCol, 'center') + // + addText(pdf, 'bold', 5, 'ACEITE', posCol + (3 * withCol), line(lastLine + 4, 8, 'write'), withCol / 4, 'center') + addText(pdf, 'normal', 9, pagador.aceite === 'A' ? 'S' : 'N', posCol + (3 * withCol), line(lastLine + 4, -2, 'write'), withCol / 4, 'center') + // + addText(pdf, 'bold', 5, titles.dataDeProcessamento?.toUpperCase(), posCol + (3 * withCol) + 40, line(lastLine + 4, 8, 'write'), withCol) + // + addText(pdf, 'bold', 5, titles.nossoNumero?.toUpperCase(), posX + (withCol * 3.5), line(lastLine + 4, 8, 'write'), withCol) + addText(pdf, 'normal', 9, billet.nosso_numero, posX + (withCol * 3.5), line(lastLine + 4, -2, 'write'), withCol, 'right') + // + // row 4 + addText(pdf, 'bold', 5, 'USO DO BANCO', posCol, line(lastLine + 5, 8, 'write'), withCol) + // + addText(pdf, 'bold', 5, titles.especie?.toUpperCase(), posX + (withCol * 0.5), line(lastLine + 5, 8, 'write'), withCol) + addText(pdf, 'normal', 9, 'R$', posX + (withCol * 0.5), line(lastLine + 5, -2, 'write'), withCol, 'center') + // + addText(pdf, 'bold', 5, titles.quantidade?.toUpperCase(), posX + (withCol * 1.55), line(lastLine + 5, 8, 'write'), withCol) + // + addText(pdf, 'bold', 5, titles.valor?.toUpperCase(), posX + (withCol * 2.75), line(lastLine + 5, 8, 'write'), withCol) + // + addText(pdf, 'bold', 5, titles.valorDoDocumento?.toUpperCase(), posX + (withCol * 3.5), line(lastLine + 5, 8, 'write'), withCol) + addText(pdf, 'bold', 9, (billet.valor_nominal).replace('.', ','), posX + (withCol * 3.5), line(lastLine + 5, -2, 'write'), withCol, 'right') + // + + // row 5 + addText(pdf, 'bold', 5, titles.instrucoes?.toUpperCase(), posCol, line(lastLine + 6, 8, 'write'), withCol * 5) + handleInstructions(billet.instrucoes, billet.data_vencimento, pdf, posCol, lastLine, withCol) + // 605 caracteres with 11 rows + addText(pdf, 'normal', 10, '', posCol, line(lastLine + 6, 0, 'write'), withCol * 4) + // row 6 + addText(pdf, 'bold', 5, '(-) DESCONTO/ABATIMENTO', posX + (withCol * 3.5), line(lastLine + 6, 8, 'write'), withCol * 5) + + // row 7 + addText(pdf, 'bold', 5, '(-) OUTRAS DEDUÇÕES', posX + (withCol * 3.5), line(lastLine + 7, 8, 'write'), withCol * 5) + // row 8 + addText(pdf, 'bold', 5, titles.moraMulta?.toUpperCase(), posX + (withCol * 3.5), line(lastLine + 8, 8, 'write'), withCol * 5) + // row 9 + addText(pdf, 'bold', 5, '(+) OUTROS ACRÉSCIMOS', posX + (withCol * 3.5), line(lastLine + 9, 8, 'write'), withCol * 5) + // row 10 + addText(pdf, 'bold', 5, '(=) VALOR COBRADO', posX + (withCol * 3.5), line(lastLine + 10, 8, 'write'), withCol * 5) + + // row 11 + handlePayer(pagador, pdf, posCol, lastLine, withCol) + + // row 13 + addText(pdf, 'bold', 5, 'SACADOR/AVALISTA', posCol, line(lastLine + 13, 8, 'write'), withCol * 5) + + // row 14 + addText(pdf, 'bold', 5, `AUTENTICAÇÃO MECÂNICA ${isReceipt ? '' : '-FICHA DE COMPENSAÇÃO'}`, posCol + withCol * 3.5, line(lastLine + 15, 0, 'write'), withCol * 5) + if (!isReceipt) { + addText(pdf, 'barCode', 32, handleCodeBar(billet.codigo_barras), posCol - 10, line(lastLine + 14, -14, 'write'), withCol * 4) + } + + // + if (isSandbox) { + addText(pdf, 'bold', 32, 'BOLETO DE TESTE', posCol, line(lastLine + 9, 8, 'write'), withCol * 5) + } +} + +module.exports = function (pdf, billet, isSandbox) { + renderPdf(pdf, 0, billet, true, isSandbox) + renderPdf(pdf, 17, billet, false, isSandbox) +} diff --git a/functions/lib/billet/utils/dimensions.js b/functions/lib/billet/utils/dimensions.js new file mode 100644 index 0000000..75a75c5 --- /dev/null +++ b/functions/lib/billet/utils/dimensions.js @@ -0,0 +1,20 @@ +const spaceCol = 120 +const spaceLine = 23 +const colStart = 27 +const colEnd = 572 + +const line = (number, diff = 0, type = 'stroke') => { + let line = type === 'stroke' ? 100 : 10 + for (let i = 0; i < number; i++) { + line += 23 + } + return line - diff +} + +module.exports = { + spaceCol, + spaceLine, + colStart, + colEnd, + line +} diff --git a/functions/lib/billet/utils/layout-pdf.js b/functions/lib/billet/utils/layout-pdf.js new file mode 100644 index 0000000..717b341 --- /dev/null +++ b/functions/lib/billet/utils/layout-pdf.js @@ -0,0 +1,94 @@ +const { join } = require('path') +const { + spaceCol, + colStart, + colEnd, + line +} = require('./dimensions') + +const dirAssets = join(process.cwd(), '/assets') + +const addStroke = ( + pdf, + lineStartX, + lineStartY, + lineEndX, + lineEndY, + type = false +) => { + const startY = -100 + const startX = 0 + const colorStroke = 'black' + + if (type === 'logo') { + return pdf + .image(dirAssets + '/images/banrisul.png', + startX + lineStartX, + startY + lineStartY, + { + fit: [100, 30] + } + ) + } if (type === 'dash') { + return pdf + .moveTo(startX + lineStartX, startY + lineStartY) + .lineTo(startX + lineEndX, startY + lineEndY) + .dash(3, { space: 5 }) + .stroke(colorStroke) + } else { + return pdf + .moveTo(startX + lineStartX, startY + lineStartY) + .lineTo(startX + lineEndX, startY + lineEndY).stroke(colorStroke) + } +} + +const renderPdf = (pdf, lastLine, isReceipt) => { + // Main Lines + addStroke(pdf, colStart, line(lastLine + 1), colEnd, line(lastLine + 1)) + addStroke(pdf, colStart, line(lastLine + 2), colEnd, line(lastLine + 2)) + addStroke(pdf, colStart, line(lastLine + 3), colEnd, line(lastLine + 3)) + addStroke(pdf, colStart, line(lastLine + 4), colEnd, line(lastLine + 4)) + addStroke(pdf, colStart, line(lastLine + 5), colEnd, line(lastLine + 5)) + // + addStroke(pdf, colEnd - spaceCol + 10, line(lastLine + 6), colEnd, line(lastLine + 6)) + addStroke(pdf, colEnd - spaceCol + 10, line(lastLine + 7), colEnd, line(lastLine + 7)) + addStroke(pdf, colEnd - spaceCol + 10, line(lastLine + 8), colEnd, line(lastLine + 8)) + addStroke(pdf, colEnd - spaceCol + 10, line(lastLine + 9), colEnd, line(lastLine + 9)) + // addStroke(pdf, colEnd - spaceCol + 10, line(lastLine + 10), colEnd, line(lastLine + 10)) + // + addStroke(pdf, colStart, line(lastLine + 10), colEnd, line(lastLine + 10)) + addStroke(pdf, colStart, line(lastLine + 14), colEnd, line(lastLine + 14)) + // colluns top + addStroke(pdf, colStart + spaceCol, line(lastLine + 1, 20), colStart + spaceCol, line(lastLine + 1)) + addStroke(pdf, colStart + spaceCol, line(lastLine + 1, 20), colStart + spaceCol, line(lastLine + 1)) + addStroke(pdf, colStart + 1.5 * spaceCol, line(lastLine + 1, 20), colStart + 1.5 * spaceCol, line(lastLine + 1)) + addStroke(pdf, colStart + 1.5 * spaceCol, line(lastLine + 1, 20), colStart + 1.5 * spaceCol, line(lastLine + 1)) + // main colluns + addStroke(pdf, colStart, line(lastLine + 1), colStart, line(lastLine + 14)) + addStroke(pdf, colEnd, line(lastLine + 1), colEnd, line(lastLine + 14)) + addStroke(pdf, colEnd - spaceCol + 10, line(lastLine + 1), colEnd - spaceCol + 10, line(lastLine + 10)) + // colluns line 3 + addStroke(pdf, colStart + spaceCol - 20, line(lastLine + 3), colStart + spaceCol - 20, line(lastLine + 4)) + addStroke(pdf, colStart + spaceCol + 80, line(lastLine + 3), colStart + spaceCol + 80, line(lastLine + 4)) + addStroke(pdf, colStart + (2.5 * spaceCol), line(lastLine + 3), colStart + (2.5 * spaceCol), line(lastLine + 4)) + addStroke(pdf, colStart + (2.5 * spaceCol) + 40, line(lastLine + 3), colStart + (2.5 * spaceCol) + 40, line(lastLine + 4)) + // colluns line 4 + addStroke(pdf, colStart + spaceCol + 10, line(lastLine + 4), colStart + spaceCol + 10, line(lastLine + 5)) + addStroke(pdf, colStart + spaceCol * 2, line(lastLine + 4), colStart + spaceCol * 2, line(lastLine + 5)) + addStroke(pdf, colStart + (2.95 * spaceCol), line(lastLine + 4), colStart + (2.95 * spaceCol), line(lastLine + 5)) + // + if (isReceipt) { + // footer + addStroke(pdf, colEnd / 2, line(lastLine + 14, -5), colEnd, line(lastLine + 14, -5)) + addStroke(pdf, colEnd / 2, line(lastLine + 14, -5), colEnd / 2, line(lastLine + 14, -33)) + addStroke(pdf, colEnd, line(lastLine + 14, -5), colEnd, line(lastLine + 14, -33)) + } +} + +module.exports = function (pdf) { + renderPdf(pdf, 1, true) + renderPdf(pdf, 18) + addStroke(pdf, colStart + 3, line(1), 0, 0, 'logo') + addStroke(pdf, colStart + 3, line(18), 0, 0, 'logo') + addStroke(pdf, colStart, line(17, 3), colEnd, line(17, 3), 'dash') +} diff --git a/functions/package-lock.json b/functions/package-lock.json index c2e4906..b79dc55 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -10,7 +10,8 @@ "@google-cloud/firestore": "^6.7.0", "express": "^4.18.2", "firebase-admin": "^11.10.1", - "firebase-functions": "^4.4.1" + "firebase-functions": "^4.4.1", + "pdfkit": "^0.13.0" }, "engines": { "node": "16" @@ -326,6 +327,14 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "node_modules/@swc/helpers": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.3.17.tgz", + "integrity": "sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -432,9 +441,9 @@ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==" }, "node_modules/@types/node": { - "version": "18.11.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.13.tgz", - "integrity": "sha512-IASpMGVcWpUsx5xBOrxMj7Bl8lqfuTY7FKAnPmu5cHkfQVWF8GulWS1jbRqA934qZL35xh5xN/+Xe/i26Bod4w==" + "version": "18.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.5.tgz", + "integrity": "sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==" }, "node_modules/@types/qs": { "version": "6.9.7", @@ -565,6 +574,18 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "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==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -592,6 +613,17 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/axios": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", @@ -669,6 +701,14 @@ "balanced-match": "^1.0.0" } }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "dependencies": { + "base64-js": "^1.1.2" + } + }, "node_modules/buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -730,6 +770,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -829,6 +877,11 @@ "node": ">= 0.10" } }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -837,11 +890,54 @@ "ms": "2.0.0" } }, + "node_modules/deep-equal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.1", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, + "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==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -867,6 +963,11 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, "node_modules/duplexify": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", @@ -926,6 +1027,25 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -1196,6 +1316,30 @@ } } }, + "node_modules/fontkit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.9.0.tgz", + "integrity": "sha512-HkW/8Lrk8jl18kzQHvAw9aTHe1cqsyx5sDnxncx652+CIfhawokEPkeM3BoIC+z/Xv7a0yMr0f3pRRwhGH455g==", + "dependencies": { + "@swc/helpers": "^0.3.13", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "deep-equal": "^2.0.5", + "dfa": "^1.2.0", + "restructure": "^2.0.1", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.3.1", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -1240,6 +1384,14 @@ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gaxios": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.0.2.tgz", @@ -1275,12 +1427,13 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" }, "funding": { @@ -1367,6 +1520,17 @@ "node": ">=12.0.0" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -1396,6 +1560,14 @@ "node": ">= 0.4.0" } }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -1404,6 +1576,28 @@ "node": ">=8" } }, + "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==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "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==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -1415,6 +1609,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -1530,6 +1738,19 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "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==", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -1538,6 +1759,85 @@ "node": ">= 0.10" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -1546,6 +1846,62 @@ "node": ">=8" } }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -1562,6 +1918,73 @@ "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==" }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, "node_modules/jose": { "version": "4.11.2", "resolved": "https://registry.npmjs.org/jose/-/jose-4.11.2.tgz", @@ -1745,6 +2168,23 @@ "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" }, + "node_modules/linebreak": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", + "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==", + "dependencies": { + "base64-js": "0.0.8", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/linebreak/node_modules/base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", @@ -1993,6 +2433,46 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -2043,6 +2523,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2064,6 +2549,22 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "node_modules/pdfkit": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.13.0.tgz", + "integrity": "sha512-AW79eHU5eLd2vgRDS9z3bSoi0FA+gYm+100LLosrQQMLUzOBGVOhG7ABcMFpJu7Bpg+MT74XYHi4k9EuU/9EZw==", + "dependencies": { + "crypto-js": "^4.0.0", + "fontkit": "^1.8.1", + "linebreak": "^1.0.2", + "png-js": "^1.0.0" + } + }, + "node_modules/png-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" + }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -2204,6 +2705,22 @@ "node": ">= 6" } }, + "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==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -2220,6 +2737,11 @@ "lodash": "^4.17.21" } }, + "node_modules/restructure": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz", + "integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==" + }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -2441,6 +2963,17 @@ "node": ">= 0.8" } }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/stream-events": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", @@ -2536,6 +3069,11 @@ "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, "node_modules/tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -2609,6 +3147,24 @@ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -2681,6 +3237,53 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/word-wrap": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", @@ -3037,6 +3640,14 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, + "@swc/helpers": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.3.17.tgz", + "integrity": "sha512-tb7Iu+oZ+zWJZ3HJqwx8oNwSDIU440hmVMDPhpACWQWnrZHK99Bxs70gT1L2dnr5Hg50ZRWEFkQCAnOVVV0z1Q==", + "requires": { + "tslib": "^2.4.0" + } + }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -3140,9 +3751,9 @@ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==" }, "@types/node": { - "version": "18.11.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.13.tgz", - "integrity": "sha512-IASpMGVcWpUsx5xBOrxMj7Bl8lqfuTY7FKAnPmu5cHkfQVWF8GulWS1jbRqA934qZL35xh5xN/+Xe/i26Bod4w==" + "version": "18.17.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.5.tgz", + "integrity": "sha512-xNbS75FxH6P4UXTPUJp/zNPq6/xsfdJKussCWNOnz4aULWIRwMgP1LgaB5RiBnMX1DPCYenuqGZfnIAx5mbFLA==" }, "@types/qs": { "version": "6.9.7", @@ -3241,6 +3852,15 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "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==", + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -3265,6 +3885,11 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, + "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==" + }, "axios": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", @@ -3321,6 +3946,14 @@ "balanced-match": "^1.0.0" } }, + "brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "requires": { + "base64-js": "^1.1.2" + } + }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", @@ -3367,6 +4000,11 @@ "wrap-ansi": "^7.0.0" } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3440,6 +4078,11 @@ "vary": "^1" } }, + "crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" + }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -3448,11 +4091,45 @@ "ms": "2.0.0" } }, + "deep-equal": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", + "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "requires": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.1", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.0", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + } + }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, + "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==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3468,6 +4145,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, "duplexify": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.2.tgz", @@ -3521,6 +4203,22 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" }, + "es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + } + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3710,6 +4408,30 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" }, + "fontkit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.9.0.tgz", + "integrity": "sha512-HkW/8Lrk8jl18kzQHvAw9aTHe1cqsyx5sDnxncx652+CIfhawokEPkeM3BoIC+z/Xv7a0yMr0f3pRRwhGH455g==", + "requires": { + "@swc/helpers": "^0.3.13", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "deep-equal": "^2.0.5", + "dfa": "^1.2.0", + "restructure": "^2.0.1", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.3.1", + "unicode-trie": "^2.0.0" + } + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -3745,6 +4467,11 @@ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, "gaxios": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-5.0.2.tgz", @@ -3771,12 +4498,13 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" }, "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" } }, @@ -3838,6 +4566,14 @@ "node-forge": "^1.3.1" } }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", @@ -3861,16 +4597,42 @@ "function-bind": "^1.1.1" } }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, + "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==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "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==" + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -3962,16 +4724,110 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "requires": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "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==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==" + }, + "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==", + "requires": { + "call-bind": "^1.0.2" + } + }, "is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -3982,6 +4838,49 @@ "resolved": "https://registry.npmjs.org/is-stream-ended/-/is-stream-ended-0.1.4.tgz", "integrity": "sha512-xj0XPvmr7bQFTvirqnFr50o0hQIh6ZItDqloxt5aJrR4NQsYeSsyFQERYGCAzfindAcnKjINnwEEgLx4IqVzQw==" }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "requires": { + "which-typed-array": "^1.1.11" + } + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==" + }, + "is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, "jose": { "version": "4.11.2", "resolved": "https://registry.npmjs.org/jose/-/jose-4.11.2.tgz", @@ -4142,6 +5041,22 @@ "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.5.tgz", "integrity": "sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA==" }, + "linebreak": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.1.0.tgz", + "integrity": "sha512-MHp03UImeVhB7XZtjd0E4n6+3xr5Dq/9xI/5FptGk5FrbDR3zagPa2DS6U8ks/3HjbKWG9Q1M2ufOzxV2qLYSQ==", + "requires": { + "base64-js": "0.0.8", + "unicode-trie": "^2.0.0" + }, + "dependencies": { + "base64-js": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", + "integrity": "sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==" + } + } + }, "linkify-it": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", @@ -4321,6 +5236,31 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "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==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -4359,6 +5299,11 @@ "yocto-queue": "^0.1.0" } }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -4374,6 +5319,22 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, + "pdfkit": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.13.0.tgz", + "integrity": "sha512-AW79eHU5eLd2vgRDS9z3bSoi0FA+gYm+100LLosrQQMLUzOBGVOhG7ABcMFpJu7Bpg+MT74XYHi4k9EuU/9EZw==", + "requires": { + "crypto-js": "^4.0.0", + "fontkit": "^1.8.1", + "linebreak": "^1.0.2", + "png-js": "^1.0.0" + } + }, + "png-js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz", + "integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g==" + }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -4478,6 +5439,16 @@ "util-deprecate": "^1.0.1" } }, + "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==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -4491,6 +5462,11 @@ "lodash": "^4.17.21" } }, + "restructure": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-2.0.1.tgz", + "integrity": "sha512-e0dOpjm5DseomnXx2M5lpdZ5zoHqF1+bqdMJUohoYVVQa7cBdnk7fdmeI6byNWP/kiME72EeTiSypTCVnpLiDg==" + }, "retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -4648,6 +5624,14 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" }, + "stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "requires": { + "internal-slot": "^1.0.4" + } + }, "stream-events": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", @@ -4725,6 +5709,11 @@ "resolved": "https://registry.npmjs.org/text-decoding/-/text-decoding-1.0.0.tgz", "integrity": "sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==" }, + "tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, "tmp": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", @@ -4780,6 +5769,24 @@ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==" }, + "unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "requires": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "requires": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -4834,6 +5841,41 @@ "webidl-conversions": "^3.0.0" } }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-typed-array": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "requires": { + "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" + } + }, "word-wrap": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", diff --git a/functions/package.json b/functions/package.json index 88da134..6851252 100644 --- a/functions/package.json +++ b/functions/package.json @@ -16,7 +16,8 @@ "@google-cloud/firestore": "^6.7.0", "express": "^4.18.2", "firebase-admin": "^11.10.1", - "firebase-functions": "^4.4.1" + "firebase-functions": "^4.4.1", + "pdfkit": "^0.13.0" }, "private": true } diff --git a/functions/routes/billet.js b/functions/routes/billet.js new file mode 100644 index 0000000..c997f91 --- /dev/null +++ b/functions/routes/billet.js @@ -0,0 +1,37 @@ +const geratePdf = require('../lib/billet/gerate-billet') + +exports.get = async ({ appSdk, admin }, req, res) => { + const collectionBillet = admin.firestore().collection('billets') + try { + const { orderId } = req.query + const doc = await collectionBillet.doc(orderId).get() + let billet + if (doc) { + billet = doc.data() + } + if (billet) { + const { titulo } = billet + + const bufferFile = await geratePdf(titulo, billet.isSandbox) + res.setHeader('Content-Length', Buffer.byteLength(bufferFile)) + res.setHeader('Content-Type', 'application/pdf') + res.setHeader('Cache-Control', 'public, max-age=60') + res.setHeader('Content-Disposition', `attachment; filename=${orderId || 'Boleto-Banrisul'}.pdf`) + res.send(bufferFile) + } else { + res.status(404) + .send({ + error: 'Not Found', + message: `Document #${orderId} not found` + }) + } + } catch (err) { + console.error(err) + res.status(500) + const { message } = err + res.send({ + error: 'BILLET_API_ERROR', + message + }) + } +} diff --git a/functions/routes/ecom/modules/apply-discount.js b/functions/routes/ecom/modules/apply-discount.js deleted file mode 100644 index e7a3ed4..0000000 --- a/functions/routes/ecom/modules/apply-discount.js +++ /dev/null @@ -1,44 +0,0 @@ -exports.post = ({ appSdk, admin }, req, res) => { - /** - * Requests coming from Modules API have two object properties on body: `params` and `application`. - * `application` is a copy of your app installed by the merchant, - * including the properties `data` and `hidden_data` with admin settings configured values. - * JSON Schema reference for the Apply Discount module objects: - * `params`: https://apx-mods.e-com.plus/api/v1/apply_discount/schema.json?store_id=100 - * `response`: https://apx-mods.e-com.plus/api/v1/apply_discount/response_schema.json?store_id=100 - * - * Complete (advanced) example in our default discouts app: - * https://github.com/ecomplus/discounts/blob/master/routes/ecom/modules/apply-discount.js - */ - - const { params, application } = req.body - const { storeId } = req - const response = {} - // merge all app options configured by merchant - const appData = Object.assign({}, application.data, application.hidden_data) - - if (appData.available_extra_discount) { - response.available_extra_discount = appData.available_extra_discount - } - if (params.discount_coupon) { - // should match discount by coupon code - } - - /* DO THE STUFF HERE TO FILL RESPONSE OBJECT WITH DISCOUNT OPTIONS */ - - /** - * Sample snippets: - - // set discount value - response.discount_rule = { - label: 'X Campaign', - extra_discount: { - value: 20.5, - flags: ['x-coupon'] - } - } - - */ - - res.send(response) -} diff --git a/functions/routes/ecom/modules/calculate-shipping.js b/functions/routes/ecom/modules/calculate-shipping.js deleted file mode 100644 index 26a7b4b..0000000 --- a/functions/routes/ecom/modules/calculate-shipping.js +++ /dev/null @@ -1,69 +0,0 @@ -exports.post = ({ appSdk }, req, res) => { - /** - * Treat `params` and (optionally) `application` from request body to properly mount the `response`. - * JSON Schema reference for Calculate Shipping module objects: - * `params`: https://apx-mods.e-com.plus/api/v1/calculate_shipping/schema.json?store_id=100 - * `response`: https://apx-mods.e-com.plus/api/v1/calculate_shipping/response_schema.json?store_id=100 - * - * Examples in published apps: - * https://github.com/ecomplus/app-mandabem/blob/master/functions/routes/ecom/modules/calculate-shipping.js - * https://github.com/ecomplus/app-datafrete/blob/master/functions/routes/ecom/modules/calculate-shipping.js - * https://github.com/ecomplus/app-jadlog/blob/master/functions/routes/ecom/modules/calculate-shipping.js - */ - - const { params, application } = req.body - const { storeId } = req - // setup basic required response object - const response = { - shipping_services: [] - } - // merge all app options configured by merchant - const appData = Object.assign({}, application.data, application.hidden_data) - - if (appData.free_shipping_from_value >= 0) { - response.free_shipping_from_value = appData.free_shipping_from_value - } - if (!params.to) { - // just a free shipping preview with no shipping address received - // respond only with free shipping option - res.send(response) - return - } - - /* DO THE STUFF HERE TO FILL RESPONSE OBJECT WITH SHIPPING SERVICES */ - - /** - * Sample snippets: - - if (params.items) { - let totalWeight = 0 - params.items.forEach(item => { - // treat items to ship - totalWeight += item.quantity * item.weight.value - }) - } - - // add new shipping service option - response.shipping_services.push({ - label: appData.label || 'My shipping method', - carrier: 'My carrier', - shipping_line: { - from: appData.from, - to: params.to, - package: { - weight: { - value: totalWeight - } - }, - price: 10, - delivery_time: { - days: 3, - working_days: true - } - } - }) - - */ - - res.send(response) -} diff --git a/functions/routes/ecom/modules/create-transaction.js b/functions/routes/ecom/modules/create-transaction.js index 8b8b650..53418d4 100644 --- a/functions/routes/ecom/modules/create-transaction.js +++ b/functions/routes/ecom/modules/create-transaction.js @@ -1,4 +1,10 @@ -exports.post = ({ appSdk, admin }, req, res) => { +const { baseUri } = require('../../../__env') +const Banrisul = require('../../../lib/banrisul/auth/create-access') +const getOurNumber = require('../../../lib/banrisul/calculate-our-number') +const createBodyToBillet = require('../../../lib/banrisul/payload-to-billet') + +exports.post = async ({ appSdk, admin }, req, res) => { + const collectionBillet = admin.firestore().collection('billets') /** * Requests coming from Modules API have two object properties on body: `params` and `application`. * `application` is a copy of your app installed by the merchant, @@ -17,33 +23,91 @@ exports.post = ({ appSdk, admin }, req, res) => { // merge all app options configured by merchant const appData = Object.assign({}, application.data, application.hidden_data) // setup required `transaction` response object - const transaction = {} + const { amount } = params + const orderId = params.order_id // indicates whether the buyer should be redirected to payment link right after checkout let redirectToPayment = false + const transaction = { + amount: amount.total + } - /** - * Do the stuff here, call external web service or just fill the `transaction` object - * according to the `appData` configured options for the chosen payment method. - */ + if (params.payment_method.code === 'banking_billet') { + const banrisul = new Banrisul(appData.client_id, appData.client_secret, storeId) + try { + if (appData.beneficiary_code) { + await banrisul.preparing - // WIP: - switch (params.payment_method.code) { - case 'credit_card': - // you may need to handle card hash and create transaction on gateway API - break - case 'banking_billet': - // create new "Boleto bancário" - break - case 'online_debit': - redirectToPayment = true - break - default: - break - } + const documentRef = banrisul.documentRef && await banrisul.documentRef.get() + const docAuthBarisul = documentRef?.data() + const lastBilletNumber = (docAuthBarisul?.lastBilletNumber || 0) + 1 + const banrisulAxios = banrisul.axios + + const ourNumber = getOurNumber(lastBilletNumber) + const body = createBodyToBillet(appData, params, ourNumber) + + console.log('>>body ', JSON.stringify(body)) + redirectToPayment = false - res.send({ - redirect_to_payment: redirectToPayment, - transaction - }) + // test + // const data = require('../../../lib/billet/billet-test') + const { data } = await banrisulAxios.post('/boletos', body, { + headers: { + 'bergs-beneficiario': appData.beneficiary_code + } + }) + + console.log('>> boleto ', JSON.stringify(data)) + transaction.banking_billet = { + code: data.titulo?.linha_digitavel, + valid_thru: new Date(data.titulo?.data_vencimento).toISOString(), + link: `${baseUri}/billet?orderId=${orderId}` + } + + transaction.intermediator = { + transaction_id: data?.titulo?.nosso_numero, + transaction_reference: data?.titulo?.nosso_numero, + transaction_code: data.retorno + } + + await collectionBillet.doc(orderId).set({ ...data, storeId, isHomologation: appData.is_homologation }) + + banrisul.documentRef.set({ lastBilletNumber }, { merge: true }) + .catch(console.error) + + res.send({ + redirect_to_payment: redirectToPayment, + transaction + }) + } else { + throw new Error('Beneficiary code not found') + } + } catch (error) { + console.log(error.response) + // try to debug request error + const errCode = 'BANRISUL_TRANSACTION_ERR' + let { message } = error + const err = new Error(`${errCode} #${storeId} - ${orderId} => ${message}`) + if (error.response) { + const { status, data } = error.response + if (status !== 401 && status !== 403) { + err.payment = JSON.stringify(transaction) + err.status = status + if (typeof data === 'object' && data) { + err.response = JSON.stringify(data) + } else { + err.response = data + } + } else if (data && Array.isArray(data.errors) && data.errors[0] && data.errors[0].message) { + message = data.errors[0].message + } + } + console.error(err) + res.status(409) + res.send({ + error: errCode, + message + }) + } + } } diff --git a/functions/routes/ecom/modules/list-payments.js b/functions/routes/ecom/modules/list-payments.js index 9d76a82..f16ce92 100644 --- a/functions/routes/ecom/modules/list-payments.js +++ b/functions/routes/ecom/modules/list-payments.js @@ -12,38 +12,83 @@ exports.post = ({ appSdk }, req, res) => { * https://github.com/ecomplus/app-custom-payment/blob/master/functions/routes/ecom/modules/list-payments.js */ - const { params, application } = req.body - const { storeId } = req + const { application, params } = req.body + // const { storeId } = req // setup basic required response object const response = { payment_gateways: [] } - // merge all app options configured by merchant const appData = Object.assign({}, application.data, application.hidden_data) + const isHomologation = appData.is_homologation - /* DO THE STUFF HERE TO FILL RESPONSE OBJECT WITH PAYMENT GATEWAYS */ + const amount = { ...params.amount } || {} - /** - * Sample snippets: + if (!appData.client_id || !appData.client_secret) { + return res.status(409).send({ + error: 'NO_BANRISUL_KEYS', + message: 'Client ID e/ou Secret da API indefinido(s) (lojista deve configurar o aplicativo)' + }) + } // add new payment method option - response.payment_gateways.push({ + const gateway = { intermediator: { - code: 'paupay', - link: 'https://www.palpay.com.br', - name: 'paupay' + code: 'banrisul', + link: 'https://www.banrisul.com.br/', + name: 'Banrisul' }, - payment_url: 'https://www.palpay.com.br/', type: 'payment', payment_method: { code: 'banking_billet', name: 'Boleto Bancário' }, - label: 'Boleto Bancário', - expiration_date: appData.expiration_date || 14 - }) + label: `Boleto Bancário${isHomologation ? ' - Homologação' : ''}`, + expiration_date: appData.expiration_date || 7 + } + + const discount = appData.discount + + if (discount) { + gateway.discount = { + apply_at: discount.apply_at, + type: discount.type, + value: discount.value + } + + // check amount value to apply discount + if (amount.total < (discount.min_amount || 0)) { + delete gateway.discount + } else { + delete discount.min_amount + + // fix local amount object + const applyDiscount = discount.apply_at + + const maxDiscount = amount[applyDiscount || 'subtotal'] + let discountValue + if (discount.type === 'percentage') { + discountValue = maxDiscount * discount.value / 100 + } else { + discountValue = discount.value + if (discountValue > maxDiscount) { + discountValue = maxDiscount + } + } + + if (discountValue) { + amount.discount = (amount.discount || 0) + discountValue + amount.total -= discountValue + if (amount.total < 0) { + amount.total = 0 + } + } + } + if (response.discount_option) { + response.discount_option.min_amount = discount.min_amount + } + } - */ + response.payment_gateways.push(gateway) res.send(response) } diff --git a/hosting/description.md b/hosting/description.md index e0e5c32..d7665d8 100644 --- a/hosting/description.md +++ b/hosting/description.md @@ -1,3 +1,76 @@ -# My Awesome E-Com Plus App +# Boleto Banrisul + +# Antes de comerçar +Será necessário solicitar ao banco Banrisul as credenciais para a homologação do aplicativo. + +Ref.: [Documentação Api Cobrança Banrisul](https://developers-openbanking.banrisul.com.br/pages/PORTAL_V1.6.6/docs/clientes-banrisul/api-cobranca-v1.1.0.html) + + +
+ +## 1) Deverá encaminhar um e-mail solicitando a integração com a Api de cobrança. + +
+ +Encaminhar e-mail para: ```atendimento_teste_cobranca@banrisul.com.br``` + +Informações solicitadas pelo banco para cadastramento: + +> CNPJ: +> +> Razão Social: +> +> Quantidade de requisições/chamadas por dia (aproximado) +> *(Recomendamos aqui uma média de vendas por dia X 2)* : +> +> Nome do responsável técnico: +> +> E-mail de contato do responsável técnico: +> +> OBS: O “Convite” será enviado para este e-mail; +> +> Nome da aplicação (apelido): +> +> Por exemplo "Sua Loja E-com Banrisul” +> +> Sandbox: sim ( ) não ( ) +> +> Produção: sim ( ) não ( ) + + +> **Obs.:** +> * no Sandbox não é necessário usar um código beneficiário ativo; em produção sim, mesmo que seja apenas para teste. +> +> * se tiverem código beneficiário ativo, favor informar na resposta deste e-mail. + +> Após o cadastramento vocês receberão um “Convite” no e-mail informado neste cadastro para acessar o portal e concluir o cadastramento. +> +> Serão dois “Convites”: um para o Sandbox e outro para Produção. +> +> Tanto em Produção quanto no Sandbox o Secret não estará visível no primeiro acesso, sendo necessário alterá-lo. +> +> Após a alteração, em Sandbox a liberação é automática. +> +> Em Produção o Banco deverá ser comunicado para a liberação. + +
+ +## 2) Acesso ao portal do Desenvolvedor Banrisul +
+ +Após cadastro realizado no portal do Desenvolvedor do Banrisul, obtenha as credenciais de produção do banco e as adicionei ao nosso aplicativo. + +* [Portal Banrisul](https://developersdev.banrisul.com.br/admin/login?to-default-config=true) + +## 3) Homologação + +* Crie um pedido com a opção homologação habilitada. +* Em seguida desabilite a opção homologação e crie 5 pedidos e salve os PDFs +* Envie os 5 PDFs juntamente com os códigos de retornos, que são códigos das transações, para o e-mail: `atendimento_teste_cobranca@banrisul.com.br` para conferência. + +
+ +> ***Informações Banrisul:*** +> +> A equipe Banrisul fará a conferência de campos e informações constantes nos boletos, algo que evitará transtornos futuros ou reclamações de pagadores. Se os boletos estiverem aderentes às regras abaixo, a sua organização será liberada em produção. -Somethings about my app and what it does...