@magnet-cms/plugin-sentry 1.0.0
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/dist/backend/index.cjs +921 -0
- package/dist/backend/index.d.cts +21 -0
- package/dist/backend/index.d.ts +21 -0
- package/dist/backend/index.js +7 -0
- package/dist/chunk-NDBQHOLK.js +907 -0
- package/dist/frontend/bundle.iife.js +24998 -0
- package/dist/frontend/bundle.iife.js.map +1 -0
- package/dist/index.cjs +922 -0
- package/dist/index.d.cts +305 -0
- package/dist/index.d.ts +305 -0
- package/dist/index.js +6 -0
- package/package.json +87 -0
- package/src/admin/components/error-metrics.tsx +54 -0
- package/src/admin/components/feedback-widget.tsx +76 -0
- package/src/admin/components/recent-issues.tsx +100 -0
- package/src/admin/hooks/use-project-filter.ts +59 -0
- package/src/admin/index.ts +121 -0
- package/src/admin/pages/sentry-dashboard.tsx +149 -0
- package/src/admin/pages/sentry-issues.tsx +269 -0
- package/src/admin/pages/sentry-settings.tsx +182 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { EnvVarRequirement, PluginMagnetProvider } from '@magnet-cms/common';
|
|
2
|
+
export { SentryCron } from '@sentry/nestjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for the Sentry plugin.
|
|
6
|
+
*
|
|
7
|
+
* Passed via `SentryPlugin.forRoot({ ... })` and injected in services via
|
|
8
|
+
* the `SENTRY_OPTIONS` token.
|
|
9
|
+
*
|
|
10
|
+
* All fields are optional — DSN is auto-resolved from the `SENTRY_DSN`
|
|
11
|
+
* environment variable when not provided.
|
|
12
|
+
*/
|
|
13
|
+
interface SentryPluginConfig {
|
|
14
|
+
/**
|
|
15
|
+
* Sentry DSN (Data Source Name).
|
|
16
|
+
* Auto-resolved from `SENTRY_DSN` environment variable if not provided.
|
|
17
|
+
* @example 'https://abc123@o0.ingest.sentry.io/12345'
|
|
18
|
+
*/
|
|
19
|
+
dsn?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Sample rate for performance tracing (0.0 to 1.0).
|
|
22
|
+
* Set to 1.0 in development, 0.1 in production to reduce overhead.
|
|
23
|
+
* @default 0.1
|
|
24
|
+
*/
|
|
25
|
+
tracesSampleRate?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Sample rate for profiling sessions (0.0 to 1.0).
|
|
28
|
+
* Requires `@sentry/profiling-node` peer dependency.
|
|
29
|
+
* @default 1.0
|
|
30
|
+
*/
|
|
31
|
+
profileSessionSampleRate?: number;
|
|
32
|
+
/**
|
|
33
|
+
* The deployment environment (e.g., 'production', 'staging', 'development').
|
|
34
|
+
* Auto-resolved from `NODE_ENV` or `SENTRY_ENVIRONMENT` if not provided.
|
|
35
|
+
*/
|
|
36
|
+
environment?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The release version string (e.g., 'v1.0.0' or a git SHA).
|
|
39
|
+
* Auto-resolved from `SENTRY_RELEASE` if not provided.
|
|
40
|
+
*/
|
|
41
|
+
release?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Enable Sentry debug mode — logs Sentry SDK activity to the console.
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
debug?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Whether Sentry is enabled. Set to `false` to disable all Sentry activity.
|
|
49
|
+
* Useful to disable in test environments.
|
|
50
|
+
* @default true
|
|
51
|
+
*/
|
|
52
|
+
enabled?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Attach stack traces to all captured events, not just errors.
|
|
55
|
+
* @default true
|
|
56
|
+
*/
|
|
57
|
+
attachStacktrace?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Maximum number of breadcrumbs to store.
|
|
60
|
+
* @default 100
|
|
61
|
+
*/
|
|
62
|
+
maxBreadcrumbs?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Sentry API auth token for fetching issues and project stats.
|
|
65
|
+
* Auto-resolved from `SENTRY_AUTH_TOKEN` environment variable.
|
|
66
|
+
* Required for the admin dashboard to display error metrics.
|
|
67
|
+
*/
|
|
68
|
+
authToken?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Sentry organization slug.
|
|
71
|
+
* Auto-resolved from `SENTRY_ORG` environment variable.
|
|
72
|
+
* @example 'my-company'
|
|
73
|
+
*/
|
|
74
|
+
organization?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Sentry project slug.
|
|
77
|
+
* Auto-resolved from `SENTRY_PROJECT` environment variable.
|
|
78
|
+
* @example 'my-app'
|
|
79
|
+
*/
|
|
80
|
+
project?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Sentry Web API base URL for admin dashboard proxying.
|
|
83
|
+
* Defaults to `https://sentry.io`, or inferred from the DSN ingest host
|
|
84
|
+
* (e.g. `https://us.sentry.io` when the DSN uses `ingest.us.sentry.io`).
|
|
85
|
+
* Override for self-hosted or non-default regions.
|
|
86
|
+
* Auto-resolved from `SENTRY_URL` environment variable.
|
|
87
|
+
*/
|
|
88
|
+
sentryUrl?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Response shape from GET /sentry/config endpoint.
|
|
92
|
+
* Used by the frontend to initialize the Sentry Browser SDK.
|
|
93
|
+
*/
|
|
94
|
+
interface SentryClientConfig {
|
|
95
|
+
/** Public Sentry DSN — safe to expose to authenticated admin users */
|
|
96
|
+
dsn: string;
|
|
97
|
+
/** Whether Sentry is enabled */
|
|
98
|
+
enabled: boolean;
|
|
99
|
+
/** Deployment environment */
|
|
100
|
+
environment: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Sentry Plugin for Magnet CMS
|
|
105
|
+
*
|
|
106
|
+
* Provides Sentry error tracking, performance monitoring, cron job
|
|
107
|
+
* monitoring, and a user feedback widget.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* MagnetModule.forRoot([
|
|
112
|
+
* MongooseDatabaseAdapter.forRoot(),
|
|
113
|
+
* SentryPlugin.forRoot({
|
|
114
|
+
* dsn: 'https://...@sentry.io/...',
|
|
115
|
+
* tracesSampleRate: 0.1,
|
|
116
|
+
* }),
|
|
117
|
+
* ], { admin: true })
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
declare class SentryPlugin {
|
|
121
|
+
/** Resolved configuration — stored statically so lifecycle hooks can access it */
|
|
122
|
+
static _resolvedConfig: SentryPluginConfig | undefined;
|
|
123
|
+
/** Environment variables used by this plugin */
|
|
124
|
+
static readonly envVars: EnvVarRequirement[];
|
|
125
|
+
/**
|
|
126
|
+
* Create a configured plugin provider for MagnetModule.forRoot().
|
|
127
|
+
*
|
|
128
|
+
* Auto-resolves DSN from the SENTRY_DSN environment variable if not provided.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* SentryPlugin.forRoot({
|
|
133
|
+
* tracesSampleRate: 0.1,
|
|
134
|
+
* environment: 'production',
|
|
135
|
+
* })
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
static forRoot(config?: Partial<SentryPluginConfig>): PluginMagnetProvider;
|
|
139
|
+
/**
|
|
140
|
+
* Called by the plugin lifecycle service after NestJS module initialization.
|
|
141
|
+
* Initializes the Sentry SDK if not already initialized (e.g., via instrument.ts).
|
|
142
|
+
*
|
|
143
|
+
* NOTE: For full performance auto-instrumentation (HTTP, DB query tracing),
|
|
144
|
+
* initialize Sentry before NestJS bootstrap by importing `instrument.ts`
|
|
145
|
+
* at the top of main.ts and calling `initSentryInstrumentation()`.
|
|
146
|
+
* Late initialization still captures errors and breadcrumbs correctly.
|
|
147
|
+
*/
|
|
148
|
+
onPluginInit(): Promise<void>;
|
|
149
|
+
/**
|
|
150
|
+
* Called when the application shuts down.
|
|
151
|
+
* Flushes pending Sentry events before exit.
|
|
152
|
+
*/
|
|
153
|
+
onPluginDestroy(): Promise<void>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Initialize Sentry instrumentation before NestJS bootstrap.
|
|
158
|
+
*
|
|
159
|
+
* For full performance tracing (HTTP, DB queries), call this function
|
|
160
|
+
* at the very top of your `main.ts` file, BEFORE any other imports.
|
|
161
|
+
*
|
|
162
|
+
* This is an alternative to using `instrument.ts` with Sentry's own
|
|
163
|
+
* initialization pattern. It reads config from the same source as
|
|
164
|
+
* `SentryPlugin.forRoot()`.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* // main.ts — call BEFORE other imports
|
|
169
|
+
* import { initSentryInstrumentation } from '@magnet-cms/plugin-sentry'
|
|
170
|
+
* initSentryInstrumentation()
|
|
171
|
+
*
|
|
172
|
+
* // Then import NestJS and the rest of your app
|
|
173
|
+
* import { NestFactory } from '@nestjs/core'
|
|
174
|
+
* import { AppModule } from './app.module'
|
|
175
|
+
*
|
|
176
|
+
* async function bootstrap() {
|
|
177
|
+
* const app = await NestFactory.create(AppModule)
|
|
178
|
+
* await app.listen(3000)
|
|
179
|
+
* }
|
|
180
|
+
* bootstrap()
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* @param config - Optional Sentry configuration. Defaults to reading
|
|
184
|
+
* `SENTRY_DSN` and other env vars automatically.
|
|
185
|
+
*/
|
|
186
|
+
declare function initSentryInstrumentation(config?: Partial<SentryPluginConfig>): void;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Injection token for Sentry plugin options.
|
|
190
|
+
* Extracted to a separate file to avoid circular imports between
|
|
191
|
+
* sentry.module.ts and sentry-config.controller.ts.
|
|
192
|
+
*/
|
|
193
|
+
declare const SENTRY_OPTIONS = "SENTRY_OPTIONS";
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Wrap an async function in a Sentry performance span.
|
|
197
|
+
*
|
|
198
|
+
* This is a no-op when @sentry/nestjs is not installed or Sentry is
|
|
199
|
+
* not initialized — the callback always executes regardless.
|
|
200
|
+
*
|
|
201
|
+
* @param name - Span name (shown in Sentry performance UI)
|
|
202
|
+
* @param op - Span operation type (e.g., 'db.query', 'http.request', 'function')
|
|
203
|
+
* @param fn - Async function to instrument
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* const result = await withSentrySpan('process-order', 'function', async () => {
|
|
208
|
+
* return processOrder(orderId)
|
|
209
|
+
* })
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
declare function withSentrySpan<T>(name: string, op: string, fn: () => Promise<T>): Promise<T>;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Method decorator that wraps an async method in a Sentry performance span.
|
|
216
|
+
*
|
|
217
|
+
* No-op when @sentry/nestjs is not installed or Sentry is not initialized.
|
|
218
|
+
* The decorated method always executes regardless of Sentry availability.
|
|
219
|
+
*
|
|
220
|
+
* @param name - Span name (defaults to `ClassName.methodName`)
|
|
221
|
+
* @param op - Span operation type (default: 'function')
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* @Injectable()
|
|
226
|
+
* export class OrderService {
|
|
227
|
+
* @SentrySpan('process-order', 'function')
|
|
228
|
+
* async processOrder(id: string): Promise<Order> {
|
|
229
|
+
* // This execution is tracked as a Sentry span
|
|
230
|
+
* return this.orderRepo.process(id)
|
|
231
|
+
* }
|
|
232
|
+
* }
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
type AsyncMethod = (...args: unknown[]) => Promise<unknown>;
|
|
236
|
+
/**
|
|
237
|
+
* Stage 3 TC39 decorator factory compatible with both Bun and NestJS
|
|
238
|
+
* (which uses emitDecoratorMetadata + experimentalDecorators).
|
|
239
|
+
*
|
|
240
|
+
* When used with NestJS's legacy decorator mode, TypeScript compiles this
|
|
241
|
+
* as a standard method decorator. Bun's test runner also handles this correctly.
|
|
242
|
+
*/
|
|
243
|
+
declare function SentrySpan(name?: string, op?: string): (targetOrMethod: object | AsyncMethod, propertyKeyOrContext?: string | symbol | ClassMethodDecoratorContext, descriptor?: PropertyDescriptor) => PropertyDescriptor | AsyncMethod | undefined;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Re-export SentryCron from @sentry/nestjs for convenience.
|
|
247
|
+
*
|
|
248
|
+
* Use @SentryCron to monitor cron jobs in Sentry. Apply it AFTER @Cron()
|
|
249
|
+
* from @nestjs/schedule.
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```typescript
|
|
253
|
+
* import { Cron, CronExpression } from '@nestjs/schedule'
|
|
254
|
+
* import { SentryCron } from '@magnet-cms/plugin-sentry'
|
|
255
|
+
*
|
|
256
|
+
* @Injectable()
|
|
257
|
+
* export class TasksService {
|
|
258
|
+
* @Cron(CronExpression.EVERY_HOUR)
|
|
259
|
+
* @SentryCron('hourly-cleanup', {
|
|
260
|
+
* schedule: { type: 'crontab', value: '0 * * * *' },
|
|
261
|
+
* checkinMargin: 5,
|
|
262
|
+
* maxRuntime: 30,
|
|
263
|
+
* })
|
|
264
|
+
* handleCleanup() {
|
|
265
|
+
* // Sentry monitors this job and alerts if it misses or takes too long
|
|
266
|
+
* }
|
|
267
|
+
* }
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Magnet-flavored Sentry cron decorator with automatic slug generation.
|
|
273
|
+
*
|
|
274
|
+
* Wraps @SentryCron and auto-generates a monitor slug from the class and
|
|
275
|
+
* method name when no explicit slug is provided.
|
|
276
|
+
*
|
|
277
|
+
* @param slug - Monitor slug in Sentry (default: auto-generated from method name)
|
|
278
|
+
* @param options - Additional Sentry monitor options
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```typescript
|
|
282
|
+
* @Cron(CronExpression.EVERY_MINUTE)
|
|
283
|
+
* @MagnetSentryCron()
|
|
284
|
+
* handleMinuteTask() {
|
|
285
|
+
* // Slug auto-generated as "TasksService-handleMinuteTask"
|
|
286
|
+
* }
|
|
287
|
+
*
|
|
288
|
+
* @Cron(CronExpression.EVERY_HOUR)
|
|
289
|
+
* @MagnetSentryCron('hourly-digest')
|
|
290
|
+
* sendDigest() {
|
|
291
|
+
* // Uses explicit slug "hourly-digest"
|
|
292
|
+
* }
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
declare function MagnetSentryCron(slug?: string, options?: {
|
|
296
|
+
schedule?: {
|
|
297
|
+
type: 'crontab' | 'interval';
|
|
298
|
+
value: string;
|
|
299
|
+
};
|
|
300
|
+
checkinMargin?: number;
|
|
301
|
+
maxRuntime?: number;
|
|
302
|
+
timezone?: string;
|
|
303
|
+
}): MethodDecorator;
|
|
304
|
+
|
|
305
|
+
export { MagnetSentryCron, SENTRY_OPTIONS, type SentryClientConfig, SentryPlugin, type SentryPluginConfig, SentrySpan, initSentryInstrumentation, withSentrySpan };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import { EnvVarRequirement, PluginMagnetProvider } from '@magnet-cms/common';
|
|
2
|
+
export { SentryCron } from '@sentry/nestjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for the Sentry plugin.
|
|
6
|
+
*
|
|
7
|
+
* Passed via `SentryPlugin.forRoot({ ... })` and injected in services via
|
|
8
|
+
* the `SENTRY_OPTIONS` token.
|
|
9
|
+
*
|
|
10
|
+
* All fields are optional — DSN is auto-resolved from the `SENTRY_DSN`
|
|
11
|
+
* environment variable when not provided.
|
|
12
|
+
*/
|
|
13
|
+
interface SentryPluginConfig {
|
|
14
|
+
/**
|
|
15
|
+
* Sentry DSN (Data Source Name).
|
|
16
|
+
* Auto-resolved from `SENTRY_DSN` environment variable if not provided.
|
|
17
|
+
* @example 'https://abc123@o0.ingest.sentry.io/12345'
|
|
18
|
+
*/
|
|
19
|
+
dsn?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Sample rate for performance tracing (0.0 to 1.0).
|
|
22
|
+
* Set to 1.0 in development, 0.1 in production to reduce overhead.
|
|
23
|
+
* @default 0.1
|
|
24
|
+
*/
|
|
25
|
+
tracesSampleRate?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Sample rate for profiling sessions (0.0 to 1.0).
|
|
28
|
+
* Requires `@sentry/profiling-node` peer dependency.
|
|
29
|
+
* @default 1.0
|
|
30
|
+
*/
|
|
31
|
+
profileSessionSampleRate?: number;
|
|
32
|
+
/**
|
|
33
|
+
* The deployment environment (e.g., 'production', 'staging', 'development').
|
|
34
|
+
* Auto-resolved from `NODE_ENV` or `SENTRY_ENVIRONMENT` if not provided.
|
|
35
|
+
*/
|
|
36
|
+
environment?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The release version string (e.g., 'v1.0.0' or a git SHA).
|
|
39
|
+
* Auto-resolved from `SENTRY_RELEASE` if not provided.
|
|
40
|
+
*/
|
|
41
|
+
release?: string;
|
|
42
|
+
/**
|
|
43
|
+
* Enable Sentry debug mode — logs Sentry SDK activity to the console.
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
debug?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Whether Sentry is enabled. Set to `false` to disable all Sentry activity.
|
|
49
|
+
* Useful to disable in test environments.
|
|
50
|
+
* @default true
|
|
51
|
+
*/
|
|
52
|
+
enabled?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Attach stack traces to all captured events, not just errors.
|
|
55
|
+
* @default true
|
|
56
|
+
*/
|
|
57
|
+
attachStacktrace?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Maximum number of breadcrumbs to store.
|
|
60
|
+
* @default 100
|
|
61
|
+
*/
|
|
62
|
+
maxBreadcrumbs?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Sentry API auth token for fetching issues and project stats.
|
|
65
|
+
* Auto-resolved from `SENTRY_AUTH_TOKEN` environment variable.
|
|
66
|
+
* Required for the admin dashboard to display error metrics.
|
|
67
|
+
*/
|
|
68
|
+
authToken?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Sentry organization slug.
|
|
71
|
+
* Auto-resolved from `SENTRY_ORG` environment variable.
|
|
72
|
+
* @example 'my-company'
|
|
73
|
+
*/
|
|
74
|
+
organization?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Sentry project slug.
|
|
77
|
+
* Auto-resolved from `SENTRY_PROJECT` environment variable.
|
|
78
|
+
* @example 'my-app'
|
|
79
|
+
*/
|
|
80
|
+
project?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Sentry Web API base URL for admin dashboard proxying.
|
|
83
|
+
* Defaults to `https://sentry.io`, or inferred from the DSN ingest host
|
|
84
|
+
* (e.g. `https://us.sentry.io` when the DSN uses `ingest.us.sentry.io`).
|
|
85
|
+
* Override for self-hosted or non-default regions.
|
|
86
|
+
* Auto-resolved from `SENTRY_URL` environment variable.
|
|
87
|
+
*/
|
|
88
|
+
sentryUrl?: string;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Response shape from GET /sentry/config endpoint.
|
|
92
|
+
* Used by the frontend to initialize the Sentry Browser SDK.
|
|
93
|
+
*/
|
|
94
|
+
interface SentryClientConfig {
|
|
95
|
+
/** Public Sentry DSN — safe to expose to authenticated admin users */
|
|
96
|
+
dsn: string;
|
|
97
|
+
/** Whether Sentry is enabled */
|
|
98
|
+
enabled: boolean;
|
|
99
|
+
/** Deployment environment */
|
|
100
|
+
environment: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Sentry Plugin for Magnet CMS
|
|
105
|
+
*
|
|
106
|
+
* Provides Sentry error tracking, performance monitoring, cron job
|
|
107
|
+
* monitoring, and a user feedback widget.
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* MagnetModule.forRoot([
|
|
112
|
+
* MongooseDatabaseAdapter.forRoot(),
|
|
113
|
+
* SentryPlugin.forRoot({
|
|
114
|
+
* dsn: 'https://...@sentry.io/...',
|
|
115
|
+
* tracesSampleRate: 0.1,
|
|
116
|
+
* }),
|
|
117
|
+
* ], { admin: true })
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
declare class SentryPlugin {
|
|
121
|
+
/** Resolved configuration — stored statically so lifecycle hooks can access it */
|
|
122
|
+
static _resolvedConfig: SentryPluginConfig | undefined;
|
|
123
|
+
/** Environment variables used by this plugin */
|
|
124
|
+
static readonly envVars: EnvVarRequirement[];
|
|
125
|
+
/**
|
|
126
|
+
* Create a configured plugin provider for MagnetModule.forRoot().
|
|
127
|
+
*
|
|
128
|
+
* Auto-resolves DSN from the SENTRY_DSN environment variable if not provided.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* SentryPlugin.forRoot({
|
|
133
|
+
* tracesSampleRate: 0.1,
|
|
134
|
+
* environment: 'production',
|
|
135
|
+
* })
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
static forRoot(config?: Partial<SentryPluginConfig>): PluginMagnetProvider;
|
|
139
|
+
/**
|
|
140
|
+
* Called by the plugin lifecycle service after NestJS module initialization.
|
|
141
|
+
* Initializes the Sentry SDK if not already initialized (e.g., via instrument.ts).
|
|
142
|
+
*
|
|
143
|
+
* NOTE: For full performance auto-instrumentation (HTTP, DB query tracing),
|
|
144
|
+
* initialize Sentry before NestJS bootstrap by importing `instrument.ts`
|
|
145
|
+
* at the top of main.ts and calling `initSentryInstrumentation()`.
|
|
146
|
+
* Late initialization still captures errors and breadcrumbs correctly.
|
|
147
|
+
*/
|
|
148
|
+
onPluginInit(): Promise<void>;
|
|
149
|
+
/**
|
|
150
|
+
* Called when the application shuts down.
|
|
151
|
+
* Flushes pending Sentry events before exit.
|
|
152
|
+
*/
|
|
153
|
+
onPluginDestroy(): Promise<void>;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Initialize Sentry instrumentation before NestJS bootstrap.
|
|
158
|
+
*
|
|
159
|
+
* For full performance tracing (HTTP, DB queries), call this function
|
|
160
|
+
* at the very top of your `main.ts` file, BEFORE any other imports.
|
|
161
|
+
*
|
|
162
|
+
* This is an alternative to using `instrument.ts` with Sentry's own
|
|
163
|
+
* initialization pattern. It reads config from the same source as
|
|
164
|
+
* `SentryPlugin.forRoot()`.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```typescript
|
|
168
|
+
* // main.ts — call BEFORE other imports
|
|
169
|
+
* import { initSentryInstrumentation } from '@magnet-cms/plugin-sentry'
|
|
170
|
+
* initSentryInstrumentation()
|
|
171
|
+
*
|
|
172
|
+
* // Then import NestJS and the rest of your app
|
|
173
|
+
* import { NestFactory } from '@nestjs/core'
|
|
174
|
+
* import { AppModule } from './app.module'
|
|
175
|
+
*
|
|
176
|
+
* async function bootstrap() {
|
|
177
|
+
* const app = await NestFactory.create(AppModule)
|
|
178
|
+
* await app.listen(3000)
|
|
179
|
+
* }
|
|
180
|
+
* bootstrap()
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* @param config - Optional Sentry configuration. Defaults to reading
|
|
184
|
+
* `SENTRY_DSN` and other env vars automatically.
|
|
185
|
+
*/
|
|
186
|
+
declare function initSentryInstrumentation(config?: Partial<SentryPluginConfig>): void;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Injection token for Sentry plugin options.
|
|
190
|
+
* Extracted to a separate file to avoid circular imports between
|
|
191
|
+
* sentry.module.ts and sentry-config.controller.ts.
|
|
192
|
+
*/
|
|
193
|
+
declare const SENTRY_OPTIONS = "SENTRY_OPTIONS";
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Wrap an async function in a Sentry performance span.
|
|
197
|
+
*
|
|
198
|
+
* This is a no-op when @sentry/nestjs is not installed or Sentry is
|
|
199
|
+
* not initialized — the callback always executes regardless.
|
|
200
|
+
*
|
|
201
|
+
* @param name - Span name (shown in Sentry performance UI)
|
|
202
|
+
* @param op - Span operation type (e.g., 'db.query', 'http.request', 'function')
|
|
203
|
+
* @param fn - Async function to instrument
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* const result = await withSentrySpan('process-order', 'function', async () => {
|
|
208
|
+
* return processOrder(orderId)
|
|
209
|
+
* })
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
declare function withSentrySpan<T>(name: string, op: string, fn: () => Promise<T>): Promise<T>;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Method decorator that wraps an async method in a Sentry performance span.
|
|
216
|
+
*
|
|
217
|
+
* No-op when @sentry/nestjs is not installed or Sentry is not initialized.
|
|
218
|
+
* The decorated method always executes regardless of Sentry availability.
|
|
219
|
+
*
|
|
220
|
+
* @param name - Span name (defaults to `ClassName.methodName`)
|
|
221
|
+
* @param op - Span operation type (default: 'function')
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* @Injectable()
|
|
226
|
+
* export class OrderService {
|
|
227
|
+
* @SentrySpan('process-order', 'function')
|
|
228
|
+
* async processOrder(id: string): Promise<Order> {
|
|
229
|
+
* // This execution is tracked as a Sentry span
|
|
230
|
+
* return this.orderRepo.process(id)
|
|
231
|
+
* }
|
|
232
|
+
* }
|
|
233
|
+
* ```
|
|
234
|
+
*/
|
|
235
|
+
type AsyncMethod = (...args: unknown[]) => Promise<unknown>;
|
|
236
|
+
/**
|
|
237
|
+
* Stage 3 TC39 decorator factory compatible with both Bun and NestJS
|
|
238
|
+
* (which uses emitDecoratorMetadata + experimentalDecorators).
|
|
239
|
+
*
|
|
240
|
+
* When used with NestJS's legacy decorator mode, TypeScript compiles this
|
|
241
|
+
* as a standard method decorator. Bun's test runner also handles this correctly.
|
|
242
|
+
*/
|
|
243
|
+
declare function SentrySpan(name?: string, op?: string): (targetOrMethod: object | AsyncMethod, propertyKeyOrContext?: string | symbol | ClassMethodDecoratorContext, descriptor?: PropertyDescriptor) => PropertyDescriptor | AsyncMethod | undefined;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Re-export SentryCron from @sentry/nestjs for convenience.
|
|
247
|
+
*
|
|
248
|
+
* Use @SentryCron to monitor cron jobs in Sentry. Apply it AFTER @Cron()
|
|
249
|
+
* from @nestjs/schedule.
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```typescript
|
|
253
|
+
* import { Cron, CronExpression } from '@nestjs/schedule'
|
|
254
|
+
* import { SentryCron } from '@magnet-cms/plugin-sentry'
|
|
255
|
+
*
|
|
256
|
+
* @Injectable()
|
|
257
|
+
* export class TasksService {
|
|
258
|
+
* @Cron(CronExpression.EVERY_HOUR)
|
|
259
|
+
* @SentryCron('hourly-cleanup', {
|
|
260
|
+
* schedule: { type: 'crontab', value: '0 * * * *' },
|
|
261
|
+
* checkinMargin: 5,
|
|
262
|
+
* maxRuntime: 30,
|
|
263
|
+
* })
|
|
264
|
+
* handleCleanup() {
|
|
265
|
+
* // Sentry monitors this job and alerts if it misses or takes too long
|
|
266
|
+
* }
|
|
267
|
+
* }
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Magnet-flavored Sentry cron decorator with automatic slug generation.
|
|
273
|
+
*
|
|
274
|
+
* Wraps @SentryCron and auto-generates a monitor slug from the class and
|
|
275
|
+
* method name when no explicit slug is provided.
|
|
276
|
+
*
|
|
277
|
+
* @param slug - Monitor slug in Sentry (default: auto-generated from method name)
|
|
278
|
+
* @param options - Additional Sentry monitor options
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```typescript
|
|
282
|
+
* @Cron(CronExpression.EVERY_MINUTE)
|
|
283
|
+
* @MagnetSentryCron()
|
|
284
|
+
* handleMinuteTask() {
|
|
285
|
+
* // Slug auto-generated as "TasksService-handleMinuteTask"
|
|
286
|
+
* }
|
|
287
|
+
*
|
|
288
|
+
* @Cron(CronExpression.EVERY_HOUR)
|
|
289
|
+
* @MagnetSentryCron('hourly-digest')
|
|
290
|
+
* sendDigest() {
|
|
291
|
+
* // Uses explicit slug "hourly-digest"
|
|
292
|
+
* }
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
declare function MagnetSentryCron(slug?: string, options?: {
|
|
296
|
+
schedule?: {
|
|
297
|
+
type: 'crontab' | 'interval';
|
|
298
|
+
value: string;
|
|
299
|
+
};
|
|
300
|
+
checkinMargin?: number;
|
|
301
|
+
maxRuntime?: number;
|
|
302
|
+
timezone?: string;
|
|
303
|
+
}): MethodDecorator;
|
|
304
|
+
|
|
305
|
+
export { MagnetSentryCron, SENTRY_OPTIONS, type SentryClientConfig, SentryPlugin, type SentryPluginConfig, SentrySpan, initSentryInstrumentation, withSentrySpan };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { init_plugin, init_sentry_module } from './chunk-NDBQHOLK.js';
|
|
2
|
+
export { MagnetSentryCron, SENTRY_OPTIONS, SentryCron, SentryPlugin, SentrySpan, initSentryInstrumentation, withSentrySpan } from './chunk-NDBQHOLK.js';
|
|
3
|
+
|
|
4
|
+
// src/index.ts
|
|
5
|
+
init_plugin();
|
|
6
|
+
init_sentry_module();
|
package/package.json
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@magnet-cms/plugin-sentry",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Sentry plugin for Magnet CMS — error tracking, performance monitoring, cron monitoring, and user feedback",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.cts",
|
|
16
|
+
"default": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"./backend": {
|
|
20
|
+
"import": {
|
|
21
|
+
"types": "./dist/backend/index.d.ts",
|
|
22
|
+
"default": "./dist/backend/index.js"
|
|
23
|
+
},
|
|
24
|
+
"require": {
|
|
25
|
+
"types": "./dist/backend/index.d.cts",
|
|
26
|
+
"default": "./dist/backend/index.cjs"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"./frontend": {
|
|
30
|
+
"import": "./src/admin/index.ts",
|
|
31
|
+
"types": "./src/admin/index.ts"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"types": "./dist/index.d.ts",
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"src/admin"
|
|
38
|
+
],
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build:dev": "tsup --watch",
|
|
41
|
+
"build": "tsup && bun run build:frontend",
|
|
42
|
+
"build:frontend": "vite build",
|
|
43
|
+
"build:frontend:watch": "vite build --watch"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@magnet-cms/admin": "workspace:*",
|
|
47
|
+
"@magnet-cms/common": "workspace:*",
|
|
48
|
+
"@magnet-cms/core": "workspace:*",
|
|
49
|
+
"@magnet-cms/ui": "workspace:*",
|
|
50
|
+
"@magnet-cms/utils": "workspace:*",
|
|
51
|
+
"@nestjs/common": "^11.1.12",
|
|
52
|
+
"@repo/biome": "workspace:*",
|
|
53
|
+
"@repo/tsup": "workspace:*",
|
|
54
|
+
"@repo/typescript-config": "workspace:*",
|
|
55
|
+
"@sentry/browser": "^9.0.0",
|
|
56
|
+
"@types/react": "^19.0.1",
|
|
57
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
58
|
+
"lucide-react": "^0.468.0",
|
|
59
|
+
"react": "^19.0.0",
|
|
60
|
+
"react-router-dom": "^7.1.1",
|
|
61
|
+
"reflect-metadata": "0.2.2",
|
|
62
|
+
"vite": "^6.0.7"
|
|
63
|
+
},
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"@magnet-cms/admin": "^0.2.0",
|
|
66
|
+
"@magnet-cms/common": "^0.2.0",
|
|
67
|
+
"@magnet-cms/core": "^2.0.0",
|
|
68
|
+
"@magnet-cms/ui": "^0.1.3",
|
|
69
|
+
"@magnet-cms/utils": "^0.1.1",
|
|
70
|
+
"@nestjs/common": "^11.1.12",
|
|
71
|
+
"@sentry/nestjs": "^9.0.0",
|
|
72
|
+
"lucide-react": ">=0.400.0",
|
|
73
|
+
"react": ">=18.0.0",
|
|
74
|
+
"react-router-dom": ">=6.0.0",
|
|
75
|
+
"reflect-metadata": "0.2.2"
|
|
76
|
+
},
|
|
77
|
+
"peerDependenciesMeta": {
|
|
78
|
+
"@sentry/nestjs": {
|
|
79
|
+
"optional": false
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"magnet": {
|
|
83
|
+
"type": "plugin",
|
|
84
|
+
"backend": true,
|
|
85
|
+
"frontend": true
|
|
86
|
+
}
|
|
87
|
+
}
|