@nicnocquee/dataqueue-dashboard 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.
@@ -0,0 +1,7 @@
1
+ import type { DashboardConfig } from './types.js';
2
+ /**
3
+ * Handle an incoming request and return a Response.
4
+ * This is the framework-agnostic core of the dashboard.
5
+ */
6
+ export declare function handleRequest(request: Request, config: DashboardConfig): Promise<Response>;
7
+ //# sourceMappingURL=api-handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-handlers.d.ts","sourceRoot":"","sources":["../../src/core/api-handlers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EAGhB,MAAM,YAAY,CAAC;AAqFpB;;;GAGG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,QAAQ,CAAC,CA6HnB"}
@@ -0,0 +1,193 @@
1
+ import { generateDashboardHTML } from './html.js';
2
+ const DEFAULT_PAGE_SIZE = 25;
3
+ function serializeJob(job) {
4
+ return {
5
+ id: job.id,
6
+ jobType: job.jobType,
7
+ payload: job.payload,
8
+ status: job.status,
9
+ createdAt: toISO(job.createdAt),
10
+ updatedAt: toISO(job.updatedAt),
11
+ lockedAt: job.lockedAt ? toISO(job.lockedAt) : null,
12
+ lockedBy: job.lockedBy,
13
+ attempts: job.attempts,
14
+ maxAttempts: job.maxAttempts,
15
+ nextAttemptAt: job.nextAttemptAt ? toISO(job.nextAttemptAt) : null,
16
+ priority: job.priority,
17
+ runAt: toISO(job.runAt),
18
+ pendingReason: job.pendingReason,
19
+ errorHistory: job.errorHistory,
20
+ timeoutMs: job.timeoutMs,
21
+ forceKillOnTimeout: job.forceKillOnTimeout,
22
+ failureReason: job.failureReason,
23
+ completedAt: job.completedAt ? toISO(job.completedAt) : null,
24
+ startedAt: job.startedAt ? toISO(job.startedAt) : null,
25
+ lastRetriedAt: job.lastRetriedAt ? toISO(job.lastRetriedAt) : null,
26
+ lastFailedAt: job.lastFailedAt ? toISO(job.lastFailedAt) : null,
27
+ lastCancelledAt: job.lastCancelledAt ? toISO(job.lastCancelledAt) : null,
28
+ tags: job.tags,
29
+ idempotencyKey: job.idempotencyKey,
30
+ waitUntil: job.waitUntil ? toISO(job.waitUntil) : null,
31
+ waitTokenId: job.waitTokenId,
32
+ stepData: job.stepData,
33
+ progress: job.progress,
34
+ };
35
+ }
36
+ function serializeEvent(event) {
37
+ return {
38
+ id: event.id,
39
+ jobId: event.jobId,
40
+ eventType: event.eventType,
41
+ createdAt: toISO(event.createdAt),
42
+ metadata: event.metadata,
43
+ };
44
+ }
45
+ function toISO(date) {
46
+ if (date instanceof Date)
47
+ return date.toISOString();
48
+ return date;
49
+ }
50
+ function json(data, status = 200) {
51
+ return new Response(JSON.stringify(data), {
52
+ status,
53
+ headers: { 'Content-Type': 'application/json' },
54
+ });
55
+ }
56
+ function html(content, status = 200) {
57
+ return new Response(content, {
58
+ status,
59
+ headers: { 'Content-Type': 'text/html; charset=utf-8' },
60
+ });
61
+ }
62
+ /**
63
+ * Parse the path segments after the base path.
64
+ * E.g., for basePath="/admin/dq" and URL "/admin/dq/api/jobs/5",
65
+ * returns ["api", "jobs", "5"].
66
+ */
67
+ function parsePathSegments(url, basePath) {
68
+ const u = new URL(url);
69
+ const normalized = basePath.endsWith('/') ? basePath : basePath + '/';
70
+ const rest = u.pathname.startsWith(normalized)
71
+ ? u.pathname.slice(normalized.length)
72
+ : u.pathname.slice(basePath.length);
73
+ return rest
74
+ .split('/')
75
+ .map((s) => s.trim())
76
+ .filter(Boolean);
77
+ }
78
+ /**
79
+ * Handle an incoming request and return a Response.
80
+ * This is the framework-agnostic core of the dashboard.
81
+ */
82
+ export async function handleRequest(request, config) {
83
+ const { jobQueue, basePath } = config;
84
+ const method = request.method.toUpperCase();
85
+ const segments = parsePathSegments(request.url, basePath);
86
+ try {
87
+ // --- GET routes ---
88
+ if (method === 'GET') {
89
+ // GET /api/jobs - list jobs
90
+ if (segments[0] === 'api' && segments[1] === 'jobs' && !segments[2]) {
91
+ const url = new URL(request.url);
92
+ const status = url.searchParams.get('status');
93
+ const jobType = url.searchParams.get('jobType');
94
+ const limit = parseInt(url.searchParams.get('limit') || String(DEFAULT_PAGE_SIZE), 10);
95
+ const offset = parseInt(url.searchParams.get('offset') || '0', 10);
96
+ let jobs;
97
+ if (status) {
98
+ jobs = await jobQueue.getJobsByStatus(status, limit + 1, offset);
99
+ }
100
+ else if (jobType) {
101
+ jobs = await jobQueue.getJobs({ jobType }, limit + 1, offset);
102
+ }
103
+ else {
104
+ jobs = await jobQueue.getAllJobs(limit + 1, offset);
105
+ }
106
+ const hasMore = jobs.length > limit;
107
+ if (hasMore)
108
+ jobs = jobs.slice(0, limit);
109
+ return json({
110
+ jobs: jobs.map(serializeJob),
111
+ hasMore,
112
+ });
113
+ }
114
+ // GET /api/jobs/:id/events - job events
115
+ if (segments[0] === 'api' &&
116
+ segments[1] === 'jobs' &&
117
+ segments[2] &&
118
+ segments[3] === 'events') {
119
+ const id = parseInt(segments[2], 10);
120
+ if (isNaN(id))
121
+ return json({ error: 'Invalid job ID' }, 400);
122
+ const events = await jobQueue.getJobEvents(id);
123
+ return json({ events: events.map(serializeEvent) });
124
+ }
125
+ // GET /api/jobs/:id - single job
126
+ if (segments[0] === 'api' && segments[1] === 'jobs' && segments[2]) {
127
+ const id = parseInt(segments[2], 10);
128
+ if (isNaN(id))
129
+ return json({ error: 'Invalid job ID' }, 400);
130
+ const job = await jobQueue.getJob(id);
131
+ if (!job)
132
+ return json({ error: 'Job not found' }, 404);
133
+ return json({ job: serializeJob(job) });
134
+ }
135
+ // GET / or any non-API path - serve dashboard HTML
136
+ if (segments[0] !== 'api') {
137
+ return html(generateDashboardHTML(basePath));
138
+ }
139
+ }
140
+ // --- POST routes ---
141
+ if (method === 'POST') {
142
+ // POST /api/jobs/:id/cancel
143
+ if (segments[0] === 'api' &&
144
+ segments[1] === 'jobs' &&
145
+ segments[2] &&
146
+ segments[3] === 'cancel') {
147
+ const id = parseInt(segments[2], 10);
148
+ if (isNaN(id))
149
+ return json({ error: 'Invalid job ID' }, 400);
150
+ try {
151
+ await jobQueue.cancelJob(id);
152
+ return json({ ok: true });
153
+ }
154
+ catch (err) {
155
+ return json({ ok: false, error: err.message }, 400);
156
+ }
157
+ }
158
+ // POST /api/jobs/:id/retry
159
+ if (segments[0] === 'api' &&
160
+ segments[1] === 'jobs' &&
161
+ segments[2] &&
162
+ segments[3] === 'retry') {
163
+ const id = parseInt(segments[2], 10);
164
+ if (isNaN(id))
165
+ return json({ error: 'Invalid job ID' }, 400);
166
+ try {
167
+ await jobQueue.retryJob(id);
168
+ return json({ ok: true });
169
+ }
170
+ catch (err) {
171
+ return json({ ok: false, error: err.message }, 400);
172
+ }
173
+ }
174
+ // POST /api/process - manually trigger processing
175
+ if (segments[0] === 'api' && segments[1] === 'process') {
176
+ const { jobHandlers, processorOptions } = config;
177
+ const processor = jobQueue.createProcessor(jobHandlers, {
178
+ workerId: `dashboard-${Date.now()}`,
179
+ batchSize: 10,
180
+ ...processorOptions,
181
+ });
182
+ const processed = await processor.start();
183
+ return json({ processed });
184
+ }
185
+ }
186
+ return json({ error: 'Not found' }, 404);
187
+ }
188
+ catch (err) {
189
+ console.error('[dataqueue-dashboard] Error:', err);
190
+ return json({ error: err.message || 'Internal server error' }, 500);
191
+ }
192
+ }
193
+ //# sourceMappingURL=api-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-handlers.js","sourceRoot":"","sources":["../../src/core/api-handlers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Generate the complete dashboard HTML page.
3
+ * The page is a self-contained React SPA with embedded CSS and JS.
4
+ * React and ReactDOM are loaded from esm.sh CDN.
5
+ */
6
+ export declare function generateDashboardHTML(basePath: string): string;
7
+ //# sourceMappingURL=html.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/core/html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA2B9D"}