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...