@robthepcguy/rag-vault 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +24 -0
- package/README.md +421 -0
- package/dist/bin/install-skills.d.ts +20 -0
- package/dist/bin/install-skills.d.ts.map +1 -0
- package/dist/bin/install-skills.js +196 -0
- package/dist/bin/install-skills.js.map +1 -0
- package/dist/chunker/index.d.ts +11 -0
- package/dist/chunker/index.d.ts.map +1 -0
- package/dist/chunker/index.js +6 -0
- package/dist/chunker/index.js.map +1 -0
- package/dist/chunker/semantic-chunker.d.ts +96 -0
- package/dist/chunker/semantic-chunker.d.ts.map +1 -0
- package/dist/chunker/semantic-chunker.js +267 -0
- package/dist/chunker/semantic-chunker.js.map +1 -0
- package/dist/chunker/sentence-splitter.d.ts +16 -0
- package/dist/chunker/sentence-splitter.d.ts.map +1 -0
- package/dist/chunker/sentence-splitter.js +114 -0
- package/dist/chunker/sentence-splitter.js.map +1 -0
- package/dist/embedder/index.d.ts +55 -0
- package/dist/embedder/index.d.ts.map +1 -0
- package/dist/embedder/index.js +146 -0
- package/dist/embedder/index.js.map +1 -0
- package/dist/errors/index.d.ts +73 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +170 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/html-parser.d.ts +14 -0
- package/dist/parser/html-parser.d.ts.map +1 -0
- package/dist/parser/html-parser.js +99 -0
- package/dist/parser/html-parser.js.map +1 -0
- package/dist/parser/index.d.ts +144 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +446 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/pdf-filter.d.ts +89 -0
- package/dist/parser/pdf-filter.d.ts.map +1 -0
- package/dist/parser/pdf-filter.js +304 -0
- package/dist/parser/pdf-filter.js.map +1 -0
- package/dist/server/index.d.ts +144 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +518 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/raw-data-utils.d.ts +81 -0
- package/dist/server/raw-data-utils.d.ts.map +1 -0
- package/dist/server/raw-data-utils.js +196 -0
- package/dist/server/raw-data-utils.js.map +1 -0
- package/dist/server/schemas.d.ts +186 -0
- package/dist/server/schemas.d.ts.map +1 -0
- package/dist/server/schemas.js +99 -0
- package/dist/server/schemas.js.map +1 -0
- package/dist/utils/config-parsers.d.ts +14 -0
- package/dist/utils/config-parsers.d.ts.map +1 -0
- package/dist/utils/config-parsers.js +47 -0
- package/dist/utils/config-parsers.js.map +1 -0
- package/dist/utils/config.d.ts +37 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +52 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +64 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/math.d.ts +34 -0
- package/dist/utils/math.d.ts.map +1 -0
- package/dist/utils/math.js +73 -0
- package/dist/utils/math.js.map +1 -0
- package/dist/utils/process-handlers.d.ts +26 -0
- package/dist/utils/process-handlers.d.ts.map +1 -0
- package/dist/utils/process-handlers.js +69 -0
- package/dist/utils/process-handlers.js.map +1 -0
- package/dist/vectordb/index.d.ts +210 -0
- package/dist/vectordb/index.d.ts.map +1 -0
- package/dist/vectordb/index.js +613 -0
- package/dist/vectordb/index.js.map +1 -0
- package/dist/web/api-routes.d.ts +9 -0
- package/dist/web/api-routes.d.ts.map +1 -0
- package/dist/web/api-routes.js +127 -0
- package/dist/web/api-routes.js.map +1 -0
- package/dist/web/config-routes.d.ts +7 -0
- package/dist/web/config-routes.d.ts.map +1 -0
- package/dist/web/config-routes.js +54 -0
- package/dist/web/config-routes.js.map +1 -0
- package/dist/web/database-manager.d.ts +130 -0
- package/dist/web/database-manager.d.ts.map +1 -0
- package/dist/web/database-manager.js +382 -0
- package/dist/web/database-manager.js.map +1 -0
- package/dist/web/http-server.d.ts +28 -0
- package/dist/web/http-server.d.ts.map +1 -0
- package/dist/web/http-server.js +311 -0
- package/dist/web/http-server.js.map +1 -0
- package/dist/web/index.d.ts +3 -0
- package/dist/web/index.d.ts.map +1 -0
- package/dist/web/index.js +114 -0
- package/dist/web/index.js.map +1 -0
- package/dist/web/middleware/async-handler.d.ts +17 -0
- package/dist/web/middleware/async-handler.d.ts.map +1 -0
- package/dist/web/middleware/async-handler.js +26 -0
- package/dist/web/middleware/async-handler.js.map +1 -0
- package/dist/web/middleware/auth.d.ts +22 -0
- package/dist/web/middleware/auth.d.ts.map +1 -0
- package/dist/web/middleware/auth.js +81 -0
- package/dist/web/middleware/auth.js.map +1 -0
- package/dist/web/middleware/error-handler.d.ts +36 -0
- package/dist/web/middleware/error-handler.d.ts.map +1 -0
- package/dist/web/middleware/error-handler.js +68 -0
- package/dist/web/middleware/error-handler.js.map +1 -0
- package/dist/web/middleware/index.d.ts +6 -0
- package/dist/web/middleware/index.d.ts.map +1 -0
- package/dist/web/middleware/index.js +19 -0
- package/dist/web/middleware/index.js.map +1 -0
- package/dist/web/middleware/rate-limit.d.ts +38 -0
- package/dist/web/middleware/rate-limit.d.ts.map +1 -0
- package/dist/web/middleware/rate-limit.js +116 -0
- package/dist/web/middleware/rate-limit.js.map +1 -0
- package/dist/web/middleware/request-logger.d.ts +52 -0
- package/dist/web/middleware/request-logger.d.ts.map +1 -0
- package/dist/web/middleware/request-logger.js +74 -0
- package/dist/web/middleware/request-logger.js.map +1 -0
- package/dist/web/types.d.ts +6 -0
- package/dist/web/types.d.ts.map +1 -0
- package/dist/web/types.js +4 -0
- package/dist/web/types.js.map +1 -0
- package/package.json +135 -0
- package/skills/rag-vault/SKILL.md +111 -0
- package/skills/rag-vault/references/html-ingestion.md +73 -0
- package/skills/rag-vault/references/query-optimization.md +57 -0
- package/skills/rag-vault/references/result-refinement.md +54 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// HTTP server for web frontend
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.createHttpServerWithManager = createHttpServerWithManager;
|
|
41
|
+
exports.createHttpServer = createHttpServer;
|
|
42
|
+
exports.startServer = startServer;
|
|
43
|
+
const node_crypto_1 = require("node:crypto");
|
|
44
|
+
const node_fs_1 = require("node:fs");
|
|
45
|
+
const promises_1 = require("node:fs/promises");
|
|
46
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
47
|
+
const compression_1 = __importDefault(require("compression"));
|
|
48
|
+
const cors_1 = __importDefault(require("cors"));
|
|
49
|
+
const express_1 = __importDefault(require("express"));
|
|
50
|
+
const file_type_1 = require("file-type");
|
|
51
|
+
const helmet_1 = __importDefault(require("helmet"));
|
|
52
|
+
const multer_1 = __importDefault(require("multer"));
|
|
53
|
+
const api_routes_js_1 = require("./api-routes.js");
|
|
54
|
+
const config_routes_js_1 = require("./config-routes.js");
|
|
55
|
+
const index_js_1 = require("./middleware/index.js");
|
|
56
|
+
// ============================================
|
|
57
|
+
// Constants
|
|
58
|
+
// ============================================
|
|
59
|
+
/** Default JSON body limit (5MB) - prevents DoS from large payloads */
|
|
60
|
+
const DEFAULT_JSON_LIMIT = '5mb';
|
|
61
|
+
/** Default allowed CORS origins (localhost only for security) */
|
|
62
|
+
const DEFAULT_CORS_ORIGINS = [
|
|
63
|
+
'http://localhost:5173',
|
|
64
|
+
'http://localhost:3000',
|
|
65
|
+
'http://127.0.0.1:5173',
|
|
66
|
+
'http://127.0.0.1:3000',
|
|
67
|
+
];
|
|
68
|
+
/** File size limit for uploads (100MB) */
|
|
69
|
+
const FILE_SIZE_LIMIT_BYTES = 100 * 1024 * 1024;
|
|
70
|
+
/** Default request timeout (30 seconds) */
|
|
71
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 30000;
|
|
72
|
+
/** Minimum allowed request timeout (1 second) */
|
|
73
|
+
const MIN_REQUEST_TIMEOUT_MS = 1000;
|
|
74
|
+
/**
|
|
75
|
+
* Get request timeout from environment variable or use default
|
|
76
|
+
* @returns Request timeout in milliseconds
|
|
77
|
+
*/
|
|
78
|
+
function getRequestTimeoutMs() {
|
|
79
|
+
const envValue = process.env['REQUEST_TIMEOUT_MS'];
|
|
80
|
+
if (!envValue)
|
|
81
|
+
return DEFAULT_REQUEST_TIMEOUT_MS;
|
|
82
|
+
const parsed = Number.parseInt(envValue, 10);
|
|
83
|
+
if (Number.isNaN(parsed) || parsed < MIN_REQUEST_TIMEOUT_MS) {
|
|
84
|
+
console.warn(`Invalid REQUEST_TIMEOUT_MS value "${envValue}". Using default ${DEFAULT_REQUEST_TIMEOUT_MS}ms.`);
|
|
85
|
+
return DEFAULT_REQUEST_TIMEOUT_MS;
|
|
86
|
+
}
|
|
87
|
+
return parsed;
|
|
88
|
+
}
|
|
89
|
+
/** Allowed MIME types for file uploads (validated by magic bytes) */
|
|
90
|
+
const ALLOWED_MIME_TYPES = [
|
|
91
|
+
'application/pdf',
|
|
92
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
93
|
+
'text/plain',
|
|
94
|
+
'text/markdown',
|
|
95
|
+
'text/html',
|
|
96
|
+
'application/json',
|
|
97
|
+
];
|
|
98
|
+
/**
|
|
99
|
+
* Create and configure Express app with DatabaseManager
|
|
100
|
+
*/
|
|
101
|
+
async function createHttpServerWithManager(dbManager, config) {
|
|
102
|
+
// Create server accessor
|
|
103
|
+
const serverAccessor = () => {
|
|
104
|
+
return dbManager.getServer();
|
|
105
|
+
};
|
|
106
|
+
// Create config router to add before error handlers
|
|
107
|
+
const configRouter = (0, config_routes_js_1.createConfigRouter)(dbManager);
|
|
108
|
+
const app = await createHttpServerInternal(serverAccessor, config, configRouter);
|
|
109
|
+
return app;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create and configure Express app (legacy - direct RAGServer)
|
|
113
|
+
*/
|
|
114
|
+
async function createHttpServer(ragServer, config) {
|
|
115
|
+
return createHttpServerInternal(() => ragServer, config);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Internal function to create Express app
|
|
119
|
+
*/
|
|
120
|
+
/**
|
|
121
|
+
* Validate file content using magic bytes
|
|
122
|
+
* Returns true if file type is allowed, false otherwise
|
|
123
|
+
*/
|
|
124
|
+
async function validateFileContent(filePath) {
|
|
125
|
+
try {
|
|
126
|
+
const buffer = await (0, promises_1.readFile)(filePath);
|
|
127
|
+
const type = await (0, file_type_1.fileTypeFromBuffer)(buffer);
|
|
128
|
+
// Allow text files which may not have magic bytes
|
|
129
|
+
if (!type) {
|
|
130
|
+
// Check if it's likely a text file by looking for common text patterns
|
|
131
|
+
const sample = buffer.subarray(0, 1024).toString('utf-8');
|
|
132
|
+
const isLikelyText = !sample.includes('\x00'); // No null bytes
|
|
133
|
+
return isLikelyText;
|
|
134
|
+
}
|
|
135
|
+
return ALLOWED_MIME_TYPES.includes(type.mime);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Request timeout middleware
|
|
143
|
+
* Aborts requests that take longer than the specified timeout
|
|
144
|
+
*/
|
|
145
|
+
function requestTimeout(timeoutMs) {
|
|
146
|
+
return (_req, res, next) => {
|
|
147
|
+
const timeoutId = setTimeout(() => {
|
|
148
|
+
if (!res.headersSent) {
|
|
149
|
+
res.status(503).json({
|
|
150
|
+
error: 'Request timeout',
|
|
151
|
+
code: 'REQUEST_TIMEOUT',
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}, timeoutMs);
|
|
155
|
+
res.on('finish', () => clearTimeout(timeoutId));
|
|
156
|
+
res.on('close', () => clearTimeout(timeoutId));
|
|
157
|
+
next();
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Parse CORS origins from environment variable with validation
|
|
162
|
+
*/
|
|
163
|
+
function parseCorsOrigins(env) {
|
|
164
|
+
if (!env || env.trim() === '')
|
|
165
|
+
return DEFAULT_CORS_ORIGINS;
|
|
166
|
+
if (env === '*') {
|
|
167
|
+
console.warn('[SECURITY] CORS_ORIGINS="*" allows all origins. This is not recommended for production environments.');
|
|
168
|
+
return '*';
|
|
169
|
+
}
|
|
170
|
+
return env
|
|
171
|
+
.split(',')
|
|
172
|
+
.map((o) => o.trim())
|
|
173
|
+
.filter(Boolean);
|
|
174
|
+
}
|
|
175
|
+
async function createHttpServerInternal(serverAccessor, config, configRouter) {
|
|
176
|
+
const app = (0, express_1.default)();
|
|
177
|
+
// Security headers (helmet)
|
|
178
|
+
app.use((0, helmet_1.default)({
|
|
179
|
+
contentSecurityPolicy: {
|
|
180
|
+
directives: {
|
|
181
|
+
defaultSrc: ["'self'"],
|
|
182
|
+
scriptSrc: ["'self'"],
|
|
183
|
+
styleSrc: ["'self'", "'unsafe-inline'"], // For Tailwind CSS
|
|
184
|
+
imgSrc: ["'self'", 'data:'],
|
|
185
|
+
connectSrc: ["'self'"],
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
}));
|
|
189
|
+
// Response compression
|
|
190
|
+
app.use((0, compression_1.default)());
|
|
191
|
+
// Request timeout for API routes (configurable via REQUEST_TIMEOUT_MS env var)
|
|
192
|
+
app.use('/api', requestTimeout(getRequestTimeoutMs()));
|
|
193
|
+
// CORS configuration
|
|
194
|
+
// CORS_ORIGINS env var: comma-separated list of allowed origins, or "*" for all
|
|
195
|
+
const corsOrigins = parseCorsOrigins(process.env['CORS_ORIGINS']);
|
|
196
|
+
app.use((0, cors_1.default)({
|
|
197
|
+
origin: corsOrigins,
|
|
198
|
+
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
|
|
199
|
+
allowedHeaders: ['Content-Type', 'Authorization', 'X-API-Key'],
|
|
200
|
+
}));
|
|
201
|
+
// JSON body parser with size limit to prevent DoS
|
|
202
|
+
const jsonLimit = process.env['JSON_BODY_LIMIT'] || DEFAULT_JSON_LIMIT;
|
|
203
|
+
app.use(express_1.default.json({ limit: jsonLimit }));
|
|
204
|
+
// Request ID tracking for tracing and debugging
|
|
205
|
+
app.use((req, res, next) => {
|
|
206
|
+
const requestId = req.headers['x-request-id'] || (0, node_crypto_1.randomUUID)();
|
|
207
|
+
res.setHeader('X-Request-ID', requestId);
|
|
208
|
+
next();
|
|
209
|
+
});
|
|
210
|
+
// Request logging (enabled when REQUEST_LOGGING=true)
|
|
211
|
+
if ((0, index_js_1.isRequestLoggingEnabled)()) {
|
|
212
|
+
app.use((0, index_js_1.createRequestLogger)());
|
|
213
|
+
}
|
|
214
|
+
// Rate limiting (configurable via RATE_LIMIT_* env vars)
|
|
215
|
+
const rateLimitConfig = (0, index_js_1.getRateLimitConfigFromEnv)();
|
|
216
|
+
app.use('/api', (0, index_js_1.createRateLimiter)(rateLimitConfig));
|
|
217
|
+
// API Key authentication (enabled when RAG_API_KEY env var is set)
|
|
218
|
+
app.use('/api', index_js_1.apiKeyAuth);
|
|
219
|
+
// Ensure upload directory exists
|
|
220
|
+
if (!(0, node_fs_1.existsSync)(config.uploadDir)) {
|
|
221
|
+
await (0, promises_1.mkdir)(config.uploadDir, { recursive: true });
|
|
222
|
+
}
|
|
223
|
+
// Configure multer for file uploads
|
|
224
|
+
const storage = multer_1.default.diskStorage({
|
|
225
|
+
destination: (_req, _file, cb) => {
|
|
226
|
+
cb(null, config.uploadDir);
|
|
227
|
+
},
|
|
228
|
+
filename: (_req, file, cb) => {
|
|
229
|
+
// Preserve original filename with timestamp prefix
|
|
230
|
+
const timestamp = Date.now();
|
|
231
|
+
const safeName = file.originalname.replace(/[^a-zA-Z0-9.-]/g, '_');
|
|
232
|
+
cb(null, `${timestamp}-${safeName}`);
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
const upload = (0, multer_1.default)({
|
|
236
|
+
storage,
|
|
237
|
+
limits: {
|
|
238
|
+
fileSize: FILE_SIZE_LIMIT_BYTES,
|
|
239
|
+
},
|
|
240
|
+
fileFilter: (_req, file, cb) => {
|
|
241
|
+
// Allow common document types by MIME type or extension
|
|
242
|
+
const allowedExtensions = ['.pdf', '.docx', '.txt', '.md', '.html', '.json'];
|
|
243
|
+
const ext = node_path_1.default.extname(file.originalname).toLowerCase();
|
|
244
|
+
if (ALLOWED_MIME_TYPES.includes(file.mimetype) || allowedExtensions.includes(ext)) {
|
|
245
|
+
cb(null, true);
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
cb(new Error(`File type not allowed: ${file.mimetype}`));
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
// API routes
|
|
253
|
+
const apiRouter = (0, api_routes_js_1.createApiRouter)(serverAccessor);
|
|
254
|
+
// Apply multer middleware to upload endpoint with magic byte validation
|
|
255
|
+
app.use('/api/v1/files/upload', upload.single('file'), async (req, res, next) => {
|
|
256
|
+
// Multer adds file to req.file
|
|
257
|
+
const file = req.file;
|
|
258
|
+
if (file) {
|
|
259
|
+
// Validate file content using magic bytes
|
|
260
|
+
const isValid = await validateFileContent(file.path);
|
|
261
|
+
if (!isValid) {
|
|
262
|
+
// Delete the uploaded file
|
|
263
|
+
const { unlink } = await Promise.resolve().then(() => __importStar(require('node:fs/promises')));
|
|
264
|
+
try {
|
|
265
|
+
await unlink(file.path);
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
// Ignore deletion errors
|
|
269
|
+
}
|
|
270
|
+
res.status(400).json({
|
|
271
|
+
error: 'File content does not match allowed types',
|
|
272
|
+
code: 'INVALID_FILE_CONTENT',
|
|
273
|
+
});
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
next();
|
|
278
|
+
});
|
|
279
|
+
app.use('/api/v1', apiRouter);
|
|
280
|
+
// Add config routes if provided (must be before error handlers)
|
|
281
|
+
if (configRouter) {
|
|
282
|
+
app.use('/api/v1/config', configRouter);
|
|
283
|
+
}
|
|
284
|
+
// Serve static files in production
|
|
285
|
+
if (config.staticDir && (0, node_fs_1.existsSync)(config.staticDir)) {
|
|
286
|
+
app.use(express_1.default.static(config.staticDir));
|
|
287
|
+
// SPA fallback - serve index.html for all non-API routes
|
|
288
|
+
app.get('*', (req, res) => {
|
|
289
|
+
if (!req.path.startsWith('/api/')) {
|
|
290
|
+
res.sendFile(node_path_1.default.join(config.staticDir, 'index.html'));
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
// 404 handler for API routes
|
|
295
|
+
app.use('/api/*', index_js_1.notFoundHandler);
|
|
296
|
+
// Error handling middleware
|
|
297
|
+
app.use(index_js_1.errorHandler);
|
|
298
|
+
return app;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Start HTTP server
|
|
302
|
+
*/
|
|
303
|
+
function startServer(app, port) {
|
|
304
|
+
return new Promise((resolve) => {
|
|
305
|
+
app.listen(port, () => {
|
|
306
|
+
console.log(`Web server running at http://localhost:${port}`);
|
|
307
|
+
resolve();
|
|
308
|
+
});
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=http-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-server.js","sourceRoot":"","sources":["../../src/web/http-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
// Entry point for RAG Web Server
|
|
4
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
5
|
+
if (k2 === undefined) k2 = k;
|
|
6
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
7
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
8
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
9
|
+
}
|
|
10
|
+
Object.defineProperty(o, k2, desc);
|
|
11
|
+
}) : (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
o[k2] = m[k];
|
|
14
|
+
}));
|
|
15
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
16
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
17
|
+
}) : function(o, v) {
|
|
18
|
+
o["default"] = v;
|
|
19
|
+
});
|
|
20
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
21
|
+
var ownKeys = function(o) {
|
|
22
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
23
|
+
var ar = [];
|
|
24
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
25
|
+
return ar;
|
|
26
|
+
};
|
|
27
|
+
return ownKeys(o);
|
|
28
|
+
};
|
|
29
|
+
return function (mod) {
|
|
30
|
+
if (mod && mod.__esModule) return mod;
|
|
31
|
+
var result = {};
|
|
32
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
33
|
+
__setModuleDefault(result, mod);
|
|
34
|
+
return result;
|
|
35
|
+
};
|
|
36
|
+
})();
|
|
37
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
38
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
39
|
+
};
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
const node_fs_1 = require("node:fs");
|
|
42
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
43
|
+
const config_js_1 = require("../utils/config.js");
|
|
44
|
+
const process_handlers_js_1 = require("../utils/process-handlers.js");
|
|
45
|
+
const index_js_1 = require("./middleware/index.js");
|
|
46
|
+
// Setup global error handlers
|
|
47
|
+
(0, process_handlers_js_1.setupProcessHandlers)();
|
|
48
|
+
// Setup graceful shutdown
|
|
49
|
+
(0, process_handlers_js_1.setupGracefulShutdown)();
|
|
50
|
+
// Register rate limiter cleanup for graceful shutdown
|
|
51
|
+
(0, process_handlers_js_1.onShutdown)(() => {
|
|
52
|
+
console.error('Cleaning up rate limiter...');
|
|
53
|
+
(0, index_js_1.stopRateLimiterCleanup)();
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* Entry point - Start RAG Web Server
|
|
57
|
+
*/
|
|
58
|
+
async function main() {
|
|
59
|
+
try {
|
|
60
|
+
// Dynamic imports to avoid loading heavy modules at CLI parse time
|
|
61
|
+
const { RAGServer } = await Promise.resolve().then(() => __importStar(require('../server/index.js')));
|
|
62
|
+
const { createHttpServerWithManager, startServer } = await Promise.resolve().then(() => __importStar(require('./http-server.js')));
|
|
63
|
+
const { DatabaseManager } = await Promise.resolve().then(() => __importStar(require('./database-manager.js')));
|
|
64
|
+
// Configuration from environment
|
|
65
|
+
const port = Number.parseInt(process.env['WEB_PORT'] || '3000', 10);
|
|
66
|
+
const uploadDir = process.env['UPLOAD_DIR'] || './uploads/';
|
|
67
|
+
// Determine static files directory
|
|
68
|
+
// Check relative to cwd for development and relative to dist for production
|
|
69
|
+
let staticDir;
|
|
70
|
+
const cwd = process.cwd();
|
|
71
|
+
const devStaticPath = node_path_1.default.resolve(cwd, 'web-ui/dist');
|
|
72
|
+
const prodStaticPath = node_path_1.default.resolve(cwd, 'dist/web-ui');
|
|
73
|
+
// Check which exists
|
|
74
|
+
if ((0, node_fs_1.existsSync)(devStaticPath)) {
|
|
75
|
+
staticDir = devStaticPath;
|
|
76
|
+
}
|
|
77
|
+
else if ((0, node_fs_1.existsSync)(prodStaticPath)) {
|
|
78
|
+
staticDir = prodStaticPath;
|
|
79
|
+
}
|
|
80
|
+
// Build RAG config from environment
|
|
81
|
+
const config = (0, config_js_1.buildRAGConfig)();
|
|
82
|
+
console.log('Starting RAG Web Server...');
|
|
83
|
+
console.log('Configuration:', { ...config, port, uploadDir, staticDir });
|
|
84
|
+
// Create DatabaseManager with server factory
|
|
85
|
+
const { dbPath, ...baseConfig } = config;
|
|
86
|
+
const dbManager = new DatabaseManager((cfg) => new RAGServer(cfg), baseConfig);
|
|
87
|
+
// Initialize with the configured database
|
|
88
|
+
await dbManager.initialize(dbPath);
|
|
89
|
+
// Create and start HTTP server with DatabaseManager
|
|
90
|
+
const httpConfig = {
|
|
91
|
+
port,
|
|
92
|
+
uploadDir,
|
|
93
|
+
};
|
|
94
|
+
if (staticDir !== undefined) {
|
|
95
|
+
httpConfig.staticDir = staticDir;
|
|
96
|
+
}
|
|
97
|
+
const app = await createHttpServerWithManager(dbManager, httpConfig);
|
|
98
|
+
await startServer(app, port);
|
|
99
|
+
console.log('RAG Web Server started successfully');
|
|
100
|
+
if (staticDir) {
|
|
101
|
+
console.log(`Serving UI from: ${staticDir}`);
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
console.log('No UI build found. Run "pnpm ui:build" to build the frontend.');
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
console.error('Failed to start RAG Web Server:', error);
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Execute main
|
|
113
|
+
main();
|
|
114
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/web/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Async request handler type
|
|
4
|
+
*/
|
|
5
|
+
export type AsyncHandler = (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Wraps an async route handler to automatically catch errors
|
|
8
|
+
* and pass them to Express error middleware
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* router.post('/search', asyncHandler(async (req, res) => {
|
|
12
|
+
* const results = await search(req.body.query)
|
|
13
|
+
* res.json({ results })
|
|
14
|
+
* }))
|
|
15
|
+
*/
|
|
16
|
+
export declare function asyncHandler(handler: AsyncHandler): AsyncHandler;
|
|
17
|
+
//# sourceMappingURL=async-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-handler.d.ts","sourceRoot":"","sources":["../../../src/web/middleware/async-handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAE9D;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAE7F;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,YAAY,GAAG,YAAY,CAQhE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Express async handler wrapper
|
|
3
|
+
// Eliminates try/catch boilerplate in route handlers
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.asyncHandler = asyncHandler;
|
|
6
|
+
/**
|
|
7
|
+
* Wraps an async route handler to automatically catch errors
|
|
8
|
+
* and pass them to Express error middleware
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* router.post('/search', asyncHandler(async (req, res) => {
|
|
12
|
+
* const results = await search(req.body.query)
|
|
13
|
+
* res.json({ results })
|
|
14
|
+
* }))
|
|
15
|
+
*/
|
|
16
|
+
function asyncHandler(handler) {
|
|
17
|
+
return async (req, res, next) => {
|
|
18
|
+
try {
|
|
19
|
+
await handler(req, res, next);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
next(error);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=async-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"async-handler.js","sourceRoot":"","sources":["../../../src/web/middleware/async-handler.ts"],"names":[],"mappings":";AAAA,gCAAgC;AAChC,qDAAqD;;AAmBrD,oCAQC;AAlBD;;;;;;;;;GASG;AACH,SAAgB,YAAY,CAAC,OAAqB;IAChD,OAAO,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAiB,EAAE;QAC9E,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAA;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,CAAA;QACb,CAAC;IACH,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* API Key authentication middleware
|
|
4
|
+
*
|
|
5
|
+
* Validates requests against RAG_API_KEY environment variable.
|
|
6
|
+
* If RAG_API_KEY is not set, authentication is disabled (local-only mode).
|
|
7
|
+
*
|
|
8
|
+
* Accepts API key via:
|
|
9
|
+
* - Authorization header: "Bearer <key>" or "ApiKey <key>"
|
|
10
|
+
* - X-API-Key header
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // Enable by setting environment variable
|
|
14
|
+
* RAG_API_KEY=your-secret-key npm start
|
|
15
|
+
*
|
|
16
|
+
* // Client usage
|
|
17
|
+
* fetch('/api/v1/search', {
|
|
18
|
+
* headers: { 'Authorization': 'Bearer your-secret-key' }
|
|
19
|
+
* })
|
|
20
|
+
*/
|
|
21
|
+
export declare function apiKeyAuth(req: Request, res: Response, next: NextFunction): void;
|
|
22
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/web/middleware/auth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAE9D;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAoChF"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// API Key authentication middleware
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.apiKeyAuth = apiKeyAuth;
|
|
5
|
+
const node_crypto_1 = require("node:crypto");
|
|
6
|
+
/**
|
|
7
|
+
* API Key authentication middleware
|
|
8
|
+
*
|
|
9
|
+
* Validates requests against RAG_API_KEY environment variable.
|
|
10
|
+
* If RAG_API_KEY is not set, authentication is disabled (local-only mode).
|
|
11
|
+
*
|
|
12
|
+
* Accepts API key via:
|
|
13
|
+
* - Authorization header: "Bearer <key>" or "ApiKey <key>"
|
|
14
|
+
* - X-API-Key header
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Enable by setting environment variable
|
|
18
|
+
* RAG_API_KEY=your-secret-key npm start
|
|
19
|
+
*
|
|
20
|
+
* // Client usage
|
|
21
|
+
* fetch('/api/v1/search', {
|
|
22
|
+
* headers: { 'Authorization': 'Bearer your-secret-key' }
|
|
23
|
+
* })
|
|
24
|
+
*/
|
|
25
|
+
function apiKeyAuth(req, res, next) {
|
|
26
|
+
const configuredKey = process.env['RAG_API_KEY'];
|
|
27
|
+
// If no API key configured, skip authentication (local-only mode)
|
|
28
|
+
if (!configuredKey) {
|
|
29
|
+
next();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Extract API key from request
|
|
33
|
+
const authHeader = req.headers['authorization'];
|
|
34
|
+
const xApiKey = req.headers['x-api-key'];
|
|
35
|
+
let providedKey;
|
|
36
|
+
if (authHeader) {
|
|
37
|
+
// Support "Bearer <key>" and "ApiKey <key>" formats
|
|
38
|
+
const match = authHeader.match(/^(?:Bearer|ApiKey)\s+(.+)$/i);
|
|
39
|
+
if (match?.[1]) {
|
|
40
|
+
providedKey = match[1];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
else if (typeof xApiKey === 'string') {
|
|
44
|
+
providedKey = xApiKey;
|
|
45
|
+
}
|
|
46
|
+
// Validate API key using timing-safe comparison
|
|
47
|
+
if (!providedKey || !safeCompare(providedKey, configuredKey)) {
|
|
48
|
+
res.status(401).json({
|
|
49
|
+
error: 'Unauthorized',
|
|
50
|
+
code: 'AUTH_REQUIRED',
|
|
51
|
+
message: 'Valid API key required. Set RAG_API_KEY environment variable.',
|
|
52
|
+
});
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
next();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Timing-safe string comparison to prevent timing attacks
|
|
59
|
+
*
|
|
60
|
+
* Uses Node.js crypto.timingSafeEqual with padding to prevent length leaks.
|
|
61
|
+
* Both strings are padded to the same length before comparison.
|
|
62
|
+
* Length comparison is computed BEFORE timing-safe comparison to prevent
|
|
63
|
+
* timing leaks from short-circuit evaluation.
|
|
64
|
+
*/
|
|
65
|
+
function safeCompare(a, b) {
|
|
66
|
+
const bufA = Buffer.from(a);
|
|
67
|
+
const bufB = Buffer.from(b);
|
|
68
|
+
// Compute length match FIRST (constant time for number comparison)
|
|
69
|
+
// This prevents timing leaks from short-circuit evaluation
|
|
70
|
+
const lengthsMatch = bufA.length === bufB.length;
|
|
71
|
+
// Pad to same length to prevent length timing leak in content comparison
|
|
72
|
+
const maxLen = Math.max(bufA.length, bufB.length);
|
|
73
|
+
const padA = Buffer.alloc(maxLen);
|
|
74
|
+
const padB = Buffer.alloc(maxLen);
|
|
75
|
+
bufA.copy(padA);
|
|
76
|
+
bufB.copy(padB);
|
|
77
|
+
// Use Node.js timing-safe comparison and verify original lengths match
|
|
78
|
+
// lengthsMatch is already computed, so no timing leak from && evaluation
|
|
79
|
+
return (0, node_crypto_1.timingSafeEqual)(padA, padB) && lengthsMatch;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/web/middleware/auth.ts"],"names":[],"mappings":";AAAA,oCAAoC;;AAwBpC,gCAoCC;AA1DD,6CAA6C;AAG7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,UAAU,CAAC,GAAY,EAAE,GAAa,EAAE,IAAkB;IACxE,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;IAEhD,kEAAkE;IAClE,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,IAAI,EAAE,CAAA;QACN,OAAM;IACR,CAAC;IAED,+BAA+B;IAC/B,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;IAC/C,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IAExC,IAAI,WAA+B,CAAA;IAEnC,IAAI,UAAU,EAAE,CAAC;QACf,oDAAoD;QACpD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;QAC7D,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACf,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QACxB,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QACvC,WAAW,GAAG,OAAO,CAAA;IACvB,CAAC;IAED,gDAAgD;IAChD,IAAI,CAAC,WAAW,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,aAAa,CAAC,EAAE,CAAC;QAC7D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC;YACnB,KAAK,EAAE,cAAc;YACrB,IAAI,EAAE,eAAe;YACrB,OAAO,EAAE,+DAA+D;SACzE,CAAC,CAAA;QACF,OAAM;IACR,CAAC;IAED,IAAI,EAAE,CAAA;AACR,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACvC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC3B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAE3B,mEAAmE;IACnE,2DAA2D;IAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAA;IAEhD,yEAAyE;IACzE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACjD,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IACjC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACf,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAEf,uEAAuE;IACvE,yEAAyE;IACzE,OAAO,IAAA,6BAAe,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,YAAY,CAAA;AACpD,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { NextFunction, Request, Response } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* HTTP status codes for API responses
|
|
4
|
+
*/
|
|
5
|
+
export declare enum HttpStatus {
|
|
6
|
+
OK = 200,
|
|
7
|
+
CREATED = 201,
|
|
8
|
+
NO_CONTENT = 204,
|
|
9
|
+
BAD_REQUEST = 400,
|
|
10
|
+
UNAUTHORIZED = 401,
|
|
11
|
+
FORBIDDEN = 403,
|
|
12
|
+
NOT_FOUND = 404,
|
|
13
|
+
CONFLICT = 409,
|
|
14
|
+
TOO_MANY_REQUESTS = 429,
|
|
15
|
+
INTERNAL_ERROR = 500,
|
|
16
|
+
SERVICE_UNAVAILABLE = 503
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Express error handling middleware
|
|
20
|
+
*
|
|
21
|
+
* Handles:
|
|
22
|
+
* - RAGError subclasses (with proper status codes)
|
|
23
|
+
* - Generic errors (500 Internal Server Error)
|
|
24
|
+
*
|
|
25
|
+
* In production, hides stack traces and internal details.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* // Add as the last middleware
|
|
29
|
+
* app.use(errorHandler)
|
|
30
|
+
*/
|
|
31
|
+
export declare function errorHandler(err: Error, _req: Request, res: Response, _next: NextFunction): void;
|
|
32
|
+
/**
|
|
33
|
+
* 404 Not Found handler
|
|
34
|
+
*/
|
|
35
|
+
export declare function notFoundHandler(_req: Request, res: Response): void;
|
|
36
|
+
//# sourceMappingURL=error-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handler.d.ts","sourceRoot":"","sources":["../../../src/web/middleware/error-handler.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAG9D;;GAEG;AACH,oBAAY,UAAU;IACpB,EAAE,MAAM;IACR,OAAO,MAAM;IACb,UAAU,MAAM;IAChB,WAAW,MAAM;IACjB,YAAY,MAAM;IAClB,SAAS,MAAM;IACf,SAAS,MAAM;IACf,QAAQ,MAAM;IACd,iBAAiB,MAAM;IACvB,cAAc,MAAM;IACpB,mBAAmB,MAAM;CAC1B;AAWD;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,GAAG,IAAI,CA2BhG;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI,CAElE"}
|