Skip to content

Commit

Permalink
feat: first prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
DrJume committed Aug 23, 2023
1 parent 777dd22 commit c0076dd
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 17 deletions.
93 changes: 81 additions & 12 deletions src/module.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,88 @@
import { defineNuxtModule, addPlugin, createResolver } from "@nuxt/kit";
import { type NuxtApp } from '#app/nuxt'
import { type SentryVitePluginOptions, sentryVitePlugin } from '@sentry/vite-plugin'
import { type Options as SentryVueOptions } from '@sentry/vue/types/types'
import defu from 'defu'
import {
addPlugin,
addVitePlugin,
createResolver,
defineNuxtModule,
resolvePath,
useLogger,
} from 'nuxt/kit'
import { type Plugin } from 'vite'

// Module options TypeScript interface definition
export interface ModuleOptions {}
export interface ModuleOptions {
/** @default true */
deleteSourcemapsAfterUpload?: boolean

vitePlugin: SentryVitePluginOptions
}

declare module '@nuxt/schema' {
interface PublicRuntimeConfig {
sentry:
| undefined
| {
dsn?: string
}
}
interface NuxtConfig {
sentry?: ModuleOptions
}
interface AppConfigInput {
sentry?: {
client?: (app: NuxtApp) => Partial<Omit<SentryVueOptions, 'Vue' | 'app' | 'dsn'>>
}
}
}

const logger = useLogger('nuxt:sentry')

export default defineNuxtModule<ModuleOptions>({
meta: {
name: "@falcondev-it/nuxt-sentry",
configKey: "myModule",
name: '@falcondev-it/nuxt-sentry',
configKey: 'sentry',
},
// Default configuration options of the Nuxt module
defaults: {},
setup(options, nuxt) {
const resolver = createResolver(import.meta.url);

// Do not add the extension since the `.ts` will be transpiled to `.mjs` after `npm run prepack`
addPlugin(resolver.resolve("./runtime/plugin"));
async setup(_moduleOptions, nuxt) {
if (!nuxt.options.runtimeConfig.public.sentry?.dsn) {
logger.warn('No Sentry DSN provided. Provide it in `runtimeConfig.public.sentry.dsn`')
return
}

const moduleOptions = defu(_moduleOptions, {
deleteSourcemapsAfterUpload: true,
vitePlugin: {
disable: process.env.NODE_ENV !== 'production' || !process.env.CI,
release: {
deploy: {
env: process.env.NODE_ENV ?? 'development',
},
},
},
} satisfies Partial<ModuleOptions>)

const resolver = createResolver(import.meta.url)

const appConfigFile = await resolvePath(resolver.resolve('./runtime/app.config.ts'))
nuxt.hook('app:resolve', (app) => {
app.configs.push(appConfigFile)
})

nuxt.options.sourcemap.client = true

const defaults: SentryVitePluginOptions = {}
if (moduleOptions.deleteSourcemapsAfterUpload) {
defaults.sourcemaps = {
filesToDeleteAfterUpload: ['.output/**/*.map'],
}
}

nuxt.options.build.transpile.push('@sentry/vue')

addVitePlugin(() => sentryVitePlugin(defu(moduleOptions.vitePlugin, defaults)) as Plugin)

addPlugin(resolver.resolve('./runtime/sentry.client.ts'))
},
});
})
19 changes: 19 additions & 0 deletions src/runtime/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { BrowserTracing, Replay, vueRouterInstrumentation } from '@sentry/vue'

export default defineAppConfig({
sentry: {
client: (nuxt) => ({
integrations: [
new BrowserTracing({
routingInstrumentation: vueRouterInstrumentation(nuxt.$router, {
routeLabel: 'path',
}),
}),
new Replay(),
],
tracesSampleRate: 1,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1,
}),
},
})
5 changes: 0 additions & 5 deletions src/runtime/plugin.ts

This file was deleted.

28 changes: 28 additions & 0 deletions src/runtime/sentry.client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { captureException, init, withScope } from '@sentry/vue'

export default defineNuxtPlugin({
enforce: 'pre',
setup(nuxt) {
if (!process.dev) return

const dsn = useRuntimeConfig().public.sentry?.dsn
const { client } = useAppConfig().sentry

init({
app: nuxt.vueApp,
dsn,
...client(nuxt.vueApp.$nuxt),
})

nuxt.vueApp.config.errorHandler = (err, context) => {
withScope((scope) => {
scope.setExtra('context', context)
captureException(err)
})
}

nuxt.hook('app:error', (err) => {
captureException(err)
})
},
})

0 comments on commit c0076dd

Please sign in to comment.