workmatic 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,464 @@
1
+ :root {
2
+ --bg-primary: #0a0a0f;
3
+ --bg-secondary: #12121a;
4
+ --bg-tertiary: #1a1a26;
5
+ --bg-hover: #22222e;
6
+ --text-primary: #f0f0f5;
7
+ --text-secondary: #8888a0;
8
+ --text-muted: #55556a;
9
+ --border: #2a2a3a;
10
+ --accent: #7c5dfa;
11
+ --accent-hover: #9277ff;
12
+ --ready: #3b82f6;
13
+ --ready-bg: rgba(59, 130, 246, 0.1);
14
+ --running: #f59e0b;
15
+ --running-bg: rgba(245, 158, 11, 0.1);
16
+ --done: #10b981;
17
+ --done-bg: rgba(16, 185, 129, 0.1);
18
+ --failed: #f97316;
19
+ --failed-bg: rgba(249, 115, 22, 0.1);
20
+ --dead: #ef4444;
21
+ --dead-bg: rgba(239, 68, 68, 0.1);
22
+ --radius: 12px;
23
+ --radius-sm: 8px;
24
+ --shadow: 0 4px 24px rgba(0, 0, 0, 0.4);
25
+ --font-sans: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
26
+ --font-mono: 'JetBrains Mono', monospace;
27
+ }
28
+
29
+ * {
30
+ margin: 0;
31
+ padding: 0;
32
+ box-sizing: border-box;
33
+ }
34
+
35
+ body {
36
+ font-family: var(--font-sans);
37
+ background: var(--bg-primary);
38
+ color: var(--text-primary);
39
+ min-height: 100vh;
40
+ line-height: 1.6;
41
+ }
42
+
43
+ .container {
44
+ max-width: 1400px;
45
+ margin: 0 auto;
46
+ padding: 2rem;
47
+ }
48
+
49
+ /* Header */
50
+ header {
51
+ display: flex;
52
+ justify-content: space-between;
53
+ align-items: center;
54
+ margin-bottom: 2rem;
55
+ padding-bottom: 1.5rem;
56
+ border-bottom: 1px solid var(--border);
57
+ }
58
+
59
+ h1 {
60
+ display: flex;
61
+ align-items: center;
62
+ gap: 0.75rem;
63
+ font-size: 1.5rem;
64
+ font-weight: 700;
65
+ letter-spacing: -0.02em;
66
+ }
67
+
68
+ .logo {
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ width: 40px;
73
+ height: 40px;
74
+ background: linear-gradient(135deg, var(--accent) 0%, #5d3fd3 100%);
75
+ border-radius: var(--radius-sm);
76
+ font-weight: 700;
77
+ font-size: 1.25rem;
78
+ }
79
+
80
+ .header-controls {
81
+ display: flex;
82
+ align-items: center;
83
+ gap: 1rem;
84
+ }
85
+
86
+ .refresh-indicator {
87
+ width: 8px;
88
+ height: 8px;
89
+ border-radius: 50%;
90
+ background: var(--done);
91
+ animation: pulse 2s ease-in-out infinite;
92
+ }
93
+
94
+ @keyframes pulse {
95
+ 0%, 100% { opacity: 1; }
96
+ 50% { opacity: 0.4; }
97
+ }
98
+
99
+ /* Forms */
100
+ select, button {
101
+ font-family: var(--font-sans);
102
+ font-size: 0.875rem;
103
+ }
104
+
105
+ select {
106
+ background: var(--bg-secondary);
107
+ color: var(--text-primary);
108
+ border: 1px solid var(--border);
109
+ padding: 0.625rem 2rem 0.625rem 0.875rem;
110
+ border-radius: var(--radius-sm);
111
+ cursor: pointer;
112
+ appearance: none;
113
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%238888a0' stroke-width='2'%3E%3Cpolyline points='6,9 12,15 18,9'/%3E%3C/svg%3E");
114
+ background-repeat: no-repeat;
115
+ background-position: right 0.5rem center;
116
+ transition: border-color 0.2s, box-shadow 0.2s;
117
+ }
118
+
119
+ select:hover {
120
+ border-color: var(--accent);
121
+ }
122
+
123
+ select:focus {
124
+ outline: none;
125
+ border-color: var(--accent);
126
+ box-shadow: 0 0 0 3px rgba(124, 93, 250, 0.2);
127
+ }
128
+
129
+ button {
130
+ background: var(--bg-secondary);
131
+ color: var(--text-primary);
132
+ border: 1px solid var(--border);
133
+ padding: 0.625rem 1rem;
134
+ border-radius: var(--radius-sm);
135
+ cursor: pointer;
136
+ font-weight: 500;
137
+ transition: all 0.2s;
138
+ }
139
+
140
+ button:hover:not(:disabled) {
141
+ background: var(--bg-hover);
142
+ border-color: var(--accent);
143
+ }
144
+
145
+ button:disabled {
146
+ opacity: 0.4;
147
+ cursor: not-allowed;
148
+ }
149
+
150
+ button.primary {
151
+ background: var(--accent);
152
+ border-color: var(--accent);
153
+ }
154
+
155
+ button.primary:hover:not(:disabled) {
156
+ background: var(--accent-hover);
157
+ border-color: var(--accent-hover);
158
+ }
159
+
160
+ /* Stats Section */
161
+ .stats-section {
162
+ margin-bottom: 2rem;
163
+ }
164
+
165
+ .stats-grid {
166
+ display: grid;
167
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
168
+ gap: 1rem;
169
+ }
170
+
171
+ .stat-card {
172
+ background: var(--bg-secondary);
173
+ border: 1px solid var(--border);
174
+ border-radius: var(--radius);
175
+ padding: 1.25rem;
176
+ display: flex;
177
+ align-items: center;
178
+ gap: 1rem;
179
+ transition: transform 0.2s, box-shadow 0.2s;
180
+ }
181
+
182
+ .stat-card:hover {
183
+ transform: translateY(-2px);
184
+ box-shadow: var(--shadow);
185
+ }
186
+
187
+ .stat-icon {
188
+ width: 48px;
189
+ height: 48px;
190
+ border-radius: var(--radius-sm);
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ }
195
+
196
+ .stat-icon svg {
197
+ width: 24px;
198
+ height: 24px;
199
+ }
200
+
201
+ .stat-card.ready .stat-icon { background: var(--ready-bg); color: var(--ready); }
202
+ .stat-card.running .stat-icon { background: var(--running-bg); color: var(--running); }
203
+ .stat-card.done .stat-icon { background: var(--done-bg); color: var(--done); }
204
+ .stat-card.failed .stat-icon { background: var(--failed-bg); color: var(--failed); }
205
+ .stat-card.dead .stat-icon { background: var(--dead-bg); color: var(--dead); }
206
+
207
+ .stat-content {
208
+ display: flex;
209
+ flex-direction: column;
210
+ }
211
+
212
+ .stat-value {
213
+ font-size: 1.75rem;
214
+ font-weight: 700;
215
+ line-height: 1.2;
216
+ font-family: var(--font-mono);
217
+ }
218
+
219
+ .stat-label {
220
+ font-size: 0.875rem;
221
+ color: var(--text-secondary);
222
+ text-transform: uppercase;
223
+ letter-spacing: 0.05em;
224
+ }
225
+
226
+ /* Workers Section */
227
+ .workers-section {
228
+ margin-bottom: 2rem;
229
+ }
230
+
231
+ .workers-section h2, .jobs-section h2 {
232
+ font-size: 1.125rem;
233
+ font-weight: 600;
234
+ margin-bottom: 1rem;
235
+ color: var(--text-secondary);
236
+ }
237
+
238
+ .workers-grid {
239
+ display: flex;
240
+ flex-wrap: wrap;
241
+ gap: 1rem;
242
+ }
243
+
244
+ .worker-card {
245
+ background: var(--bg-secondary);
246
+ border: 1px solid var(--border);
247
+ border-radius: var(--radius);
248
+ padding: 1rem 1.25rem;
249
+ display: flex;
250
+ align-items: center;
251
+ gap: 1rem;
252
+ }
253
+
254
+ .worker-info {
255
+ display: flex;
256
+ flex-direction: column;
257
+ gap: 0.25rem;
258
+ }
259
+
260
+ .worker-queue {
261
+ font-weight: 600;
262
+ font-family: var(--font-mono);
263
+ font-size: 0.9rem;
264
+ }
265
+
266
+ .worker-status {
267
+ font-size: 0.8rem;
268
+ color: var(--text-secondary);
269
+ display: flex;
270
+ align-items: center;
271
+ gap: 0.5rem;
272
+ }
273
+
274
+ .worker-status .dot {
275
+ width: 8px;
276
+ height: 8px;
277
+ border-radius: 50%;
278
+ }
279
+
280
+ .worker-status .dot.running { background: var(--done); }
281
+ .worker-status .dot.paused { background: var(--running); }
282
+ .worker-status .dot.stopped { background: var(--text-muted); }
283
+
284
+ .worker-controls {
285
+ display: flex;
286
+ gap: 0.5rem;
287
+ }
288
+
289
+ .worker-controls button {
290
+ padding: 0.5rem 0.75rem;
291
+ font-size: 0.8rem;
292
+ }
293
+
294
+ /* Jobs Section */
295
+ .jobs-section {
296
+ background: var(--bg-secondary);
297
+ border: 1px solid var(--border);
298
+ border-radius: var(--radius);
299
+ padding: 1.5rem;
300
+ }
301
+
302
+ .jobs-header {
303
+ display: flex;
304
+ justify-content: space-between;
305
+ align-items: center;
306
+ margin-bottom: 1rem;
307
+ }
308
+
309
+ .jobs-filters {
310
+ display: flex;
311
+ gap: 0.75rem;
312
+ }
313
+
314
+ .jobs-table-container {
315
+ overflow-x: auto;
316
+ margin: 0 -1.5rem;
317
+ padding: 0 1.5rem;
318
+ }
319
+
320
+ .jobs-table {
321
+ width: 100%;
322
+ border-collapse: collapse;
323
+ font-size: 0.875rem;
324
+ }
325
+
326
+ .jobs-table th {
327
+ text-align: left;
328
+ padding: 0.875rem 1rem;
329
+ border-bottom: 1px solid var(--border);
330
+ color: var(--text-secondary);
331
+ font-weight: 500;
332
+ font-size: 0.8rem;
333
+ text-transform: uppercase;
334
+ letter-spacing: 0.05em;
335
+ white-space: nowrap;
336
+ }
337
+
338
+ .jobs-table td {
339
+ padding: 0.875rem 1rem;
340
+ border-bottom: 1px solid var(--border);
341
+ vertical-align: middle;
342
+ }
343
+
344
+ .jobs-table tbody tr {
345
+ transition: background 0.15s;
346
+ }
347
+
348
+ .jobs-table tbody tr:hover {
349
+ background: var(--bg-hover);
350
+ }
351
+
352
+ .job-id {
353
+ font-family: var(--font-mono);
354
+ font-size: 0.8rem;
355
+ color: var(--accent);
356
+ }
357
+
358
+ .job-queue {
359
+ font-family: var(--font-mono);
360
+ font-size: 0.8rem;
361
+ background: var(--bg-tertiary);
362
+ padding: 0.25rem 0.5rem;
363
+ border-radius: 4px;
364
+ }
365
+
366
+ .job-status {
367
+ display: inline-flex;
368
+ align-items: center;
369
+ padding: 0.25rem 0.625rem;
370
+ border-radius: 999px;
371
+ font-size: 0.75rem;
372
+ font-weight: 600;
373
+ text-transform: uppercase;
374
+ letter-spacing: 0.03em;
375
+ }
376
+
377
+ .job-status.ready { background: var(--ready-bg); color: var(--ready); }
378
+ .job-status.running { background: var(--running-bg); color: var(--running); }
379
+ .job-status.done { background: var(--done-bg); color: var(--done); }
380
+ .job-status.failed { background: var(--failed-bg); color: var(--failed); }
381
+ .job-status.dead { background: var(--dead-bg); color: var(--dead); }
382
+
383
+ .job-priority {
384
+ font-family: var(--font-mono);
385
+ text-align: center;
386
+ }
387
+
388
+ .job-attempts {
389
+ font-family: var(--font-mono);
390
+ }
391
+
392
+ .job-time {
393
+ color: var(--text-secondary);
394
+ font-size: 0.8rem;
395
+ white-space: nowrap;
396
+ }
397
+
398
+ .job-error {
399
+ max-width: 200px;
400
+ overflow: hidden;
401
+ text-overflow: ellipsis;
402
+ white-space: nowrap;
403
+ color: var(--dead);
404
+ font-size: 0.8rem;
405
+ font-family: var(--font-mono);
406
+ }
407
+
408
+ .job-error:empty::before {
409
+ content: '-';
410
+ color: var(--text-muted);
411
+ }
412
+
413
+ /* Pagination */
414
+ .pagination {
415
+ display: flex;
416
+ justify-content: center;
417
+ align-items: center;
418
+ gap: 1rem;
419
+ margin-top: 1.5rem;
420
+ padding-top: 1rem;
421
+ border-top: 1px solid var(--border);
422
+ }
423
+
424
+ #page-info {
425
+ font-size: 0.875rem;
426
+ color: var(--text-secondary);
427
+ }
428
+
429
+ /* Empty state */
430
+ .empty-state {
431
+ text-align: center;
432
+ padding: 3rem 1rem;
433
+ color: var(--text-secondary);
434
+ }
435
+
436
+ .empty-state svg {
437
+ width: 48px;
438
+ height: 48px;
439
+ margin-bottom: 1rem;
440
+ opacity: 0.5;
441
+ }
442
+
443
+ /* Responsive */
444
+ @media (max-width: 768px) {
445
+ .container {
446
+ padding: 1rem;
447
+ }
448
+
449
+ header {
450
+ flex-direction: column;
451
+ gap: 1rem;
452
+ align-items: flex-start;
453
+ }
454
+
455
+ .stats-grid {
456
+ grid-template-columns: repeat(2, 1fr);
457
+ }
458
+
459
+ .jobs-header {
460
+ flex-direction: column;
461
+ gap: 1rem;
462
+ align-items: flex-start;
463
+ }
464
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Workmatic CLI
4
+ *
5
+ * Commands:
6
+ * stats <db> Show job statistics
7
+ * export <db> [output] Export jobs to CSV
8
+ * import <db> <input> Import jobs from CSV
9
+ * purge <db> [--status=done] Delete jobs by status
10
+ * retry <db> [--status=dead] Retry failed/dead jobs
11
+ * pause <db> <queue> Pause a queue (workers stop claiming)
12
+ * resume <db> <queue> Resume a paused queue
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;GAWG"}