Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@honeybadger-io/webpack

Package Overview
Dependencies
Maintainers
6
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@honeybadger-io/webpack - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0-beta.0

20

CHANGELOG.md

@@ -9,2 +9,22 @@ # Changelog

## [1.3.0-beta.0] - 2021-03-22
### Added
- Add retry functionality for fetch requests via
[fetch-retry](https://github.com/vercel/fetch-retry)
- Add a retry option that defaults to 3, with a max number of retries
of 10.
- Add a warning if no assets will be uploaded. Uses console.info instead
of process.stdout.write.
- Add a configurable `endpoint` to the constructor, defaults to
`https://api.honeybadger.io/v1/source_maps`
- Add a check for auxiliary files for Webpack 5 compatibility
- Add Webpack 5 compatibility
- Make Webpack 4+ a peerDependency
### Fixed
- fetch separates response errors from network errors.
400+ status codes are treated separately from actual network errors.
- Attempt to reduce `ECONNRESET` and `SOCKETTIMEOUT` errors by
using `fetch-retry`
## [1.2.0] - 2019-12-18

@@ -11,0 +31,0 @@ ### Changed

6

dist/constants.js

@@ -6,8 +6,10 @@ "use strict";

});
exports.REQUIRED_FIELDS = exports.ENDPOINT = exports.PLUGIN_NAME = void 0;
exports.REQUIRED_FIELDS = exports.MAX_RETRIES = exports.ENDPOINT = exports.PLUGIN_NAME = void 0;
var PLUGIN_NAME = 'HoneybadgerSourceMapPlugin';
exports.PLUGIN_NAME = PLUGIN_NAME;
var ENDPOINT = 'https://api.honeybadger.io/v1/source_maps ';
var ENDPOINT = 'https://api.honeybadger.io/v1/source_maps';
exports.ENDPOINT = ENDPOINT;
var MAX_RETRIES = 10;
exports.MAX_RETRIES = MAX_RETRIES;
var REQUIRED_FIELDS = ['apiKey', 'assetsUrl'];
exports.REQUIRED_FIELDS = REQUIRED_FIELDS;

@@ -5,4 +5,8 @@ "use strict";

var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));

@@ -12,6 +16,10 @@

var _async = _interopRequireDefault(require("async"));
var _fs = require("fs");
var _request = _interopRequireDefault(require("request"));
var _path = require("path");
var _nodeFetch = _interopRequireDefault(require("node-fetch"));
var _fetchRetry = _interopRequireDefault(require("@vercel/fetch-retry"));
var _verror = _interopRequireDefault(require("verror"));

@@ -23,2 +31,4 @@

var _formData = _interopRequireDefault(require("form-data"));
var _helpers = require("./helpers");

@@ -28,17 +38,22 @@

