@dargmuesli/nuxt-vio 23.0.0-beta.2 → 23.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/composables/sentry.ts +17 -0
- package/app/stores/auth.ts +13 -0
- package/node/static/index.ts +1 -0
- package/node/static/sentry.ts +42 -0
- package/nuxt.config.ts +67 -7
- package/package.json +5 -2
- package/sentry.client.config.ts +38 -0
- package/sentry.server.config.ts +36 -0
- package/server/middleware/sentry.ts +33 -0
- package/shared/utils/constants.ts +18 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { getSharedSentryConfig } from '~~/node/static'
|
|
2
|
+
|
|
3
|
+
export const useSharedSentryConfig = () => {
|
|
4
|
+
const isTesting = useIsTesting()
|
|
5
|
+
const runtimeConfig = useRuntimeConfig()
|
|
6
|
+
|
|
7
|
+
return getSharedSentryConfig({
|
|
8
|
+
enableLogs: runtimeConfig.public.sentry.logs.enable,
|
|
9
|
+
environment: runtimeConfig.public.sentry.environment,
|
|
10
|
+
host: runtimeConfig.public.sentry.host,
|
|
11
|
+
isInProduction: runtimeConfig.public.vio.isInProduction,
|
|
12
|
+
isTesting,
|
|
13
|
+
projectId: runtimeConfig.public.sentry.project.id,
|
|
14
|
+
projectPublicKey: runtimeConfig.public.sentry.project.publicKey,
|
|
15
|
+
release: runtimeConfig.public.sentry.release,
|
|
16
|
+
})
|
|
17
|
+
}
|
package/app/stores/auth.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/nuxt'
|
|
1
2
|
import { decodeJwt } from 'jose'
|
|
2
3
|
import type { JWTPayload } from 'jose'
|
|
3
4
|
import { defineStore } from 'pinia'
|
|
4
5
|
import { ref } from 'vue'
|
|
5
6
|
|
|
6
7
|
export const useVioAuthStore = defineStore('vio-auth', () => {
|
|
8
|
+
const runtimeConfig = useRuntimeConfig()
|
|
7
9
|
const jwt = ref<string>()
|
|
8
10
|
const jwtDecoded = ref<JWTPayload>()
|
|
9
11
|
const signedInUsername = ref<string>()
|
|
@@ -21,6 +23,17 @@ export const useVioAuthStore = defineStore('vio-auth', () => {
|
|
|
21
23
|
jwtDecodedNew.exp > Math.floor(Date.now() / 1000)
|
|
22
24
|
? (jwtDecodedNew.username as string | undefined)
|
|
23
25
|
: undefined
|
|
26
|
+
|
|
27
|
+
if (runtimeConfig.public.sentry.features.userTracking) {
|
|
28
|
+
Sentry.setUser(
|
|
29
|
+
signedInUsername.value
|
|
30
|
+
? {
|
|
31
|
+
id: jwtDecodedNew?.sub as string | undefined,
|
|
32
|
+
username: signedInUsername.value,
|
|
33
|
+
}
|
|
34
|
+
: null,
|
|
35
|
+
)
|
|
36
|
+
}
|
|
24
37
|
}
|
|
25
38
|
|
|
26
39
|
return {
|
package/node/static/index.ts
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type * as Sentry from '@sentry/nuxt'
|
|
2
|
+
|
|
3
|
+
export const NUXT_PUBLIC_SENTRY_ENVIRONMENT =
|
|
4
|
+
process.env.NUXT_PUBLIC_SENTRY_ENVIRONMENT
|
|
5
|
+
export const NUXT_PUBLIC_SENTRY_HOST = process.env.NUXT_PUBLIC_SENTRY_HOST || ''
|
|
6
|
+
export const NUXT_PUBLIC_SENTRY_LOGS_ENABLE =
|
|
7
|
+
process.env.NUXT_PUBLIC_SENTRY_LOGS_ENABLE !== 'false'
|
|
8
|
+
export const NUXT_PUBLIC_SENTRY_PROJECT_ID =
|
|
9
|
+
process.env.NUXT_PUBLIC_SENTRY_PROJECT_ID || ''
|
|
10
|
+
export const NUXT_PUBLIC_SENTRY_PROJECT_PUBLIC_KEY =
|
|
11
|
+
process.env.NUXT_PUBLIC_SENTRY_PROJECT_PUBLIC_KEY || ''
|
|
12
|
+
export const NUXT_PUBLIC_SENTRY_RELEASE = process.env.RELEASE_NAME
|
|
13
|
+
|
|
14
|
+
export const getSharedSentryConfig = ({
|
|
15
|
+
enableLogs,
|
|
16
|
+
environment,
|
|
17
|
+
host,
|
|
18
|
+
isInProduction,
|
|
19
|
+
isTesting,
|
|
20
|
+
projectId,
|
|
21
|
+
projectPublicKey,
|
|
22
|
+
release,
|
|
23
|
+
}: {
|
|
24
|
+
enableLogs?: boolean
|
|
25
|
+
environment?: string
|
|
26
|
+
host?: string
|
|
27
|
+
isInProduction: boolean
|
|
28
|
+
isTesting?: boolean
|
|
29
|
+
projectId?: string
|
|
30
|
+
projectPublicKey?: string
|
|
31
|
+
release?: string
|
|
32
|
+
}): Parameters<typeof Sentry.init>[0] => ({
|
|
33
|
+
dsn:
|
|
34
|
+
projectPublicKey && host && projectId
|
|
35
|
+
? `https://${projectPublicKey}@${host}/${projectId}`
|
|
36
|
+
: undefined,
|
|
37
|
+
enabled: isInProduction && !isTesting,
|
|
38
|
+
enableLogs,
|
|
39
|
+
environment,
|
|
40
|
+
release,
|
|
41
|
+
tracesSampleRate: 1.0,
|
|
42
|
+
})
|
package/nuxt.config.ts
CHANGED
|
@@ -2,7 +2,17 @@ import tailwindcss from '@tailwindcss/vite'
|
|
|
2
2
|
import { defu } from 'defu'
|
|
3
3
|
import { createResolver } from 'nuxt/kit'
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
IS_IN_STACK,
|
|
7
|
+
NUXT_PUBLIC_SENTRY_ENVIRONMENT,
|
|
8
|
+
NUXT_PUBLIC_SENTRY_HOST,
|
|
9
|
+
NUXT_PUBLIC_SENTRY_LOGS_ENABLE,
|
|
10
|
+
NUXT_PUBLIC_SENTRY_PROJECT_ID,
|
|
11
|
+
NUXT_PUBLIC_SENTRY_PROJECT_PUBLIC_KEY,
|
|
12
|
+
NUXT_PUBLIC_SENTRY_RELEASE,
|
|
13
|
+
SITE_URL,
|
|
14
|
+
VIO_NUXT_BASE_CONFIG,
|
|
15
|
+
} from './node/static'
|
|
6
16
|
import {
|
|
7
17
|
GTAG_COOKIE_ID,
|
|
8
18
|
TIMEZONE_COOKIE_NAME,
|
|
@@ -53,6 +63,7 @@ export default defineNuxtConfig(
|
|
|
53
63
|
'@nuxtjs/seo',
|
|
54
64
|
'@nuxtjs/turnstile',
|
|
55
65
|
'@pinia/nuxt',
|
|
66
|
+
'@sentry/nuxt/module',
|
|
56
67
|
'nuxt-gtag',
|
|
57
68
|
'shadcn-nuxt',
|
|
58
69
|
(_options, nuxt) => {
|
|
@@ -72,7 +83,16 @@ export default defineNuxtConfig(
|
|
|
72
83
|
) {
|
|
73
84
|
if (nuxt.options.nitro.static) {
|
|
74
85
|
nuxtConfigSecurityHeaders.contentSecurityPolicy = defu(
|
|
75
|
-
VIO_GET_CSP({
|
|
86
|
+
VIO_GET_CSP({
|
|
87
|
+
sentry:
|
|
88
|
+
NUXT_PUBLIC_SENTRY_HOST && NUXT_PUBLIC_SENTRY_PROJECT_ID
|
|
89
|
+
? {
|
|
90
|
+
host: NUXT_PUBLIC_SENTRY_HOST,
|
|
91
|
+
projectId: NUXT_PUBLIC_SENTRY_PROJECT_ID,
|
|
92
|
+
}
|
|
93
|
+
: undefined,
|
|
94
|
+
siteUrl: new URL(SITE_URL),
|
|
95
|
+
}),
|
|
76
96
|
nuxtConfigSecurityHeaders.contentSecurityPolicy,
|
|
77
97
|
)
|
|
78
98
|
}
|
|
@@ -106,6 +126,37 @@ export default defineNuxtConfig(
|
|
|
106
126
|
i18n: {
|
|
107
127
|
baseUrl: SITE_URL,
|
|
108
128
|
},
|
|
129
|
+
sentry: {
|
|
130
|
+
environment: NUXT_PUBLIC_SENTRY_ENVIRONMENT,
|
|
131
|
+
features: {
|
|
132
|
+
consoleCapture: true,
|
|
133
|
+
pinia: true,
|
|
134
|
+
profiling: true,
|
|
135
|
+
replay: true,
|
|
136
|
+
securityHeaders: true,
|
|
137
|
+
userTracking: true,
|
|
138
|
+
},
|
|
139
|
+
host: NUXT_PUBLIC_SENTRY_HOST,
|
|
140
|
+
logs: {
|
|
141
|
+
enable: NUXT_PUBLIC_SENTRY_LOGS_ENABLE,
|
|
142
|
+
},
|
|
143
|
+
profiles: {
|
|
144
|
+
sampleRate: 1.0,
|
|
145
|
+
},
|
|
146
|
+
project: {
|
|
147
|
+
id: NUXT_PUBLIC_SENTRY_PROJECT_ID,
|
|
148
|
+
publicKey: NUXT_PUBLIC_SENTRY_PROJECT_PUBLIC_KEY,
|
|
149
|
+
},
|
|
150
|
+
release: NUXT_PUBLIC_SENTRY_RELEASE,
|
|
151
|
+
replays: {
|
|
152
|
+
onError: {
|
|
153
|
+
sampleRate: 1.0,
|
|
154
|
+
},
|
|
155
|
+
session: {
|
|
156
|
+
sampleRate: 0.0,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
},
|
|
109
160
|
site: {
|
|
110
161
|
url: SITE_URL, // TODO: evaluate removal for static builds in favor of i18n.baseUrl
|
|
111
162
|
},
|
|
@@ -127,11 +178,7 @@ export default defineNuxtConfig(
|
|
|
127
178
|
},
|
|
128
179
|
tsConfig: {
|
|
129
180
|
nodeTsConfig: {
|
|
130
|
-
include: [
|
|
131
|
-
resolve('../.config'),
|
|
132
|
-
resolve('../node'),
|
|
133
|
-
// resolve('../sentry.server.config.ts'),
|
|
134
|
-
],
|
|
181
|
+
include: [resolve('../.config'), resolve('../node')],
|
|
135
182
|
},
|
|
136
183
|
vueCompilerOptions: {
|
|
137
184
|
htmlAttributes: [], // https://github.com/johnsoncodehk/volar/issues/1970#issuecomment-1276994634
|
|
@@ -290,6 +337,16 @@ export default defineNuxtConfig(
|
|
|
290
337
|
},
|
|
291
338
|
strict: true,
|
|
292
339
|
},
|
|
340
|
+
sentry: {
|
|
341
|
+
release: {
|
|
342
|
+
name: process.env.RELEASE_NAME || undefined,
|
|
343
|
+
},
|
|
344
|
+
sourcemaps: {
|
|
345
|
+
disable: !process.env.SENTRY_AUTH_TOKEN,
|
|
346
|
+
},
|
|
347
|
+
telemetry: false,
|
|
348
|
+
// `org`, `project` and `authToken` are read from the `SENTRY_ORG`, `SENTRY_PROJECT` and `SENTRY_AUTH_TOKEN` environment variables by the module itself.
|
|
349
|
+
},
|
|
293
350
|
seo: {
|
|
294
351
|
minify: false, // TODO: enable (https://github.com/harlan-zw/nuxt-seo-utils/issues/103)
|
|
295
352
|
},
|
|
@@ -326,6 +383,9 @@ export default defineNuxtConfig(
|
|
|
326
383
|
strictTransportSecurity: false, // prevent endless reload in Chrome
|
|
327
384
|
},
|
|
328
385
|
},
|
|
386
|
+
sentry: {
|
|
387
|
+
enabled: false,
|
|
388
|
+
},
|
|
329
389
|
site: {
|
|
330
390
|
debug: true,
|
|
331
391
|
},
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"@nuxtjs/seo": "5.3.14",
|
|
16
16
|
"@nuxtjs/turnstile": "1.1.3",
|
|
17
17
|
"@pinia/nuxt": "1.0.2",
|
|
18
|
+
"@sentry/nuxt": "10.71.0",
|
|
18
19
|
"@tailwindcss/forms": "0.5.11",
|
|
19
20
|
"@tailwindcss/typography": "0.5.20",
|
|
20
21
|
"@tailwindcss/vite": "4.3.3",
|
|
@@ -84,7 +85,9 @@
|
|
|
84
85
|
"server",
|
|
85
86
|
"shared",
|
|
86
87
|
"nuxt.config.ts",
|
|
87
|
-
"package.json"
|
|
88
|
+
"package.json",
|
|
89
|
+
"sentry.client.config.ts",
|
|
90
|
+
"sentry.server.config.ts"
|
|
88
91
|
],
|
|
89
92
|
"main": "nuxt.config.ts",
|
|
90
93
|
"name": "@dargmuesli/nuxt-vio",
|
|
@@ -101,7 +104,7 @@
|
|
|
101
104
|
"url": "git+https://github.com/dargmuesli/vio.git"
|
|
102
105
|
},
|
|
103
106
|
"type": "module",
|
|
104
|
-
"version": "23.0.0-beta.
|
|
107
|
+
"version": "23.0.0-beta.3",
|
|
105
108
|
"scripts": {
|
|
106
109
|
"build": "pnpm run build:node",
|
|
107
110
|
"build:node": "NUXT_PUBLIC_I18N_BASE_URL=https://app.localhost:3001 nuxt build playground",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/nuxt'
|
|
2
|
+
|
|
3
|
+
const runtimeConfig = useRuntimeConfig()
|
|
4
|
+
const sharedSentryConfig = useSharedSentryConfig()
|
|
5
|
+
|
|
6
|
+
if (sharedSentryConfig.dsn) {
|
|
7
|
+
const features = runtimeConfig.public.sentry.features
|
|
8
|
+
|
|
9
|
+
Sentry.init({
|
|
10
|
+
...sharedSentryConfig,
|
|
11
|
+
integrations: [
|
|
12
|
+
...(features.profiling ? [Sentry.browserProfilingIntegration()] : []),
|
|
13
|
+
...(features.consoleCapture
|
|
14
|
+
? [
|
|
15
|
+
Sentry.captureConsoleIntegration(),
|
|
16
|
+
Sentry.consoleLoggingIntegration(),
|
|
17
|
+
]
|
|
18
|
+
: []),
|
|
19
|
+
Sentry.httpClientIntegration(),
|
|
20
|
+
...(features.pinia ? [Sentry.piniaIntegration(usePinia())] : []),
|
|
21
|
+
...(features.replay ? [Sentry.replayIntegration()] : []),
|
|
22
|
+
Sentry.zodErrorsIntegration(),
|
|
23
|
+
],
|
|
24
|
+
profilesSampleRate: features.profiling
|
|
25
|
+
? runtimeConfig.public.sentry.profiles.sampleRate
|
|
26
|
+
: undefined,
|
|
27
|
+
replaysOnErrorSampleRate: features.replay
|
|
28
|
+
? runtimeConfig.public.sentry.replays.onError.sampleRate
|
|
29
|
+
: undefined,
|
|
30
|
+
replaysSessionSampleRate: features.replay
|
|
31
|
+
? runtimeConfig.public.sentry.replays.session.sampleRate
|
|
32
|
+
: undefined,
|
|
33
|
+
})
|
|
34
|
+
} else {
|
|
35
|
+
console.warn(
|
|
36
|
+
'Sentry configuration is incomplete, skipping Sentry initialization.',
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/nuxt'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
getSharedSentryConfig,
|
|
5
|
+
IS_IN_PRODUCTION,
|
|
6
|
+
NUXT_PUBLIC_SENTRY_ENVIRONMENT,
|
|
7
|
+
NUXT_PUBLIC_SENTRY_HOST,
|
|
8
|
+
NUXT_PUBLIC_SENTRY_LOGS_ENABLE,
|
|
9
|
+
NUXT_PUBLIC_SENTRY_PROJECT_ID,
|
|
10
|
+
NUXT_PUBLIC_SENTRY_PROJECT_PUBLIC_KEY,
|
|
11
|
+
NUXT_PUBLIC_SENTRY_RELEASE,
|
|
12
|
+
} from './node/static'
|
|
13
|
+
|
|
14
|
+
const sharedSentryConfig = getSharedSentryConfig({
|
|
15
|
+
enableLogs: NUXT_PUBLIC_SENTRY_LOGS_ENABLE,
|
|
16
|
+
environment: NUXT_PUBLIC_SENTRY_ENVIRONMENT,
|
|
17
|
+
host: NUXT_PUBLIC_SENTRY_HOST,
|
|
18
|
+
isInProduction: IS_IN_PRODUCTION,
|
|
19
|
+
isTesting: !!process.env.NUXT_PUBLIC_VIO_IS_TESTING,
|
|
20
|
+
projectId: NUXT_PUBLIC_SENTRY_PROJECT_ID,
|
|
21
|
+
projectPublicKey: NUXT_PUBLIC_SENTRY_PROJECT_PUBLIC_KEY,
|
|
22
|
+
release: NUXT_PUBLIC_SENTRY_RELEASE,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
if (sharedSentryConfig.dsn) {
|
|
26
|
+
Sentry.init({
|
|
27
|
+
...sharedSentryConfig,
|
|
28
|
+
integrations: NUXT_PUBLIC_SENTRY_LOGS_ENABLE
|
|
29
|
+
? [Sentry.consoleLoggingIntegration()]
|
|
30
|
+
: [],
|
|
31
|
+
})
|
|
32
|
+
} else {
|
|
33
|
+
console.warn(
|
|
34
|
+
'Sentry configuration is incomplete, skipping Sentry initialization.',
|
|
35
|
+
)
|
|
36
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export default defineEventHandler((event) => {
|
|
2
|
+
const runtimeConfig = useRuntimeConfig(event)
|
|
3
|
+
const sentryConfig = runtimeConfig.public.sentry
|
|
4
|
+
|
|
5
|
+
if (
|
|
6
|
+
!sentryConfig.features.securityHeaders ||
|
|
7
|
+
!sentryConfig.host ||
|
|
8
|
+
!sentryConfig.project.id ||
|
|
9
|
+
!sentryConfig.project.publicKey
|
|
10
|
+
) {
|
|
11
|
+
return
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const securityEndpointParams = [
|
|
15
|
+
`sentry_key=${sentryConfig.project.publicKey}`,
|
|
16
|
+
sentryConfig.environment &&
|
|
17
|
+
`sentry_environment=${sentryConfig.environment}`,
|
|
18
|
+
sentryConfig.release && `sentry_release=${sentryConfig.release}`,
|
|
19
|
+
]
|
|
20
|
+
.filter(Boolean)
|
|
21
|
+
.join('&')
|
|
22
|
+
|
|
23
|
+
appendHeader(
|
|
24
|
+
event,
|
|
25
|
+
'NEL',
|
|
26
|
+
'\'{"report_to":"sentry","max_age":31536000,"include_subdomains":true}\'',
|
|
27
|
+
)
|
|
28
|
+
appendHeader(
|
|
29
|
+
event,
|
|
30
|
+
'Report-To',
|
|
31
|
+
`'{"group":"sentry","max_age":31536000,"endpoints":[{"url":"https://${sentryConfig.host}/api/${sentryConfig.project.id}/security/?${securityEndpointParams}"}],"include_subdomains":true}'`,
|
|
32
|
+
)
|
|
33
|
+
})
|
|
@@ -12,7 +12,13 @@ export const COOKIE_CONTROL_CONSENT_COOKIE_NAME =
|
|
|
12
12
|
export const COOKIE_PREFIX = VIO_SITE_NAME.toLocaleLowerCase()
|
|
13
13
|
export const COOKIE_SEPARATOR = '_'
|
|
14
14
|
export const FETCH_RETRY_AMOUNT = 3
|
|
15
|
-
export const VIO_GET_CSP = ({
|
|
15
|
+
export const VIO_GET_CSP = ({
|
|
16
|
+
sentry,
|
|
17
|
+
siteUrl,
|
|
18
|
+
}: {
|
|
19
|
+
sentry?: { host: string; projectId: string }
|
|
20
|
+
siteUrl: URL
|
|
21
|
+
}) =>
|
|
16
22
|
defu(
|
|
17
23
|
{
|
|
18
24
|
// Cloudflare
|
|
@@ -26,6 +32,17 @@ export const VIO_GET_CSP = ({ siteUrl }: { siteUrl: URL }) =>
|
|
|
26
32
|
}
|
|
27
33
|
: {}),
|
|
28
34
|
},
|
|
35
|
+
{
|
|
36
|
+
// Sentry
|
|
37
|
+
...(sentry
|
|
38
|
+
? {
|
|
39
|
+
'connect-src': [
|
|
40
|
+
`https://${sentry.host}/api/${sentry.projectId}/envelope/`,
|
|
41
|
+
],
|
|
42
|
+
'worker-src': ['blob:'],
|
|
43
|
+
}
|
|
44
|
+
: {}),
|
|
45
|
+
},
|
|
29
46
|
{
|
|
30
47
|
// Google Analytics 4 (https://developers.google.com/tag-platform/tag-manager/web/csp)
|
|
31
48
|
'connect-src': [
|