@heroku-cli/command
Advanced tools
Comparing version 11.0.0 to 11.1.0
@@ -6,2 +6,3 @@ import { Interfaces } from '@oclif/core'; | ||
import { Mutex } from './mutex'; | ||
import { ParticleboardClient } from './particleboard-client'; | ||
export declare namespace APIClient { | ||
@@ -42,3 +43,5 @@ interface Options extends HTTPRequestOptions { | ||
private _auth?; | ||
private _particleboard; | ||
constructor(config: Interfaces.Config, options?: IOptions); | ||
get particleboard(): ParticleboardClient; | ||
get twoFactorMutex(): Mutex<string>; | ||
@@ -45,0 +48,0 @@ get auth(): string | undefined; |
@@ -55,2 +55,3 @@ "use strict"; | ||
}; | ||
const delinquencyConfig = { fetch_delinquency: false, warning_shown: false }; | ||
this.http = class APIHTTPClient extends deps_1.default.HTTP.HTTP.create(opts) { | ||
@@ -79,11 +80,76 @@ static async twoFactorRetry(err, url, opts = {}, retries = 3) { | ||
} | ||
static configDelinquency(url, opts) { | ||
var _a; | ||
if (((_a = opts.method) === null || _a === void 0 ? void 0 : _a.toUpperCase()) !== 'GET' || (opts.hostname && opts.hostname !== apiUrl.hostname)) { | ||
delinquencyConfig.fetch_delinquency = false; | ||
return; | ||
} | ||
if (/^\/account$/i.test(url)) { | ||
delinquencyConfig.fetch_url = '/account'; | ||
delinquencyConfig.fetch_delinquency = true; | ||
delinquencyConfig.resource_type = 'account'; | ||
return; | ||
} | ||
const match = url.match(/^\/teams\/([^#/?]+)/i); | ||
if (match) { | ||
delinquencyConfig.fetch_url = `/teams/${match[1]}`; | ||
delinquencyConfig.fetch_delinquency = true; | ||
delinquencyConfig.resource_type = 'team'; | ||
return; | ||
} | ||
delinquencyConfig.fetch_delinquency = false; | ||
} | ||
static notifyDelinquency(delinquencyInfo) { | ||
const suspension = delinquencyInfo.scheduled_suspension_time ? Date.parse(delinquencyInfo.scheduled_suspension_time).valueOf() : undefined; | ||
const deletion = delinquencyInfo.scheduled_deletion_time ? Date.parse(delinquencyInfo.scheduled_deletion_time).valueOf() : undefined; | ||
if (!suspension && !deletion) | ||
return; | ||
const resource = delinquencyConfig.resource_type; | ||
if (suspension) { | ||
const now = Date.now(); | ||
if (suspension > now) { | ||
(0, errors_1.warn)(`This ${resource} is delinquent with payment and we‘ll suspend it on ${new Date(suspension)}.`); | ||
delinquencyConfig.warning_shown = true; | ||
return; | ||
} | ||
if (deletion) | ||
(0, errors_1.warn)(`This ${resource} is delinquent with payment and we suspended it on ${new Date(suspension)}. If the ${resource} is still delinquent, we'll delete it on ${new Date(deletion)}.`); | ||
} | ||
else if (deletion) | ||
(0, errors_1.warn)(`This ${resource} is delinquent with payment and we‘ll delete it on ${new Date(deletion)}.`); | ||
delinquencyConfig.warning_shown = true; | ||
} | ||
static async request(url, opts = {}, retries = 3) { | ||
opts.headers = opts.headers || {}; | ||
opts.headers[request_id_1.requestIdHeader] = request_id_1.RequestId.create() && request_id_1.RequestId.headerValue; | ||
if (!Object.keys(opts.headers).find(h => h.toLowerCase() === 'authorization')) { | ||
if (!Object.keys(opts.headers).some(h => h.toLowerCase() === 'authorization')) { | ||
opts.headers.authorization = `Bearer ${self.auth}`; | ||
} | ||
this.configDelinquency(url, opts); | ||
retries--; | ||
try { | ||
const response = await super.request(url, opts); | ||
let response; | ||
let particleboardResponse; | ||
const particleboardClient = self.particleboard; | ||
if (delinquencyConfig.fetch_delinquency && !delinquencyConfig.warning_shown) { | ||
self._particleboard.auth = self.auth; | ||
const settledResponses = await Promise.allSettled([ | ||
super.request(url, opts), | ||
particleboardClient.get(delinquencyConfig.fetch_url), | ||
]); | ||
// Platform API request | ||
if (settledResponses[0].status === 'fulfilled') | ||
response = settledResponses[0].value; | ||
else | ||
throw settledResponses[0].reason; | ||
// Particleboard request (ignore errors) | ||
if (settledResponses[1].status === 'fulfilled') { | ||
particleboardResponse = settledResponses[1].value; | ||
} | ||
} | ||
else { | ||
response = await super.request(url, opts); | ||
} | ||
const delinquencyInfo = (particleboardResponse === null || particleboardResponse === void 0 ? void 0 : particleboardResponse.body) || {}; | ||
this.notifyDelinquency(delinquencyInfo); | ||
this.trackRequestIds(response); | ||
@@ -115,2 +181,8 @@ return response; | ||
} | ||
get particleboard() { | ||
if (this._particleboard) | ||
return this._particleboard; | ||
this._particleboard = new deps_1.default.ParticleboardClient(this.config); | ||
return this._particleboard; | ||
} | ||
get twoFactorMutex() { | ||
@@ -117,0 +189,0 @@ if (!this._twoFactorMutex) { |
@@ -6,2 +6,3 @@ /// <reference types="node" /> | ||
import apiClient = require('./api-client'); | ||
import particleboardClient = require('./particleboard-client'); | ||
import file = require('./file'); | ||
@@ -22,2 +23,3 @@ import flags = require('./flags'); | ||
readonly APIClient: typeof apiClient.APIClient; | ||
readonly ParticleboardClient: typeof particleboardClient.ParticleboardClient; | ||
readonly file: typeof file; | ||
@@ -24,0 +26,0 @@ readonly flags: typeof flags; |
@@ -28,2 +28,5 @@ "use strict"; | ||
}, | ||
get ParticleboardClient() { | ||
return fetch('./particleboard-client').ParticleboardClient; | ||
}, | ||
get file() { | ||
@@ -30,0 +33,0 @@ return fetch('./file'); |
@@ -9,3 +9,3 @@ "use strict"; | ||
const netrc_parser_1 = tslib_1.__importDefault(require("netrc-parser")); | ||
const open = require("open"); | ||
const open_1 = tslib_1.__importDefault(require("open")); | ||
const os = tslib_1.__importStar(require("os")); | ||
@@ -142,3 +142,3 @@ const api_client_1 = require("./api-client"); | ||
// ux.warn(`If browser does not open, visit ${color.greenBright(url)}`) | ||
const cp = await open(url, { app: browser, wait: false }); | ||
const cp = await (0, open_1.default)(url, Object.assign({ wait: false }, (browser ? { app: { name: browser } } : {}))); | ||
cp.on('error', err => { | ||
@@ -271,3 +271,3 @@ core_1.ux.warn(err); | ||
'browser.\n')); | ||
await open(url, { wait: false }); | ||
await (0, open_1.default)(url, { wait: false }); | ||
const password = await core_1.ux.prompt('Access token', { type: 'mask' }); | ||
@@ -274,0 +274,0 @@ core_1.ux.action.start('Validating token'); |
@@ -10,3 +10,5 @@ export declare class Vars { | ||
get gitPrefixes(): string[]; | ||
get envParticleboardUrl(): string | undefined; | ||
get particleboardUrl(): string; | ||
} | ||
export declare const vars: Vars; |
@@ -50,4 +50,16 @@ "use strict"; | ||
} | ||
get envParticleboardUrl() { | ||
return process.env.HEROKU_PARTICLEBOARD_URL; | ||
} | ||
// This should be fixed after we make our staging hostnames consistent throughout all services | ||
// changing the staging cloud URL to `particleboard.staging.herokudev.com`. | ||
get particleboardUrl() { | ||
if (this.envParticleboardUrl) | ||
return this.envParticleboardUrl; | ||
return process.env.HEROKU_CLOUD === 'staging' ? | ||
'https://particleboard-staging-cloud.herokuapp.com' : | ||
'https://particleboard.heroku.com'; | ||
} | ||
} | ||
exports.Vars = Vars; | ||
exports.vars = new Vars(); |
{ | ||
"name": "@heroku-cli/command", | ||
"description": "base class for Heroku CLI commands", | ||
"version": "11.0.0", | ||
"version": "11.1.0", | ||
"author": "Heroku", | ||
@@ -16,3 +16,3 @@ "bugs": "https://github.com/heroku/heroku-cli-command/issues", | ||
"netrc-parser": "^3.1.6", | ||
"open": "^6.2.0", | ||
"open": "^8.4.2", | ||
"uuid": "^8.3.0" | ||
@@ -47,2 +47,3 @@ }, | ||
"sinon": "^14.0.2", | ||
"stdout-stderr": "^0.1.13", | ||
"ts-node": "^10.9.1", | ||
@@ -49,0 +50,0 @@ "tslint": "^6.1.3", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
81478
40
1435
30
22
+ Addeddefine-lazy-prop@2.0.0(transitive)
+ Addedopen@8.4.2(transitive)
- Removedis-wsl@1.1.0(transitive)
- Removedopen@6.4.0(transitive)
Updatedopen@^8.4.2