@code-rag/api-server 0.1.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 +21 -0
- package/README.md +26 -0
- package/dist/dashboard/data-collector.d.ts +61 -0
- package/dist/dashboard/data-collector.js +244 -0
- package/dist/dashboard/data-collector.js.map +1 -0
- package/dist/dashboard/data-collector.test.d.ts +1 -0
- package/dist/dashboard/data-collector.test.js +334 -0
- package/dist/dashboard/data-collector.test.js.map +1 -0
- package/dist/dashboard/index.d.ts +10 -0
- package/dist/dashboard/index.js +6 -0
- package/dist/dashboard/index.js.map +1 -0
- package/dist/dashboard/routes.d.ts +18 -0
- package/dist/dashboard/routes.js +150 -0
- package/dist/dashboard/routes.js.map +1 -0
- package/dist/dashboard/templates.d.ts +47 -0
- package/dist/dashboard/templates.js +591 -0
- package/dist/dashboard/templates.js.map +1 -0
- package/dist/dashboard/templates.test.d.ts +1 -0
- package/dist/dashboard/templates.test.js +408 -0
- package/dist/dashboard/templates.test.js.map +1 -0
- package/dist/dashboard/types.d.ts +119 -0
- package/dist/dashboard/types.js +4 -0
- package/dist/dashboard/types.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/auth.d.ts +37 -0
- package/dist/middleware/auth.js +92 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +26 -0
- package/dist/middleware/rate-limit.js +79 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/openapi.d.ts +14 -0
- package/dist/openapi.js +363 -0
- package/dist/openapi.js.map +1 -0
- package/dist/routes/context.d.ts +15 -0
- package/dist/routes/context.js +84 -0
- package/dist/routes/context.js.map +1 -0
- package/dist/routes/history.d.ts +56 -0
- package/dist/routes/history.js +308 -0
- package/dist/routes/history.js.map +1 -0
- package/dist/routes/index-trigger.d.ts +21 -0
- package/dist/routes/index-trigger.js +47 -0
- package/dist/routes/index-trigger.js.map +1 -0
- package/dist/routes/search.d.ts +24 -0
- package/dist/routes/search.js +85 -0
- package/dist/routes/search.js.map +1 -0
- package/dist/routes/status.d.ts +14 -0
- package/dist/routes/status.js +37 -0
- package/dist/routes/status.js.map +1 -0
- package/dist/routes/team.d.ts +62 -0
- package/dist/routes/team.js +129 -0
- package/dist/routes/team.js.map +1 -0
- package/dist/routes/viewer.d.ts +78 -0
- package/dist/routes/viewer.js +387 -0
- package/dist/routes/viewer.js.map +1 -0
- package/dist/routes/viewer.test.d.ts +1 -0
- package/dist/routes/viewer.test.js +509 -0
- package/dist/routes/viewer.test.js.map +1 -0
- package/dist/server.d.ts +45 -0
- package/dist/server.js +227 -0
- package/dist/server.js.map +1 -0
- package/dist/server.test.d.ts +1 -0
- package/dist/server.test.js +620 -0
- package/dist/server.test.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { renderDashboardPage, esc, } from './templates.js';
|
|
3
|
+
// --- Helpers ---
|
|
4
|
+
function makeOverview(overrides = {}) {
|
|
5
|
+
return {
|
|
6
|
+
chunkCount: 1200,
|
|
7
|
+
fileCount: 240,
|
|
8
|
+
languages: ['typescript', 'python'],
|
|
9
|
+
lastIndexed: '2026-02-22T10:00:00Z',
|
|
10
|
+
storageBytes: 4_915_200,
|
|
11
|
+
health: 'healthy',
|
|
12
|
+
...overrides,
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function makeUsageStats(overrides = {}) {
|
|
16
|
+
return {
|
|
17
|
+
apiCallsToday: 150,
|
|
18
|
+
apiCallsWeek: 800,
|
|
19
|
+
apiCallsMonth: 3200,
|
|
20
|
+
storageBytes: 4_915_200,
|
|
21
|
+
costEstimate: '~$3.20/month (3200 API calls)',
|
|
22
|
+
...overrides,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function makeAnalytics(overrides = {}) {
|
|
26
|
+
return {
|
|
27
|
+
totalQueries: 450,
|
|
28
|
+
queriesPerDay: [
|
|
29
|
+
{ date: '2026-02-20', count: 100 },
|
|
30
|
+
{ date: '2026-02-21', count: 150 },
|
|
31
|
+
{ date: '2026-02-22', count: 200 },
|
|
32
|
+
],
|
|
33
|
+
topQueries: [
|
|
34
|
+
{ query: 'tree-sitter parser', count: 42 },
|
|
35
|
+
{ query: 'embedding provider', count: 31 },
|
|
36
|
+
],
|
|
37
|
+
avgResponseTimeMs: 87.5,
|
|
38
|
+
errorRate: 0.02,
|
|
39
|
+
...overrides,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function makeUser(overrides = {}) {
|
|
43
|
+
return {
|
|
44
|
+
userId: 'admin-ke...',
|
|
45
|
+
role: 'admin',
|
|
46
|
+
lastActive: '2026-02-22T09:30:00Z',
|
|
47
|
+
queryCount: 55,
|
|
48
|
+
...overrides,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function makeDashboardConfig(overrides = {}) {
|
|
52
|
+
return {
|
|
53
|
+
maxSearchRecords: 10_000,
|
|
54
|
+
maxRequestRecords: 50_000,
|
|
55
|
+
topQueriesLimit: 20,
|
|
56
|
+
...overrides,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// --- Layout & Navigation Tests ---
|
|
60
|
+
describe('renderDashboardPage', () => {
|
|
61
|
+
describe('layout', () => {
|
|
62
|
+
it('should render valid HTML with doctype', () => {
|
|
63
|
+
const html = renderDashboardPage({
|
|
64
|
+
page: 'overview',
|
|
65
|
+
data: { overview: makeOverview(), usageStats: makeUsageStats() },
|
|
66
|
+
});
|
|
67
|
+
expect(html).toContain('<!DOCTYPE html>');
|
|
68
|
+
expect(html).toContain('<html lang="en">');
|
|
69
|
+
expect(html).toContain('</html>');
|
|
70
|
+
});
|
|
71
|
+
it('should include page title', () => {
|
|
72
|
+
const html = renderDashboardPage({
|
|
73
|
+
page: 'overview',
|
|
74
|
+
data: { overview: makeOverview(), usageStats: makeUsageStats() },
|
|
75
|
+
});
|
|
76
|
+
expect(html).toContain('<title>CodeRAG Dashboard');
|
|
77
|
+
expect(html).toContain('Overview');
|
|
78
|
+
});
|
|
79
|
+
it('should include navigation sidebar', () => {
|
|
80
|
+
const html = renderDashboardPage({
|
|
81
|
+
page: 'overview',
|
|
82
|
+
data: { overview: makeOverview(), usageStats: makeUsageStats() },
|
|
83
|
+
});
|
|
84
|
+
expect(html).toContain('<nav');
|
|
85
|
+
expect(html).toContain('/dashboard/overview');
|
|
86
|
+
expect(html).toContain('/dashboard/analytics');
|
|
87
|
+
expect(html).toContain('/dashboard/users');
|
|
88
|
+
expect(html).toContain('/dashboard/settings');
|
|
89
|
+
});
|
|
90
|
+
it('should mark active page in navigation', () => {
|
|
91
|
+
const html = renderDashboardPage({
|
|
92
|
+
page: 'analytics',
|
|
93
|
+
data: { analytics: makeAnalytics() },
|
|
94
|
+
});
|
|
95
|
+
expect(html).toContain('class="active"');
|
|
96
|
+
// The active link should be the analytics one
|
|
97
|
+
expect(html).toMatch(/href="\/dashboard\/analytics"[^>]*class="active"/);
|
|
98
|
+
});
|
|
99
|
+
it('should include inline CSS', () => {
|
|
100
|
+
const html = renderDashboardPage({
|
|
101
|
+
page: 'overview',
|
|
102
|
+
data: { overview: makeOverview(), usageStats: makeUsageStats() },
|
|
103
|
+
});
|
|
104
|
+
expect(html).toContain('<style>');
|
|
105
|
+
expect(html).toContain('--primary');
|
|
106
|
+
});
|
|
107
|
+
it('should include CodeRAG logo text', () => {
|
|
108
|
+
const html = renderDashboardPage({
|
|
109
|
+
page: 'overview',
|
|
110
|
+
data: { overview: makeOverview(), usageStats: makeUsageStats() },
|
|
111
|
+
});
|
|
112
|
+
expect(html).toContain('CodeRAG');
|
|
113
|
+
expect(html).toContain('Admin Dashboard');
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
// --- Overview Page Tests ---
|
|
117
|
+
describe('overview page', () => {
|
|
118
|
+
it('should render index health badge', () => {
|
|
119
|
+
const html = renderDashboardPage({
|
|
120
|
+
page: 'overview',
|
|
121
|
+
data: { overview: makeOverview({ health: 'healthy' }), usageStats: makeUsageStats() },
|
|
122
|
+
});
|
|
123
|
+
expect(html).toContain('badge');
|
|
124
|
+
expect(html).toContain('healthy');
|
|
125
|
+
});
|
|
126
|
+
it('should render degraded health badge', () => {
|
|
127
|
+
const html = renderDashboardPage({
|
|
128
|
+
page: 'overview',
|
|
129
|
+
data: { overview: makeOverview({ health: 'degraded' }), usageStats: makeUsageStats() },
|
|
130
|
+
});
|
|
131
|
+
expect(html).toContain('badge-yellow');
|
|
132
|
+
expect(html).toContain('degraded');
|
|
133
|
+
});
|
|
134
|
+
it('should render not_initialized health badge', () => {
|
|
135
|
+
const html = renderDashboardPage({
|
|
136
|
+
page: 'overview',
|
|
137
|
+
data: { overview: makeOverview({ health: 'not_initialized' }), usageStats: makeUsageStats() },
|
|
138
|
+
});
|
|
139
|
+
expect(html).toContain('badge-red');
|
|
140
|
+
expect(html).toContain('not_initialized');
|
|
141
|
+
});
|
|
142
|
+
it('should display chunk and file counts', () => {
|
|
143
|
+
const html = renderDashboardPage({
|
|
144
|
+
page: 'overview',
|
|
145
|
+
data: { overview: makeOverview(), usageStats: makeUsageStats() },
|
|
146
|
+
});
|
|
147
|
+
expect(html).toContain('1,200');
|
|
148
|
+
expect(html).toContain('240');
|
|
149
|
+
});
|
|
150
|
+
it('should display languages', () => {
|
|
151
|
+
const html = renderDashboardPage({
|
|
152
|
+
page: 'overview',
|
|
153
|
+
data: { overview: makeOverview(), usageStats: makeUsageStats() },
|
|
154
|
+
});
|
|
155
|
+
expect(html).toContain('typescript, python');
|
|
156
|
+
});
|
|
157
|
+
it('should display "Never" when lastIndexed is null', () => {
|
|
158
|
+
const html = renderDashboardPage({
|
|
159
|
+
page: 'overview',
|
|
160
|
+
data: { overview: makeOverview({ lastIndexed: null }), usageStats: makeUsageStats() },
|
|
161
|
+
});
|
|
162
|
+
expect(html).toContain('Never');
|
|
163
|
+
});
|
|
164
|
+
it('should display usage stats', () => {
|
|
165
|
+
const html = renderDashboardPage({
|
|
166
|
+
page: 'overview',
|
|
167
|
+
data: { overview: makeOverview(), usageStats: makeUsageStats() },
|
|
168
|
+
});
|
|
169
|
+
expect(html).toContain('150');
|
|
170
|
+
expect(html).toContain('800');
|
|
171
|
+
expect(html).toContain('3,200');
|
|
172
|
+
});
|
|
173
|
+
it('should include re-index button as a form', () => {
|
|
174
|
+
const html = renderDashboardPage({
|
|
175
|
+
page: 'overview',
|
|
176
|
+
data: { overview: makeOverview(), usageStats: makeUsageStats() },
|
|
177
|
+
});
|
|
178
|
+
expect(html).toContain('method="POST"');
|
|
179
|
+
expect(html).toContain('action="/dashboard/actions/reindex"');
|
|
180
|
+
expect(html).toContain('Re-index Now');
|
|
181
|
+
});
|
|
182
|
+
it('should display flash message when provided', () => {
|
|
183
|
+
const html = renderDashboardPage({
|
|
184
|
+
page: 'overview',
|
|
185
|
+
data: {
|
|
186
|
+
overview: makeOverview(),
|
|
187
|
+
usageStats: makeUsageStats(),
|
|
188
|
+
flash: { type: 'success', text: 'Re-indexing completed successfully!' },
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
expect(html).toContain('flash-success');
|
|
192
|
+
expect(html).toContain('Re-indexing completed successfully!');
|
|
193
|
+
});
|
|
194
|
+
it('should display error flash message', () => {
|
|
195
|
+
const html = renderDashboardPage({
|
|
196
|
+
page: 'overview',
|
|
197
|
+
data: {
|
|
198
|
+
overview: makeOverview(),
|
|
199
|
+
usageStats: makeUsageStats(),
|
|
200
|
+
flash: { type: 'error', text: 'Something went wrong' },
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
expect(html).toContain('flash-error');
|
|
204
|
+
expect(html).toContain('Something went wrong');
|
|
205
|
+
});
|
|
206
|
+
it('should handle zero chunks gracefully', () => {
|
|
207
|
+
const html = renderDashboardPage({
|
|
208
|
+
page: 'overview',
|
|
209
|
+
data: {
|
|
210
|
+
overview: makeOverview({ chunkCount: 0, fileCount: 0, storageBytes: 0 }),
|
|
211
|
+
usageStats: makeUsageStats({ apiCallsToday: 0, apiCallsWeek: 0, apiCallsMonth: 0 }),
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
expect(html).toContain('0');
|
|
215
|
+
expect(html).toContain('0 B');
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
// --- Analytics Page Tests ---
|
|
219
|
+
describe('analytics page', () => {
|
|
220
|
+
it('should render total query count', () => {
|
|
221
|
+
const html = renderDashboardPage({
|
|
222
|
+
page: 'analytics',
|
|
223
|
+
data: { analytics: makeAnalytics() },
|
|
224
|
+
});
|
|
225
|
+
expect(html).toContain('450');
|
|
226
|
+
});
|
|
227
|
+
it('should render average response time', () => {
|
|
228
|
+
const html = renderDashboardPage({
|
|
229
|
+
page: 'analytics',
|
|
230
|
+
data: { analytics: makeAnalytics() },
|
|
231
|
+
});
|
|
232
|
+
expect(html).toContain('87.5');
|
|
233
|
+
});
|
|
234
|
+
it('should render error rate as percentage', () => {
|
|
235
|
+
const html = renderDashboardPage({
|
|
236
|
+
page: 'analytics',
|
|
237
|
+
data: { analytics: makeAnalytics() },
|
|
238
|
+
});
|
|
239
|
+
expect(html).toContain('2.00%');
|
|
240
|
+
});
|
|
241
|
+
it('should render query chart bars', () => {
|
|
242
|
+
const html = renderDashboardPage({
|
|
243
|
+
page: 'analytics',
|
|
244
|
+
data: { analytics: makeAnalytics() },
|
|
245
|
+
});
|
|
246
|
+
expect(html).toContain('bar-group');
|
|
247
|
+
expect(html).toContain('bar');
|
|
248
|
+
});
|
|
249
|
+
it('should render top queries table', () => {
|
|
250
|
+
const html = renderDashboardPage({
|
|
251
|
+
page: 'analytics',
|
|
252
|
+
data: { analytics: makeAnalytics() },
|
|
253
|
+
});
|
|
254
|
+
expect(html).toContain('tree-sitter parser');
|
|
255
|
+
expect(html).toContain('42');
|
|
256
|
+
expect(html).toContain('embedding provider');
|
|
257
|
+
expect(html).toContain('31');
|
|
258
|
+
});
|
|
259
|
+
it('should handle empty analytics data', () => {
|
|
260
|
+
const html = renderDashboardPage({
|
|
261
|
+
page: 'analytics',
|
|
262
|
+
data: {
|
|
263
|
+
analytics: makeAnalytics({
|
|
264
|
+
totalQueries: 0,
|
|
265
|
+
queriesPerDay: [],
|
|
266
|
+
topQueries: [],
|
|
267
|
+
avgResponseTimeMs: 0,
|
|
268
|
+
errorRate: 0,
|
|
269
|
+
}),
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
expect(html).toContain('No query');
|
|
273
|
+
expect(html).toContain('0');
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
// --- Users Page Tests ---
|
|
277
|
+
describe('users page', () => {
|
|
278
|
+
it('should render user table with role badges', () => {
|
|
279
|
+
const html = renderDashboardPage({
|
|
280
|
+
page: 'users',
|
|
281
|
+
data: { users: [makeUser()] },
|
|
282
|
+
});
|
|
283
|
+
expect(html).toContain('data-table');
|
|
284
|
+
expect(html).toContain('admin-ke...');
|
|
285
|
+
expect(html).toContain('badge');
|
|
286
|
+
expect(html).toContain('admin');
|
|
287
|
+
});
|
|
288
|
+
it('should render user role badge', () => {
|
|
289
|
+
const html = renderDashboardPage({
|
|
290
|
+
page: 'users',
|
|
291
|
+
data: { users: [makeUser({ role: 'user' })] },
|
|
292
|
+
});
|
|
293
|
+
expect(html).toContain('badge-blue');
|
|
294
|
+
expect(html).toContain('user');
|
|
295
|
+
});
|
|
296
|
+
it('should render admin role badge with purple color', () => {
|
|
297
|
+
const html = renderDashboardPage({
|
|
298
|
+
page: 'users',
|
|
299
|
+
data: { users: [makeUser({ role: 'admin' })] },
|
|
300
|
+
});
|
|
301
|
+
expect(html).toContain('badge-purple');
|
|
302
|
+
});
|
|
303
|
+
it('should show "Never" for inactive users', () => {
|
|
304
|
+
const html = renderDashboardPage({
|
|
305
|
+
page: 'users',
|
|
306
|
+
data: { users: [makeUser({ lastActive: null })] },
|
|
307
|
+
});
|
|
308
|
+
expect(html).toContain('Never');
|
|
309
|
+
});
|
|
310
|
+
it('should display query count', () => {
|
|
311
|
+
const html = renderDashboardPage({
|
|
312
|
+
page: 'users',
|
|
313
|
+
data: { users: [makeUser({ queryCount: 123 })] },
|
|
314
|
+
});
|
|
315
|
+
expect(html).toContain('123');
|
|
316
|
+
});
|
|
317
|
+
it('should show empty state when no users', () => {
|
|
318
|
+
const html = renderDashboardPage({
|
|
319
|
+
page: 'users',
|
|
320
|
+
data: { users: [] },
|
|
321
|
+
});
|
|
322
|
+
expect(html).toContain('No API keys configured');
|
|
323
|
+
});
|
|
324
|
+
it('should render multiple users', () => {
|
|
325
|
+
const html = renderDashboardPage({
|
|
326
|
+
page: 'users',
|
|
327
|
+
data: {
|
|
328
|
+
users: [
|
|
329
|
+
makeUser({ userId: 'admin-1', role: 'admin' }),
|
|
330
|
+
makeUser({ userId: 'user-1', role: 'user' }),
|
|
331
|
+
],
|
|
332
|
+
},
|
|
333
|
+
});
|
|
334
|
+
expect(html).toContain('admin-1');
|
|
335
|
+
expect(html).toContain('user-1');
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
// --- Settings Page Tests ---
|
|
339
|
+
describe('settings page', () => {
|
|
340
|
+
it('should display project configuration', () => {
|
|
341
|
+
const html = renderDashboardPage({
|
|
342
|
+
page: 'settings',
|
|
343
|
+
data: {
|
|
344
|
+
config: makeDashboardConfig(),
|
|
345
|
+
projectConfig: {
|
|
346
|
+
name: 'my-project',
|
|
347
|
+
embeddingModel: 'nomic-embed-text',
|
|
348
|
+
storagePath: '.coderag',
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
expect(html).toContain('my-project');
|
|
353
|
+
expect(html).toContain('nomic-embed-text');
|
|
354
|
+
expect(html).toContain('.coderag');
|
|
355
|
+
});
|
|
356
|
+
it('should display dashboard config values', () => {
|
|
357
|
+
const html = renderDashboardPage({
|
|
358
|
+
page: 'settings',
|
|
359
|
+
data: {
|
|
360
|
+
config: makeDashboardConfig({ maxSearchRecords: 5000 }),
|
|
361
|
+
projectConfig: null,
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
expect(html).toContain('5,000');
|
|
365
|
+
});
|
|
366
|
+
it('should show empty state when project config is null', () => {
|
|
367
|
+
const html = renderDashboardPage({
|
|
368
|
+
page: 'settings',
|
|
369
|
+
data: {
|
|
370
|
+
config: makeDashboardConfig(),
|
|
371
|
+
projectConfig: null,
|
|
372
|
+
},
|
|
373
|
+
});
|
|
374
|
+
expect(html).toContain('not loaded');
|
|
375
|
+
});
|
|
376
|
+
it('should include re-index trigger form', () => {
|
|
377
|
+
const html = renderDashboardPage({
|
|
378
|
+
page: 'settings',
|
|
379
|
+
data: {
|
|
380
|
+
config: makeDashboardConfig(),
|
|
381
|
+
projectConfig: null,
|
|
382
|
+
},
|
|
383
|
+
});
|
|
384
|
+
expect(html).toContain('method="POST"');
|
|
385
|
+
expect(html).toContain('action="/dashboard/actions/reindex"');
|
|
386
|
+
expect(html).toContain('Trigger Re-index');
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
// --- esc() Tests ---
|
|
391
|
+
describe('esc', () => {
|
|
392
|
+
it('should escape HTML special characters', () => {
|
|
393
|
+
expect(esc('<script>alert("xss")</script>')).toBe('<script>alert("xss")</script>');
|
|
394
|
+
});
|
|
395
|
+
it('should escape ampersands', () => {
|
|
396
|
+
expect(esc('a & b')).toBe('a & b');
|
|
397
|
+
});
|
|
398
|
+
it('should escape single quotes', () => {
|
|
399
|
+
expect(esc("it's")).toBe('it's');
|
|
400
|
+
});
|
|
401
|
+
it('should return empty string unchanged', () => {
|
|
402
|
+
expect(esc('')).toBe('');
|
|
403
|
+
});
|
|
404
|
+
it('should not modify safe strings', () => {
|
|
405
|
+
expect(esc('hello world')).toBe('hello world');
|
|
406
|
+
});
|
|
407
|
+
});
|
|
408
|
+
//# sourceMappingURL=templates.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.test.js","sourceRoot":"","sources":["../../src/dashboard/templates.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dashboard data types for the CodeRAG admin dashboard.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Overview of a CodeRAG index — health, size, and composition.
|
|
6
|
+
*/
|
|
7
|
+
export interface IndexOverview {
|
|
8
|
+
/** Total number of code chunks in the vector store. */
|
|
9
|
+
readonly chunkCount: number;
|
|
10
|
+
/** Number of distinct files indexed. */
|
|
11
|
+
readonly fileCount: number;
|
|
12
|
+
/** Programming languages present in the index. */
|
|
13
|
+
readonly languages: ReadonlyArray<string>;
|
|
14
|
+
/** ISO 8601 timestamp of last successful indexing run, or null if never indexed. */
|
|
15
|
+
readonly lastIndexed: string | null;
|
|
16
|
+
/** Approximate storage size in bytes used by the index. */
|
|
17
|
+
readonly storageBytes: number;
|
|
18
|
+
/** Overall index health. */
|
|
19
|
+
readonly health: 'healthy' | 'degraded' | 'not_initialized';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A single day's query count for the analytics chart.
|
|
23
|
+
*/
|
|
24
|
+
export interface DailyQueryCount {
|
|
25
|
+
/** ISO 8601 date string (YYYY-MM-DD). */
|
|
26
|
+
readonly date: string;
|
|
27
|
+
/** Number of queries on that day. */
|
|
28
|
+
readonly count: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A frequently-queried search term with its count.
|
|
32
|
+
*/
|
|
33
|
+
export interface TopQuery {
|
|
34
|
+
readonly query: string;
|
|
35
|
+
readonly count: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Aggregated search analytics for the dashboard.
|
|
39
|
+
*/
|
|
40
|
+
export interface SearchAnalytics {
|
|
41
|
+
/** Total number of search queries recorded. */
|
|
42
|
+
readonly totalQueries: number;
|
|
43
|
+
/** Per-day query counts for the requested window. */
|
|
44
|
+
readonly queriesPerDay: ReadonlyArray<DailyQueryCount>;
|
|
45
|
+
/** Most frequently issued queries, sorted descending. */
|
|
46
|
+
readonly topQueries: ReadonlyArray<TopQuery>;
|
|
47
|
+
/** Average response time in milliseconds. */
|
|
48
|
+
readonly avgResponseTimeMs: number;
|
|
49
|
+
/** Fraction of queries that resulted in an error (0..1). */
|
|
50
|
+
readonly errorRate: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Information about a configured API key user.
|
|
54
|
+
*/
|
|
55
|
+
export interface UserInfo {
|
|
56
|
+
/** Identifier for the user (truncated key or label). */
|
|
57
|
+
readonly userId: string;
|
|
58
|
+
/** Role derived from the API key configuration. */
|
|
59
|
+
readonly role: 'admin' | 'user';
|
|
60
|
+
/** ISO 8601 timestamp of last activity, or null. */
|
|
61
|
+
readonly lastActive: string | null;
|
|
62
|
+
/** Number of queries issued by this user. */
|
|
63
|
+
readonly queryCount: number;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* API usage statistics for cost tracking.
|
|
67
|
+
*/
|
|
68
|
+
export interface UsageStats {
|
|
69
|
+
/** API calls in the current day. */
|
|
70
|
+
readonly apiCallsToday: number;
|
|
71
|
+
/** API calls in the current week (last 7 days). */
|
|
72
|
+
readonly apiCallsWeek: number;
|
|
73
|
+
/** API calls in the current month (last 30 days). */
|
|
74
|
+
readonly apiCallsMonth: number;
|
|
75
|
+
/** Total storage bytes used by the index. */
|
|
76
|
+
readonly storageBytes: number;
|
|
77
|
+
/** Estimated cost string (informational). */
|
|
78
|
+
readonly costEstimate: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Dashboard-specific configuration.
|
|
82
|
+
*/
|
|
83
|
+
export interface DashboardConfig {
|
|
84
|
+
/** Maximum number of search records to retain in memory. */
|
|
85
|
+
readonly maxSearchRecords: number;
|
|
86
|
+
/** Maximum number of request records to retain in memory. */
|
|
87
|
+
readonly maxRequestRecords: number;
|
|
88
|
+
/** Number of top queries to show. */
|
|
89
|
+
readonly topQueriesLimit: number;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* A recorded search event for analytics.
|
|
93
|
+
*/
|
|
94
|
+
export interface SearchRecord {
|
|
95
|
+
readonly query: string;
|
|
96
|
+
readonly latencyMs: number;
|
|
97
|
+
readonly success: boolean;
|
|
98
|
+
readonly timestamp: number;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* A recorded HTTP request event.
|
|
102
|
+
*/
|
|
103
|
+
export interface RequestRecord {
|
|
104
|
+
readonly method: string;
|
|
105
|
+
readonly path: string;
|
|
106
|
+
readonly apiKeyId: string | null;
|
|
107
|
+
readonly timestamp: number;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Which dashboard page to render.
|
|
111
|
+
*/
|
|
112
|
+
export type DashboardPage = 'overview' | 'analytics' | 'users' | 'settings';
|
|
113
|
+
/**
|
|
114
|
+
* Optional flash message to display at the top of the page.
|
|
115
|
+
*/
|
|
116
|
+
export interface FlashMessage {
|
|
117
|
+
readonly type: 'success' | 'error' | 'info';
|
|
118
|
+
readonly text: string;
|
|
119
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/dashboard/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
export { ApiServer, API_SERVER_VERSION } from './server.js';
|
|
3
|
+
export type { ApiServerOptions } from './server.js';
|
|
4
|
+
export { parseApiKeys, createAuthMiddleware, requireAdmin } from './middleware/auth.js';
|
|
5
|
+
export type { ApiKeyEntry, AuthenticatedRequest } from './middleware/auth.js';
|
|
6
|
+
export { createRateLimitMiddleware, parseRateLimitConfig } from './middleware/rate-limit.js';
|
|
7
|
+
export type { RateLimitConfig } from './middleware/rate-limit.js';
|
|
8
|
+
export { createSearchRouter, searchRequestSchema } from './routes/search.js';
|
|
9
|
+
export type { SearchRequest, SearchResponseItem, SearchRouteDeps } from './routes/search.js';
|
|
10
|
+
export { createContextRouter, contextRequestSchema } from './routes/context.js';
|
|
11
|
+
export type { ContextRequest, ContextRouteDeps } from './routes/context.js';
|
|
12
|
+
export { createStatusRouter } from './routes/status.js';
|
|
13
|
+
export type { StatusResponse, StatusRouteDeps } from './routes/status.js';
|
|
14
|
+
export { createIndexTriggerRouter, indexTriggerRequestSchema } from './routes/index-trigger.js';
|
|
15
|
+
export type { IndexTriggerRequest, IndexTriggerCallback, IndexTriggerRouteDeps } from './routes/index-trigger.js';
|
|
16
|
+
export { createOpenAPISpec } from './openapi.js';
|
|
17
|
+
export type { OpenAPISpec } from './openapi.js';
|
|
18
|
+
export { createViewerRouter } from './routes/viewer.js';
|
|
19
|
+
export type { ViewerDeps, ViewerStatsResponse, ChunkSummary, ChunkDetail, PaginationMeta, GraphResponse, ViewerSearchResult, ViewerSearchResponse, EmbeddingPoint, } from './routes/viewer.js';
|
|
20
|
+
export { DashboardDataCollector, createDashboardRouter, renderDashboardPage, esc } from './dashboard/index.js';
|
|
21
|
+
export type { DashboardDataCollectorDeps, DashboardRouteDeps, OverviewPageData, AnalyticsPageData, UsersPageData, SettingsPageData, PageData, IndexOverview, SearchAnalytics, UserInfo, UsageStats, DashboardConfig, DashboardPage, FlashMessage, DailyQueryCount, TopQuery, SearchRecord, RequestRecord, } from './dashboard/index.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { ApiServer } from './server.js';
|
|
4
|
+
export { ApiServer, API_SERVER_VERSION } from './server.js';
|
|
5
|
+
export { parseApiKeys, createAuthMiddleware, requireAdmin } from './middleware/auth.js';
|
|
6
|
+
export { createRateLimitMiddleware, parseRateLimitConfig } from './middleware/rate-limit.js';
|
|
7
|
+
export { createSearchRouter, searchRequestSchema } from './routes/search.js';
|
|
8
|
+
export { createContextRouter, contextRequestSchema } from './routes/context.js';
|
|
9
|
+
export { createStatusRouter } from './routes/status.js';
|
|
10
|
+
export { createIndexTriggerRouter, indexTriggerRequestSchema } from './routes/index-trigger.js';
|
|
11
|
+
export { createOpenAPISpec } from './openapi.js';
|
|
12
|
+
export { createViewerRouter } from './routes/viewer.js';
|
|
13
|
+
export { DashboardDataCollector, createDashboardRouter, renderDashboardPage, esc } from './dashboard/index.js';
|
|
14
|
+
const DEFAULT_PORT = 3100;
|
|
15
|
+
async function main() {
|
|
16
|
+
const rootDir = process.argv[2] ?? process.cwd();
|
|
17
|
+
const port = parseInt(process.env['CODERAG_PORT'] ?? '', 10) || DEFAULT_PORT;
|
|
18
|
+
const server = new ApiServer({ rootDir, port });
|
|
19
|
+
await server.initialize();
|
|
20
|
+
await server.start();
|
|
21
|
+
// eslint-disable-next-line no-console
|
|
22
|
+
console.log(`[api-server] CodeRAG API server listening on http://localhost:${port}`);
|
|
23
|
+
// eslint-disable-next-line no-console
|
|
24
|
+
console.log(`[api-server] OpenAPI spec: http://localhost:${port}/api/openapi.json`);
|
|
25
|
+
// eslint-disable-next-line no-console
|
|
26
|
+
console.log(`[api-server] Health check: http://localhost:${port}/health`);
|
|
27
|
+
}
|
|
28
|
+
// Only run main when this module is executed directly (not imported)
|
|
29
|
+
const isMainModule = process.argv[1] === fileURLToPath(import.meta.url);
|
|
30
|
+
if (isMainModule) {
|
|
31
|
+
main().catch((error) => {
|
|
32
|
+
// eslint-disable-next-line no-console
|
|
33
|
+
console.error('Fatal error:', error);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAG5D,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGxF,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAG7F,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAG7E,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGhF,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAGxD,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAGhG,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAaxD,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAC;AAsB/G,MAAM,YAAY,GAAG,IAAI,CAAC;AAE1B,KAAK,UAAU,IAAI;IACjB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,YAAY,CAAC;IAE7E,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;IAC1B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IAErB,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,iEAAiE,IAAI,EAAE,CAAC,CAAC;IACrF,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,+CAA+C,IAAI,mBAAmB,CAAC,CAAC;IACpF,sCAAsC;IACtC,OAAO,CAAC,GAAG,CAAC,+CAA+C,IAAI,SAAS,CAAC,CAAC;AAC5E,CAAC;AAED,qEAAqE;AACrE,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAExE,IAAI,YAAY,EAAE,CAAC;IACjB,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;QAC9B,sCAAsC;QACtC,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Request, Response, NextFunction } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* Parsed API key with optional admin role.
|
|
4
|
+
*/
|
|
5
|
+
export interface ApiKeyEntry {
|
|
6
|
+
readonly key: string;
|
|
7
|
+
readonly admin: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Parse the CODERAG_API_KEYS env var.
|
|
11
|
+
*
|
|
12
|
+
* Format: comma-separated keys. Keys suffixed with `:admin` grant admin privileges.
|
|
13
|
+
* Example: "key1,key2:admin,key3"
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseApiKeys(envValue: string | undefined): ReadonlyArray<ApiKeyEntry>;
|
|
16
|
+
/**
|
|
17
|
+
* Express request with authenticated API key information.
|
|
18
|
+
*/
|
|
19
|
+
export interface AuthenticatedRequest extends Request {
|
|
20
|
+
apiKey?: ApiKeyEntry;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create an authentication middleware that validates API keys.
|
|
24
|
+
*
|
|
25
|
+
* Accepts keys from:
|
|
26
|
+
* - `Authorization: Bearer <key>` header
|
|
27
|
+
* - `X-API-Key: <key>` header
|
|
28
|
+
*
|
|
29
|
+
* When no API keys are configured (empty CODERAG_API_KEYS),
|
|
30
|
+
* authentication is disabled and all requests pass through.
|
|
31
|
+
*/
|
|
32
|
+
export declare function createAuthMiddleware(apiKeys: ReadonlyArray<ApiKeyEntry>): (req: Request, res: Response, next: NextFunction) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Middleware that requires admin privileges on the API key.
|
|
35
|
+
* Must be used after createAuthMiddleware.
|
|
36
|
+
*/
|
|
37
|
+
export declare function requireAdmin(req: Request, res: Response, next: NextFunction): void;
|