var HoneybadgerSourceMapPlugin =
/*#__PURE__*/
function () {
var fetch = (0, _fetchRetry["default"])(_nodeFetch["default"]);
var HoneybadgerSourceMapPlugin = /*#__PURE__*/function () {
function HoneybadgerSourceMapPlugin(_ref) {
var apiKey = _ref.apiKey,
assetsUrl = _ref.assetsUrl,
_ref$endpoint = _ref.endpoint,
endpoint = _ref$endpoint === void 0 ? _constants.ENDPOINT : _ref$endpoint,
_ref$revision = _ref.revision,
revision = _ref$revision === void 0 ? "master" : _ref$revision,
revision = _ref$revision === void 0 ? 'master' : _ref$revision,
_ref$silent = _ref.silent,
silent = _ref$silent === void 0 ? false : _ref$silent,
_ref$ignoreErrors = _ref.ignoreErrors,
ignoreErrors = _ref$ignoreErrors === void 0 ? false : _ref$ignoreErrors;
ignoreErrors = _ref$ignoreErrors === void 0 ? false : _ref$ignoreErrors,
_ref$retries = _ref.retries,
retries = _ref$retries === void 0 ? 3 : _ref$retries;
(0, _classCallCheck2["default"])(this, HoneybadgerSourceMapPlugin);
this.apiKey = apiKey;
this.assetsUrl = assetsUrl;
this.endpoint = endpoint;
this.revision = revision;

@@ -48,57 +63,83 @@ this.silent = silent;

this.emittedAssets = new Map();
this.retries = retries;
if (this.retries > _constants.MAX_RETRIES) {
this.retries = 10;
}
}
(0, _createClass2["default"])(HoneybadgerSourceMapPlugin, [{
key: "assetEmitted",
value: function assetEmitted(file, content, done) {
this.emittedAssets.set(file, content);
done();
}
}, {
key: "afterEmit",
value: function afterEmit(compilation, done) {
var _this = this;
value: function () {
var _afterEmit = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(compilation) {
var errors, _compilation$errors, _compilation$errors2, _compilation$warnings;
var errors = (0, _helpers.validateOptions)(this);
return _regenerator["default"].wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
errors = (0, _helpers.validateOptions)(this);
if (errors) {
var _compilation$errors;
if (!errors) {
_context.next = 4;
break;
}
(_compilation$errors = compilation.errors).push.apply(_compilation$errors, (0, _toConsumableArray2["default"])((0, _helpers.handleError)(errors)));
(_compilation$errors = compilation.errors).push.apply(_compilation$errors, (0, _toConsumableArray2["default"])((0, _helpers.handleError)(errors)));
return done();
}
return _context.abrupt("return");
this.uploadSourceMaps(compilation, function (err) {
if (err) {
if (!_this.ignoreErrors) {
var _compilation$errors2;
case 4:
_context.prev = 4;
_context.next = 7;
return this.uploadSourceMaps(compilation);
(_compilation$errors2 = compilation.errors).push.apply(_compilation$errors2, (0, _toConsumableArray2["default"])((0, _helpers.handleError)(err)));
} else if (!_this.silent) {
var _compilation$warnings;
case 7:
_context.next = 12;
break;
(_compilation$warnings = compilation.warnings).push.apply(_compilation$warnings, (0, _toConsumableArray2["default"])((0, _helpers.handleError)(err)));
case 9:
_context.prev = 9;
_context.t0 = _context["catch"](4);
if (!this.ignoreErrors) {
(_compilation$errors2 = compilation.errors).push.apply(_compilation$errors2, (0, _toConsumableArray2["default"])((0, _helpers.handleError)(_context.t0)));
} else if (!this.silent) {
(_compilation$warnings = compilation.warnings).push.apply(_compilation$warnings, (0, _toConsumableArray2["default"])((0, _helpers.handleError)(_context.t0)));
}
case 12:
case "end":
return _context.stop();
}
}
}
}, _callee, this, [[4, 9]]);
}));
_this.emittedAssets.clear();
function afterEmit(_x) {
return _afterEmit.apply(this, arguments);
}
done();
});
}
return afterEmit;
}()
}, {
key: "apply",
value: function apply(compiler) {
if (compiler.hooks) {
compiler.hooks.afterEmit.tapAsync(_constants.PLUGIN_NAME, this.afterEmit.bind(this));
compiler.hooks.afterEmit.tapPromise(_constants.PLUGIN_NAME, this.afterEmit.bind(this));
} // eslint-disable-next-line class-methods-use-this
if (compiler.hooks.assetEmitted) {
compiler.hooks.assetEmitted.tapAsync(_constants.PLUGIN_NAME, this.assetEmitted.bind(this));
}
} else {
compiler.plugin('after-emit', this.afterEmit.bind(this));
}
}, {
key: "getAssetPath",
value: function getAssetPath(compilation, name) {
return (0, _path.join)(compilation.getPath(compilation.compiler.outputPath), name.split('?')[0]);
}
}, {
key: "getSource",
value: function getSource(compilation, name) {
var path = this.getAssetPath(compilation, name);
return _fs.promises.readFile(path, {
encoding: 'utf-8'
});
}
}, {
key: "getAssets",

@@ -110,7 +151,8 @@ value: function getAssets(compilation) {

return (0, _lodash2["default"])(chunks, function (result, chunk) {
var chunkName = chunk.names[0];
var sourceFile = (0, _lodash["default"])(chunk.files, function (file) {
return /\.js$/.test(file);
});
var sourceMap = (0, _lodash["default"])(chunk.files, function (file) {
}); // Webpack 4 using chunk.files, Webpack 5 uses chunk.auxiliaryFiles
// https://webpack.js.org/blog/2020-10-10-webpack-5-release/#stats
var sourceMap = (chunk.auxiliaryFiles || chunk.files).find(function (file) {
return /\.js\.map$/.test(file);

@@ -130,65 +172,156 @@ });

}, {
key: "getUrlToAsset",
value: function getUrlToAsset(sourceFile) {
if (typeof sourceFile === 'string') {
var sep = this.assetsUrl.endsWith('/') ? '' : '/';
return "".concat(this.assetsUrl).concat(sep).concat(sourceFile);
}
return this.assetsUrl(sourceFile);
}
}, {
key: "uploadSourceMap",
value: function uploadSourceMap(compilation, _ref2, done) {
var _this2 = this;
value: function () {
var _uploadSourceMap = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(compilation, _ref2) {
var sourceFile, sourceMap, errorMessage, sourceMapSource, sourceFileSource, form, res, details, body;
return _regenerator["default"].wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
sourceFile = _ref2.sourceFile, sourceMap = _ref2.sourceMap;
errorMessage = "failed to upload ".concat(sourceMap, " to Honeybadger API");
_context2.prev = 2;
_context2.next = 5;
return this.getSource(compilation, sourceMap);
var sourceFile = _ref2.sourceFile,
sourceMap = _ref2.sourceMap;
case 5:
sourceMapSource = _context2.sent;
_context2.next = 8;
return this.getSource(compilation, sourceFile);
var req = _request["default"].post(_constants.ENDPOINT, function (err, res, body) {
if (!err && res.statusCode === 201) {
if (!_this2.silent) {
console.info("Uploaded ".concat(sourceMap, " to Honeybadger API")); // eslint-disable-line no-console
}
case 8:
sourceFileSource = _context2.sent;
_context2.next = 14;
break;
return done();
}
case 11:
_context2.prev = 11;
_context2.t0 = _context2["catch"](2);
throw new _verror["default"](_context2.t0, _context2.t0.message);
var errMessage = "failed to upload ".concat(sourceMap, " to Honeybadger API");
case 14:
form = new _formData["default"]();
form.append('api_key', this.apiKey);
form.append('minified_url', this.getUrlToAsset(sourceFile));
form.append('minified_file', sourceFileSource, {
filename: sourceFile,
contentType: 'application/javascript'
});
form.append('source_map', sourceMapSource, {
filename: sourceMap,
contentType: 'application/octet-stream'
});
form.append('revision', this.revision);
_context2.prev = 20;
_context2.next = 23;
return fetch(this.endpoint, {
method: 'POST',
body: form,
redirect: 'follow',
opts: {
retries: this.retries,
// Max timeout between retries, in milliseconds
maxTimeout: 1000
}
});
if (err) {
return done(new _verror["default"](err, errMessage));
}
case 23:
res = _context2.sent;
_context2.next = 29;
break;
var result;
case 26:
_context2.prev = 26;
_context2.t1 = _context2["catch"](20);
throw new _verror["default"](_context2.t1, errorMessage);
try {
var _JSON$parse = JSON.parse(body),
error = _JSON$parse.error;
case 29:
if (res.ok) {
_context2.next = 41;
break;
}
result = new Error(error ? "".concat(errMessage, ": ").concat(error) : errMessage);
} catch (parseErr) {
result = new _verror["default"](parseErr, errMessage);
}
_context2.prev = 30;
_context2.next = 33;
return res.json();
return done(result);
});
case 33:
body = _context2.sent;
var form = req.form();
form.append('api_key', this.apiKey);
form.append('minified_url', "".concat(this.assetsUrl.toString().replace(/^\//, ''), "/").concat(sourceFile.replace(/^\//, '')));
form.append('minified_file', this.emittedAssets.get(sourceFile) || compilation.assets[sourceFile].source(), {
filename: sourceFile,
contentType: 'application/javascript'
});
form.append('source_map', this.emittedAssets.get(sourceMap) || compilation.assets[sourceMap].source(), {
filename: sourceMap,
contentType: 'application/octet-stream'
});
form.append('revision', this.revision);
}
if (body && body.error) {
details = body.error;
} else {
details = "".concat(res.status, " - ").concat(res.statusText);
}
_context2.next = 40;
break;
case 37:
_context2.prev = 37;
_context2.t2 = _context2["catch"](30);
details = "".concat(res.status, " - ").concat(res.statusText);
case 40:
throw new Error("".concat(errorMessage, ": ").concat(details));
case 41:
// Success
if (!this.silent) {
// eslint-disable-next-line no-console
console.info("Uploaded ".concat(sourceMap, " to Honeybadger API"));
}
case 42:
case "end":
return _context2.stop();
}
}
}, _callee2, this, [[2, 11], [20, 26], [30, 37]]);
}));
function uploadSourceMap(_x2, _x3) {
return _uploadSourceMap.apply(this, arguments);
}
return uploadSourceMap;
}()
}, {
key: "uploadSourceMaps",
value: function uploadSourceMaps(compilation, done) {
value: function uploadSourceMaps(compilation) {
var _this = this;
var assets = this.getAssets(compilation);
var upload = this.uploadSourceMap.bind(this, compilation);
_async["default"].each(assets, upload, function (err, results) {
if (err) {
return done(err);
if (assets.length <= 0) {
// We should probably tell people they're not uploading assets.
// this is also an open issue on Rollbar sourcemap plugin
// https://github.com/thredup/rollbar-sourcemap-webpack-plugin/issues/39
if (!this.silent) {
console.info(this.noAssetsFoundMessage);
}
return done(null, results);
});
return;
}
console.info('\n');
return Promise.all(assets.map(function (asset) {
return _this.uploadSourceMap(compilation, asset);
}));
}
}, {
key: "noAssetsFoundMessage",
get: function get() {
return '\nHoneybadger could not find any sourcemaps. Nothing will be uploaded.';
}
}]);

