fetch transactions on account creation, added ynab importergit push -f

This commit is contained in:
Alex Phillips 2021-12-08 22:17:46 -05:00
parent a5be8ba4d9
commit 2caff15f67
6 changed files with 3893 additions and 6788 deletions

9289
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/helmet": "^4.0.0",
"@types/jest": "^27.0.3",
"@types/jsonwebtoken": "^8.5.5",
"@types/mongoose": "^5.11.96",
"@types/morgan": "^1.9.3",
@ -40,12 +41,11 @@
"jest": "^27.3.1",
"nodemon": "^2.0.14",
"prettier": "^2.4.1",
"ts-jest": "^27.0.7",
"ts-node": "^10.4.0",
"ts-node-dev": "^1.1.8",
"tslint": "^6.1.3",
"typescript": "^4.4.4",
"@types/jest": "^27.0.3",
"ts-jest": "^27.0.7"
"typescript": "^4.4.4"
},
"dependencies": {
"@dinero.js/currencies": "^2.0.0-alpha.8",
@ -59,9 +59,10 @@
"helmet": "^4.6.0",
"jsonwebtoken": "^8.5.1",
"morgan": "^1.10.0",
"sqlite3": "^5.0.2",
"swagger-ui-express": "^4.1.6",
"tsoa": "^3.14.0",
"typeorm": "^0.2.38",
"sqlite3": "^5.0.2"
"winston": "^3.3.3"
}
}

View File

