Skip to content

Commit 07b73d8

Browse files
authored
refactor(error): consolidate error package from sentry and utils (#126)
* refactor(error): consolidate error package from sentry and utils - Rename packages/sentry to packages/error - Move packages/utils/src/error into packages/error/src/utils - Add no-DSN fallback: log errors when reporting backend not initialized - Rename initSentry to initErrorReporting, tech-agnostic API - Update env vars: ERROR_REPORTING_DSN, ERROR_REPORTING_ENVIRONMENT - Add Next.js error reporting setup (error-reporting.*.ts, sentry shims) - Update Fastify to use initErrorReporting from @repo/error/node - Update all imports: @repo/sentry -> @repo/error, @repo/utils/error -> @repo/error - Update docs, cursor rules, and skills for @repo/error - Recommend GlitchTip in docs; Sentry also works (same DSN format) * feat(error): add Next.js global-error boundary and harden capture * fix(error): align error handling docs, env, and logging - next-v16: replace ambiguous 'Sentry reporting' with @repo/error package refs - global-error: log only sanitized metadata (digest), not raw error object - error-reporting.client: use NEXT_PUBLIC_ERROR_REPORTING_ENVIRONMENT ?? NODE_ENV - error-boundary: remove @repo/error/node from captureError JSDoc (client-only) - types: import Logger from @repo/utils/logger/types (platform-neutral) - wagmi skill: update 'Log to Sentry' comment to 'Report error via @repo/error/nextjs' - packages.mdx: move @repo/error to Mixed (root + subpath exports) - error-handler: replace Sentry comments with error-reporting abstraction refs - README: dev command sentry → error - error-handling.mdx: rename 'Initialize Sentry' to 'Error Reporting Initialization' - capture-impl: wrap log.error in try/catch, fallback to console on logger throw - utils: add @repo/utils/logger/types export * docs(error): clarify AppErrorBoundary as client-only component
1 parent e5f465e commit 07b73d8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+696
-561
lines changed

.cursor/skills/next-v16/error-handling.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# Error Handling
22

3-
Handle errors in Next.js with **Sentry reporting** (`@repo/sentry/*`) and **structured logging** (`@repo/utils/logger/server` or `@repo/utils/logger/client`).
3+
Handle errors in Next.js with the **`@repo/error` package** (Sentry-backed) and **structured logging** (`@repo/utils/logger/server` or `@repo/utils/logger/client`).
44

55
Reference: https://nextjs.org/docs/app/getting-started/error-handling
66

77
## Observability (Required)
88

9-
- Report unexpected errors with `captureError` from `@repo/sentry/nextjs`
9+
- Report unexpected errors with `captureError` from `@repo/error/nextjs`
1010
- Log operational context with `logger` from `@repo/utils/logger/server` or `@repo/utils/logger/client` (never `console.*`)
1111

1212
## Error Boundaries
@@ -18,7 +18,7 @@ Catches errors in a route segment and its children:
1818
```tsx
1919
'use client'
2020

21-
import { captureError } from '@repo/sentry/nextjs'
21+
import { captureError } from '@repo/error/nextjs'
2222
import { logger } from '@repo/utils/logger/client'
2323
import { useEffect } from 'react'
2424

@@ -58,7 +58,7 @@ Catches errors in the root layout. Same capture pattern as `error.tsx`, but it *
5858
```tsx
5959
'use client'
6060

61-
import { captureError } from '@repo/sentry/nextjs'
61+
import { captureError } from '@repo/error/nextjs'
6262
import { logger } from '@repo/utils/logger/client'
6363
import { useEffect } from 'react'
6464

@@ -97,7 +97,7 @@ Reference: https://nextjs.org/docs/app/api-reference/functions/redirect#behavior
9797
'use server'
9898

9999
import { redirect, unstable_rethrow } from 'next/navigation'
100-
import { captureError } from '@repo/sentry/nextjs'
100+
import { captureError } from '@repo/error/nextjs'
101101
import { logger } from '@repo/utils/logger/server'
102102

103103
export async function action() {
@@ -119,7 +119,7 @@ Capture, log, then return a safe result. If navigation APIs may be involved, cal
119119

120120
```tsx
121121
import { unstable_rethrow } from 'next/navigation'
122-
import { captureError } from '@repo/sentry/nextjs'
122+
import { captureError } from '@repo/error/nextjs'
123123
import { logger } from '@repo/utils/logger/server'
124124

125125
async function action() {

.cursor/skills/wagmi-v3/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ Comprehensive error handling with user-friendly messages:
543543
```tsx
544544
import { useWriteContract } from 'wagmi'
545545
import { BaseError } from 'viem'
546-
import { captureError } from '@repo/sentry/nextjs'
546+
import { captureError } from '@repo/error/nextjs'
547547
import type { WriteContractParameters } from 'wagmi/actions'
548548

549549
function useContractWriteWithErrorHandling() {
@@ -567,7 +567,7 @@ function useContractWriteWithErrorHandling() {
567567
userMessage = 'Gas estimation failed. Please try again.'
568568
}
569569

570-
// Log to Sentry
570+
// Report error via @repo/error/nextjs
571571
captureError({
572572
code: 'TRANSACTION_ERROR',
573573
error,

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Fastify • OpenAPI • Next.js • Expo — one stack, multiple platforms.
1616
- ⚙️ **Preconfigured dev tools** — Biome, Git workflows, hooks, and security checks
1717
- 🛡️ **Security & quality** — Automated checks in CI (e.g. Gitleaks, OSV)
1818
- ⛓️ **Multichain** — EVM, Solana; shared validation and chain-specific tooling
19-
- 📐 **Conventions** — Cursor rules per domain, @repo/sentry, Pino logging, shared TS and style
19+
- 📐 **Conventions** — Cursor rules per domain, @repo/error, Pino logging, shared TS and style
2020
- 🧑‍💻 **TypeScript-first** — End-to-end types from database to frontend
2121

2222
## Technology stack
@@ -39,7 +39,7 @@ Fastify • OpenAPI • Next.js • Expo — one stack, multiple platforms.
3939
- **[@repo/react](packages/react/README.md)** — React Query hooks for `@repo/core` API functions
4040
- **[@repo/ui](packages/ui/README.md)** — Shared UI component library (Shadcn/ui, Tailwind)
4141
- **[@repo/utils](packages/utils/README.md)** — Shared utilities (async, data, debug, error, logger, web3)
42-
- **[@repo/sentry](packages/sentry/README.md)**Common `captureError` interface for error reporting
42+
- **[@repo/error](packages/error/README.md)**Error reporting and utilities (`captureError`, `getErrorMessage`)
4343
- **[@repo/email](packages/email/README.md)** — Email template library built with React Email
4444
- **[@repo/notif](packages/notif/README.md)** — Notification service (email, activity) with type-safe schemas
4545

@@ -54,7 +54,7 @@ Run with `pnpm <script>`.
5454
- `setup:database` — Database tools
5555
**Primary**
5656
- `build` — Build packages and apps
57-
- `dev` — Start dev (core, react, sentry, utils, fastify, next)
57+
- `dev` — Start dev (core, react, error, utils, fastify, next)
5858
- `qa` — Full check: install → checktypes → lint → build → test (unit) → test:e2e (Fastify + Next, local spawn)
5959
**Format / Lint**
6060
- `checktypes` — Type-check all packages

apps/docu/content/docs/architecture/error-handling.mdx

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
---
22
title: "Error Handling"
3-
description: "Error handling with Sentry integration and app-level error catalogs."
3+
description: "Error handling with error reporting and app-level error catalogs."
44
---
55

6-
Complete guide for error handling across the monorepo: **`@repo/sentry`** for reporting to Sentry, **`@repo/utils/error`** for message extraction, and **app-level catalogs** for safe API responses.
6+
Complete guide for error handling across the monorepo: **`@repo/error`** for error reporting and message extraction, and **app-level catalogs** for safe API responses.
77

88
## Overview
99

10-
- **`@repo/sentry`**`captureError(options)` sends errors to Sentry (void; does not return a catalog). Use platform subpaths: `node`, `nextjs`, `browser`, `react`.
11-
- **`@repo/utils/error`**`getErrorMessage(error)` and related utilities for type-safe message extraction.
12-
- **Sentry initialization**Not in `@repo/sentry`. Initialize per your platform’s [Sentry docs](https://docs.sentry.io/platforms/) (Node, Next.js, Browser).
10+
- **`@repo/error`**`captureError(options)` sends errors to the reporting backend (void; does not return a catalog). Use platform subpaths: `node`, `nextjs`, `browser`, `react`.
11+
- **`@repo/error`**`getErrorMessage(error)` and related utilities for type-safe message extraction (base export or `@repo/error/nextjs`).
12+
- **Initialization**Use `initErrorReporting` from `@repo/error/node` or `@repo/error/nextjs`. [GlitchTip](https://glitchtip.com/sdkdocs/javascript/) is recommended; Sentry also works (same DSN format).
1313
- **Error catalogs and safe responses** – Implemented in each app (e.g. Fastify’s `apps/fastify/src/lib/catalogs/` with `getError`, `mapHttpStatusToErrorCode`). Apps build the safe `{ code, message }` response themselves.
1414

1515
**Key principles:**
@@ -23,10 +23,10 @@ Complete guide for error handling across the monorepo: **`@repo/sentry`** for re
2323

2424
```typescript
2525
// For Next.js apps
26-
import { captureError } from '@repo/sentry/nextjs'
26+
import { captureError } from '@repo/error/nextjs'
2727

2828
// For Node.js/Fastify apps
29-
// import { captureError } from '@repo/sentry/node'
29+
// import { captureError } from '@repo/error/node'
3030

3131
captureError({
3232
error,
@@ -41,14 +41,14 @@ captureError({
4141
### Extract Error Message
4242

4343
```typescript
44-
import { getErrorMessage } from '@repo/utils/error'
44+
import { getErrorMessage } from '@repo/error/nextjs'
4545

4646
const message = getErrorMessage(error) // Type-safe
4747
```
4848

49-
### Initialize Sentry
49+
### Error Reporting Initialization
5050

51-
Sentry is not initialized by `@repo/sentry`. Follow your platform’s setup:
51+
Sentry is not initialized by `@repo/error`. Follow your platform’s setup:
5252

5353
- **Next.js**: [Sentry Next.js guide](https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/)`withSentryConfig`, `instrumentation.ts`, etc.
5454
- **Node/Fastify**: [Sentry Node guide](https://docs.sentry.io/platforms/javascript/guides/node/)
@@ -96,7 +96,7 @@ reply.status(500).send(catalogError)
9696

9797
### App-level error catalogs
9898

99-
Error catalogs and safe responses are implemented **per app**, not in `@repo/sentry`. For example, the Fastify app defines catalogs in `apps/fastify/src/lib/catalogs/` (e.g. `server.ts`, `client.ts`, `common.ts`) and exposes `getError(code)`, `mapHttpStatusToErrorCode(statusCode)`. The error handler calls `captureError` from `@repo/sentry/node` then builds the response using the app’s `getError`.
99+
Error catalogs and safe responses are implemented **per app**, not in `@repo/error`. For example, the Fastify app defines catalogs in `apps/fastify/src/lib/catalogs/` (e.g. `server.ts`, `client.ts`, `common.ts`) and exposes `getError(code)`, `mapHttpStatusToErrorCode(statusCode)`. The error handler calls `captureError` from `@repo/error/node` then builds the response using the app’s `getError`.
100100

101101
**Adding new error codes:** Add them to your app’s catalog (e.g. `apps/fastify/src/lib/catalogs/`), then use `getError(yourCode)` when building responses. Use `UPPER_SNAKE_CASE` (e.g. `NETWORK_ERROR`, `USER_NOT_FOUND`).
102102

@@ -121,11 +121,11 @@ Error catalogs and safe responses are implemented **per app**, not in `@repo/sen
121121

122122
#### Global Error Handler Plugin
123123

124-
Use `captureError` from `@repo/sentry/node` (void); build the response from the app’s catalog (`getError`, `mapHttpStatusToErrorCode` from `apps/fastify/src/lib/catalogs/`):
124+
Use `captureError` from `@repo/error/node` (void); build the response from the app’s catalog (`getError`, `mapHttpStatusToErrorCode` from `apps/fastify/src/lib/catalogs/`):
125125

126126
```typescript
127127
// apps/fastify/src/plugins/error-handler.ts
128-
import { captureError } from '@repo/sentry/node'
128+
import { captureError } from '@repo/error/node'
129129
import { getError, mapHttpStatusToErrorCode } from '../lib/catalogs/mapper.js'
130130
// ... route extraction, redaction ...
131131

@@ -158,8 +158,8 @@ fastify.setErrorHandler((error, request, reply) => {
158158
// apps/next/app/layout.tsx
159159
'use client'
160160

161-
import { AppErrorBoundary } from '@repo/sentry/react'
162-
import { captureError } from '@repo/sentry/nextjs'
161+
import { AppErrorBoundary } from '@repo/error/react'
162+
import { captureError } from '@repo/error/nextjs'
163163

164164
export default function RootLayout({ children }: { children: React.ReactNode }) {
165165
return (
@@ -170,13 +170,13 @@ export default function RootLayout({ children }: { children: React.ReactNode })
170170
}
171171
```
172172

173-
**Custom implementation:** Use `captureError` from `@repo/sentry/nextjs` in `onError`; it returns void. Show user-facing message via your fallback (e.g. `getErrorMessage(error)` from `@repo/utils/error`).
173+
**Custom implementation:** Use `captureError` from `@repo/error/nextjs` in `onError`; it returns void. Show user-facing message via your fallback (e.g. `getErrorMessage(error)` from `@repo/error/nextjs`).
174174

175175
#### Event Handlers
176176

177177
```typescript
178-
import { captureError } from '@repo/sentry/nextjs'
179-
import { getErrorMessage } from '@repo/utils/error'
178+
import { captureError } from '@repo/error/nextjs'
179+
import { getErrorMessage } from '@repo/error/nextjs'
180180
import { toast } from 'sonner'
181181

182182
async function handleSubmit() {
@@ -200,7 +200,7 @@ async function handleSubmit() {
200200
```typescript
201201
// app/error.tsx
202202
'use client'
203-
import { captureError } from '@repo/sentry/nextjs'
203+
import { captureError } from '@repo/error/nextjs'
204204
import { useEffect } from 'react'
205205

206206
export default function ErrorPage({
@@ -237,8 +237,8 @@ export default function ErrorPage({
237237

238238
```typescript
239239
'use server'
240-
import { captureError } from '@repo/sentry/nextjs'
241-
import { getErrorMessage } from '@repo/utils/error'
240+
import { captureError } from '@repo/error/nextjs'
241+
import { getErrorMessage } from '@repo/error/nextjs'
242242

243243
export async function serverAction() {
244244
try {
@@ -255,7 +255,7 @@ export async function serverAction() {
255255

256256
```typescript
257257
'use server'
258-
import { captureError } from '@repo/sentry/nextjs'
258+
import { captureError } from '@repo/error/nextjs'
259259

260260
export async function serverAction() {
261261
try {
@@ -267,16 +267,16 @@ export async function serverAction() {
267267
}
268268
```
269269

270-
**Initialization:** Sentry is not initialized by `@repo/sentry`. Use [Sentry’s Next.js setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/) in `next.config`, `instrumentation.ts`, etc.
270+
**Initialization:** Sentry is not initialized by `@repo/error`. Use [Sentry’s Next.js setup](https://docs.sentry.io/platforms/javascript/guides/nextjs/manual-setup/) in `next.config`, `instrumentation.ts`, etc.
271271

272272
## API Reference
273273

274-
### `captureError(options): void` (`@repo/sentry/*`)
274+
### `captureError(options): void` (`@repo/error/*`)
275275

276276
Sends the error to Sentry asynchronously. Does not return a catalog; each app builds its own response.
277277

278278
```typescript
279-
import { captureError } from '@repo/sentry/nextjs' // or /node, /browser
279+
import { captureError } from '@repo/error/nextjs' // or /node, /browser
280280
281281
captureError({
282282
error: unknown, // Converted to Error if needed; full stack sent to Sentry
@@ -290,27 +290,27 @@ captureError({
290290
})
291291
```
292292

293-
See [packages/sentry/README.md](https://github.com/blockmatic/basilic/blob/main/packages/sentry/README.md) for full options. **Serverless:** Consider `Sentry.flush()` before function exit if the process terminates quickly.
293+
See [@repo/error](https://github.com/blockmatic/basilic/blob/main/packages/error/README.md) for full options. **Serverless:** Consider `Sentry.flush()` before function exit if the process terminates quickly.
294294

295-
### `getErrorMessage(error)` (`@repo/utils/error`)
295+
### `getErrorMessage(error)` (`@repo/error` or `@repo/error/nextjs`)
296296

297297
```typescript
298-
import { getErrorMessage } from '@repo/utils/error'
298+
import { getErrorMessage } from '@repo/error/nextjs'
299299

300300
const message = getErrorMessage(error) // Type-safe extraction from unknown
301301
```
302302

303303
### App-level: `getError`, `mapHttpStatusToErrorCode`
304304

305-
These live in each app (e.g. Fastify’s `apps/fastify/src/lib/catalogs/mapper.ts`). `mapHttpStatusToErrorCode(statusCode)` maps HTTP status to a catalog code; `getError(code)` returns `{ code, message }` for the response. Not part of `@repo/sentry`.
305+
These live in each app (e.g. Fastify’s `apps/fastify/src/lib/catalogs/mapper.ts`). `mapHttpStatusToErrorCode(statusCode)` maps HTTP status to a catalog code; `getError(code)` returns `{ code, message }` for the response. Not part of `@repo/error`.
306306

307307
## Best Practices
308308

309309
### Common Patterns
310310

311311
```typescript
312-
import { getErrorMessage } from '@repo/utils/error'
313-
import { captureError } from '@repo/sentry/nextjs'
312+
import { getErrorMessage } from '@repo/error/nextjs'
313+
import { captureError } from '@repo/error/nextjs'
314314

315315
// Extract message
316316
const message = getErrorMessage(error)

apps/docu/content/docs/architecture/esm-strategy.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Packages expose TypeScript source for workspace consumption. Two patterns exist:
4141
}
4242
```
4343

44-
**Pattern B**`source` condition for bundlers, `node`/`import` for Node (packages like `@repo/utils`, `@repo/sentry`, `@repo/email`, `@repo/notif`):
44+
**Pattern B**`source` condition for bundlers, `node`/`import` for Node (packages like `@repo/utils`, `@repo/error`, `@repo/email`, `@repo/notif`):
4545

4646
```json
4747
{
@@ -113,7 +113,7 @@ Next.js apps import TypeScript source directly using **package interpolation**:
113113
```js
114114
// next.config.mjs
115115
export default {
116-
transpilePackages: ['@repo/ui', '@repo/core', '@repo/react', '@repo/sentry', '@repo/utils'],
116+
transpilePackages: ['@repo/ui', '@repo/core', '@repo/react', '@repo/error', '@repo/utils'],
117117
serverExternalPackages: ['import-in-the-middle', 'require-in-the-middle'],
118118
webpack: config => {
119119
// Resolve "source" condition so Next.js uses TypeScript source from workspace packages

apps/docu/content/docs/architecture/logging.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,10 +215,10 @@ try {
215215
}
216216
```
217217

218-
**5. Integration with `@repo/sentry`** - When using `captureError` in Fastify, pass `request.log` to use Fastify's native logger. The catalog and response are built in the app (e.g. from `apps/fastify/src/lib/catalogs/`):
218+
**5. Integration with `@repo/error`** - When using `captureError` in Fastify, pass `request.log` to use Fastify's native logger. The catalog and response are built in the app (e.g. from `apps/fastify/src/lib/catalogs/`):
219219

220220
```typescript
221-
import { captureError } from '@repo/sentry/node'
221+
import { captureError } from '@repo/error/node'
222222

223223
fastify.setErrorHandler((error, request, reply) => {
224224
captureError({
@@ -251,4 +251,4 @@ fastify.setErrorHandler((error, request, reply) => {
251251
## Related Documentation
252252

253253
- [Installation](/docs/development) - Environment variable configuration
254-
- [Error Handling](/docs/architecture/error-handling) - Error logging with `@repo/sentry`
254+
- [Error Handling](/docs/architecture/error-handling) - Error logging with `@repo/error`

apps/docu/content/docs/deployment/vercel.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ OLLAMA_BASE_URL=https://ollama.yourdomain.com
4141
RESEND_API_KEY=re_...
4242
PORT=3001
4343
NODE_ENV=production
44-
SENTRY_DSN=https://...
44+
ERROR_REPORTING_DSN=https://...
4545
```
4646

4747
**For Web (`apps/next`):**
4848
```bash
4949
NEXT_PUBLIC_API_URL=https://api.yourdomain.com
50-
NEXT_PUBLIC_SENTRY_DSN=https://...
50+
NEXT_PUBLIC_ERROR_REPORTING_DSN=https://...
5151
```
5252

5353
**For Docs (`apps/docu`):**

apps/docu/content/docs/development/dev-tooling.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ Tasks are configured in `turbo.json` with:
130130

131131
- **`@repo/core`** - Watches OpenAPI spec and regenerates API client
132132
- **`@repo/react`** - Watches OpenAPI spec and regenerates React hooks, watches TypeScript for rebuilds
133-
- **`@repo/sentry`** - Watches TypeScript for rebuilds
133+
- **`@repo/error`** - Watches TypeScript for rebuilds
134134
- **`@repo/utils`** - Watches TypeScript for rebuilds
135135
- **`@repo/fastify`** - Starts Fastify API server with OpenAPI generation watcher
136136
- **`@repo/next`** - Starts Next.js development server
@@ -156,7 +156,7 @@ You can run apps directly, but build dependencies first:
156156

157157
```bash
158158
# Build required packages
159-
pnpm build --filter=@repo/core --filter=@repo/react --filter=@repo/sentry --filter=@repo/utils
159+
pnpm build --filter=@repo/core --filter=@repo/react --filter=@repo/error --filter=@repo/utils
160160

161161
# Then run the app
162162
cd apps/next

apps/docu/content/docs/development/package-conventions.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ For `@repo/utils`, prefer subpath imports even though a root barrel exists:
151151
```ts
152152
import { delay } from '@repo/utils/async'
153153
import { logger } from '@repo/utils/logger/server'
154-
import { getErrorMessage } from '@repo/utils/error'
154+
import { getErrorMessage } from '@repo/error'
155155
```
156156

157157
## Dependency management strategy

0 commit comments

Comments
 (0)