@@ -195,0 +328,0 @@ return HoneybadgerSourceMapPlugin;

{
"name": "@honeybadger-io/webpack",
"version": "1.2.0",
"version": "1.3.0-beta.0",
"description": "Webpack plugin to upload source maps to Honeybadger's API - http://docs.honeybadger.io/guides/source-maps.html",

@@ -12,7 +12,9 @@ "main": "./dist/HoneybadgerSourceMapPlugin.js",

"prepublishOnly": "npm run clean && npm run build && npm run test",
"test": "nyc mocha --require @babel/register",
"test": "mocha --require @babel/register",
"test:watch": "npm test -- -w",
"preversion": "npm test",
"version": "scripts/update-versions.sh",
"postversion": "git push && git push --tags"
"postversion": "git push && git push --tags",
"lint": "standard ./{src,test}/**/*.js",
"fix": "standard --fix ./{src,test}/**/*.js"
},

@@ -38,26 +40,37 @@ "repository": {

"devDependencies": {
"@babel/cli": "^7.7.5",
"@babel/core": "^7.7.5",
"@babel/plugin-transform-runtime": "^7.7.6",
"@babel/preset-env": "^7.7.6",
"@babel/register": "^7.7.4",
"cross-env": "^6.0.3",
"@babel/cli": "^7.13.10",
"@babel/core": "^7.13.10",
"@babel/plugin-transform-runtime": "^7.13.10",
"@babel/preset-env": "^7.13.10",
"@babel/register": "^7.13.8",
"chai": "^4.3.4",
"cross-env": "^7.0.0",
"debug": "^4.1.0",
"expect": "^1.20.1",
"lodash": "^4.17.15",
"mocha": "^6.2.2",
"nock": "^11.7.0",
"nyc": "^14.1.0",
"rimraf": "^3.0.0",
"husky": "^5.1.3",
"lodash": "^4.17.21",
"mocha": "^8.3.1",
"nock": "^13.0.11",
"rimraf": "^3.0.2",
"sinon": "^9.2.4",
"standard": "^16.0.3",
"watch": "^1.0.2"
},
"dependencies": {
"@babel/runtime": "^7.7.6",
"async": "^3.0.0",
"@babel/runtime": "^7.13.10",
"@vercel/fetch-retry": "^5.0.3",
"form-data": "^4.0.0",
"lodash.find": "^4.3.0",
"lodash.foreach": "^4.2.0",
"lodash.reduce": "^4.3.0",
"request": "^2.87.0",
"node-fetch": "^2.6.1",
"verror": "^1.6.1"
},
"peerDependencies": {
"webpack": ">= 4.0.0"
},
"husky": {
"hooks": {
"pre-commit": "npm run fix"
}
}
}