@ -1,9 +1,14 @@
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import api from '../../api';
import { fetchAccountTransactions } from './Transactions'
export const createAccount = createAsyncThunk('accounts/create', async ({ name, accountType, balance, date}, { getState }) => {
export const createAccount = createAsyncThunk('accounts/create', async ({ name, accountType, balance, date}, { getState, dispatch }) => {
const store = getState()
return await api.createAccount(name, accountType, balance, date, store.budgets.activeBudget.id);
const account = await api.createAccount(name, accountType, balance, date, store.budgets.activeBudget.id);
dispatch(fetchAccountTransactions({ accountId: account.id }))
return account
})
export const editAccount = createAsyncThunk('accounts/edit', async ({ id, name, balance }, { getState }) => {

565
ynab/import.js Normal file
View File

@ -0,0 +1,565 @@
import got from 'got'
import csv from 'csv-parse'
import fs from 'fs'
import { POINT_CONVERSION_COMPRESSED } from 'constants'
import prompt from 'prompt'
import { dinero, multiply, toUnit } from 'dinero.js'
import { USD } from '@dinero.js/currencies'
async function readCSV(file) {
return new Promise(resolve => {
let rows = []
let first = true
fs.createReadStream(file)
.pipe(csv({bom: true}))
.on('data', function (row) {
if (first === true) {
first = false
return
}
rows.push(row)
})
.on('end', function () {
resolve(rows)
})
})
}
export function getDateFromCSVString(date) {
let [month, day, year] = date.split('/')
const newDate = new Date(`${year}-${month}-${day}T12:00:00`)
newDate.setDate(newDate.getDate() + 1)
return newDate
}
export function getDateFromAPIString(date) {
let [year, month, day] = date.split('-').map(val => parseInt(val))
const newDate = new Date(`${year}-${month}-${day}T12:00:00`)
newDate.setDate(newDate.getDate() + 1)
return newDate
}
class BudgE {
constructor(host) {
this.host = host
}
async login(email, password) {
const response = (await this.makeRequest(`login`, 'post', { json: {
email, password
}}))
this.token = response.token
const budgets = await this.getBudgets()
this.budgetId = budgets[0].id
return response
}
async getBudgets() {
const response = (await this.makeRequest(`budgets`)).data
return response
}
async postTransaciton(payload) {
const response = (await this.makeRequest(`budgets/${this.budgetId}/transactions`, 'post', { json: payload })).data
return response
}
async findOrCreateAccount (name, type, balance, date) {
const accounts = (await this.makeRequest(`budgets/${this.budgetId}/accounts`)).data
let filtered = accounts.filter(account => account.name === name)
if (filtered.length === 1) {
return filtered[0]
}
return (await this.makeRequest(`budgets/${this.budgetId}/accounts`, 'post', { json: {
name, type, balance: balance.toJSON().amount, date: date.toISOString().split('T')[0]
} })).data
}
async findOrCreateCategoryGroup (name) {
const categoryGroups = (await this.makeRequest(`budgets/${this.budgetId}/categories`)).data
let filtered = categoryGroups.filter(group => group.name === name)
if (filtered.length === 1) {
return filtered[0]
}
try {
return (await this.makeRequest(`budgets/${this.budgetId}/categories/groups`, 'post', { json: { name } })).data
} catch (err) {
console.log(err.response.body)
process.exit()
}
}
async findOrCreateCategory (name, categoryGroupId) {
const categoryGroups = (await this.makeRequest(`budgets/${this.budgetId}/categories`)).data
const categories = categoryGroups.reduce((acc, group) => {
return acc.concat(group.categories)
}, [])
let filtered = categories.filter(category => category.name === name)
if (filtered.length === 1) {
return filtered[0]
}
try {
console.log(`Creating category ${name}`)
return (await this.makeRequest(`budgets/${this.budgetId}/categories`, 'post', { json: { name, categoryGroupId } })).data
} catch (err) {
console.log(err.response.body)
process.exit()
}
}
async findOrCreatePayee(name) {
const payees = (await this.makeRequest(`budgets/${this.budgetId}/payees`)).data
let filtered = payees.filter(payee => payee.name === name)
if (filtered.length === 1) {
return filtered[0]
}
try {
return (await this.makeRequest(`budgets/${this.budgetId}/payees`, 'post', { json: { name } })).data
} catch (err) {
console.log(err.response.body)
process.exit()
}
}
async updateCategoryMonth(categoryId, month, budgeted) {
return (await this.makeRequest(`budgets/${this.budgetId}/categories/${categoryId}/${month}`, 'put', { json: { budgeted } })).data
}
async makeRequest(url, method = 'get', options = {}) {
let response = await got[method](`${this.host}/api/${url}`, {
...options,
headers: {
'x-access-token': this.token,
Accept: 'application/json',
}
})
return JSON.parse(response.body)
}
}
class YNAB {
constructor(token, budgetId, registerFile, budgetFile) {
this.token = token
this.budgetId = budgetId
this.registerFile = registerFile
this.budgetFile = budgetFile
}
async getAccounts() {
if (fs.existsSync(this.registerFile)) {
return await this.getAccountsFromRegisterFile()
}
return (await this.makeRequest('accounts')).accounts
}
async getAccountsFromRegisterFile() {
const rows = await readCSV(this.registerFile)
let retval = []
for (const row of rows) {
retval.push(row[0])
}
retval = [...new Set(retval)]
return retval.map(name => ({ name }))
}
async getBudgetMonths() {
if (fs.existsSync(this.budgetFile)) {
const rows = await readCSV(this.budgetFile)
let dates = {}
for (const row of rows) {
if (row[0] === 'Month') {
continue
}
if (!dates[row[0]]) {
dates[row[0]] = 0
}
dates[row[0]] += parseFloat(row[4].replace('$', '')) * 1000
}
let retval = []
for (const date in dates) {
const year = (new Date(date)).getFullYear()
const month = (new Date(date)).getMonth() + 1
retval.push({
budgeted: dates[date],
month: `${year}-${month}-01`,
})
}
return retval
}
return (await this.makeRequest('months')).months
}
async getCategoriesFromBudgetFile() {
const rows = await readCSV(this.budgetFile)
let groups = {}
for (const row of rows) {
if (!groups[row[2]]) {
groups[row[2]] = new Set()
}
groups[row[2]].add(row[3])
}
let retval = []
for (const group in groups) {
groups[group] = [...groups[group]]
retval.push({
name: group,
categories: groups[group].map(category => {
return { name: category }
})
})
}
return retval
}
async getCategories() {
if (fs.existsSync(this.budgetFile)) {
return await this.getCategoriesFromBudgetFile()
}
return (await this.makeRequest('categories')).category_groups
}
async getCategoryMonthsFromBudgetFile() {
let retval = []
const rows = await readCSV(this.budgetFile)
for (const row of rows) {
let budgetDate = new Date(row[0])
budgetDate.setHours(12)
retval.push({
"name": row[3],
"month": budgetDate,
"budgeted": parseInt(row[4].replace('$', '').replace('.', '')),
"activity": parseInt(row[5].replace('$', '').replace('.', '')),
"balance": parseInt(row[6].replace('$', '').replace('.', '')),
})
}
retval = retval.sort(function(a,b){
return b.date - a.date
})
return retval.map(catMonth => ({
...catMonth,
month: catMonth.month.toISOString().split('T')[0],
}))
}
async getCategoryMonths() {
if (fs.existsSync(this.budgetFile)) {
return await this.getCategoryMonthsFromBudgetFile()
}
// @TODO: fix
return (await this.makeRequest(`months/${month}/categories/${categoryId}`)).category
}
async getCategoryMonthFromBudgetFile(categoryName, month) {
const rows = await readCSV(this.budgetFile)
for (const row of rows) {
let budgetDate = new Date(row[0])
if (`${budgetDate.getFullYear()}-${(budgetDate.getMonth()) + 1}-01` !== month) {
continue
}
if (categoryName === row[3]) {
return {
"name": categoryName,
"budgeted": parseFloat(row[4].replace('$', '')) * 1000,
"activity": parseFloat(row[5].replace('$', '')) * 1000,
"balance": parseFloat(row[6].replace('$', '')) * 1000,
}
}
}
}
async getCategoryMonth(categoryId, categoryName, month) {
if (fs.existsSync(this.budgetFile)) {
return await this.getCategoryMonthFromBudgetFile(categoryName, month)
}
return (await this.makeRequest(`months/${month}/categories/${categoryId}`)).category
}
async getTransactionsFromRegisterFile() {
const rows = await readCSV(this.registerFile)
let retval = []
for (const row of rows) {
const outflow = parseInt(row[8].replace('$', '').replace('.', ''))
const inflow = parseInt(row[9].replace('$', '').replace('.', ''))
let amount = inflow
if (outflow !== 0) {
amount = outflow * -1
}
let status = 2
switch (row[10].toLowerCase()) {
case 'cleared':
status = 1
break
case 'uncleared':
status = 0
break
}
retval.push({
"original_date": row[2],
"date": getDateFromCSVString(row[2]),
"amount": dinero({ amount, currency: USD }),
"memo": row[7],
"status": status,
"account_name": row[0],
"payee_name": row[3],
"category_name": row[6],
})
}
return retval.sort(function(a,b){
return b.date - a.date;
})
}
async getTransactions() {
if (fs.existsSync(this.registerFile)) {
return await this.getTransactionsFromRegisterFile()
}
return (await this.makeRequest('transactions')).transactions.map(transaction => ({
...transaction,
amount: dinero({ amount: transaction.amount, currency: USD, scale: 3 }),
date: getDateFromAPIString(transaction.date)
}))
}
async makeRequest(endpoint, method = 'get') {
process.exit()
console.log(`YNAB REQUEST: https://api.youneedabudget.com/v1/budgets/${this.budgetId}/${endpoint}`)
return JSON.parse((await got[method](`https://api.youneedabudget.com/v1/budgets/${this.budgetId}/${endpoint}`, {
headers: {
Authorization: `Bearer ${this.token}`
}
})).body).data
}
}
(async () => {
const loginInfo = (await prompt.get([
{
description: 'Budg-E URL (ex: https://budg-e.mydomain.com)',
name: 'host',
required: true,
},
{
description: 'Budg-E email',
name: 'email',
required: true,
}, {
description: 'Budg-E password',
name: 'password',
hidden: true,
}]
))
const budge = new BudgE(loginInfo.host)
await budge.login(loginInfo.email, loginInfo.password)
const fileInfo = (await prompt.get([{
description: 'Budget CSV Location',
name: 'budget',
required: true,
default: "/config/budget.csv",
}, {
description: 'Register CSV Location',
name: 'register',
required: true,
default: "/config/register.csv",
}]
))
const ynab = new YNAB('', '', fileInfo.register, fileInfo.budget)
if (!fs.existsSync(fileInfo.register) || !fs.existsSync(fileInfo.budget)) {
console.log("Budget or register file does not exist.")
process.exit(1)
}
let category_groups = await ynab.getCategories()
for (let category_group of category_groups) {
// Skip auto-generated CC group / categories
if (category_group.name === 'Credit Card Payments') {
continue
}
const categoryGroup = await budge.findOrCreateCategoryGroup(category_group.name)
for (let ynab_category of category_group['categories']) {
const category = await budge.findOrCreateCategory(ynab_category.name, categoryGroup.id)
}
}
let ynab_accounts = await ynab.getAccounts()
for (let ynab_account of ynab_accounts) {
const run = (await prompt.get({
name: 'yesno',
message: `Import account ${ynab_account.name}?`,
validator: /y[es]*|n[o]?/,
warning: 'Must respond yes or no',
default: 'no'
})).yesno
if (run === 'no') {
continue
}
let newAccountType = null
switch (ynab_account.type) {
case 'checking':
case 'savings':
newAccountType = 0
case 'creditCard':
newAccountType = 1
break
case undefined:
console.log(`\nAccount '${ynab_account.name}' type is unknown, specify the account type: `)
newAccountType = (await prompt.get({
name: 'accounttype',
message: 'Account type is unknown, specify the account type: 0 = Bank, 1 = Credit Card, 2 = Tracking',
validator: /0|1|2|skip/,
warning: 'Must respond 0, 1, 2 or skip',
default: 0,
})).accounttype
break
default:
console.log(`skipping account ${ynab_account.name}: ${ynab_account.type}`)
continue
}
if (!newAccountType || newAccountType === 'skip') {
continue
}
const transactions = await ynab.getTransactions()
let account = null
// Create account with starting balance
for (let transaction of transactions) {
if (transaction.payee_name == "Starting Balance" && transaction.account_name === ynab_account.name) {
console.log(`Setting starting balance of account ${ynab_account.name} to ${toUnit(transaction.amount)}`)
if (newAccountType == 1) {
account = await budge.findOrCreateAccount(ynab_account.name, newAccountType, multiply(transaction.amount, -1), transaction.date)
} else {
account = await budge.findOrCreateAccount(ynab_account.name, newAccountType, transaction.amount, transaction.date)
}
}
}
// Pull in transactions, but skip transfers until all accounts are in
for (let transaction of transactions) {
if (transaction.payee_name == "Starting Balance" || transaction.account_name !== ynab_account.name) {
continue
}
if (transaction.payee_name.match(/Transfer : /)) {
continue
}
console.log(`Importing transaction: ${transaction.payee_name}, ${toUnit(transaction.amount)}, ${transaction.date.toISOString().split('T')[0]}`)
let category = null
if (transaction.category_name === 'Ready to Assign') {
transaction.category_name = 'To be Budgeted'
}
if (transaction.category_name) {
category = await budge.findOrCreateCategory(transaction.category_name)
}
const payee = await budge.findOrCreatePayee(transaction.payee_name)
await budge.postTransaciton({
accountId: account.id,
payeeId: payee.id,
amount: transaction.amount.toJSON().amount,
date: transaction.date.toISOString().split('T')[0],
memo: transaction.memo,
categoryId: category ? category.id : null,
status: transaction.status,
})
}
}
for (let ynab_account of ynab_accounts) {
const run = (await prompt.get({
name: 'yesno',
message: `Run transfers for account ${ynab_account.name}?`,
validator: /y[es]*|n[o]?/,
warning: 'Must respond yes or no',
default: 'no'
})).yesno
if (run === 'no') {
continue
}
const transactions = await ynab.getTransactions()
const account = await budge.findOrCreateAccount(ynab_account.name)
// Pull in transfer transactions
for (let transaction of transactions) {
if (transaction.account_name !== ynab_account.name) {
continue
}
if (!transaction.payee_name.match(/Transfer : /)) {
continue
}
console.log(`Importing transaction: ${transaction.payee_name}, ${toUnit(transaction.amount)}, ${transaction.date.toISOString().split('T')[0]}`)
let category = null
if (transaction.category_name === 'Ready to Assign') {
transaction.category_name = 'To be Budgeted'
}
if (transaction.category_name) {
category = await budge.findOrCreateCategory(transaction.category_name)
}
const payee = await budge.findOrCreatePayee(transaction.payee_name)
await budge.postTransaciton({
accountId: account.id,
payeeId: payee.id,
amount: transaction.amount.toJSON().amount,
date: transaction.date.toISOString().split('T')[0],
memo: transaction.memo,
categoryId: category ? category.id : null,
status: transaction.status,
})
}
}
const categoryMonths = await ynab.getCategoryMonths()
for (const categoryMonth of categoryMonths) {
const category = await budge.findOrCreateCategory(categoryMonth.name)
console.log(`Updating category month ${category.name} - ${categoryMonth.month}: ${categoryMonth.budgeted}`)
await budge.updateCategoryMonth(category.id, categoryMonth.month, categoryMonth.budgeted)
}
})()

789
ynab/package-lock.json generated Normal file
View File

@ -0,0 +1,789 @@
{
"name": "ynab_import",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "ynab_import",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@dinero.js/currencies": "^2.0.0-alpha.8",
"csv-parse": "^4.16.3",
"dinero.js": "^2.0.0-alpha.8",
"got": "^11.8.3",
"prompt": "^1.2.0"
}
},
"node_modules/@dinero.js/calculator-number": {
"version": "2.0.0-alpha.8",
"resolved": "https://registry.npmjs.org/@dinero.js/calculator-number/-/calculator-number-2.0.0-alpha.8.tgz",
"integrity": "sha512-/L+N7g5DjcS6wlMb2hcOXWBKW2TGiG+vZDZr9ow0nsHUTdwtMarL1bmBH9fGldHhH2XsxcrjN9H+036yeNzh3Q==",
"dependencies": {
"@dinero.js/core": "2.0.0-alpha.8"
}
},
"node_modules/@dinero.js/core": {
"version": "2.0.0-alpha.8",
"resolved": "https://registry.npmjs.org/@dinero.js/core/-/core-2.0.0-alpha.8.tgz",
"integrity": "sha512-3jaw2j6J/SshlCZz5KhHkh8zP47HRmt9RpnjR0BJs2awpweVuZIyyX9qzGVUEVpml9IwzQ1U+YdXevhOxtcDgg==",
"dependencies": {
"@dinero.js/currencies": "2.0.0-alpha.8"
}
},
"node_modules/@dinero.js/currencies": {
"version": "2.0.0-alpha.8",
"resolved": "https://registry.npmjs.org/@dinero.js/currencies/-/currencies-2.0.0-alpha.8.tgz",
"integrity": "sha512-zApiqtuuPwjiM9LJA5/kNcT48VSHRiz2/mktkXjIpfxrJKzthXybUAgEenExIH6dYhLDgVmsLQZtZFOsdYl0Ag=="
},
"node_modules/@sindresorhus/is": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz",
"integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/is?sponsor=1"
}
},
"node_modules/@szmarczak/http-timer": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
"dependencies": {
"defer-to-connect": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@types/cacheable-request": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz",
"integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==",
"dependencies": {
"@types/http-cache-semantics": "*",
"@types/keyv": "*",
"@types/node": "*",
"@types/responselike": "*"
}
},
"node_modules/@types/http-cache-semantics": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
"integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
},
"node_modules/@types/keyv": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz",
"integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": {
"version": "16.11.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz",
"integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw=="
},
"node_modules/@types/responselike": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
"integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/async": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
},
"node_modules/cacheable-lookup": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==",
"engines": {
"node": ">=10.6.0"
}
},
"node_modules/cacheable-request": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz",
"integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==",
"dependencies": {
"clone-response": "^1.0.2",
"get-stream": "^5.1.0",
"http-cache-semantics": "^4.0.0",
"keyv": "^4.0.0",
"lowercase-keys": "^2.0.0",
"normalize-url": "^6.0.1",
"responselike": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/clone-response": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
"integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
"dependencies": {
"mimic-response": "^1.0.0"
}
},
"node_modules/colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
"engines": {
"node": ">=0.1.90"
}
},
"node_modules/csv-parse": {
"version": "4.16.3",
"resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz",
"integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg=="
},
"node_modules/cycle": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
"integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"dependencies": {
"mimic-response": "^3.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/decompress-response/node_modules/mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/defer-to-connect": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==",
"engines": {
"node": ">=10"
}
},
"node_modules/dinero.js": {
"version": "2.0.0-alpha.8",
"resolved": "https://registry.npmjs.org/dinero.js/-/dinero.js-2.0.0-alpha.8.tgz",
"integrity": "sha512-6bl+g6oh6iQ6vPR5Pd4qr7D+P5e51GYRUT3jl8HYqYeejYC5sd9OVTTbXC3WU7L25mAIbOm+diiTVz1rL4QLwg==",
"dependencies": {
"@dinero.js/calculator-number": "2.0.0-alpha.8",
"@dinero.js/core": "2.0.0-alpha.8",
"@dinero.js/currencies": "2.0.0-alpha.8"
}
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/eyes": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
"integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=",
"engines": {
"node": "> 0.1.90"
}
},
"node_modules/get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"dependencies": {
"pump": "^3.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/got": {
"version": "11.8.3",
"resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz",
"integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==",
"dependencies": {
"@sindresorhus/is": "^4.0.0",
"@szmarczak/http-timer": "^4.0.5",
"@types/cacheable-request": "^6.0.1",
"@types/responselike": "^1.0.0",
"cacheable-lookup": "^5.0.3",
"cacheable-request": "^7.0.2",
"decompress-response": "^6.0.0",
"http2-wrapper": "^1.0.0-beta.5.2",
"lowercase-keys": "^2.0.0",
"p-cancelable": "^2.0.0",
"responselike": "^2.0.0"
},
"engines": {
"node": ">=10.19.0"
},
"funding": {
"url": "https://github.com/sindresorhus/got?sponsor=1"
}
},
"node_modules/http-cache-semantics": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
},
"node_modules/http2-wrapper": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
"dependencies": {
"quick-lru": "^5.1.1",
"resolve-alpn": "^1.0.0"
},
"engines": {
"node": ">=10.19.0"
}
},
"node_modules/isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
},
"node_modules/keyv": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.4.tgz",
"integrity": "sha512-vqNHbAc8BBsxk+7QBYLW0Y219rWcClspR6WSeoHYKG5mnsSoOH+BL1pWq02DDCVdvvuUny5rkBlzMRzoqc+GIg==",
"dependencies": {
"json-buffer": "3.0.1"
}
},
"node_modules/lowercase-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
"engines": {
"node": ">=8"
}
},
"node_modules/mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
"engines": {
"node": ">=4"
}
},
"node_modules/mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
},
"node_modules/normalize-url": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/p-cancelable": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
"integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==",
"engines": {
"node": ">=8"
}
},
"node_modules/prompt": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/prompt/-/prompt-1.2.0.tgz",
"integrity": "sha512-iGerYRpRUg5ZyC+FJ/25G5PUKuWAGRjW1uOlhX7Pi3O5YygdK6R+KEaBjRbHSkU5vfS5PZCltSPZdDtUYwRCZA==",
"dependencies": {
"async": "~0.9.0",
"colors": "^1.1.2",
"read": "1.0.x",
"revalidator": "0.1.x",
"winston": "2.x"
},
"engines": {
"node": ">= 0.6.6"
}
},
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/quick-lru": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/read": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
"integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
"dependencies": {
"mute-stream": "~0.0.4"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/resolve-alpn": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
},
"node_modules/responselike": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz",
"integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==",
"dependencies": {
"lowercase-keys": "^2.0.0"
}
},
"node_modules/revalidator": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
"integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=",
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
"engines": {
"node": "*"
}
},
"node_modules/winston": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz",
"integrity": "sha512-TWoamHt5yYvsMarGlGEQE59SbJHqGsZV8/lwC+iCcGeAe0vUaOh+Lv6SYM17ouzC/a/LB1/hz/7sxFBtlu1l4A==",
"dependencies": {
"async": "~1.0.0",
"colors": "1.0.x",
"cycle": "1.0.x",
"eyes": "0.1.x",
"isstream": "0.1.x",
"stack-trace": "0.0.x"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/winston/node_modules/async": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz",
"integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k="
},
"node_modules/winston/node_modules/colors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
"integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
"engines": {
"node": ">=0.1.90"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
},
"dependencies": {
"@dinero.js/calculator-number": {
"version": "2.0.0-alpha.8",
"resolved": "https://registry.npmjs.org/@dinero.js/calculator-number/-/calculator-number-2.0.0-alpha.8.tgz",
"integrity": "sha512-/L+N7g5DjcS6wlMb2hcOXWBKW2TGiG+vZDZr9ow0nsHUTdwtMarL1bmBH9fGldHhH2XsxcrjN9H+036yeNzh3Q==",
"requires": {
"@dinero.js/core": "2.0.0-alpha.8"
}
},
"@dinero.js/core": {
"version": "2.0.0-alpha.8",
"resolved": "https://registry.npmjs.org/@dinero.js/core/-/core-2.0.0-alpha.8.tgz",
"integrity": "sha512-3jaw2j6J/SshlCZz5KhHkh8zP47HRmt9RpnjR0BJs2awpweVuZIyyX9qzGVUEVpml9IwzQ1U+YdXevhOxtcDgg==",
"requires": {
"@dinero.js/currencies": "2.0.0-alpha.8"
}
},
"@dinero.js/currencies": {
"version": "2.0.0-alpha.8",
"resolved": "https://registry.npmjs.org/@dinero.js/currencies/-/currencies-2.0.0-alpha.8.tgz",
"integrity": "sha512-zApiqtuuPwjiM9LJA5/kNcT48VSHRiz2/mktkXjIpfxrJKzthXybUAgEenExIH6dYhLDgVmsLQZtZFOsdYl0Ag=="
},
"@sindresorhus/is": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz",
"integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw=="
},
"@szmarczak/http-timer": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz",
"integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==",
"requires": {
"defer-to-connect": "^2.0.0"
}
},
"@types/cacheable-request": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.2.tgz",
"integrity": "sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==",
"requires": {
"@types/http-cache-semantics": "*",
"@types/keyv": "*",
"@types/node": "*",
"@types/responselike": "*"
}
},
"@types/http-cache-semantics": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz",
"integrity": "sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ=="
},
"@types/keyv": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.3.tgz",
"integrity": "sha512-FXCJgyyN3ivVgRoml4h94G/p3kY+u/B86La+QptcqJaWtBWtmc6TtkNfS40n9bIvyLteHh7zXOtgbobORKPbDg==",
"requires": {
"@types/node": "*"
}
},
"@types/node": {
"version": "16.11.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz",
"integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw=="
},
"@types/responselike": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.0.tgz",
"integrity": "sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==",
"requires": {
"@types/node": "*"
}
},
"async": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
},
"cacheable-lookup": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
"integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="
},
"cacheable-request": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.2.tgz",
"integrity": "sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==",
"requires": {
"clone-response": "^1.0.2",
"get-stream": "^5.1.0",
"http-cache-semantics": "^4.0.0",
"keyv": "^4.0.0",
"lowercase-keys": "^2.0.0",
"normalize-url": "^6.0.1",
"responselike": "^2.0.0"
}
},
"clone-response": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz",
"integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=",
"requires": {
"mimic-response": "^1.0.0"
}
},
"colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA=="
},
"csv-parse": {
"version": "4.16.3",
"resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-4.16.3.tgz",
"integrity": "sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg=="
},
"cycle": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
"integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI="
},
"decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"requires": {
"mimic-response": "^3.1.0"
},
"dependencies": {
"mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="
}
}
},
"defer-to-connect": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz",
"integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="
},
"dinero.js": {
"version": "2.0.0-alpha.8",
"resolved": "https://registry.npmjs.org/dinero.js/-/dinero.js-2.0.0-alpha.8.tgz",
"integrity": "sha512-6bl+g6oh6iQ6vPR5Pd4qr7D+P5e51GYRUT3jl8HYqYeejYC5sd9OVTTbXC3WU7L25mAIbOm+diiTVz1rL4QLwg==",
"requires": {
"@dinero.js/calculator-number": "2.0.0-alpha.8",
"@dinero.js/core": "2.0.0-alpha.8",
"@dinero.js/currencies": "2.0.0-alpha.8"
}
},
"end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"requires": {
"once": "^1.4.0"
}
},
"eyes": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
"integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A="
},
"get-stream": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
"integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
"requires": {
"pump": "^3.0.0"
}
},
"got": {
"version": "11.8.3",
"resolved": "https://registry.npmjs.org/got/-/got-11.8.3.tgz",
"integrity": "sha512-7gtQ5KiPh1RtGS9/Jbv1ofDpBFuq42gyfEib+ejaRBJuj/3tQFeR5+gw57e4ipaU8c/rCjvX6fkQz2lyDlGAOg==",
"requires": {
"@sindresorhus/is": "^4.0.0",
"@szmarczak/http-timer": "^4.0.5",
"@types/cacheable-request": "^6.0.1",
"@types/responselike": "^1.0.0",
"cacheable-lookup": "^5.0.3",
"cacheable-request": "^7.0.2",
"decompress-response": "^6.0.0",
"http2-wrapper": "^1.0.0-beta.5.2",
"lowercase-keys": "^2.0.0",
"p-cancelable": "^2.0.0",
"responselike": "^2.0.0"
}
},
"http-cache-semantics": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz",
"integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ=="
},
"http2-wrapper": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz",
"integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==",
"requires": {
"quick-lru": "^5.1.1",
"resolve-alpn": "^1.0.0"
}
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
},
"keyv": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.4.tgz",
"integrity": "sha512-vqNHbAc8BBsxk+7QBYLW0Y219rWcClspR6WSeoHYKG5mnsSoOH+BL1pWq02DDCVdvvuUny5rkBlzMRzoqc+GIg==",
"requires": {
"json-buffer": "3.0.1"
}
},
"lowercase-keys": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
"integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="
},
"mimic-response": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
"integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="
},
"mute-stream": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
},
"normalize-url": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
"integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"requires": {
"wrappy": "1"
}
},
"p-cancelable": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
"integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="
},
"prompt": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/prompt/-/prompt-1.2.0.tgz",
"integrity": "sha512-iGerYRpRUg5ZyC+FJ/25G5PUKuWAGRjW1uOlhX7Pi3O5YygdK6R+KEaBjRbHSkU5vfS5PZCltSPZdDtUYwRCZA==",
"requires": {
"async": "~0.9.0",
"colors": "^1.1.2",
"read": "1.0.x",
"revalidator": "0.1.x",
"winston": "2.x"
}
},
"pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"quick-lru": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="
},
"read": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
"integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=",
"requires": {
"mute-stream": "~0.0.4"
}
},
"resolve-alpn": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz",
"integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="
},
"responselike": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.0.tgz",
"integrity": "sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==",
"requires": {
"lowercase-keys": "^2.0.0"
}
},
"revalidator": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
"integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs="
},
"stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA="
},
"winston": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.5.tgz",
"integrity": "sha512-TWoamHt5yYvsMarGlGEQE59SbJHqGsZV8/lwC+iCcGeAe0vUaOh+Lv6SYM17ouzC/a/LB1/hz/7sxFBtlu1l4A==",
"requires": {
"async": "~1.0.0",
"colors": "1.0.x",
"cycle": "1.0.x",
"eyes": "0.1.x",
"isstream": "0.1.x",
"stack-trace": "0.0.x"
},
"dependencies": {
"async": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz",
"integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k="
},
"colors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
"integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs="
}
}
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}
}
}

20
ynab/package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "ynab_import",
"version": "1.0.0",
"description": "",
"main": "import.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@dinero.js/currencies": "^2.0.0-alpha.8",
"csv-parse": "^4.16.3",
"dinero.js": "^2.0.0-alpha.8",
"got": "^11.8.3",
"prompt": "^1.2.0"
},
"type": "module"
}