@stacksjs/error-handling 0.70.22 → 0.70.25

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.
@@ -0,0 +1,381 @@
1
+ export declare function isFrameworkFrame(file: string): boolean;
2
+ /**
3
+ * Render a simple production error page
4
+ */
5
+ export declare function renderProductionErrorPage(status: number): string;
6
+ /**
7
+ * Render the contextual hint block (common causes, suggestion, doc link)
8
+ * for a given HTTP status. Returns an empty string for statuses without
9
+ * enriched data so the dev page degrades gracefully.
10
+ */
11
+ export declare function renderHttpErrorHints(status: number): string;
12
+ /**
13
+ * Create an error handler instance
14
+ */
15
+ export declare function createErrorHandler(config?: ErrorPageConfig): ErrorPageHandler;
16
+ /**
17
+ * Render an error page (alias)
18
+ */
19
+ export declare function renderErrorPage(error: Error, status?: number, config?: ErrorPageConfig): string;
20
+ /**
21
+ * Render error (alias)
22
+ */
23
+ export declare function renderError(error: Error, status?: number): string;
24
+ /**
25
+ * Create an error response
26
+ */
27
+ export declare function errorResponse(error: Error, status?: number, config?: ErrorPageConfig): Response;
28
+ // HTTP error definitions. Each entry includes a doc link, likely causes,
29
+ // and a concrete suggestion so the dev-mode error page reads like a hint
30
+ // instead of just "something went wrong".
31
+ export declare const HTTP_ERRORS: {
32
+ 400: {
33
+ status: 400;
34
+ title: 'Bad Request';
35
+ message: 'The request was malformed or invalid.';
36
+ docLink: `${DOCS_BASE}/400`;
37
+ commonCauses: readonly ['JSON body is missing or has a syntax error', 'A required field is absent from the payload', 'Content-Type header does not match the body format'];
38
+ suggestion: 'Inspect the request body and Content-Type — most 400s come from malformed JSON or a missing required field.'
39
+ };
40
+ 401: {
41
+ status: 401;
42
+ title: 'Unauthorized';
43
+ message: 'Authentication is required to access this resource.';
44
+ docLink: `${DOCS_BASE}/401`;
45
+ commonCauses: readonly ['No Authorization header was sent', 'The bearer token expired', 'The session cookie was cleared'];
46
+ suggestion: 'Confirm a valid `Authorization: Bearer <token>` header is sent and the token has not expired.'
47
+ };
48
+ 403: {
49
+ status: 403;
50
+ title: 'Forbidden';
51
+ message: 'You do not have permission to access this resource.';
52
+ docLink: `${DOCS_BASE}/403`;
53
+ commonCauses: readonly ['The authenticated user lacks the required ability or role', 'A Gate or policy denied access (see app/Gates.ts)', 'The token was issued without the needed ability'];
54
+ suggestion: 'Check Gates / policies and the abilities encoded in the access token.'
55
+ };
56
+ 404: {
57
+ status: 404;
58
+ title: 'Not Found';
59
+ message: 'The requested resource could not be found.';
60
+ docLink: `${DOCS_BASE}/404`;
61
+ commonCauses: readonly ['The route is not registered in app/Routes.ts', 'A typo in the URL path', 'A model lookup returned no row (ModelNotFoundError)'];
62
+ suggestion: 'Run `buddy route:list` to see registered routes, or verify the model exists with the given id.'
63
+ };
64
+ 405: {
65
+ status: 405;
66
+ title: 'Method Not Allowed';
67
+ message: 'The request method is not supported for this resource.';
68
+ docLink: `${DOCS_BASE}/405`;
69
+ commonCauses: readonly ['The route is registered for a different HTTP method', 'A form posted GET when the route expects POST'];
70
+ suggestion: 'Confirm the HTTP method in `app/Routes.ts` matches what the client sent.'
71
+ };
72
+ 408: {
73
+ status: 408;
74
+ title: 'Request Timeout';
75
+ message: 'The request took too long to complete.';
76
+ docLink: `${DOCS_BASE}/408`;
77
+ commonCauses: readonly ['A long-running query or external API call exceeded the timeout', 'The client uploaded a slow body that stalled'];
78
+ suggestion: 'Move slow work into a queued job, or raise the route timeout if the work is genuinely long.'
79
+ };
80
+ 409: {
81
+ status: 409;
82
+ title: 'Conflict';
83
+ message: 'The request conflicts with the current state of the resource.';
84
+ docLink: `${DOCS_BASE}/409`;
85
+ commonCauses: readonly ['A unique-constraint violation (duplicate email, slug, etc.)', 'Optimistic locking detected a stale write'];
86
+ suggestion: 'Re-fetch the resource and retry, or surface the conflict to the user.'
87
+ };
88
+ 410: {
89
+ status: 410;
90
+ title: 'Gone';
91
+ message: 'The requested resource is no longer available.';
92
+ docLink: `${DOCS_BASE}/410`;
93
+ commonCauses: readonly ['The resource was permanently deleted', 'A signed URL expired'];
94
+ suggestion: 'Issue a fresh signed URL or fall back to the canonical resource.'
95
+ };
96
+ 422: {
97
+ status: 422;
98
+ title: 'Unprocessable Entity';
99
+ message: 'The request was well-formed but could not be processed.';
100
+ docLink: `${DOCS_BASE}/422`;
101
+ commonCauses: readonly ['Validation rules from the action / model rejected the payload', 'A field value is outside the allowed range or shape'];
102
+ suggestion: 'Inspect `errors` in the response body — each key maps to a failing field.'
103
+ };
104
+ 429: {
105
+ status: 429;
106
+ title: 'Too Many Requests';
107
+ message: 'You have exceeded the rate limit.';
108
+ docLink: `${DOCS_BASE}/429`;
109
+ commonCauses: readonly ['Rate-limit middleware tripped on this IP / token', 'A retry loop is hammering the endpoint'];
110
+ suggestion: 'Honor the `Retry-After` response header and back off before retrying.'
111
+ };
112
+ 500: {
113
+ status: 500;
114
+ title: 'Internal Server Error';
115
+ message: 'An unexpected error occurred on the server.';
116
+ docLink: `${DOCS_BASE}/500`;
117
+ commonCauses: readonly ['An unhandled exception in an action or middleware', 'A failing database connection or migration', 'A misconfigured environment variable'];
118
+ suggestion: 'Check server logs for the original stack trace — the error page above shows the throw site in dev.'
119
+ };
120
+ 502: {
121
+ status: 502;
122
+ title: 'Bad Gateway';
123
+ message: 'The server received an invalid response from an upstream server.';
124
+ docLink: `${DOCS_BASE}/502`;
125
+ commonCauses: readonly ['An upstream HTTP API returned a malformed response', 'A reverse proxy could not reach the origin'];
126
+ suggestion: 'Verify the upstream service is healthy and returning the expected content type.'
127
+ };
128
+ 503: {
129
+ status: 503;
130
+ title: 'Service Unavailable';
131
+ message: 'The service is temporarily unavailable.';
132
+ docLink: `${DOCS_BASE}/503`;
133
+ commonCauses: readonly ['Maintenance mode is enabled', 'A health check is failing', 'A dependency (db, redis, queue) is down'];
134
+ suggestion: 'Run `buddy doctor` and check dependent services.'
135
+ };
136
+ 504: {
137
+ status: 504;
138
+ title: 'Gateway Timeout';
139
+ message: 'The upstream server did not respond in time.';
140
+ docLink: `${DOCS_BASE}/504`;
141
+ commonCauses: readonly ['An upstream HTTP call exceeded its deadline', 'A long-running database query timed out'];
142
+ suggestion: 'Move the work to a queued job or raise the upstream timeout if the latency is expected.'
143
+ }
144
+ };
145
+ // CSS for error pages
146
+ export declare const ERROR_PAGE_CSS: `
147
+ * { box-sizing: border-box; margin: 0; padding: 0; }
148
+ body {
149
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
150
+ line-height: 1.6;
151
+ color: #1a1a2e;
152
+ background: #f8f9fa;
153
+ }
154
+ .dark body { background: #1a1a2e; color: #e8e8e8; }
155
+ .container { max-width: 1200px; margin: 0 auto; padding: 2rem; }
156
+ .error-header {
157
+ background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
158
+ color: white;
159
+ padding: 2rem;
160
+ border-radius: 12px;
161
+ margin-bottom: 1.5rem;
162
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
163
+ }
164
+ .error-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
165
+ .error-message { font-size: 1.1rem; opacity: 0.9; word-break: break-word; }
166
+ .error-status { font-size: 0.875rem; opacity: 0.75; margin-top: 0.5rem; }
167
+ .card {
168
+ background: white;
169
+ border-radius: 12px;
170
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
171
+ margin-bottom: 1.5rem;
172
+ overflow: hidden;
173
+ }
174
+ .dark .card { background: #252540; }
175
+ .card-header {
176
+ padding: 1rem 1.5rem;
177
+ border-bottom: 1px solid #e9ecef;
178
+ font-weight: 600;
179
+ display: flex;
180
+ align-items: center;
181
+ gap: 0.5rem;
182
+ }
183
+ .dark .card-header { border-bottom-color: #3a3a5a; }
184
+ .card-body { padding: 1.5rem; }
185
+ .stack-frame {
186
+ padding: 1rem 1.5rem;
187
+ border-bottom: 1px solid #e9ecef;
188
+ cursor: pointer;
189
+ transition: background 0.2s;
190
+ }
191
+ .stack-frame:hover { background: #f8f9fa; }
192
+ .dark .stack-frame:hover { background: #1a1a2e; }
193
+ .stack-frame:last-child { border-bottom: none; }
194
+ .stack-frame.expanded { background: #f8f9fa; }
195
+ .dark .stack-frame.expanded { background: #1a1a2e; }
196
+ .frame-file { font-family: 'Monaco', 'Menlo', monospace; font-size: 0.875rem; color: #6c757d; }
197
+ .frame-function { font-weight: 500; color: #495057; }
198
+ .dark .frame-function { color: #e8e8e8; }
199
+ .frame-line { color: #dc3545; font-weight: 600; }
200
+ .code-snippet {
201
+ background: #282c34;
202
+ color: #abb2bf;
203
+ padding: 1rem;
204
+ margin-top: 0.5rem;
205
+ border-radius: 8px;
206
+ overflow-x: auto;
207
+ font-family: 'Monaco', 'Menlo', monospace;
208
+ font-size: 0.8125rem;
209
+ line-height: 1.8;
210
+ }
211
+ .code-line { display: flex; }
212
+ .code-line-number {
213
+ width: 3rem;
214
+ text-align: right;
215
+ padding-right: 1rem;
216
+ color: #636d83;
217
+ user-select: none;
218
+ }
219
+ .code-line-content { flex: 1; }
220
+ .code-line.highlight { background: rgba(220, 53, 69, 0.2); }
221
+ .code-line.highlight .code-line-number { color: #dc3545; }
222
+ .info-table { width: 100%; border-collapse: collapse; }
223
+ .info-table td { padding: 0.75rem 0; border-bottom: 1px solid #e9ecef; }
224
+ .dark .info-table td { border-bottom-color: #3a3a5a; }
225
+ .info-table td:first-child { font-weight: 500; width: 30%; color: #6c757d; }
226
+ .info-table tr:last-child td { border-bottom: none; }
227
+ .query-item {
228
+ padding: 1rem;
229
+ background: #f8f9fa;
230
+ border-radius: 8px;
231
+ margin-bottom: 0.75rem;
232
+ font-family: 'Monaco', 'Menlo', monospace;
233
+ font-size: 0.8125rem;
234
+ }
235
+ .dark .query-item { background: #1a1a2e; }
236
+ .query-time { color: #6c757d; font-size: 0.75rem; margin-top: 0.5rem; }
237
+ .badge {
238
+ display: inline-block;
239
+ padding: 0.25rem 0.5rem;
240
+ border-radius: 4px;
241
+ font-size: 0.75rem;
242
+ font-weight: 500;
243
+ }
244
+ .badge-method { background: #e7f5ff; color: #1971c2; }
245
+ .dark .badge-method { background: #1971c2; color: white; }
246
+ .production-page {
247
+ display: flex;
248
+ flex-direction: column;
249
+ align-items: center;
250
+ justify-content: center;
251
+ min-height: 100vh;
252
+ text-align: center;
253
+ padding: 2rem;
254
+ }
255
+ .production-status { font-size: 6rem; font-weight: 700; color: #dee2e6; margin-bottom: 1rem; }
256
+ .production-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
257
+ .production-message { color: #6c757d; margin-bottom: 2rem; }
258
+ .production-link { color: #0d6efd; text-decoration: none; }
259
+ .production-link:hover { text-decoration: underline; }
260
+ .error-hint {
261
+ border-left: 4px solid #f59f00;
262
+ background: #fff9db;
263
+ }
264
+ .dark .error-hint, .auto .error-hint { background: #2b2410; border-left-color: #f59f00; }
265
+ .error-hint .card-header { color: #845200; }
266
+ .dark .error-hint .card-header, .auto .error-hint .card-header { color: #ffd43b; }
267
+ .error-hint-causes { margin: 0 0 0.75rem 1.25rem; padding: 0; }
268
+ .error-hint-causes li { margin: 0.2rem 0; }
269
+ .error-hint-suggestion { font-weight: 500; margin-bottom: 0.75rem; }
270
+ .error-hint-doc { color: #0d6efd; text-decoration: none; }
271
+ .error-hint-doc:hover { text-decoration: underline; }
272
+ @media (prefers-color-scheme: dark) {
273
+ .auto body { background: #1a1a2e; color: #e8e8e8; }
274
+ .auto .card { background: #252540; }
275
+ .auto .card-header { border-bottom-color: #3a3a5a; }
276
+ .auto .stack-frame:hover { background: #1a1a2e; }
277
+ .auto .stack-frame.expanded { background: #1a1a2e; }
278
+ .auto .frame-function { color: #e8e8e8; }
279
+ .auto .info-table td { border-bottom-color: #3a3a5a; }
280
+ .auto .query-item { background: #1a1a2e; }
281
+ .auto .badge-method { background: #1971c2; color: white; }
282
+ }
283
+ `;
284
+ /**
285
+ * Error Page Rendering - Ignition-style error pages
286
+ *
287
+ * Provides beautiful development error pages with full stack traces,
288
+ * database queries, and request context.
289
+ */
290
+ // Types
291
+ export declare interface ErrorPageConfig {
292
+ appName?: string
293
+ theme?: 'light' | 'dark' | 'auto'
294
+ showEnvironment?: boolean
295
+ showQueries?: boolean
296
+ showRequest?: boolean
297
+ enableCopyMarkdown?: boolean
298
+ snippetLines?: number
299
+ basePaths?: string[]
300
+ showFrameworkFrames?: boolean
301
+ }
302
+ export declare interface RequestContext {
303
+ method: string
304
+ url: string
305
+ headers: Record<string, string>
306
+ queryParams?: Record<string, string>
307
+ body?: unknown
308
+ }
309
+ export declare interface RoutingContext {
310
+ controller?: string
311
+ routeName?: string
312
+ middleware?: string[]
313
+ }
314
+ export declare interface UserContext {
315
+ id?: string | number
316
+ email?: string
317
+ name?: string
318
+ }
319
+ export declare interface QueryInfo {
320
+ query: string
321
+ time?: number
322
+ connection?: string
323
+ }
324
+ export declare interface StackFrame {
325
+ file: string
326
+ line: number
327
+ column?: number
328
+ function?: string
329
+ code?: string
330
+ }
331
+ export declare interface CodeSnippet {
332
+ file: string
333
+ line: number
334
+ code: string[]
335
+ highlight: number
336
+ }
337
+ export declare interface EnvironmentContext {
338
+ nodeVersion?: string
339
+ platform?: string
340
+ arch?: string
341
+ env?: Record<string, string>
342
+ }
343
+ export declare interface JobContext {
344
+ name?: string
345
+ queue?: string
346
+ attempts?: number
347
+ }
348
+ export declare interface ErrorPageData {
349
+ error: Error
350
+ status: number
351
+ stack: StackFrame[]
352
+ request?: RequestContext
353
+ routing?: RoutingContext
354
+ user?: UserContext
355
+ queries?: QueryInfo[]
356
+ environment?: EnvironmentContext
357
+ job?: JobContext
358
+ framework?: { name: string, version?: string }
359
+ }
360
+ export declare interface HttpError {
361
+ status: HttpStatusCode
362
+ title: string
363
+ message: string
364
+ docLink?: string
365
+ commonCauses?: string[]
366
+ suggestion?: string
367
+ }
368
+ export type HttpStatusCode = 400 | 401 | 403 | 404 | 405 | 408 | 409 | 410 | 422 | 429 | 500 | 502 | 503 | 504;
369
+ /**
370
+ * Error Page Handler class
371
+ */
372
+ export declare class ErrorPageHandler {
373
+ constructor(config?: ErrorPageConfig);
374
+ setFramework(name: string, version?: string): this;
375
+ setRequest(request: Request | RequestContext): this;
376
+ setRouting(routing: RoutingContext): this;
377
+ setUser(user: UserContext): this;
378
+ addQuery(query: string, time?: number, connection?: string): this;
379
+ render(error: Error, status?: number): string;
380
+ handleError(error: Error, status?: number): Response;
381
+ }
@@ -0,0 +1,30 @@
1
+ import * as path from '@stacksjs/path';
2
+ import type { LogErrorOptions } from '@stacksjs/logging';
3
+ // Function to update the default log path when config is available
4
+ export declare function setLogPath(path: string): void;
5
+ export declare function writeToLogFile(message: string, options?: WriteOptions): Promise<void>;
6
+ export declare function handleError(err: string | Error | object | unknown, options?: LogErrorOptions | Record<string, any>): Error;
7
+ /**
8
+ * Context information attached to errors for better debugging.
9
+ */
10
+ export declare interface ErrorContext {
11
+ requestId?: string
12
+ url?: string
13
+ method?: string
14
+ userId?: string | number
15
+ ip?: string
16
+ userAgent?: string
17
+ [key: string]: unknown
18
+ }
19
+ declare interface WriteOptions {
20
+ logFile?: string
21
+ }
22
+ declare type ErrorMessage = string;
23
+ export declare class ErrorHandler {
24
+ static isTestEnvironment: boolean;
25
+ static shouldExitProcess: boolean;
26
+ static handle(err: Error | ErrorMessage | unknown, options?: LogErrorOptions): Error;
27
+ static handleError(err: Error, options?: LogErrorOptions): Error;
28
+ static writeErrorToFile(err: Error | unknown, context?: ErrorContext): Promise<void>;
29
+ static writeErrorToConsole(err: string | Error | unknown): void;
30
+ }
@@ -0,0 +1,49 @@
1
+ import type { ErrorPageConfig, RequestContext, RoutingContext } from './error-page';
2
+ /**
3
+ * Create a new HTTP error handler
4
+ */
5
+ export declare function createHttpErrorHandler(options?: {
6
+ isDevelopment?: boolean
7
+ config?: ErrorPageConfig
8
+ }): HttpErrorHandler;
9
+ /**
10
+ * Quick helper to render an error page for HTTP errors
11
+ */
12
+ export declare function renderHttpError(error: Error, request?: Request, options?: {
13
+ status?: number
14
+ isDevelopment?: boolean
15
+ config?: ErrorPageConfig
16
+ }): Response;
17
+ /**
18
+ * Express/Hono style error middleware
19
+ */
20
+ export declare function errorMiddleware(options?: {
21
+ isDevelopment?: boolean
22
+ config?: ErrorPageConfig
23
+ }): void;
24
+ export declare class HttpError extends Error {
25
+ details?: unknown;
26
+ public status: number;
27
+ constructor(status: number, message: string, details?: unknown);
28
+ }
29
+ /**
30
+ * HTTP error handler with Ignition-style error pages
31
+ */
32
+ export declare class HttpErrorHandler {
33
+ constructor(options?: {
34
+ isDevelopment?: boolean
35
+ config?: ErrorPageConfig
36
+ });
37
+ setRequest(request: Request | RequestContext): this;
38
+ setRouting(routing: RoutingContext): this;
39
+ addQuery(query: string, time?: number, connection?: string): this;
40
+ handle(error: Error, status?: number): Response;
41
+ notFound(message?: string): Response;
42
+ serverError(error: Error): Response;
43
+ forbidden(message?: string): Response;
44
+ unauthorized(message?: string): Response;
45
+ badRequest(message?: string): Response;
46
+ validationError(message?: string): Response;
47
+ tooManyRequests(message?: string): Response;
48
+ serviceUnavailable(message?: string): Response;
49
+ }
@@ -0,0 +1,42 @@
1
+ // Result type exports
2
+ export type {
3
+ Err,
4
+ Ok,
5
+ Result,
6
+ ResultAsync,
7
+ } from 'ts-error-handling';
8
+ // Error page exports (Ignition-style) - local implementation
9
+ export type {
10
+ CodeSnippet,
11
+ EnvironmentContext,
12
+ ErrorPageConfig,
13
+ ErrorPageData,
14
+ HttpError as HttpErrorInfo,
15
+ HttpStatusCode,
16
+ JobContext,
17
+ QueryInfo,
18
+ RequestContext,
19
+ RoutingContext,
20
+ StackFrame,
21
+ UserContext,
22
+ } from './error-page';
23
+ export * from './handler';
24
+ export * from './http';
25
+ export * from './model';
26
+ export * from './utils';
27
+ export {
28
+ err,
29
+ fromPromise,
30
+ ok,
31
+ } from 'ts-error-handling';
32
+ export {
33
+ createErrorHandler,
34
+ ERROR_PAGE_CSS,
35
+ ErrorPageHandler,
36
+ errorResponse,
37
+ HTTP_ERRORS,
38
+ renderError,
39
+ renderErrorPage,
40
+ renderHttpErrorHints,
41
+ renderProductionErrorPage,
42
+ } from './error-page';
@@ -0,0 +1,4 @@
1
+ export declare class ModelNotFoundException extends Error {
2
+ public status: number;
3
+ constructor(status: number, message: string);
4
+ }
@@ -0,0 +1 @@
1
+ export declare function rescue<T, F>(fn: () => T | Promise<T>, fallback: F, onError?: (error: Error) => void): T | F | Promise<T | F>;
package/package.json CHANGED
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "name": "@stacksjs/error-handling",
3
3
  "type": "module",