@@ -34,2 +34,7 @@ # Honeybadger's Webpack Source Map Plugin

<dt><code>endpoint</code> (optional &mdash; default: "https://api.honeybadger.io/v1/source_maps")</dt>
<dd>Where to upload your sourcemaps to. Perhaps you have a self hosted
sourcemap server you would like to upload your sourcemaps to instead
of honeybadger.</dd>
<dt><code>revision</code> (optional &mdash; default: "master")</dt>

@@ -43,2 +48,9 @@ <dd>The deploy revision (i.e. commit sha) that your source map applies to. This could also be a code version. For best results, set it to something unique every time your code changes.</dd>

<dd>If true, webpack compilation errors are treated as warnings.</dd>
<dt><code>retries</code> (optional &mdash; default: 3, max: 10)</dt>
<dd>This package implements fetch retry functionality via
https://github.com/vercel/fetch-retry </br>
Retrying helps fix issues like `ECONNRESET` and `SOCKETTIMEOUT`
errors and retries on 429 and 500 errors as well.
</dd>
</dl>

@@ -87,2 +99,6 @@

## Changelog
See https://github.com/honeybadger-io/honeybadger-webpack/blob/master/CHANGELOG.md
## Contributing

@@ -110,3 +126,2 @@

## License

@@ -113,0 +128,0 @@

