@bloomneo/appkit 1.2.9
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/LICENSE +21 -0
- package/README.md +902 -0
- package/bin/appkit.js +71 -0
- package/bin/commands/generate.js +1050 -0
- package/bin/templates/backend/README.md.template +39 -0
- package/bin/templates/backend/api.http.template +0 -0
- package/bin/templates/backend/docs/APPKIT_CLI.md +507 -0
- package/bin/templates/backend/docs/APPKIT_COMMENTS_GUIDELINES.md +61 -0
- package/bin/templates/backend/docs/APPKIT_LLM_GUIDE.md +2539 -0
- package/bin/templates/backend/package.json.template +34 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.http.template +29 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.route.ts.template +36 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.service.ts.template +88 -0
- package/bin/templates/backend/src/api/features/welcome/welcome.types.ts.template +18 -0
- package/bin/templates/backend/src/api/lib/api-router.ts.template +84 -0
- package/bin/templates/backend/src/api/server.ts.template +188 -0
- package/bin/templates/backend/tsconfig.api.json.template +24 -0
- package/bin/templates/backend/tsconfig.json.template +40 -0
- package/bin/templates/feature/feature.http.template +63 -0
- package/bin/templates/feature/feature.route.ts.template +36 -0
- package/bin/templates/feature/feature.service.ts.template +81 -0
- package/bin/templates/feature/feature.types.ts.template +23 -0
- package/bin/templates/feature-db/feature.http.template +63 -0
- package/bin/templates/feature-db/feature.model.ts.template +74 -0
- package/bin/templates/feature-db/feature.route.ts.template +58 -0
- package/bin/templates/feature-db/feature.service.ts.template +231 -0
- package/bin/templates/feature-db/feature.types.ts.template +25 -0
- package/bin/templates/feature-db/schema-addition.prisma.template +9 -0
- package/bin/templates/feature-db/seeding/README.md.template +57 -0
- package/bin/templates/feature-db/seeding/feature.seed.js.template +67 -0
- package/bin/templates/feature-user/schema-addition.prisma.template +19 -0
- package/bin/templates/feature-user/user.http.template +157 -0
- package/bin/templates/feature-user/user.model.ts.template +244 -0
- package/bin/templates/feature-user/user.route.ts.template +379 -0
- package/bin/templates/feature-user/user.seed.js.template +182 -0
- package/bin/templates/feature-user/user.service.ts.template +426 -0
- package/bin/templates/feature-user/user.types.ts.template +127 -0
- package/dist/auth/auth.d.ts +182 -0
- package/dist/auth/auth.d.ts.map +1 -0
- package/dist/auth/auth.js +477 -0
- package/dist/auth/auth.js.map +1 -0
- package/dist/auth/defaults.d.ts +104 -0
- package/dist/auth/defaults.d.ts.map +1 -0
- package/dist/auth/defaults.js +374 -0
- package/dist/auth/defaults.js.map +1 -0
- package/dist/auth/index.d.ts +70 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +94 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/cache/cache.d.ts +118 -0
- package/dist/cache/cache.d.ts.map +1 -0
- package/dist/cache/cache.js +249 -0
- package/dist/cache/cache.js.map +1 -0
- package/dist/cache/defaults.d.ts +63 -0
- package/dist/cache/defaults.d.ts.map +1 -0
- package/dist/cache/defaults.js +193 -0
- package/dist/cache/defaults.js.map +1 -0
- package/dist/cache/index.d.ts +101 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +203 -0
- package/dist/cache/index.js.map +1 -0
- package/dist/cache/strategies/memory.d.ts +138 -0
- package/dist/cache/strategies/memory.d.ts.map +1 -0
- package/dist/cache/strategies/memory.js +348 -0
- package/dist/cache/strategies/memory.js.map +1 -0
- package/dist/cache/strategies/redis.d.ts +105 -0
- package/dist/cache/strategies/redis.d.ts.map +1 -0
- package/dist/cache/strategies/redis.js +318 -0
- package/dist/cache/strategies/redis.js.map +1 -0
- package/dist/config/config.d.ts +62 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +107 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/defaults.d.ts +44 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +217 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/index.d.ts +105 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +163 -0
- package/dist/config/index.js.map +1 -0
- package/dist/database/adapters/mongoose.d.ts +106 -0
- package/dist/database/adapters/mongoose.d.ts.map +1 -0
- package/dist/database/adapters/mongoose.js +480 -0
- package/dist/database/adapters/mongoose.js.map +1 -0
- package/dist/database/adapters/prisma.d.ts +106 -0
- package/dist/database/adapters/prisma.d.ts.map +1 -0
- package/dist/database/adapters/prisma.js +494 -0
- package/dist/database/adapters/prisma.js.map +1 -0
- package/dist/database/defaults.d.ts +87 -0
- package/dist/database/defaults.d.ts.map +1 -0
- package/dist/database/defaults.js +271 -0
- package/dist/database/defaults.js.map +1 -0
- package/dist/database/index.d.ts +137 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +490 -0
- package/dist/database/index.js.map +1 -0
- package/dist/email/defaults.d.ts +100 -0
- package/dist/email/defaults.d.ts.map +1 -0
- package/dist/email/defaults.js +400 -0
- package/dist/email/defaults.js.map +1 -0
- package/dist/email/email.d.ts +139 -0
- package/dist/email/email.d.ts.map +1 -0
- package/dist/email/email.js +316 -0
- package/dist/email/email.js.map +1 -0
- package/dist/email/index.d.ts +176 -0
- package/dist/email/index.d.ts.map +1 -0
- package/dist/email/index.js +251 -0
- package/dist/email/index.js.map +1 -0
- package/dist/email/strategies/console.d.ts +90 -0
- package/dist/email/strategies/console.d.ts.map +1 -0
- package/dist/email/strategies/console.js +268 -0
- package/dist/email/strategies/console.js.map +1 -0
- package/dist/email/strategies/resend.d.ts +84 -0
- package/dist/email/strategies/resend.d.ts.map +1 -0
- package/dist/email/strategies/resend.js +266 -0
- package/dist/email/strategies/resend.js.map +1 -0
- package/dist/email/strategies/smtp.d.ts +77 -0
- package/dist/email/strategies/smtp.d.ts.map +1 -0
- package/dist/email/strategies/smtp.js +286 -0
- package/dist/email/strategies/smtp.js.map +1 -0
- package/dist/error/defaults.d.ts +40 -0
- package/dist/error/defaults.d.ts.map +1 -0
- package/dist/error/defaults.js +75 -0
- package/dist/error/defaults.js.map +1 -0
- package/dist/error/error.d.ts +140 -0
- package/dist/error/error.d.ts.map +1 -0
- package/dist/error/error.js +200 -0
- package/dist/error/error.js.map +1 -0
- package/dist/error/index.d.ts +145 -0
- package/dist/error/index.d.ts.map +1 -0
- package/dist/error/index.js +145 -0
- package/dist/error/index.js.map +1 -0
- package/dist/event/defaults.d.ts +111 -0
- package/dist/event/defaults.d.ts.map +1 -0
- package/dist/event/defaults.js +378 -0
- package/dist/event/defaults.js.map +1 -0
- package/dist/event/event.d.ts +171 -0
- package/dist/event/event.d.ts.map +1 -0
- package/dist/event/event.js +391 -0
- package/dist/event/event.js.map +1 -0
- package/dist/event/index.d.ts +173 -0
- package/dist/event/index.d.ts.map +1 -0
- package/dist/event/index.js +302 -0
- package/dist/event/index.js.map +1 -0
- package/dist/event/strategies/memory.d.ts +122 -0
- package/dist/event/strategies/memory.d.ts.map +1 -0
- package/dist/event/strategies/memory.js +331 -0
- package/dist/event/strategies/memory.js.map +1 -0
- package/dist/event/strategies/redis.d.ts +115 -0
- package/dist/event/strategies/redis.d.ts.map +1 -0
- package/dist/event/strategies/redis.js +434 -0
- package/dist/event/strategies/redis.js.map +1 -0
- package/dist/index.d.ts +58 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/defaults.d.ts +67 -0
- package/dist/logger/defaults.d.ts.map +1 -0
- package/dist/logger/defaults.js +213 -0
- package/dist/logger/defaults.js.map +1 -0
- package/dist/logger/index.d.ts +84 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +101 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/logger.d.ts +165 -0
- package/dist/logger/logger.d.ts.map +1 -0
- package/dist/logger/logger.js +843 -0
- package/dist/logger/logger.js.map +1 -0
- package/dist/logger/transports/console.d.ts +102 -0
- package/dist/logger/transports/console.d.ts.map +1 -0
- package/dist/logger/transports/console.js +276 -0
- package/dist/logger/transports/console.js.map +1 -0
- package/dist/logger/transports/database.d.ts +153 -0
- package/dist/logger/transports/database.d.ts.map +1 -0
- package/dist/logger/transports/database.js +539 -0
- package/dist/logger/transports/database.js.map +1 -0
- package/dist/logger/transports/file.d.ts +146 -0
- package/dist/logger/transports/file.d.ts.map +1 -0
- package/dist/logger/transports/file.js +464 -0
- package/dist/logger/transports/file.js.map +1 -0
- package/dist/logger/transports/http.d.ts +128 -0
- package/dist/logger/transports/http.d.ts.map +1 -0
- package/dist/logger/transports/http.js +401 -0
- package/dist/logger/transports/http.js.map +1 -0
- package/dist/logger/transports/webhook.d.ts +152 -0
- package/dist/logger/transports/webhook.d.ts.map +1 -0
- package/dist/logger/transports/webhook.js +485 -0
- package/dist/logger/transports/webhook.js.map +1 -0
- package/dist/queue/defaults.d.ts +66 -0
- package/dist/queue/defaults.d.ts.map +1 -0
- package/dist/queue/defaults.js +205 -0
- package/dist/queue/defaults.js.map +1 -0
- package/dist/queue/index.d.ts +124 -0
- package/dist/queue/index.d.ts.map +1 -0
- package/dist/queue/index.js +116 -0
- package/dist/queue/index.js.map +1 -0
- package/dist/queue/queue.d.ts +156 -0
- package/dist/queue/queue.d.ts.map +1 -0
- package/dist/queue/queue.js +387 -0
- package/dist/queue/queue.js.map +1 -0
- package/dist/queue/transports/database.d.ts +165 -0
- package/dist/queue/transports/database.d.ts.map +1 -0
- package/dist/queue/transports/database.js +595 -0
- package/dist/queue/transports/database.js.map +1 -0
- package/dist/queue/transports/memory.d.ts +143 -0
- package/dist/queue/transports/memory.d.ts.map +1 -0
- package/dist/queue/transports/memory.js +415 -0
- package/dist/queue/transports/memory.js.map +1 -0
- package/dist/queue/transports/redis.d.ts +203 -0
- package/dist/queue/transports/redis.d.ts.map +1 -0
- package/dist/queue/transports/redis.js +744 -0
- package/dist/queue/transports/redis.js.map +1 -0
- package/dist/security/defaults.d.ts +64 -0
- package/dist/security/defaults.d.ts.map +1 -0
- package/dist/security/defaults.js +159 -0
- package/dist/security/defaults.js.map +1 -0
- package/dist/security/index.d.ts +110 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +160 -0
- package/dist/security/index.js.map +1 -0
- package/dist/security/security.d.ts +138 -0
- package/dist/security/security.d.ts.map +1 -0
- package/dist/security/security.js +419 -0
- package/dist/security/security.js.map +1 -0
- package/dist/storage/defaults.d.ts +79 -0
- package/dist/storage/defaults.d.ts.map +1 -0
- package/dist/storage/defaults.js +358 -0
- package/dist/storage/defaults.js.map +1 -0
- package/dist/storage/index.d.ts +153 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +242 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/storage.d.ts +151 -0
- package/dist/storage/storage.d.ts.map +1 -0
- package/dist/storage/storage.js +439 -0
- package/dist/storage/storage.js.map +1 -0
- package/dist/storage/strategies/local.d.ts +117 -0
- package/dist/storage/strategies/local.d.ts.map +1 -0
- package/dist/storage/strategies/local.js +368 -0
- package/dist/storage/strategies/local.js.map +1 -0
- package/dist/storage/strategies/r2.d.ts +130 -0
- package/dist/storage/strategies/r2.d.ts.map +1 -0
- package/dist/storage/strategies/r2.js +470 -0
- package/dist/storage/strategies/r2.js.map +1 -0
- package/dist/storage/strategies/s3.d.ts +121 -0
- package/dist/storage/strategies/s3.d.ts.map +1 -0
- package/dist/storage/strategies/s3.js +461 -0
- package/dist/storage/strategies/s3.js.map +1 -0
- package/dist/util/defaults.d.ts +77 -0
- package/dist/util/defaults.d.ts.map +1 -0
- package/dist/util/defaults.js +193 -0
- package/dist/util/defaults.js.map +1 -0
- package/dist/util/index.d.ts +97 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +165 -0
- package/dist/util/index.js.map +1 -0
- package/dist/util/util.d.ts +145 -0
- package/dist/util/util.d.ts.map +1 -0
- package/dist/util/util.js +481 -0
- package/dist/util/util.js.map +1 -0
- package/package.json +234 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core error class with semantic HTTP status codes and middleware
|
|
3
|
+
* @module @bloomneo/appkit/error
|
|
4
|
+
* @file src/error/error.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: Building apps that need semantic HTTP error handling
|
|
7
|
+
* @llm-rule AVOID: Using directly - always get instance via errorClass.get()
|
|
8
|
+
* @llm-rule NOTE: Provides semantic error creation (badRequest, unauthorized) and Express middleware
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Error class with semantic HTTP status codes and middleware functionality
|
|
12
|
+
*/
|
|
13
|
+
export class ErrorClass {
|
|
14
|
+
config;
|
|
15
|
+
constructor(config) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a 400 Bad Request error
|
|
20
|
+
* @llm-rule WHEN: Client sends invalid input data (missing fields, wrong format)
|
|
21
|
+
* @llm-rule AVOID: Using for server-side validation errors - use conflict() instead
|
|
22
|
+
* @llm-rule NOTE: EXAMPLES: missing email, invalid JSON, malformed request body
|
|
23
|
+
* @llm-rule NOTE: PATTERN: if (!req.body.email) throw error.badRequest('Email required');
|
|
24
|
+
*/
|
|
25
|
+
badRequest(message) {
|
|
26
|
+
const error = new Error(message || this.config.messages.badRequest);
|
|
27
|
+
error.statusCode = 400;
|
|
28
|
+
error.type = 'BAD_REQUEST';
|
|
29
|
+
return error;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a 401 Unauthorized error
|
|
33
|
+
* @llm-rule WHEN: Authentication is required but missing or invalid
|
|
34
|
+
* @llm-rule AVOID: Using for permission issues - use forbidden() for access control
|
|
35
|
+
* @llm-rule NOTE: EXAMPLES: missing token, invalid token, expired session
|
|
36
|
+
* @llm-rule NOTE: PATTERN: if (!token) throw error.unauthorized('Token required');
|
|
37
|
+
*/
|
|
38
|
+
unauthorized(message) {
|
|
39
|
+
const error = new Error(message || this.config.messages.unauthorized);
|
|
40
|
+
error.statusCode = 401;
|
|
41
|
+
error.type = 'UNAUTHORIZED';
|
|
42
|
+
return error;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Creates a 403 Forbidden error
|
|
46
|
+
* @llm-rule WHEN: User is authenticated but lacks permission for the action
|
|
47
|
+
* @llm-rule AVOID: Using for authentication issues - use unauthorized() instead
|
|
48
|
+
* @llm-rule NOTE: EXAMPLES: insufficient role, blocked user, admin-only endpoint
|
|
49
|
+
* @llm-rule NOTE: PATTERN: if (!user.isAdmin) throw error.forbidden('Admin access required');
|
|
50
|
+
*/
|
|
51
|
+
forbidden(message) {
|
|
52
|
+
const error = new Error(message || this.config.messages.forbidden);
|
|
53
|
+
error.statusCode = 403;
|
|
54
|
+
error.type = 'FORBIDDEN';
|
|
55
|
+
return error;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Creates a 404 Not Found error
|
|
59
|
+
* @llm-rule WHEN: Requested resource does not exist
|
|
60
|
+
* @llm-rule AVOID: Using for business logic failures - use conflict() instead
|
|
61
|
+
* @llm-rule NOTE: EXAMPLES: user not found, post not found, missing file
|
|
62
|
+
* @llm-rule NOTE: PATTERN: if (!user) throw error.notFound('User not found');
|
|
63
|
+
*/
|
|
64
|
+
notFound(message) {
|
|
65
|
+
const error = new Error(message || this.config.messages.notFound);
|
|
66
|
+
error.statusCode = 404;
|
|
67
|
+
error.type = 'NOT_FOUND';
|
|
68
|
+
return error;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Creates a 409 Conflict error
|
|
72
|
+
* @llm-rule WHEN: Business logic conflicts or resource already exists
|
|
73
|
+
* @llm-rule AVOID: Using for validation errors - use badRequest() for input validation
|
|
74
|
+
* @llm-rule NOTE: EXAMPLES: email already exists, duplicate username, state conflicts
|
|
75
|
+
* @llm-rule NOTE: PATTERN: if (existingUser) throw error.conflict('Email already registered');
|
|
76
|
+
*/
|
|
77
|
+
conflict(message) {
|
|
78
|
+
const error = new Error(message || this.config.messages.conflict);
|
|
79
|
+
error.statusCode = 409;
|
|
80
|
+
error.type = 'CONFLICT';
|
|
81
|
+
return error;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Creates a 500 Server Error
|
|
85
|
+
* @llm-rule WHEN: Internal server failures like database errors, external API failures
|
|
86
|
+
* @llm-rule AVOID: Using for business logic issues - use appropriate 4xx errors instead
|
|
87
|
+
* @llm-rule NOTE: EXAMPLES: database connection failure, external API timeout, file system errors
|
|
88
|
+
* @llm-rule NOTE: PATTERN: catch (dbError) { throw error.serverError('Database unavailable'); }
|
|
89
|
+
*/
|
|
90
|
+
serverError(message) {
|
|
91
|
+
const error = new Error(message || this.config.messages.serverError);
|
|
92
|
+
error.statusCode = 500;
|
|
93
|
+
error.type = 'SERVER_ERROR';
|
|
94
|
+
return error;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Creates a custom error with any status code
|
|
98
|
+
* @llm-rule WHEN: Need custom HTTP status codes not covered by semantic methods
|
|
99
|
+
* @llm-rule AVOID: Using for standard HTTP codes - use semantic methods instead
|
|
100
|
+
* @llm-rule NOTE: EXAMPLES: 429 rate limit, 503 service unavailable, 418 teapot
|
|
101
|
+
* @llm-rule NOTE: PATTERN: error.createError(429, 'Rate limit exceeded', 'RATE_LIMIT');
|
|
102
|
+
*/
|
|
103
|
+
createError(statusCode, message, type) {
|
|
104
|
+
const error = new Error(message);
|
|
105
|
+
error.statusCode = statusCode;
|
|
106
|
+
error.type = type || `HTTP_${statusCode}`;
|
|
107
|
+
return error;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Creates production-ready Express error handling middleware
|
|
111
|
+
* @llm-rule WHEN: Setting up Express app error handling - use as last middleware
|
|
112
|
+
* @llm-rule AVOID: Using multiple error handlers - this should be the final middleware
|
|
113
|
+
* @llm-rule NOTE: MIDDLEWARE SETUP: app.use(error.handleErrors()); // Must be LAST
|
|
114
|
+
* @llm-rule NOTE: AUTO-FEATURES: dev vs prod responses, stack trace hiding, error logging
|
|
115
|
+
*/
|
|
116
|
+
handleErrors(options = {}) {
|
|
117
|
+
// Use instance config as defaults, allow options to override
|
|
118
|
+
const showStack = options.showStack !== undefined
|
|
119
|
+
? options.showStack
|
|
120
|
+
: this.config.middleware.showStack;
|
|
121
|
+
const logErrors = options.logErrors !== undefined
|
|
122
|
+
? options.logErrors
|
|
123
|
+
: this.config.middleware.logErrors;
|
|
124
|
+
return (error, req, res, next) => {
|
|
125
|
+
// Log errors if enabled
|
|
126
|
+
if (logErrors) {
|
|
127
|
+
console.error('Error:', error.message);
|
|
128
|
+
if (showStack && error.stack) {
|
|
129
|
+
console.error('Stack:', error.stack);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Determine status code
|
|
133
|
+
const statusCode = error.statusCode || 500;
|
|
134
|
+
// Determine error type
|
|
135
|
+
const errorType = error.type || (statusCode >= 500 ? 'SERVER_ERROR' : 'CLIENT_ERROR');
|
|
136
|
+
// Build response object
|
|
137
|
+
const response = {
|
|
138
|
+
error: errorType,
|
|
139
|
+
message: error.message || 'An error occurred',
|
|
140
|
+
};
|
|
141
|
+
// Include stack trace in development
|
|
142
|
+
if (showStack && error.stack) {
|
|
143
|
+
response.stack = error.stack;
|
|
144
|
+
}
|
|
145
|
+
// Send error response
|
|
146
|
+
res.status(statusCode).json(response);
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Wraps async route handlers to catch errors automatically
|
|
151
|
+
* @llm-rule WHEN: Creating async Express route handlers that might throw errors
|
|
152
|
+
* @llm-rule AVOID: Manual try/catch in every route - this handles it automatically
|
|
153
|
+
* @llm-rule NOTE: ASYNC PATTERN: app.post('/route', error.asyncRoute(async (req, res) => {...}));
|
|
154
|
+
* @llm-rule NOTE: ERROR FLOW: thrown errors → automatically caught → sent to handleErrors middleware
|
|
155
|
+
*/
|
|
156
|
+
asyncRoute(fn) {
|
|
157
|
+
return (req, res, next) => {
|
|
158
|
+
Promise.resolve(fn(req, res, next)).catch(next);
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Checks if error is a 4xx client error
|
|
163
|
+
* @llm-rule WHEN: Need to categorize errors for logging or metrics
|
|
164
|
+
* @llm-rule AVOID: Manual status code checking - this handles the logic
|
|
165
|
+
* @llm-rule NOTE: CLIENT ERRORS: 400-499 status codes (user's fault)
|
|
166
|
+
*/
|
|
167
|
+
isClientError(error) {
|
|
168
|
+
return error.statusCode >= 400 && error.statusCode < 500;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Checks if error is a 5xx server error
|
|
172
|
+
* @llm-rule WHEN: Need to categorize errors for monitoring or alerting
|
|
173
|
+
* @llm-rule AVOID: Manual status code checking - this handles the logic
|
|
174
|
+
* @llm-rule NOTE: SERVER ERRORS: 500-599 status codes (server's fault)
|
|
175
|
+
*/
|
|
176
|
+
isServerError(error) {
|
|
177
|
+
return error.statusCode >= 500;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Gets current environment detection info
|
|
181
|
+
* @llm-rule WHEN: Need to check current environment configuration
|
|
182
|
+
* @llm-rule AVOID: Direct process.env access - this provides parsed config
|
|
183
|
+
*/
|
|
184
|
+
getEnvironmentInfo() {
|
|
185
|
+
return {
|
|
186
|
+
isDevelopment: this.config.environment.isDevelopment,
|
|
187
|
+
isProduction: this.config.environment.isProduction,
|
|
188
|
+
nodeEnv: this.config.environment.nodeEnv,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Gets current error configuration
|
|
193
|
+
* @llm-rule WHEN: Debugging error setup or inspecting current settings
|
|
194
|
+
* @llm-rule AVOID: Accessing config directly - this provides clean interface
|
|
195
|
+
*/
|
|
196
|
+
getConfig() {
|
|
197
|
+
return { ...this.config };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
//# sourceMappingURL=error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.js","sourceRoot":"","sources":["../../src/error/error.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ultra-simple semantic error handling that just works
|
|
3
|
+
* @module @bloomneo/appkit/error
|
|
4
|
+
* @file src/error/index.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: Building apps that need semantic HTTP error handling
|
|
7
|
+
* @llm-rule AVOID: Complex error setups with multiple libraries - this handles everything in one API
|
|
8
|
+
* @llm-rule NOTE: Provides semantic error creation (badRequest, unauthorized) and Express middleware
|
|
9
|
+
* @llm-rule NOTE: Common pattern - errorClass.get() → throw error.badRequest() → app.use(error.handleErrors())
|
|
10
|
+
* @llm-rule NOTE: COMPLETE SETUP: const error = errorClass.get(); app.use(error.handleErrors()); // Done!
|
|
11
|
+
*/
|
|
12
|
+
import { ErrorClass } from './error.js';
|
|
13
|
+
import { type ErrorConfig } from './defaults.js';
|
|
14
|
+
export interface AppError extends Error {
|
|
15
|
+
statusCode: number;
|
|
16
|
+
type: string;
|
|
17
|
+
}
|
|
18
|
+
export interface ExpressRequest {
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
}
|
|
21
|
+
export interface ExpressResponse {
|
|
22
|
+
status: (code: number) => ExpressResponse;
|
|
23
|
+
json: (data: any) => void;
|
|
24
|
+
}
|
|
25
|
+
export interface ExpressNextFunction {
|
|
26
|
+
(error?: any): void;
|
|
27
|
+
}
|
|
28
|
+
export type ExpressErrorHandler = (error: AppError, req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => void;
|
|
29
|
+
export type AsyncRouteHandler = (req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => Promise<any>;
|
|
30
|
+
export interface ErrorHandlerOptions {
|
|
31
|
+
showStack?: boolean;
|
|
32
|
+
logErrors?: boolean;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Get error instance - the only function you need to learn
|
|
36
|
+
* Environment variables parsed once for performance
|
|
37
|
+
* @llm-rule WHEN: Starting any error operation - this is your main entry point
|
|
38
|
+
* @llm-rule AVOID: Calling new ErrorClass() directly - always use this function
|
|
39
|
+
* @llm-rule NOTE: USAGE FLOW: get() → create errors → setup middleware → done
|
|
40
|
+
* @llm-rule NOTE: TYPICAL SETUP: const error = errorClass.get(); app.use(error.handleErrors());
|
|
41
|
+
*/
|
|
42
|
+
declare function get(overrides?: Partial<ErrorConfig>): ErrorClass;
|
|
43
|
+
/**
|
|
44
|
+
* Reset global instance (useful for testing or config changes)
|
|
45
|
+
* @llm-rule WHEN: Testing error logic with different configurations
|
|
46
|
+
* @llm-rule AVOID: Using in production - only for tests and development
|
|
47
|
+
* @llm-rule NOTE: TEST PATTERN: const error = errorClass.reset({showStack: false}); // Clean slate
|
|
48
|
+
*/
|
|
49
|
+
declare function reset(newConfig?: Partial<ErrorConfig>): ErrorClass;
|
|
50
|
+
/**
|
|
51
|
+
* Clear global instance cache (for testing)
|
|
52
|
+
* @llm-rule WHEN: Testing error configurations or between test suites
|
|
53
|
+
* @llm-rule AVOID: Using in production - only for tests
|
|
54
|
+
*/
|
|
55
|
+
declare function clearCache(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Single error export with semantic methods and Express integration
|
|
58
|
+
* @llm-rule NOTE: TWO USAGE PATTERNS: errorClass.get().badRequest() OR errorClass.badRequest() (shortcuts)
|
|
59
|
+
* @llm-rule NOTE: MIDDLEWARE PATTERN: app.use(error.handleErrors()); // Global error handling
|
|
60
|
+
*/
|
|
61
|
+
export declare const errorClass: {
|
|
62
|
+
readonly get: typeof get;
|
|
63
|
+
readonly reset: typeof reset;
|
|
64
|
+
readonly clearCache: typeof clearCache;
|
|
65
|
+
/**
|
|
66
|
+
* Creates 400 Bad Request error
|
|
67
|
+
* @llm-rule WHEN: Client input validation failures (missing/invalid data)
|
|
68
|
+
* @llm-rule NOTE: EXAMPLES: missing email, invalid JSON, malformed request
|
|
69
|
+
* @llm-rule NOTE: PATTERN: if (!email) throw error.badRequest('Email required');
|
|
70
|
+
*/
|
|
71
|
+
readonly badRequest: (message?: string) => import("./error.js").AppError;
|
|
72
|
+
/**
|
|
73
|
+
* Creates 401 Unauthorized error
|
|
74
|
+
* @llm-rule WHEN: Authentication required but missing or invalid
|
|
75
|
+
* @llm-rule NOTE: EXAMPLES: missing token, expired session, invalid credentials
|
|
76
|
+
* @llm-rule NOTE: PATTERN: if (!token) throw error.unauthorized('Login required');
|
|
77
|
+
*/
|
|
78
|
+
readonly unauthorized: (message?: string) => import("./error.js").AppError;
|
|
79
|
+
/**
|
|
80
|
+
* Creates 403 Forbidden error
|
|
81
|
+
* @llm-rule WHEN: User authenticated but lacks permission for action
|
|
82
|
+
* @llm-rule NOTE: EXAMPLES: insufficient role, admin-only endpoint, blocked user
|
|
83
|
+
* @llm-rule NOTE: PATTERN: if (!user.isAdmin) throw error.forbidden('Admin only');
|
|
84
|
+
*/
|
|
85
|
+
readonly forbidden: (message?: string) => import("./error.js").AppError;
|
|
86
|
+
/**
|
|
87
|
+
* Creates 404 Not Found error
|
|
88
|
+
* @llm-rule WHEN: Requested resource does not exist in database/system
|
|
89
|
+
* @llm-rule NOTE: EXAMPLES: user not found, post not found, file missing
|
|
90
|
+
* @llm-rule NOTE: PATTERN: if (!user) throw error.notFound('User not found');
|
|
91
|
+
*/
|
|
92
|
+
readonly notFound: (message?: string) => import("./error.js").AppError;
|
|
93
|
+
/**
|
|
94
|
+
* Creates 409 Conflict error
|
|
95
|
+
* @llm-rule WHEN: Business logic conflicts or duplicate resources
|
|
96
|
+
* @llm-rule NOTE: EXAMPLES: email already exists, username taken, state conflicts
|
|
97
|
+
* @llm-rule NOTE: PATTERN: if (existingUser) throw error.conflict('Email exists');
|
|
98
|
+
*/
|
|
99
|
+
readonly conflict: (message?: string) => import("./error.js").AppError;
|
|
100
|
+
/**
|
|
101
|
+
* Creates 500 Server Error
|
|
102
|
+
* @llm-rule WHEN: Internal failures like database/API errors
|
|
103
|
+
* @llm-rule NOTE: EXAMPLES: database down, external API timeout, file system errors
|
|
104
|
+
* @llm-rule NOTE: PATTERN: catch (dbError) { throw error.serverError('DB unavailable'); }
|
|
105
|
+
*/
|
|
106
|
+
readonly serverError: (message?: string) => import("./error.js").AppError;
|
|
107
|
+
/**
|
|
108
|
+
* Creates custom error with any status code
|
|
109
|
+
* @llm-rule WHEN: Need non-standard HTTP status codes
|
|
110
|
+
* @llm-rule NOTE: EXAMPLES: 429 rate limit, 503 maintenance, 418 teapot
|
|
111
|
+
* @llm-rule NOTE: PATTERN: error.createError(429, 'Rate limited', 'RATE_LIMIT');
|
|
112
|
+
*/
|
|
113
|
+
readonly createError: (statusCode: number, message: string, type?: string) => import("./error.js").AppError;
|
|
114
|
+
/**
|
|
115
|
+
* Express error handling middleware - handles all thrown errors
|
|
116
|
+
* @llm-rule WHEN: Setting up Express app - use as LAST middleware
|
|
117
|
+
* @llm-rule AVOID: Multiple error handlers - this should be the final one
|
|
118
|
+
* @llm-rule NOTE: EXPRESS SETUP: app.use(error.handleErrors()); // Must be last!
|
|
119
|
+
* @llm-rule NOTE: AUTO-FEATURES: dev vs prod responses, stack hiding, error logging
|
|
120
|
+
*/
|
|
121
|
+
readonly handleErrors: (options?: ErrorHandlerOptions) => import("./error.js").ExpressErrorHandler;
|
|
122
|
+
/**
|
|
123
|
+
* Async route wrapper - automatically catches thrown errors
|
|
124
|
+
* @llm-rule WHEN: Creating async Express routes that might throw errors
|
|
125
|
+
* @llm-rule AVOID: Manual try/catch in routes - this handles it automatically
|
|
126
|
+
* @llm-rule NOTE: ASYNC PATTERN: app.post('/api', error.asyncRoute(async (req, res) => {...}));
|
|
127
|
+
* @llm-rule NOTE: ERROR FLOW: throw error → asyncRoute catches → handleErrors processes
|
|
128
|
+
*/
|
|
129
|
+
readonly asyncRoute: (fn: AsyncRouteHandler) => (req: import("./error.js").ExpressRequest, res: import("./error.js").ExpressResponse, next: import("./error.js").ExpressNextFunction) => void;
|
|
130
|
+
/**
|
|
131
|
+
* Checks if error is 4xx client error
|
|
132
|
+
* @llm-rule WHEN: Categorizing errors for logging/metrics
|
|
133
|
+
* @llm-rule NOTE: CLIENT ERRORS: 400-499 (user's fault)
|
|
134
|
+
*/
|
|
135
|
+
readonly isClientError: (err: AppError) => boolean;
|
|
136
|
+
/**
|
|
137
|
+
* Checks if error is 5xx server error
|
|
138
|
+
* @llm-rule WHEN: Categorizing errors for monitoring/alerting
|
|
139
|
+
* @llm-rule NOTE: SERVER ERRORS: 500-599 (server's fault)
|
|
140
|
+
*/
|
|
141
|
+
readonly isServerError: (err: AppError) => boolean;
|
|
142
|
+
};
|
|
143
|
+
export type { ErrorConfig } from './defaults.js';
|
|
144
|
+
export { ErrorClass } from './error.js';
|
|
145
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/error/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAEnE,MAAM,WAAW,QAAS,SAAQ,KAAK;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,eAAe,CAAC;IAC1C,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,CAAC,KAAK,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,QAAQ,EACf,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,mBAAmB,KACtB,IAAI,CAAC;AAEV,MAAM,MAAM,iBAAiB,GAAG,CAC9B,GAAG,EAAE,cAAc,EACnB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,mBAAmB,KACtB,OAAO,CAAC,GAAG,CAAC,CAAC;AAElB,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAKD;;;;;;;GAOG;AACH,iBAAS,GAAG,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,UAAU,CAS7D;AAED;;;;;GAKG;AACH,iBAAS,KAAK,CAAC,SAAS,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,UAAU,CAK/D;AAED;;;;GAIG;AACH,iBAAS,UAAU,IAAI,IAAI,CAE1B;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU;;;;IASrB;;;;;OAKG;oCACoB,MAAM;IAE7B;;;;;OAKG;sCACsB,MAAM;IAE/B;;;;;OAKG;mCACmB,MAAM;IAE5B;;;;;OAKG;kCACkB,MAAM;IAE3B;;;;;OAKG;kCACkB,MAAM;IAE3B;;;;;OAKG;qCACqB,MAAM;IAE9B;;;;;OAKG;uCACuB,MAAM,WAAW,MAAM,SAAS,MAAM;IAGhE;;;;;;OAMG;sCACsB,mBAAmB;IAE5C;;;;;;OAMG;8BACc,iBAAiB;IAElC;;;;OAIG;kCACkB,QAAQ;IAE7B;;;;OAIG;kCACkB,QAAQ;CACrB,CAAC;AAGX,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ultra-simple semantic error handling that just works
|
|
3
|
+
* @module @bloomneo/appkit/error
|
|
4
|
+
* @file src/error/index.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: Building apps that need semantic HTTP error handling
|
|
7
|
+
* @llm-rule AVOID: Complex error setups with multiple libraries - this handles everything in one API
|
|
8
|
+
* @llm-rule NOTE: Provides semantic error creation (badRequest, unauthorized) and Express middleware
|
|
9
|
+
* @llm-rule NOTE: Common pattern - errorClass.get() → throw error.badRequest() → app.use(error.handleErrors())
|
|
10
|
+
* @llm-rule NOTE: COMPLETE SETUP: const error = errorClass.get(); app.use(error.handleErrors()); // Done!
|
|
11
|
+
*/
|
|
12
|
+
import { ErrorClass } from './error.js';
|
|
13
|
+
import { getSmartDefaults } from './defaults.js';
|
|
14
|
+
// Global error instance for performance
|
|
15
|
+
let globalError = null;
|
|
16
|
+
/**
|
|
17
|
+
* Get error instance - the only function you need to learn
|
|
18
|
+
* Environment variables parsed once for performance
|
|
19
|
+
* @llm-rule WHEN: Starting any error operation - this is your main entry point
|
|
20
|
+
* @llm-rule AVOID: Calling new ErrorClass() directly - always use this function
|
|
21
|
+
* @llm-rule NOTE: USAGE FLOW: get() → create errors → setup middleware → done
|
|
22
|
+
* @llm-rule NOTE: TYPICAL SETUP: const error = errorClass.get(); app.use(error.handleErrors());
|
|
23
|
+
*/
|
|
24
|
+
function get(overrides = {}) {
|
|
25
|
+
// Lazy initialization - parse environment once
|
|
26
|
+
if (!globalError) {
|
|
27
|
+
const defaults = getSmartDefaults();
|
|
28
|
+
const config = { ...defaults, ...overrides };
|
|
29
|
+
globalError = new ErrorClass(config);
|
|
30
|
+
}
|
|
31
|
+
return globalError;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reset global instance (useful for testing or config changes)
|
|
35
|
+
* @llm-rule WHEN: Testing error logic with different configurations
|
|
36
|
+
* @llm-rule AVOID: Using in production - only for tests and development
|
|
37
|
+
* @llm-rule NOTE: TEST PATTERN: const error = errorClass.reset({showStack: false}); // Clean slate
|
|
38
|
+
*/
|
|
39
|
+
function reset(newConfig = {}) {
|
|
40
|
+
const defaults = getSmartDefaults();
|
|
41
|
+
const config = { ...defaults, ...newConfig };
|
|
42
|
+
globalError = new ErrorClass(config);
|
|
43
|
+
return globalError;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Clear global instance cache (for testing)
|
|
47
|
+
* @llm-rule WHEN: Testing error configurations or between test suites
|
|
48
|
+
* @llm-rule AVOID: Using in production - only for tests
|
|
49
|
+
*/
|
|
50
|
+
function clearCache() {
|
|
51
|
+
globalError = null;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Single error export with semantic methods and Express integration
|
|
55
|
+
* @llm-rule NOTE: TWO USAGE PATTERNS: errorClass.get().badRequest() OR errorClass.badRequest() (shortcuts)
|
|
56
|
+
* @llm-rule NOTE: MIDDLEWARE PATTERN: app.use(error.handleErrors()); // Global error handling
|
|
57
|
+
*/
|
|
58
|
+
export const errorClass = {
|
|
59
|
+
// Core method
|
|
60
|
+
get,
|
|
61
|
+
// Utility methods
|
|
62
|
+
reset,
|
|
63
|
+
clearCache,
|
|
64
|
+
// Error creation shortcuts - automatically call get()
|
|
65
|
+
/**
|
|
66
|
+
* Creates 400 Bad Request error
|
|
67
|
+
* @llm-rule WHEN: Client input validation failures (missing/invalid data)
|
|
68
|
+
* @llm-rule NOTE: EXAMPLES: missing email, invalid JSON, malformed request
|
|
69
|
+
* @llm-rule NOTE: PATTERN: if (!email) throw error.badRequest('Email required');
|
|
70
|
+
*/
|
|
71
|
+
badRequest: (message) => get().badRequest(message),
|
|
72
|
+
/**
|
|
73
|
+
* Creates 401 Unauthorized error
|
|
74
|
+
* @llm-rule WHEN: Authentication required but missing or invalid
|
|
75
|
+
* @llm-rule NOTE: EXAMPLES: missing token, expired session, invalid credentials
|
|
76
|
+
* @llm-rule NOTE: PATTERN: if (!token) throw error.unauthorized('Login required');
|
|
77
|
+
*/
|
|
78
|
+
unauthorized: (message) => get().unauthorized(message),
|
|
79
|
+
/**
|
|
80
|
+
* Creates 403 Forbidden error
|
|
81
|
+
* @llm-rule WHEN: User authenticated but lacks permission for action
|
|
82
|
+
* @llm-rule NOTE: EXAMPLES: insufficient role, admin-only endpoint, blocked user
|
|
83
|
+
* @llm-rule NOTE: PATTERN: if (!user.isAdmin) throw error.forbidden('Admin only');
|
|
84
|
+
*/
|
|
85
|
+
forbidden: (message) => get().forbidden(message),
|
|
86
|
+
/**
|
|
87
|
+
* Creates 404 Not Found error
|
|
88
|
+
* @llm-rule WHEN: Requested resource does not exist in database/system
|
|
89
|
+
* @llm-rule NOTE: EXAMPLES: user not found, post not found, file missing
|
|
90
|
+
* @llm-rule NOTE: PATTERN: if (!user) throw error.notFound('User not found');
|
|
91
|
+
*/
|
|
92
|
+
notFound: (message) => get().notFound(message),
|
|
93
|
+
/**
|
|
94
|
+
* Creates 409 Conflict error
|
|
95
|
+
* @llm-rule WHEN: Business logic conflicts or duplicate resources
|
|
96
|
+
* @llm-rule NOTE: EXAMPLES: email already exists, username taken, state conflicts
|
|
97
|
+
* @llm-rule NOTE: PATTERN: if (existingUser) throw error.conflict('Email exists');
|
|
98
|
+
*/
|
|
99
|
+
conflict: (message) => get().conflict(message),
|
|
100
|
+
/**
|
|
101
|
+
* Creates 500 Server Error
|
|
102
|
+
* @llm-rule WHEN: Internal failures like database/API errors
|
|
103
|
+
* @llm-rule NOTE: EXAMPLES: database down, external API timeout, file system errors
|
|
104
|
+
* @llm-rule NOTE: PATTERN: catch (dbError) { throw error.serverError('DB unavailable'); }
|
|
105
|
+
*/
|
|
106
|
+
serverError: (message) => get().serverError(message),
|
|
107
|
+
/**
|
|
108
|
+
* Creates custom error with any status code
|
|
109
|
+
* @llm-rule WHEN: Need non-standard HTTP status codes
|
|
110
|
+
* @llm-rule NOTE: EXAMPLES: 429 rate limit, 503 maintenance, 418 teapot
|
|
111
|
+
* @llm-rule NOTE: PATTERN: error.createError(429, 'Rate limited', 'RATE_LIMIT');
|
|
112
|
+
*/
|
|
113
|
+
createError: (statusCode, message, type) => get().createError(statusCode, message, type),
|
|
114
|
+
// Middleware and utility shortcuts
|
|
115
|
+
/**
|
|
116
|
+
* Express error handling middleware - handles all thrown errors
|
|
117
|
+
* @llm-rule WHEN: Setting up Express app - use as LAST middleware
|
|
118
|
+
* @llm-rule AVOID: Multiple error handlers - this should be the final one
|
|
119
|
+
* @llm-rule NOTE: EXPRESS SETUP: app.use(error.handleErrors()); // Must be last!
|
|
120
|
+
* @llm-rule NOTE: AUTO-FEATURES: dev vs prod responses, stack hiding, error logging
|
|
121
|
+
*/
|
|
122
|
+
handleErrors: (options) => get().handleErrors(options),
|
|
123
|
+
/**
|
|
124
|
+
* Async route wrapper - automatically catches thrown errors
|
|
125
|
+
* @llm-rule WHEN: Creating async Express routes that might throw errors
|
|
126
|
+
* @llm-rule AVOID: Manual try/catch in routes - this handles it automatically
|
|
127
|
+
* @llm-rule NOTE: ASYNC PATTERN: app.post('/api', error.asyncRoute(async (req, res) => {...}));
|
|
128
|
+
* @llm-rule NOTE: ERROR FLOW: throw error → asyncRoute catches → handleErrors processes
|
|
129
|
+
*/
|
|
130
|
+
asyncRoute: (fn) => get().asyncRoute(fn),
|
|
131
|
+
/**
|
|
132
|
+
* Checks if error is 4xx client error
|
|
133
|
+
* @llm-rule WHEN: Categorizing errors for logging/metrics
|
|
134
|
+
* @llm-rule NOTE: CLIENT ERRORS: 400-499 (user's fault)
|
|
135
|
+
*/
|
|
136
|
+
isClientError: (err) => get().isClientError(err),
|
|
137
|
+
/**
|
|
138
|
+
* Checks if error is 5xx server error
|
|
139
|
+
* @llm-rule WHEN: Categorizing errors for monitoring/alerting
|
|
140
|
+
* @llm-rule NOTE: SERVER ERRORS: 500-599 (server's fault)
|
|
141
|
+
*/
|
|
142
|
+
isServerError: (err) => get().isServerError(err),
|
|
143
|
+
};
|
|
144
|
+
export { ErrorClass } from './error.js';
|
|
145
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/error/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAoB,MAAM,eAAe,CAAC;AAsCnE,wCAAwC;AACxC,IAAI,WAAW,GAAsB,IAAI,CAAC;AAE1C;;;;;;;GAOG;AACH,SAAS,GAAG,CAAC,YAAkC,EAAE;IAC/C,+CAA+C;IAC/C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;QACpC,MAAM,MAAM,GAAgB,EAAE,GAAG,QAAQ,EAAE,GAAG,SAAS,EAAE,CAAC;QAC1D,WAAW,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,SAAS,KAAK,CAAC,YAAkC,EAAE;IACjD,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,MAAM,MAAM,GAAgB,EAAE,GAAG,QAAQ,EAAE,GAAG,SAAS,EAAE,CAAC;IAC1D,WAAW,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;IACrC,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,SAAS,UAAU;IACjB,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,cAAc;IACd,GAAG;IAEH,kBAAkB;IAClB,KAAK;IACL,UAAU;IAEV,sDAAsD;IACtD;;;;;OAKG;IACH,UAAU,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;IAE3D;;;;;OAKG;IACH,YAAY,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;IAE/D;;;;;OAKG;IACH,SAAS,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC;IAEzD;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;IAEvD;;;;;OAKG;IACH,QAAQ,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC;IAEvD;;;;;OAKG;IACH,WAAW,EAAE,CAAC,OAAgB,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC;IAE7D;;;;;OAKG;IACH,WAAW,EAAE,CAAC,UAAkB,EAAE,OAAe,EAAE,IAAa,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC;IAEjH,mCAAmC;IACnC;;;;;;OAMG;IACH,YAAY,EAAE,CAAC,OAA6B,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC;IAE5E;;;;;;OAMG;IACH,UAAU,EAAE,CAAC,EAAqB,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;IAE3D;;;;OAIG;IACH,aAAa,EAAE,CAAC,GAAa,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC;IAE1D;;;;OAIG;IACH,aAAa,EAAE,CAAC,GAAa,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC;CAClD,CAAC;AAIX,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart defaults and environment validation for event system with auto-strategy detection
|
|
3
|
+
* @module @bloomneo/appkit/event
|
|
4
|
+
* @file src/event/defaults.ts
|
|
5
|
+
*
|
|
6
|
+
* @llm-rule WHEN: App startup - need to configure event system and connection strategy
|
|
7
|
+
* @llm-rule AVOID: Calling multiple times - expensive environment parsing, use lazy loading in get()
|
|
8
|
+
* @llm-rule NOTE: Called once at startup, cached globally for performance
|
|
9
|
+
* @llm-rule NOTE: Auto-detects Redis vs Memory based on REDIS_URL environment variable
|
|
10
|
+
*/
|
|
11
|
+
export interface RedisConfig {
|
|
12
|
+
url: string;
|
|
13
|
+
password?: string;
|
|
14
|
+
maxRetries: number;
|
|
15
|
+
retryDelay: number;
|
|
16
|
+
connectTimeout: number;
|
|
17
|
+
commandTimeout: number;
|
|
18
|
+
keyPrefix: string;
|
|
19
|
+
}
|
|
20
|
+
export interface MemoryConfig {
|
|
21
|
+
maxListeners: number;
|
|
22
|
+
maxHistory: number;
|
|
23
|
+
checkInterval: number;
|
|
24
|
+
enableGC: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface EventConfig {
|
|
27
|
+
strategy: 'redis' | 'memory';
|
|
28
|
+
namespace: string;
|
|
29
|
+
redis?: RedisConfig;
|
|
30
|
+
memory?: MemoryConfig;
|
|
31
|
+
history: {
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
maxSize: number;
|
|
34
|
+
};
|
|
35
|
+
environment: {
|
|
36
|
+
isDevelopment: boolean;
|
|
37
|
+
isProduction: boolean;
|
|
38
|
+
isTest: boolean;
|
|
39
|
+
nodeEnv: string;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Gets smart defaults using environment variables with auto-strategy detection
|
|
44
|
+
* @llm-rule WHEN: App startup to get production-ready event configuration
|
|
45
|
+
* @llm-rule AVOID: Calling repeatedly - expensive validation, cache the result
|
|
46
|
+
* @llm-rule NOTE: Auto-detects strategy: REDIS_URL → Redis, no REDIS_URL → Memory
|
|
47
|
+
*/
|
|
48
|
+
export declare function getSmartDefaults(): EventConfig;
|
|
49
|
+
/**
|
|
50
|
+
* Gets event configuration summary for debugging and health checks
|
|
51
|
+
* @llm-rule WHEN: Debugging event configuration or building health check endpoints
|
|
52
|
+
* @llm-rule AVOID: Exposing sensitive connection details - this only shows safe info
|
|
53
|
+
*/
|
|
54
|
+
export declare function getConfigSummary(): {
|
|
55
|
+
strategy: string;
|
|
56
|
+
namespace: string;
|
|
57
|
+
historyEnabled: boolean;
|
|
58
|
+
redisConnected: boolean;
|
|
59
|
+
environment: string;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Validates that required event configuration is present for production
|
|
63
|
+
* @llm-rule WHEN: App startup validation for production deployments
|
|
64
|
+
* @llm-rule AVOID: Skipping validation - missing event config causes runtime issues
|
|
65
|
+
*/
|
|
66
|
+
export declare function validateProductionRequirements(): void;
|
|
67
|
+
/**
|
|
68
|
+
* Validates startup configuration and throws detailed errors
|
|
69
|
+
* @llm-rule WHEN: App startup to ensure event configuration is valid before starting
|
|
70
|
+
* @llm-rule AVOID: Skipping validation - catches config issues early
|
|
71
|
+
* @llm-rule NOTE: Comprehensive validation for production readiness
|
|
72
|
+
*/
|
|
73
|
+
export declare function validateStartupConfiguration(): {
|
|
74
|
+
strategy: string;
|
|
75
|
+
warnings: string[];
|
|
76
|
+
errors: string[];
|
|
77
|
+
ready: boolean;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Performs comprehensive event system health check
|
|
81
|
+
* @llm-rule WHEN: Health check endpoints or monitoring systems
|
|
82
|
+
* @llm-rule AVOID: Running in critical path - this is for monitoring only
|
|
83
|
+
* @llm-rule NOTE: Returns detailed health status without exposing sensitive data
|
|
84
|
+
*/
|
|
85
|
+
export declare function performHealthCheck(): {
|
|
86
|
+
status: 'healthy' | 'warning' | 'error';
|
|
87
|
+
strategy: string;
|
|
88
|
+
configured: boolean;
|
|
89
|
+
issues: string[];
|
|
90
|
+
ready: boolean;
|
|
91
|
+
timestamp: string;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Gets optimal event configuration for different environments
|
|
95
|
+
* @llm-rule WHEN: Setting up environment-specific event behavior
|
|
96
|
+
* @llm-rule AVOID: Manual environment handling - this provides optimal defaults
|
|
97
|
+
*/
|
|
98
|
+
export declare function getEnvironmentOptimizedConfig(): EventConfig;
|
|
99
|
+
/**
|
|
100
|
+
* Checks if Redis is available and properly configured
|
|
101
|
+
* @llm-rule WHEN: Conditional logic based on event capabilities
|
|
102
|
+
* @llm-rule AVOID: Complex event detection - just use events normally, strategy handles it
|
|
103
|
+
*/
|
|
104
|
+
export declare function hasRedis(): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Gets recommended configuration for microservices
|
|
107
|
+
* @llm-rule WHEN: Setting up events for microservices architecture
|
|
108
|
+
* @llm-rule AVOID: Default config for microservices - needs specific tuning
|
|
109
|
+
*/
|
|
110
|
+
export declare function getMicroservicesConfig(): Partial<EventConfig>;
|
|
111
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/event/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,OAAO,EAAE;QACP,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,WAAW,EAAE;QACX,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,MAAM,EAAE,OAAO,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,CAmD9C;AAuJD;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;CACrB,CAUA;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,IAAI,IAAI,CAmBrD;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,IAAI;IAC9C,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;CAChB,CA0DA;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI;IACpC,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAsCA;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI,WAAW,CA4B3D;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAGlC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAAC,WAAW,CAAC,CAgB7D"}
|