UNPKG

@heroku/plugin-ai

Version:
98 lines (97 loc) 4.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.formatState = exports.grandfatheredPrice = exports.formatPriceText = exports.formatPrice = exports.trapConfirmationRequired = void 0; exports.handlePlatformApiErrors = handlePlatformApiErrors; const tslib_1 = require("tslib"); /* eslint-disable no-return-await */ const color_1 = tslib_1.__importDefault(require("@heroku-cli/color")); const api_client_1 = require("@heroku-cli/command/lib/api-client"); const core_1 = require("@oclif/core"); const printf_1 = tslib_1.__importDefault(require("printf")); const confirmCommand_1 = tslib_1.__importDefault(require("../../confirmCommand")); const trapConfirmationRequired = async function (app, confirm, fn) { return await fn(confirm) .catch(async (error) => { if (!error.body || error.body.id !== 'confirmation_required') throw error; await (0, confirmCommand_1.default)(app, confirm, error.body.message); return await fn(app); }); }; exports.trapConfirmationRequired = trapConfirmationRequired; /** * Error handler * @param error Error thrown when attempting to create the model resource. * @param cmdContext Context of the command that failed. * @returns never * * There's a problem with this error handler implementation, because it relies on the specific error message * returned from API in order to format the error correctly. This is prone to fail if changes are introduced * upstream on error messages. We should rely on the error `id` but API returns a generic `invalid_params`. */ function handlePlatformApiErrors(error, cmdContext = {}) { if (error instanceof api_client_1.HerokuAPIError && error.body.id === 'invalid_params') { if (cmdContext.as && error.body.message?.includes('start with a letter')) { core_1.ux.error(`${cmdContext.as} is an invalid alias. Alias must start with a letter and can only contain uppercase letters, numbers, and underscores.`, { exit: 1 }); } if (cmdContext.modelName && error.body.message?.includes('add-on plan')) { core_1.ux.error(`${cmdContext.modelName} is an invalid model name. Run ${color_1.default.cmd('heroku ai:models:list')} for a list of valid models per region.`, { exit: 1 }); } } throw error; } // This function assumes that price.cents will reflect price per month. // If the API returns any unit other than month // this function will need to be updated. const formatPrice = function ({ price, hourly }) { if (!price) return; if (price.contract) return 'contract'; if (price.cents === 0) return 'free'; // we are using a standardized 720 hours/month if (hourly) return `~$${((price.cents / 100) / 720).toFixed(3)}/hour`; const fmt = price.cents % 100 === 0 ? '$%.0f/%s' : '$%.02f/%s'; return (0, printf_1.default)(fmt, price.cents / 100, price.unit); }; exports.formatPrice = formatPrice; const formatPriceText = function (price) { const priceHourly = (0, exports.formatPrice)({ price, hourly: true }); const priceMonthly = (0, exports.formatPrice)({ price, hourly: false }); if (!priceHourly) return ''; if (priceHourly === 'free' || priceHourly === 'contract') return `${color_1.default.green(priceHourly)}`; return `${color_1.default.green(priceHourly)} (max ${priceMonthly})`; }; exports.formatPriceText = formatPriceText; const grandfatheredPrice = function (addon) { const price = addon.plan?.price; return Object.assign({}, price, { cents: addon.billed_price?.cents, contract: addon.billed_price?.contract, }); }; exports.grandfatheredPrice = grandfatheredPrice; const formatState = function (state) { switch (state) { case 'provisioned': state = 'created'; break; case 'provisioning': state = 'creating'; break; case 'deprovisioning': state = 'destroying'; break; case 'deprovisioned': state = 'errored'; break; default: state = ''; } return state; }; exports.formatState = formatState;