export const PLUGIN_NAME = 'HoneybadgerSourceMapPlugin'
export const ENDPOINT = 'https://api.honeybadger.io/v1/source_maps ';
export const ENDPOINT = 'https://api.honeybadger.io/v1/source_maps'
export const MAX_RETRIES = 10
export const REQUIRED_FIELDS = [
'apiKey',
'assetsUrl',
];
'assetsUrl'
]

@@ -1,17 +0,17 @@

import VError from 'verror';
import { REQUIRED_FIELDS } from './constants';
import VError from 'verror'
import { REQUIRED_FIELDS } from './constants'
export function handleError(err, prefix = 'HoneybadgerSourceMapPlugin') {
export function handleError (err, prefix = 'HoneybadgerSourceMapPlugin') {
if (!err) {
return [];
return []
}
const errors = [].concat(err);
return errors.map(e => new VError(e, prefix));
const errors = [].concat(err)
return errors.map(e => new VError(e, prefix))
}
export function validateOptions(ref) {
export function validateOptions (ref) {
const errors = REQUIRED_FIELDS.reduce((result, field) => {
if (ref && ref[field]) {
return result;
return result
}

@@ -22,6 +22,6 @@

new Error(`required field, '${field}', is missing.`)
];
}, []);
]
}, [])
return errors.length ? errors : null;
return errors.length ? errors : null
}

@@ -1,73 +0,89 @@