4
- "version": "0.70.22",
4
+ "version": "0.70.25",
5
5
  "description": "Type safe error handling.",
6
6
  "author": "Chris Breuer",
7
- "contributors": ["Chris Breuer <chris@stacksjs.org>"],
7
+ "contributors": [
8
+ "Chris Breuer <chris@stacksjs.com>"
9
+ ],
8
10
  "license": "MIT",
9
11
  "funding": "https://github.com/sponsors/chrisbbreuer",
10
12
  "homepage": "https://github.com/stacksjs/stacks/tree/main/storage/framework/core/error-handling#readme",
@@ -16,9 +18,17 @@
16
18
  "bugs": {
17
19
  "url": "https://github.com/stacksjs/stacks/issues"
18
20
  },
19
- "keywords": ["errors", "error-handling", "neverthrow", "type safe", "stacks"],
21
+ "keywords": [
22
+ "errors",
23
+ "error-handling",
24
+ "neverthrow",
25
+ "type safe",
26
+ "stacks"
27
+ ],
20
28
  "exports": {
21
29
  ".": {
30
+ "bun": "./src/index.ts",
31
+ "types": "./dist/index.d.ts",
22
32
  "import": "./dist/index.js"
23
33
  },
24
34
  "./*": {
@@ -27,19 +37,25 @@
27
37
  },
28
38
  "module": "dist/index.js",
29
39
  "types": "dist/index.d.ts",
30
- "files": ["README.md", "dist"],
40
+ "files": [
41
+ "README.md",
42
+ "dist"
43
+ ],
31
44
  "scripts": {
32
45
  "build": "bun build.ts",
33
46
  "typecheck": "bun tsc --noEmit",
34
47
  "prepublishOnly": "bun run build"
35
48
  },
49
+ "dependencies": {
50
+ "ts-error-handling": "^0.1.1"
51
+ },
36
52
  "devDependencies": {
37
- "@stacksjs/cli": "0.70.18",
38
- "@stacksjs/config": "0.70.18",
39
- "@stacksjs/development": "0.70.18",
40
- "@stacksjs/path": "0.70.18",
41
- "@stacksjs/types": "0.70.18",
42
- "@stacksjs/validation": "0.70.18",
43
- "neverthrow": "^8.2.0"
44
- }
53
+ "@stacksjs/cli": "0.70.23",
54
+ "@stacksjs/config": "0.70.23",
55
+ "better-dx": "^0.2.12",
56
+ "@stacksjs/path": "0.70.23",
57
+ "@stacksjs/types": "0.70.23",
58
+ "@stacksjs/validation": "0.70.23"
59
+ },
60
+ "sideEffects": false
45
61
  }
