├── .editorconfig
├── .github
├── renovate.json5
└── workflows
│ └── checks.yml
├── .gitignore
├── .yarnrc.yml
├── LICENSE.md
├── README.md
├── bin
└── test.ts
├── configure.ts
├── eslint.config.js
├── index.ts
├── package.json
├── providers
└── sentry_provider.ts
├── src
├── define_config.ts
├── middleware.ts
├── sentry.ts
└── types
│ └── main.ts
├── stubs
├── config
│ └── sentry.stub
└── main.ts
├── tests
├── configure.spec.ts
└── fixtures
│ ├── base_fixture.ts
│ └── configure_fixture.ts
├── tsconfig.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.json]
12 | insert_final_newline = false
13 |
14 | [*.md]
15 | trim_trailing_whitespace = false
16 |
--------------------------------------------------------------------------------
/.github/renovate.json5:
--------------------------------------------------------------------------------
1 | {
2 | $schema: "https://docs.renovatebot.com/renovate-schema.json",
3 | extends: ["config:recommended", "schedule:weekly", "group:allNonMajor"],
4 | labels: ["dependencies"],
5 | rangeStrategy: "bump",
6 | packageRules: [
7 | {
8 | matchDepTypes: ["peerDependencies"],
9 | enabled: false,
10 | },
11 | ],
12 | ignoreDeps: [
13 | // manually bumping
14 | "node",
15 | "@types/node"
16 | ],
17 | }
18 |
--------------------------------------------------------------------------------
/.github/workflows/checks.yml:
--------------------------------------------------------------------------------
1 | name: checks
2 | on:
3 | - push
4 | - pull_request
5 |
6 | jobs:
7 | test:
8 | uses: boringnode/.github/.github/workflows/test.yml@main
9 |
10 | lint:
11 | uses: boringnode/.github/.github/workflows/lint.yml@main
12 |
13 | typecheck:
14 | uses: boringnode/.github/.github/workflows/typecheck.yml@main
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build
2 | build
3 |
4 | # Node & Dependencies
5 | node_modules
6 | coverage
7 |
8 | # Build tools specific
9 | .yarn/*
10 | !.yarn/patches
11 | !.yarn/plugins
12 | !.yarn/releases
13 | !.yarn/sdks
14 | !.yarn/versions
15 | npm-debug.log
16 | yarn-error.log
17 |
18 | # Editors specific
19 | .fleet
20 | .idea
21 | .vscode
22 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | nodeLinker: node-modules
2 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # The MIT License
2 |
3 | Copyright 2023 Romain Lanz, contributors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
5 |
6 |
7 | [![typescript-image]][typescript-url]
8 | [![gh-workflow-image]][gh-workflow-url]
9 | [![npm-image]][npm-url]
10 | [![npm-download-image]][npm-download-url]
11 | [![license-image]][license-url]
12 |
13 |
14 |
15 |
16 |
17 | `@rlanz/sentry` is a simple wrapper around the Sentry SDK to make it easier to use in a AdonisJS application.
18 |
19 | ## Installation
20 |
21 | ```sh
22 | node ace add @rlanz/sentry
23 | ```
24 |
25 | ## Usage
26 |
27 | The package will automatically register a middleware and configure the Sentry SDK.
28 |
29 | ```ts
30 | import type { HttpContext } from '@adonisjs/core/http'
31 | import { Sentry } from '@rlanz/sentry'
32 |
33 | export default class HelloController {
34 | greet({ params, response}: HttpContext) {
35 | Sentry.captureMessage(`Hello, ${params.name}!`)
36 |
37 | return response.ok({ message: `Hello, ${params.name}!` })
38 | }
39 | }
40 | ```
41 |
42 | The SDK is automatically scoped to the current request.
43 |
44 | ```ts
45 | import { inject } from '@adonisjs/core'
46 | import { Sentry } from '@rlanz/sentry'
47 |
48 | @inject()
49 | export class GreetingService {
50 | greet(name: string) {
51 | Sentry.captureMessage(`Hello, ${name}!`)
52 |
53 | return `Hello, ${name}!`
54 | }
55 | }
56 | ```
57 |
58 | ### Capturing Errors
59 |
60 | You can capture errors by calling the `captureException` method on the SDK inside your exception handler.
61 |
62 | ```ts
63 | import { Sentry } from '@rlanz/sentry'
64 |
65 | export default class HttpExceptionHandler extends ExceptionHandler {
66 | // ...
67 |
68 | async report(error: unknown, ctx: HttpContext) {
69 | if (this.shouldReport(error as any)) {
70 | Sentry.captureException(error)
71 | }
72 |
73 | return super.report(error, ctx)
74 | }
75 | }
76 | ```
77 |
78 | ### Assigning User Context
79 |
80 | You can assign user context to the Sentry SDK by calling the `setUser` method on the SDK once you are logged in.
81 |
82 | ```ts
83 | import { Sentry } from '@rlanz/sentry'
84 |
85 | export default class SilentAuthMiddleware {
86 | async handle(ctx: HttpContext, next: NextFn) {
87 | // We are authenticating the user
88 | await ctx.auth.check()
89 |
90 | // If the user is authenticated, we assign the user context to Sentry
91 | if (ctx.auth.isAuthenticated) {
92 | const user = ctx.auth.getUserOrFail()
93 |
94 | Sentry.setUser({
95 | id: user.id,
96 | email: user.email,
97 | username: user.username,
98 | });
99 | }
100 |
101 | return await next();
102 | }
103 | }
104 | ```
105 |
106 | ### Adding Integrations
107 |
108 | Sentry provides multiple integrations to enhance the data captured by the SDK. You can add integrations by changing the `integrations` array inside the configuration `config/sentry.ts`.
109 |
110 | For example, if you want to add profiling to your application, you can add the `Profiler` integration.
111 |
112 | ```sh
113 | npm install @sentry/profiling-node
114 | ```
115 |
116 | ```ts
117 | // config/sentry.ts
118 |
119 | import { nodeProfilingIntegration } from '@sentry/profiling-node';
120 |
121 | export default defineConfig({
122 | // ...
123 | integrations: [nodeProfilingIntegration()],
124 | profilesSampleRate: 0.2,
125 | })
126 | ```
127 |
128 | [gh-workflow-image]: https://img.shields.io/github/actions/workflow/status/RomainLanz/sentry/checks.yml?branch=0.3&style=for-the-badge
129 | [gh-workflow-url]: https://github.com/RomainLanz/sentry/actions/workflows/checks.yml
130 | [npm-image]: https://img.shields.io/npm/v/@rlanz/sentry.svg?style=for-the-badge&logo=npm
131 | [npm-url]: https://www.npmjs.com/package/@rlanz/sentry
132 | [npm-download-image]: https://img.shields.io/npm/dm/@rlanz/sentry?style=for-the-badge
133 | [npm-download-url]: https://www.npmjs.com/package/@rlanz/sentry
134 | [typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
135 | [typescript-url]: https://www.typescriptlang.org
136 | [license-image]: https://img.shields.io/npm/l/@rlanz/sentry?color=blueviolet&style=for-the-badge
137 | [license-url]: LICENSE.md
138 |
--------------------------------------------------------------------------------
/bin/test.ts:
--------------------------------------------------------------------------------
1 | import { assert } from '@japa/assert'
2 | import { fileSystem } from '@japa/file-system'
3 | import { processCLIArgs, configure, run } from '@japa/runner'
4 |
5 | /*
6 | |--------------------------------------------------------------------------
7 | | Configure tests
8 | |--------------------------------------------------------------------------
9 | |
10 | | The configure method accepts the configuration to configure the Japa
11 | | tests runner.
12 | |
13 | | The first method call "processCLIArgs" process the command line arguments
14 | | and turns them into a config object. Using this method is not mandatory.
15 | |
16 | | Please consult japa.dev/runner-config for the config docs.
17 | */
18 | processCLIArgs(process.argv.slice(2))
19 | configure({
20 | files: ['tests/**/*.spec.ts'],
21 | plugins: [assert(), fileSystem({ autoClean: true })],
22 | })
23 |
24 | /*
25 | |--------------------------------------------------------------------------
26 | | Run tests
27 | |--------------------------------------------------------------------------
28 | |
29 | | The following "run" method is required to execute all the tests.
30 | |
31 | */
32 | await run()
33 |
--------------------------------------------------------------------------------
/configure.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | import { stubsRoot } from './stubs/main.js'
11 | import type Configure from '@adonisjs/core/commands/configure'
12 |
13 | /**
14 | * Configures the package
15 | */
16 | export async function configure(command: Configure) {
17 | const codemods = await command.createCodemods()
18 |
19 | /**
20 | * Publish config file
21 | */
22 | await codemods.makeUsingStub(stubsRoot, 'config/sentry.stub', {})
23 |
24 | /**
25 | * Define environment variables
26 | */
27 | await codemods.defineEnvVariables({ SENTRY_DSN: '' })
28 | /**
29 | * Define environment variables validations
30 | */
31 | await codemods.defineEnvValidations({
32 | variables: {
33 | SENTRY_DSN: 'Env.schema.string()',
34 | },
35 | leadingComment: 'Variables for configuring @rlanz/sentry package',
36 | })
37 |
38 | /**
39 | * Register middleware
40 | */
41 | await codemods.registerMiddleware('router', [
42 | {
43 | path: '@rlanz/sentry/middleware',
44 | position: 'before',
45 | },
46 | ])
47 |
48 | /**
49 | * Register provider
50 | */
51 | await codemods.updateRcFile((rcFile) => {
52 | rcFile.addProvider('@rlanz/sentry/provider')
53 | })
54 | }
55 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | import { configPkg } from '@adonisjs/eslint-config'
2 |
3 | export default configPkg({
4 | ignores: ['coverage'],
5 | })
6 |
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | export { Sentry } from './src/sentry.js'
11 | export { configure } from './configure.js'
12 | export { stubsRoot } from './stubs/main.js'
13 | export { defineConfig } from './src/define_config.js'
14 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@rlanz/sentry",
3 | "description": "A wrapper around the Sentry SDK to make it easier to use in a AdonisJS application",
4 | "version": "0.3.3",
5 | "engines": {
6 | "node": ">= 20.11.0"
7 | },
8 | "main": "build/index.js",
9 | "type": "module",
10 | "files": [
11 | "build"
12 | ],
13 | "exports": {
14 | ".": "./build/index.js",
15 | "./middleware": "./build/src/middleware.js",
16 | "./provider": "./build/providers/sentry_provider.js"
17 | },
18 | "scripts": {
19 | "build": "yarn clean && tsc && yarn copy:templates",
20 | "clean": "del-cli build",
21 | "copy:templates": "copyfiles \"stubs/**/*.stub\" --up=\"1\" build",
22 | "format": "prettier --write .",
23 | "lint": "eslint . --ext=.ts",
24 | "prepublishOnly": "yarn build",
25 | "release": "release-it",
26 | "quick:test": "node --enable-source-maps --import=ts-node-maintained/register/esm bin/test.ts",
27 | "test": "c8 yarn quick:test",
28 | "typecheck": "tsc --noEmit"
29 | },
30 | "dependencies": {
31 | "@poppinss/utils": "^6.9.2",
32 | "@sentry/node": "^9.8.0"
33 | },
34 | "devDependencies": {
35 | "@adonisjs/assembler": "^7.8.2",
36 | "@adonisjs/core": "^6.17.2",
37 | "@adonisjs/eslint-config": "^2.0.0",
38 | "@adonisjs/prettier-config": "^1.4.4",
39 | "@adonisjs/tsconfig": "^1.4.0",
40 | "@japa/assert": "^4.0.1",
41 | "@japa/file-system": "^2.3.2",
42 | "@japa/runner": "^4.2.0",
43 | "@swc/core": "1.11.13",
44 | "@types/node": "^20.17.22",
45 | "c8": "^10.1.3",
46 | "copyfiles": "^2.4.1",
47 | "del-cli": "^6.0.0",
48 | "eslint": "^9.23.0",
49 | "prettier": "^3.5.3",
50 | "release-it": "^18.1.2",
51 | "ts-node-maintained": "^10.9.5",
52 | "typescript": "^5.8.2"
53 | },
54 | "author": "Romain Lanz ",
55 | "license": "MIT",
56 | "keywords": [
57 | "sentry",
58 | "adonisjs",
59 | "adonis"
60 | ],
61 | "prettier": "@adonisjs/prettier-config",
62 | "publishConfig": {
63 | "access": "public",
64 | "tag": "latest"
65 | },
66 | "release-it": {
67 | "git": {
68 | "commitMessage": "chore(release): ${version}",
69 | "tagAnnotation": "v${version}",
70 | "tagName": "v${version}"
71 | },
72 | "github": {
73 | "release": true,
74 | "releaseName": "v${version}",
75 | "web": true
76 | }
77 | },
78 | "packageManager": "yarn@4.7.0"
79 | }
80 |
--------------------------------------------------------------------------------
/providers/sentry_provider.ts:
--------------------------------------------------------------------------------
1 | import { Sentry } from '../src/sentry.js'
2 | import type { ApplicationService } from '@adonisjs/core/types'
3 | import type { SentryConfig } from '../src/types/main.js'
4 |
5 | export default class SentryProvider {
6 | constructor(protected app: ApplicationService) {}
7 |
8 | async boot() {
9 | const config = this.app.config.get('sentry', {})
10 |
11 | if (config.enabled) {
12 | Sentry.init(config)
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/define_config.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | import type { SentryConfig } from './types/main.js'
11 |
12 | export function defineConfig(config: T): T {
13 | return config
14 | }
15 |
--------------------------------------------------------------------------------
/src/middleware.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | import { Sentry } from './sentry.js'
11 | import type { HttpContext } from '@adonisjs/core/http'
12 | import type { NextFn } from '@adonisjs/core/types/http'
13 |
14 | export default class SentryMiddleware {
15 | async handle(ctx: HttpContext, next: NextFn) {
16 | const activeSpan = Sentry.getActiveSpan()
17 | const rootSpan = activeSpan && Sentry.getRootSpan(activeSpan)
18 |
19 | if (rootSpan) {
20 | Sentry.updateSpanName(rootSpan, ctx.routeKey || 'unknown')
21 | }
22 |
23 | return next()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/sentry.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | import * as Sentry from '@sentry/node'
11 |
12 | export { Sentry }
13 |
--------------------------------------------------------------------------------
/src/types/main.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | import * as Sentry from '@sentry/node'
11 |
12 | export interface SentryConfig extends Sentry.NodeOptions {
13 | /**
14 | * Enable or disable Sentry
15 | */
16 | enabled: boolean
17 |
18 | dsn: string
19 | }
20 |
--------------------------------------------------------------------------------
/stubs/config/sentry.stub:
--------------------------------------------------------------------------------
1 | {{{
2 | exports({ to: app.configPath('sentry.ts') })
3 | }}}
4 |
5 | import env from '#start/env'
6 | import app from '@adonisjs/core/services/app'
7 | import { defineConfig } from '@rlanz/sentry'
8 |
9 | export default defineConfig({
10 | /**
11 | * Enable or disable Sentry
12 | */
13 | enabled: app.inProduction,
14 |
15 | /**
16 | * The environment Sentry is running in
17 | */
18 | environment: app.nodeEnvironment,
19 |
20 | /**
21 | * The DSN of the project
22 | */
23 | dsn: env.get('SENTRY_DSN'),
24 |
25 | /**
26 | * Additional integrations to use with the Sentry SDK
27 | * @see https://docs.sentry.io/platforms/javascript/guides/node/configuration/integrations/#available-integrations
28 | */
29 | integrations: [],
30 |
31 | /**
32 | * The sample rate of traces to send to Sentry
33 | * @see https://docs.sentry.io/platforms/javascript/guides/node/configuration/sampling
34 | */
35 | tracesSampleRate: 0.2,
36 | })
37 |
--------------------------------------------------------------------------------
/stubs/main.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | *
7 | * For the full copyright and license information, please view the LICENSE
8 | * file that was distributed with this source code.
9 | */
10 |
11 | import { getDirname } from '@poppinss/utils'
12 |
13 | export const stubsRoot = getDirname(import.meta.url)
14 |
--------------------------------------------------------------------------------
/tests/configure.spec.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | import { test } from '@japa/runner'
11 | import { ConfigureFixture } from './fixtures/configure_fixture.js'
12 |
13 | test.group('Configure', (group) => {
14 | group.tap((t) => t.timeout(10_000))
15 |
16 | let fixture: ConfigureFixture
17 |
18 | group.each.setup(async () => {
19 | fixture = new ConfigureFixture()
20 | })
21 |
22 | test('should register provider', async () => {
23 | await fixture.givenIHaveAnApplication()
24 |
25 | await fixture.whenIRunConfigure()
26 |
27 | await fixture.thenShouldRegisterProvider()
28 | })
29 |
30 | test('should create configuration file', async () => {
31 | await fixture.givenIHaveAnApplication()
32 |
33 | await fixture.whenIRunConfigure()
34 |
35 | await fixture.thenConfigurationShouldBeCreated()
36 | })
37 |
38 | test('should register middleware', async () => {
39 | await fixture.givenIHaveAnApplication()
40 |
41 | await fixture.whenIRunConfigure()
42 |
43 | await fixture.thenShouldRegisterMiddleware()
44 | })
45 |
46 | test('should add environment variables', async () => {
47 | await fixture.givenIHaveAnApplication()
48 |
49 | await fixture.whenIRunConfigure()
50 |
51 | await fixture.thenEnvironmentVariablesShouldBeAdded()
52 | })
53 | })
54 |
--------------------------------------------------------------------------------
/tests/fixtures/base_fixture.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | import { IgnitorFactory } from '@adonisjs/core/factories'
11 | import { getActiveTest } from '@japa/runner'
12 | import type { Test } from '@japa/runner/core'
13 | import { assertExists } from '@poppinss/utils/assert'
14 | import { Application } from '@adonisjs/core/app'
15 |
16 | export const BASE_URL = new URL('./tmp/', import.meta.url)
17 |
18 | export class BaseFixture {
19 | protected context: { app: Application | undefined } = {
20 | app: undefined,
21 | }
22 |
23 | protected test: Test | undefined
24 |
25 | getActiveTest() {
26 | if (this.test) {
27 | return this.test
28 | }
29 |
30 | this.test = getActiveTest()
31 |
32 | assertExists(this.test, 'Cannot access test context outside of a test')
33 |
34 | return this.test
35 | }
36 |
37 | async givenIHaveAnApplication() {
38 | this.getActiveTest().context.fs.baseUrl = BASE_URL
39 | this.getActiveTest().context.fs.basePath = BASE_URL.pathname
40 |
41 | await this.getActiveTest().context.fs.create('.env', '')
42 | await this.getActiveTest().context.fs.createJson('tsconfig.json', {})
43 | await this.getActiveTest().context.fs.create(
44 | 'start/env.ts',
45 | `export default Env.create(new URL('./'), {})`
46 | )
47 | await this.getActiveTest().context.fs.create(
48 | 'start/kernel.ts',
49 | `
50 | import router from '@adonisjs/core/services/router'
51 | import server from '@adonisjs/core/services/server'
52 |
53 | router.use([
54 | () => import('@adonisjs/core/bodyparser_middleware'),
55 | ])
56 |
57 | server.use([])
58 | `
59 | )
60 | await this.getActiveTest().context.fs.create('adonisrc.ts', `export default defineConfig({})`)
61 |
62 | const ignitor = new IgnitorFactory()
63 | .withCoreProviders()
64 | .withCoreConfig()
65 | .create(BASE_URL, {
66 | importer: (filePath) => {
67 | if (filePath.startsWith('./') || filePath.startsWith('../')) {
68 | return import(new URL(filePath, BASE_URL).href)
69 | }
70 |
71 | return import(filePath)
72 | },
73 | })
74 |
75 | const app = ignitor.createApp('web')
76 | await app.init().then(() => app.boot())
77 |
78 | this.context.app = app
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/tests/fixtures/configure_fixture.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * @rlanz/sentry
3 | *
4 | * (c) Romain Lanz
5 | *
6 | * For the full copyright and license information, please view the LICENSE
7 | * file that was distributed with this source code.
8 | */
9 |
10 | import { assertExists } from '@poppinss/utils/assert'
11 | import { BaseFixture } from './base_fixture.js'
12 | import Configure from '@adonisjs/core/commands/configure'
13 |
14 | export class ConfigureFixture extends BaseFixture {
15 | async whenIRunConfigure() {
16 | assertExists(this.context.app, 'Cannot access app context without initializing it')
17 |
18 | const ace = await this.context.app.container.make('ace')
19 | ace.ui.switchMode('raw')
20 |
21 | const command = await ace.create(Configure, ['../../../index.js'])
22 | await command.exec()
23 | }
24 |
25 | async thenShouldRegisterProvider() {
26 | await this.getActiveTest().context.assert.fileExists('adonisrc.ts')
27 | await this.getActiveTest().context.assert.fileContains('adonisrc.ts', '@rlanz/sentry/provider')
28 | }
29 |
30 | async thenShouldRegisterMiddleware() {
31 | await this.getActiveTest().context.assert.fileExists('start/kernel.ts')
32 | await this.getActiveTest().context.assert.fileContains(
33 | 'start/kernel.ts',
34 | '@rlanz/sentry/middleware'
35 | )
36 | }
37 |
38 | async thenConfigurationShouldBeCreated() {
39 | await this.getActiveTest().context.assert.fileExists('config/sentry.ts')
40 | }
41 |
42 | async thenEnvironmentVariablesShouldBeAdded() {
43 | await this.getActiveTest().context.assert.fileContains('.env', 'SENTRY_DSN')
44 | await this.getActiveTest().context.assert.fileContains(
45 | 'start/env.ts',
46 | 'SENTRY_DSN: Env.schema.string()'
47 | )
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@adonisjs/tsconfig/tsconfig.package.json",
3 | "compilerOptions": {
4 | "rootDir": "./",
5 | "outDir": "./build"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------