import async from 'async';
import request from 'request';
import VError from 'verror';
import find from 'lodash.find';
import reduce from 'lodash.reduce';
import { handleError, validateOptions } from './helpers';
import { ENDPOINT, PLUGIN_NAME } from './constants';
import { promises as fs } from 'fs'
import { join } from 'path'
import nodeFetch from 'node-fetch'
import fetchRetry from '@vercel/fetch-retry'
import VError from 'verror'
import find from 'lodash.find'
import reduce from 'lodash.reduce'
import FormData from 'form-data'
import { handleError, validateOptions } from './helpers'
import { ENDPOINT, PLUGIN_NAME, MAX_RETRIES } from './constants'
const fetch = fetchRetry(nodeFetch)
class HoneybadgerSourceMapPlugin {
constructor({
constructor ({
apiKey,
assetsUrl,
revision = "master",
endpoint = ENDPOINT,
revision = 'master',
silent = false,
ignoreErrors = false
ignoreErrors = false,
retries = 3
}) {
this.apiKey = apiKey;
this.assetsUrl = assetsUrl;
this.revision = revision;
this.silent = silent;
this.ignoreErrors = ignoreErrors;
this.emittedAssets = new Map();
}
this.apiKey = apiKey
this.assetsUrl = assetsUrl
this.endpoint = endpoint
this.revision = revision
this.silent = silent
this.ignoreErrors = ignoreErrors
this.emittedAssets = new Map()
assetEmitted(file, content, done) {
this.emittedAssets.set(file, content);
done();
this.retries = retries
if (this.retries > MAX_RETRIES) {
this.retries = 10
}
}
afterEmit(compilation, done) {
const errors = validateOptions(this);
async afterEmit (compilation) {
const errors = validateOptions(this)
if (errors) {
compilation.errors.push(...handleError(errors));
return done();
compilation.errors.push(...handleError(errors))
return
}
this.uploadSourceMaps(compilation, (err) => {
if (err) {
if (!this.ignoreErrors) {
compilation.errors.push(...handleError(err));
} else if (!this.silent) {
compilation.warnings.push(...handleError(err));
}
try {
await this.uploadSourceMaps(compilation)
} catch (err) {
if (!this.ignoreErrors) {
compilation.errors.push(...handleError(err))
} else if (!this.silent) {
compilation.warnings.push(...handleError(err))
}
this.emittedAssets.clear();
done();
});
}
}
apply(compiler) {
if (compiler.hooks) {
compiler.hooks.afterEmit.tapAsync(PLUGIN_NAME, this.afterEmit.bind(this));
if (compiler.hooks.assetEmitted) {
compiler.hooks.assetEmitted.tapAsync(PLUGIN_NAME, this.assetEmitted.bind(this));
}
} else {
compiler.plugin('after-emit', this.afterEmit.bind(this));
}
apply (compiler) {
compiler.hooks.afterEmit.tapPromise(PLUGIN_NAME, this.afterEmit.bind(this))
}
getAssets(compilation) {
const { chunks } = compilation.getStats().toJson();
// eslint-disable-next-line class-methods-use-this
getAssetPath (compilation, name) {
return join(
compilation.getPath(compilation.compiler.outputPath),
name.split('?')[0]
)
}
getSource (compilation, name) {
const path = this.getAssetPath(compilation, name)
return fs.readFile(path, { encoding: 'utf-8' })
}
getAssets (compilation) {
const { chunks } = compilation.getStats().toJson()
return reduce(chunks, (result, chunk) => {
const chunkName = chunk.names[0];
const sourceFile = find(chunk.files, file => /\.js$/.test(file))
const sourceFile = find(chunk.files, file => /\.js$/.test(file));
const sourceMap = find(chunk.files, file => /\.js\.map$/.test(file));
// Webpack 4 using chunk.files, Webpack 5 uses chunk.auxiliaryFiles
// https://webpack.js.org/blog/2020-10-10-webpack-5-release/#stats
const sourceMap = (chunk.auxiliaryFiles || chunk.files).find(file =>
/\.js\.map$/.test(file)
)
if (!sourceFile || !sourceMap) {
return result;
return result
}

@@ -78,59 +94,109 @@

{ sourceFile, sourceMap }
];
}, []);
]
}, [])
}
uploadSourceMap(compilation, { sourceFile, sourceMap }, done) {
const req = request.post(ENDPOINT, (err, res, body) => {
if (!err && res.statusCode === 201) {
if (!this.silent) {
console.info(`Uploaded ${sourceMap} to Honeybadger API`); // eslint-disable-line no-console
}
return done();
}
getUrlToAsset (sourceFile) {
if (typeof sourceFile === 'string') {
const sep = this.assetsUrl.endsWith('/') ? '' : '/'
return `${this.assetsUrl}${sep}${sourceFile}`
}
return this.assetsUrl(sourceFile)
}
const errMessage = `failed to upload ${sourceMap} to Honeybadger API`;
if (err) {
return done(new VError(err, errMessage));
}
async uploadSourceMap (compilation, { sourceFile, sourceMap }) {
const errorMessage = `failed to upload ${sourceMap} to Honeybadger API`
let result;
let sourceMapSource
let sourceFileSource
try {
sourceMapSource = await this.getSource(compilation, sourceMap)
sourceFileSource = await this.getSource(compilation, sourceFile)
} catch (err) {
throw new VError(err, err.message)
}
const form = new FormData()
form.append('api_key', this.apiKey)
form.append('minified_url', this.getUrlToAsset(sourceFile))
form.append('minified_file', sourceFileSource, {
filename: sourceFile,
contentType: 'application/javascript'
})
form.append('source_map', sourceMapSource, {
filename: sourceMap,
contentType: 'application/octet-stream'
})
form.append('revision', this.revision)
let res
try {
res = await fetch(this.endpoint, {
method: 'POST',
body: form,
redirect: 'follow',
opts: {
retries: this.retries,
// Max timeout between retries, in milliseconds
maxTimeout: 1000
}
})
} catch (err) {
// network / operational errors. Does not include 404 / 500 errors
throw new VError(err, errorMessage)
}
// >= 400 responses
if (!res.ok) {
// Attempt to parse error details from response
let details
try {
const { error } = JSON.parse(body);
result = new Error(error ? `${errMessage}: ${error}` : errMessage);
const body = await res.json()
if (body && body.error) {
details = body.error
} else {
details = `${res.status} - ${res.statusText}`
}
} catch (parseErr) {
result = new VError(parseErr, errMessage);
details = `${res.status} - ${res.statusText}`
}
return done(result);
});
throw new Error(`${errorMessage}: ${details}`)
}
const form = req.form();
form.append('api_key', this.apiKey);
form.append('minified_url', `${this.assetsUrl.toString().replace(/^\//, '')}/${sourceFile.replace(/^\//, '')}`);
form.append('minified_file', (this.emittedAssets.get(sourceFile) || compilation.assets[sourceFile].source()), {
filename: sourceFile,
contentType: 'application/javascript'
});
form.append('source_map', (this.emittedAssets.get(sourceMap) || compilation.assets[sourceMap].source()), {
filename: sourceMap,
contentType: 'application/octet-stream'
});
form.append('revision', this.revision);
// Success
if (!this.silent) {
// eslint-disable-next-line no-console
console.info(`Uploaded ${sourceMap} to Honeybadger API`)
}
}
uploadSourceMaps(compilation, done) {
const assets = this.getAssets(compilation);
const upload = this.uploadSourceMap.bind(this, compilation);
uploadSourceMaps (compilation) {
const assets = this.getAssets(compilation)
async.each(assets, upload, (err, results) => {
if (err) {
return done(err);
if (assets.length <= 0) {
// We should probably tell people they're not uploading assets.
// this is also an open issue on Rollbar sourcemap plugin
// https://github.com/thredup/rollbar-sourcemap-webpack-plugin/issues/39
if (!this.silent) {
console.info(this.noAssetsFoundMessage)
}
return done(null, results);
});
return
}
console.info('\n')
return Promise.all(
assets.map(asset => this.uploadSourceMap(compilation, asset))
)
}
get noAssetsFoundMessage () {
return '\nHoneybadger could not find any sourcemaps. Nothing will be uploaded.'
}
}
module.exports = HoneybadgerSourceMapPlugin;
module.exports = HoneybadgerSourceMapPlugin

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc