forked from imbue11235/webpack-bugsnag-plugins
-
Notifications
You must be signed in to change notification settings - Fork 0
/
source-map-uploader-plugin.js
102 lines (87 loc) · 2.99 KB
/
source-map-uploader-plugin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
'use strict'
const upload = require('bugsnag-sourcemaps').upload
const resolve = require('url').resolve
const fs = require('graceful-fs');
const parallel = require('run-parallel-limit')
const LOG_PREFIX = `[BugsnagSourceMapUploaderPlugin]`
const PUBLIC_PATH_ERR =
'Cannot determine "minifiedUrl" argument for bugsnag-sourcemaps. ' +
'Please set "publicPath" in Webpack config ("output" section) ' +
'or set "publicPath" in BugsnagSourceMapUploaderPlugin constructor.'
class BugsnagSourceMapUploaderPlugin {
constructor (options) {
this.apiKey = options.apiKey
this.publicPath = options.publicPath
this.appVersion = options.appVersion
this.overwrite = options.overwrite
this.endpoint = options.endpoint
this.cleanUp = options.cleanUp
this.validate()
}
validate () {
if (typeof this.apiKey !== 'string' || this.apiKey.length < 1) {
throw new Error(`${LOG_PREFIX} "apiKey" is required`)
}
}
cleanupMap(map) {
fs.unlink(map, error => {
if (error) {
console.warn(`${LOG_PREFIX} ` + error)
return
}
console.log(`${LOG_PREFIX} "${map}" has been deleted`)
})
}
apply (compiler) {
compiler.plugin('after-emit', (compilation, cb) => {
const stats = compilation.getStats().toJson()
const publicPath = this.publicPath || stats.publicPath
if (!publicPath) {
console.warn(`${LOG_PREFIX} ${PUBLIC_PATH_ERR}`)
return cb()
}
const chunkToSourceMapDescriptor = chunk => {
// find a .map file in this chunk
const map = chunk.files.find(file => /.+\.map(\?.*)?$/.test(file))
// find a corresponding source file in the chunk
const source = map ? chunk.files.find(file => file === map.replace('.map', '')) : null
if (!source || !map) {
console.warn(`${LOG_PREFIX} no source/map pair found for chunk "${chunk.id}"`)
return null
}
return {
source: compilation.assets[source].existsAt,
map: compilation.assets[map].existsAt,
url: resolve(
// ensure publicPath has a trailing slash
publicPath.replace(/[^/]$/, '$&/'),
source
).toString()
}
}
const sourceMaps = stats.chunks.map(chunkToSourceMapDescriptor).filter(Boolean)
parallel(sourceMaps.map(sm => cb => {
console.log(`${LOG_PREFIX} uploading sourcemap for "${sm.url}"`)
const up = upload(this.getUploadOpts(sm), cb)
if (this.cleanUp) {
up.then(() => {
this.cleanupMap(sm.map)
})
}
}), 10, cb)
})
}
getUploadOpts (sm) {
const opts = {
apiKey: this.apiKey,
appVersion: this.appVersion,
minifiedUrl: sm.url,
minifiedFile: sm.source,
sourceMap: sm.map
}
if (this.endpoint) opts.endpoint = this.endpoint
if (this.overwrite) opts.overwrite = this.overwrite
return opts
}
}
module.exports = BugsnagSourceMapUploaderPlugin