UNPKG

fin

Version:

Developer CLI for Fin. Fin is the easiest way to launch your own SaaS.

182 lines (160 loc) 5.74 kB
'use strict' const ccValidator = require('credit-card') const { prompt } = require('enquirer') const cardBrands = require('../card-brands') const createBillingSource = require('../create-billing-source') const handleError = require('../handle-error') const spinner = require('../spinner') module.exports = (program, client) => { program .command('cc <command> [id]') .alias('billing') .description('Manages your credit cards and billing methods') .action(async (cmd, id) => { program.requireAuthentication() try { switch (cmd) { case 'ls': { const [ user, sources ] = await spinner( Promise.all([ client.getBilling(), client.listBillingSources() ]), 'Getting billing sources' ) // TODO: better output formatting // TODO: better highlighting of default source console.log(JSON.stringify(sources, null, 2)) console.log(`default source: ${user.stripeDefaultSource}`) break } case 'add': { const temp = { } const prompts = [ { type: 'input', name: 'name', message: 'Full Name', validate: (value) => { return value.trim().length > 0 } }, { type: 'input', name: 'cardNumber', message: 'Card Number', hint: '#### #### #### ####', format: (value) => { value = value.replace(/\s/g, '') value = value.replace(/[^\d]/g, '') if (value.length >= 4) { value = value.slice(0, 4) + ' ' + value.slice(4) if (value.length >= 9) { value = value.slice(0, 9) + ' ' + value.slice(9) if (value.length >= 14) { value = value.slice(0, 14) + ' ' + value.slice(14) if (value.length <= 19) { value = value.slice(0, 19) } } } } return value }, validate: (value) => { value = value.replace(/\s/g, '') const type = ccValidator.determineCardType(value) return type && ccValidator.isValidCardNumber(value, type) }, result: (value) => { temp.cardNumber = value.replace(/\s/g, '') temp.type = ccValidator.determineCardType(temp.cardNumber) temp.brand = cardBrands[temp.type] return temp.cardNumber } }, { type: 'input', name: 'ccv', message: 'CCV', hint: '###', validate: (value) => { const brand = temp.brand.toLowerCase() return ccValidator.doesCvvMatchType(value, brand) } }, { type: 'input', name: 'expDate', message: 'Expiration Date', hint: 'mm/yyyy', validate: (value) => { const parts = value.replace(/\s/g, '').split('/') return !ccValidator.isExpired(...parts) }, result: (value) => { return value.replace(/\s/g, '').split('/') } } ] console.log('Please enter your credit card details:') const card = await prompt(prompts) let token try { const result = await spinner( createBillingSource(card), 'Creating secure billing token' ) token = result.id } catch (err) { console.error('Error initializing payment source', err.message) process.exit(1) } const source = await spinner( client.addBillingSource({ source: token }), 'Attaching billing source to user' ) console.log(JSON.stringify(source, null, 2)) break } case 'rm': { if (!id) { console.error('error: you must specify the id of a billing source id to remove') process.exit(1) } const source = await spinner( client.removeBillingSource(id), 'Removing billing source' ) console.log(JSON.stringify(source, null, 2)) break } case 'set-default': { if (!id) { console.error('error: you must specify the id of a billing source id to set-default') process.exit(1) } const source = await spinner( client.setDefaultBillingSource(id), 'Setting default billing source' ) console.log(JSON.stringify(source, null, 2)) break } default: { if (!cmd) { console.error('error: must specify a billing command (ls, add, rm, or set-default)') } else { console.error(`error: invalid billing command [${cmd}] (ls, add, rm, or set-default)`) } process.exit(1) } } } catch (err) { handleError(err) } }) }