package/dist/handler.d.ts DELETED
@@ -1,93 +0,0 @@
1
- import type { ErrorOptions } from '@stacksjs/logging';
2
-
3
- declare type ErrorMessage = string
4
-
5
- export class ErrorHandler {
6
- static isTestEnvironment = false
7
- static shouldExitProcess = true
8
-
9
- static handle(err: Error | ErrorMessage | unknown, options?: ErrorOptions): Error {
10
- this.shouldExitProcess = options?.shouldExit !== false
11
- if (options?.silent !== true)
12
- this.writeErrorToConsole(err)
13
-
14
- let errorMessage: string
15
-
16
- if (options?.message) {
17
- errorMessage = options.message
18
- }
19
- else if (err instanceof Error) {
20
- errorMessage = err.message
21
- }
22
- else if (typeof err === 'string') {
23
- errorMessage = err
24
- }
25
- else {
26
- errorMessage = JSON.stringify(err)
27
- }
28
-
29
- const error = new Error(errorMessage)
30
-
31
- if (err instanceof Error) {
32
- Object.assign(error, err)
33
- }
34
-
35
- this.writeErrorToFile(error).catch(e => console.error(e))
36
-
37
- return error
38
- }
39
-
40
- static handleError(err: Error, options?: ErrorOptions): Error {
41
- this.handle(err, options)
42
- return err
43
- }
44
-
45
- static async writeErrorToFile(err: Error | unknown): Promise<void> {
46
- if (!(err instanceof Error)) {
47
- console.error('Error is not an instance of Error:', err)
48
- return
49
- }
50
-
51
- const formattedError = `[${new Date().toISOString()}] ${err.name}: ${err.message}\n`
52
- const logFilePath = path.logsPath('stacks.log') ?? path.logsPath('errors.log')
53
-
54
- try {
55
- await mkdir(path.dirname(logFilePath), { recursive: true })
56
- await appendFile(logFilePath, formattedError)
57
- }
58
- catch (error) {
59
- console.error('Failed to write to error file:', error)
60
- }
61
- }
62
-
63
- static writeErrorToConsole(err: string | Error | unknown): void {
64
- console.error(err)
65
-
66
- const errorString = typeof err === 'string' ? err : err instanceof Error ? err.message : JSON.stringify(err)
67
-
68
- if (
69
- errorString.includes('bunx --bun cdk destroy')
70
- || errorString === `Failed to execute command: ${italic('bunx --bun eslint . --fix')}`
71
- || errorString === `Failed to execute command: ${italic('bun storage/framework/core/actions/src/lint/fix.ts')}`
72
- ) {
73
- if (!this.isTestEnvironment) {
74
- console.log(
75
- 'No need to worry. The edge function is currently being destroyed. Please run `buddy undeploy` shortly again, and continue doing so until it succeeds running.',
76
- )
77
- console.log('Hoping to see you back soon!')
78
- }
79
- }
80
-
81
- if (this.shouldExitProcess) {
82
- process.exit(ExitCode.FatalError)
83
- }
84
- }
85
- }
86
-
87
- interface WriteOptions {
88
- logFile?: string
89
- }
90
-
91
- let defaultLogPath = 'storage/logs/stacks.log'
92
- export declare function setLogPath(path: string): void;
93
- export declare function handleError(err: string | Error | object | unknown, options?: ErrorOptions | Record<string, any>): Error;
package/dist/http.d.ts DELETED
@@ -1,6 +0,0 @@
1
- export declare class HttpError extends Error {
2
- constructor(public status: number, message: string) {
3
- super(message)
4
- this.name = 'Server Error!'
5
- }
6
- }