-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat(nuxt): Configure sentry in external config #12681
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5feabda
7c329d4
e1f1ade
a0079a8
78ec3a0
77a741c
31c1158
5f93aa6
b24f39d
2f5097f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,16 +12,28 @@ | |
"files": [ | ||
"/build" | ||
], | ||
"main": "build/module.cjs", | ||
"module": "build/module.mjs", | ||
"types": "build/types.d.ts", | ||
"main": "build/cjs/index.server.js", | ||
"module": "build/esm/index.server.js", | ||
"browser": "build/esm/index.client.js", | ||
"types": "build/types/index.types.d.ts", | ||
"exports": { | ||
"./package.json": "./package.json", | ||
".": { | ||
"types": "./build/types.d.ts", | ||
"import": "./build/module.mjs", | ||
"require": "./build/module.cjs" | ||
"types": "./build/types/index.types.d.ts", | ||
"browser": { | ||
"import": "./build/esm/index.client.js", | ||
"require": "./build/cjs/index.client.js" | ||
}, | ||
"node": { | ||
"import": "./build/esm/index.server.js", | ||
"require": "./build/cjs/index.server.js" | ||
} | ||
}, | ||
"./package.json": "./package.json" | ||
"./module": { | ||
"types": "./build/module/types.d.ts", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: Will we have to do the same as for solid here, where types for a submodule export have to be in the root? 😬 no need to adjust this in this PR, but have a look at it in a follow up, and maybe sync with @andreiborza on this :) |
||
"import": "./build/module/module.mjs", | ||
"require": "./build/module/module.cjs" | ||
} | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
|
@@ -31,6 +43,7 @@ | |
}, | ||
"dependencies": { | ||
"@nuxt/kit": "^3.12.2", | ||
"@sentry/browser": "8.13.0", | ||
"@sentry/core": "8.13.0", | ||
"@sentry/node": "8.13.0", | ||
"@sentry/opentelemetry": "8.13.0", | ||
|
@@ -44,12 +57,14 @@ | |
"nuxt": "^3.12.2" | ||
}, | ||
"scripts": { | ||
"build": "run-p build:transpile", | ||
"build": "run-p build:transpile build:types build:nuxt-module", | ||
"build:dev": "yarn build", | ||
"build:transpile": "nuxt-module-build build --outDir build", | ||
"build:nuxt-module": "nuxt-module-build build --outDir build/module", | ||
"build:transpile": "rollup -c rollup.npm.config.mjs", | ||
"build:types": "tsc -p tsconfig.types.json", | ||
"build:watch": "run-p build:transpile:watch build:types:watch", | ||
"build:dev:watch": "yarn build:watch", | ||
"build:transpile:watch": "nuxt-module-build build --outDir build --watch", | ||
"build:transpile:watch": "rollup -c rollup.npm.config.mjs --watch", | ||
"build:types:watch": "tsc -p tsconfig.types.json --watch", | ||
"build:tarball": "npm pack", | ||
"circularDepCheck": "madge --circular src/index.client.ts && madge --circular src/index.server.ts && madge --circular src/index.types.ts", | ||
|
@@ -72,7 +87,8 @@ | |
"^build:types" | ||
], | ||
"outputs": [ | ||
"{projectRoot}/build" | ||
"{projectRoot}/build", | ||
"{projectRoot}/build/module" | ||
] | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollup-utils'; | ||
|
||
export default makeNPMConfigVariants( | ||
makeBaseNPMConfig({ | ||
entrypoints: ['src/index.client.ts', 'src/client/index.ts'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need both of these entry points? What's the difference between them? |
||
}), | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,19 @@ | ||
import { init as initBrowser } from '@sentry/browser'; | ||
import { applySdkMetadata } from '@sentry/core'; | ||
import type { Client } from '@sentry/types'; | ||
import { init as initVue } from '@sentry/vue'; | ||
import type { SentryVueOptions } from '../common/types'; | ||
import type { SentryNuxtOptions } from '../common/types'; | ||
|
||
/** | ||
* Initializes the client-side of the Nuxt SDK | ||
* | ||
* @param options Configuration options for the SDK. | ||
*/ | ||
export function init(options: SentryVueOptions): Client | undefined { | ||
export function init(options: SentryNuxtOptions): Client | undefined { | ||
const sentryOptions = { | ||
...options, | ||
}; | ||
|
||
applySdkMetadata(sentryOptions, 'nuxt', ['nuxt', 'vue']); | ||
|
||
return initVue(sentryOptions); | ||
return initBrowser(sentryOptions); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
declare const __DEBUG_BUILD__: boolean; | ||
|
||
/** | ||
* This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. | ||
* | ||
* ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. | ||
*/ | ||
export const DEBUG_BUILD = __DEBUG_BUILD__; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
|
||
/** Returns an import snippet */ | ||
export function buildSdkInitFileImportSnippet(filePath: string): string { | ||
const posixPath = filePath.split(path.sep).join(path.posix.sep); | ||
|
||
// normalize to forward slashed for Windows-based systems | ||
const normalizedPath = posixPath.replace(/\\/g, '/'); | ||
|
||
return `import '${normalizedPath}';`; | ||
} | ||
|
||
/** | ||
* Script tag inside `nuxt-root.vue` (root component we get from NuxtApp) | ||
*/ | ||
export const SCRIPT_TAG = '<script setup>'; | ||
|
||
/** | ||
* Adds a top-level import statement right after <script setup>. | ||
* This should happen as early as possible (e.g. in root component) | ||
*/ | ||
export function addImportStatement(filePath: string, importStatement: string): void { | ||
AbhiPrasad marked this conversation as resolved.
Show resolved
Hide resolved
|
||
try { | ||
const data = fs.readFileSync(filePath, 'utf8'); | ||
const scriptIndex = data.indexOf(SCRIPT_TAG); | ||
|
||
if (scriptIndex === -1) { | ||
// eslint-disable-next-line no-console | ||
console.warn(`[Sentry] Sentry not initialized. Could not find ${SCRIPT_TAG} in ${filePath}`); | ||
return; | ||
} | ||
|
||
// Insert the import statement after the script tag | ||
const output = data.replace(SCRIPT_TAG, `${SCRIPT_TAG}\n${importStatement}\n`); | ||
|
||
try { | ||
fs.writeFileSync(filePath, output, 'utf8'); | ||
} catch (err) { | ||
// eslint-disable-next-line no-console | ||
console.error(`[Sentry] Error writing file to ${filePath}: ${err}`); | ||
} | ||
} catch (err) { | ||
// eslint-disable-next-line no-console | ||
console.error(`[Sentry] Error reading file at ${filePath}: ${err}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. l: we should have emit a error message if we fail to find |
||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import type { init } from '@sentry/vue'; | ||
|
||
export type SentryVueOptions = Parameters<typeof init>[0] & object; | ||
// Omitting 'app' as the Nuxt SDK will add the app instance in the client plugin (users do not have to provide this) | ||
export type SentryNuxtOptions = Omit<Parameters<typeof init>[0] & object, 'app'>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export {}; | ||
export * from './client'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,49 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import { type Resolver, addPlugin, createResolver, defineNuxtModule } from '@nuxt/kit'; | ||
import type { SentryVueOptions } from './common/types'; | ||
import { addImportStatement, buildSdkInitFileImportSnippet } from './common/snippets'; | ||
import type { SentryNuxtOptions } from './common/types'; | ||
|
||
export type ModuleOptions = SentryVueOptions; | ||
export type ModuleOptions = SentryNuxtOptions; | ||
|
||
export default defineNuxtModule<ModuleOptions>({ | ||
meta: { | ||
name: '@sentry/nuxt', | ||
name: '@sentry/nuxt/module', | ||
configKey: 'sentry', | ||
compatibility: { | ||
nuxt: '^3.0.0', | ||
}, | ||
}, | ||
// Default configuration options of the Nuxt module | ||
defaults: {}, | ||
setup(_moduleOptions, _nuxt) { | ||
setup(_moduleOptions, nuxt) { | ||
const resolver: Resolver = createResolver(import.meta.url); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. l: Can we double check to see if this works with CJS? How does this get transpiled? We currently have There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the module, I am using the nuxt module builder which transpiles the files exactly how they should be imported in Nuxt. The
|
||
|
||
const pathToClientInit = findDefaultSdkInitFile('client'); | ||
|
||
if (pathToClientInit) { | ||
nuxt.hook('app:templates', nuxtApp => { | ||
if (nuxtApp.rootComponent) { | ||
try { | ||
addImportStatement(nuxtApp.rootComponent, buildSdkInitFileImportSnippet(pathToClientInit)); | ||
} catch (err) { | ||
// eslint-disable-next-line no-console | ||
console.error(`[Sentry] Could not add import statement to root component. ${err}`); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
if (resolver) { | ||
addPlugin(resolver.resolve('runtime/plugins/sentry.client.js')); | ||
addPlugin(resolver.resolve('./runtime/plugins/sentry.client')); | ||
} | ||
}, | ||
}); | ||
|
||
function findDefaultSdkInitFile(type: /* 'server' | */ 'client'): string | undefined { | ||
const possibleFileExtensions = ['ts', 'js', 'mjs', 'cjs', 'mts', 'cts']; | ||
|
||
const cwd = process.cwd(); | ||
return possibleFileExtensions | ||
.map(e => path.resolve(path.join(cwd, `sentry.${type}.config.${e}`))) | ||
.find(filename => fs.existsSync(filename)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,13 @@ | ||
import { defineNuxtPlugin, useRuntimeConfig } from 'nuxt/app'; | ||
import { init } from '../../client'; | ||
import { getClient } from '@sentry/core'; | ||
import { vueIntegration } from '@sentry/vue'; | ||
import { defineNuxtPlugin } from 'nuxt/app'; | ||
|
||
export default defineNuxtPlugin(nuxtApp => { | ||
const config = useRuntimeConfig(); | ||
const sentryConfig = config.public.sentry || {}; | ||
nuxtApp.hook('app:created', vueApp => { | ||
const sentryClient = getClient(); | ||
|
||
init({ | ||
...sentryConfig, | ||
app: nuxtApp.vueApp, | ||
if (sentryClient) { | ||
sentryClient.addIntegration(vueIntegration({ app: vueApp })); | ||
} | ||
}); | ||
}); |
Uh oh!
There was an error while loading. Please reload this page.