-
Notifications
You must be signed in to change notification settings - Fork 112
/
Copy pathhooks.ts
135 lines (119 loc) · 5.37 KB
/
hooks.ts
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { fileURLToPath } from 'url'
import { resolve } from 'path'
import { defu } from 'defu'
import type { ConsolaInstance } from 'consola'
import type { Configuration as WebpackConfig } from 'webpack'
import type { SentryWebpackPluginOptions } from '@sentry/webpack-plugin'
import type { Options } from '@sentry/types'
import * as Sentry from '@sentry/node'
import { addPluginTemplate, addTemplate, addWebpackPlugin } from './kit-shim'
import type { Nuxt } from './kit-shim'
import type { ModuleConfiguration } from './types/configuration'
import { clientSentryEnabled, serverSentryEnabled, canInitialize } from './utils'
import { resolveRelease, ResolvedClientOptions, resolveClientOptions, ResolvedServerOptions, resolveServerOptions } from './options'
import type { SentryHandlerProxy } from './options'
const RESOLVED_RELEASE_FILENAME = 'sentry.release.config.mjs'
export async function buildHook (nuxt: Nuxt, moduleOptions: ModuleConfiguration, logger: ConsolaInstance): Promise<void> {
const release = await resolveRelease(moduleOptions)
const templateDir = fileURLToPath(new URL('./templates', import.meta.url))
const pluginOptionClient = clientSentryEnabled(moduleOptions) && canInitialize(moduleOptions) ? moduleOptions.lazy ? 'lazy' : 'client' : 'mocked'
const clientOptions: ResolvedClientOptions = defu({ config: { release } }, await resolveClientOptions(nuxt, moduleOptions, logger))
addPluginTemplate({
src: resolve(templateDir, `plugin.${pluginOptionClient}.js`),
filename: 'sentry.client.js',
mode: 'client',
options: clientOptions,
})
if (pluginOptionClient !== 'mocked') {
addTemplate({
src: resolve(templateDir, 'client.shared.js'),
filename: 'sentry.client.shared.js',
options: clientOptions,
})
}
const pluginOptionServer = serverSentryEnabled(moduleOptions) ? 'server' : 'mocked'
const serverOptions: ResolvedServerOptions = defu({ config: { release } }, await resolveServerOptions(nuxt, moduleOptions, logger))
addPluginTemplate({
src: resolve(templateDir, `plugin.${pluginOptionServer}.js`),
filename: 'sentry.server.js',
mode: 'server',
options: serverOptions,
})
if (serverSentryEnabled(moduleOptions)) {
addTemplate({
src: resolve(templateDir, 'options.ejs'),
filename: RESOLVED_RELEASE_FILENAME,
options: { release },
})
}
// Tree shake debugging code if not running in dev mode and Sentry debug option is not enabled on the client.
if (!clientOptions.dev && !clientOptions.config.debug) {
const webpack = await import('webpack').then(m => m.default || m)
addWebpackPlugin(new webpack.DefinePlugin({
__SENTRY_DEBUG__: 'false',
}))
}
}
export async function webpackConfigHook (nuxt: Nuxt, webpackConfigs: WebpackConfig[], options: ModuleConfiguration, logger: ConsolaInstance): Promise<void> {
let WebpackPlugin: typeof import('@sentry/webpack-plugin')
try {
WebpackPlugin = await import('@sentry/webpack-plugin').then(m => m.default || m)
} catch {
throw new Error('The "@sentry/webpack-plugin" package must be installed as a dev dependency to use the "publishRelease" option.')
}
const publishRelease: SentryWebpackPluginOptions = defu(options.publishRelease)
if (!publishRelease.sourcemaps) {
publishRelease.sourcemaps = {}
}
if (!publishRelease.sourcemaps.ignore) {
publishRelease.sourcemaps.ignore = []
}
if (!Array.isArray(publishRelease.sourcemaps.ignore)) {
publishRelease.sourcemaps.ignore = [publishRelease.sourcemaps.ignore]
}
if (!publishRelease.release) {
publishRelease.release = {}
}
publishRelease.release.name = publishRelease.release.name || options.config.release || await resolveRelease(options)
if (!publishRelease.release.name) {
// We've already tried to determine "release" manually using Sentry CLI so to avoid webpack plugin crashing, we'll just bail here.
logger.warn('Sentry release will not be published because "config.release" or "publishRelease.release.name" was not set nor it ' +
'was possible to determine it automatically from the repository.')
return
}
for (const config of webpackConfigs) {
config.devtool = options.sourceMapStyle
config.plugins = config.plugins || []
config.plugins.push(WebpackPlugin.sentryWebpackPlugin(publishRelease))
}
}
export async function initializeServerSentry (nuxt: Nuxt, moduleOptions: ModuleConfiguration, sentryHandlerProxy: SentryHandlerProxy, logger: ConsolaInstance): Promise<void> {
if (process.sentry) {
return
}
let release: string | undefined
try {
const path = resolve(nuxt.options.buildDir, RESOLVED_RELEASE_FILENAME)
release = (await import(path)).release
} catch {
// Ignored
}
const serverOptions = await resolveServerOptions(nuxt, moduleOptions, logger)
const config: Options = defu({ release }, serverOptions.config)
process.sentry = Sentry
if (canInitialize(moduleOptions)) {
Sentry.init(config)
sentryHandlerProxy.errorHandler = Sentry.Handlers.errorHandler()
sentryHandlerProxy.requestHandler = Sentry.Handlers.requestHandler(moduleOptions.requestHandlerConfig)
if (serverOptions.tracing) {
sentryHandlerProxy.tracingHandler = Sentry.Handlers.tracingHandler()
}
}
}
export async function shutdownServerSentry (): Promise<void> {
if (process.sentry) {
await process.sentry.close()
// @ts-expect-error not mutable in types
process.sentry = undefined
}
}