@qodalis/cli-server-plugin-jobs 1.0.0-beta.3

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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/dist/cli-job-execution-context.d.ts +8 -0
  4. package/dist/cli-job-execution-context.d.ts.map +1 -0
  5. package/dist/cli-job-execution-context.js +17 -0
  6. package/dist/cli-job-execution-context.js.map +1 -0
  7. package/dist/cli-job-logger.d.ts +11 -0
  8. package/dist/cli-job-logger.d.ts.map +1 -0
  9. package/dist/cli-job-logger.js +30 -0
  10. package/dist/cli-job-logger.js.map +1 -0
  11. package/dist/cli-job-scheduler.d.ts +77 -0
  12. package/dist/cli-job-scheduler.d.ts.map +1 -0
  13. package/dist/cli-job-scheduler.js +435 -0
  14. package/dist/cli-job-scheduler.js.map +1 -0
  15. package/dist/cli-jobs-builder.d.ts +44 -0
  16. package/dist/cli-jobs-builder.d.ts.map +1 -0
  17. package/dist/cli-jobs-builder.js +59 -0
  18. package/dist/cli-jobs-builder.js.map +1 -0
  19. package/dist/cli-jobs-controller.d.ts +5 -0
  20. package/dist/cli-jobs-controller.d.ts.map +1 -0
  21. package/dist/cli-jobs-controller.js +140 -0
  22. package/dist/cli-jobs-controller.js.map +1 -0
  23. package/dist/in-memory-job-storage-provider.d.ts +21 -0
  24. package/dist/in-memory-job-storage-provider.d.ts.map +1 -0
  25. package/dist/in-memory-job-storage-provider.js +49 -0
  26. package/dist/in-memory-job-storage-provider.js.map +1 -0
  27. package/dist/index.d.ts +8 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +19 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/interval-parser.d.ts +6 -0
  32. package/dist/interval-parser.d.ts.map +1 -0
  33. package/dist/interval-parser.js +25 -0
  34. package/dist/interval-parser.js.map +1 -0
  35. package/dist/tsconfig.tsbuildinfo +1 -0
  36. package/package.json +40 -0
@@ -0,0 +1,435 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JobError = exports.CliJobScheduler = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const cron_parser_1 = require("cron-parser");
6
+ const cli_job_execution_context_1 = require("./cli-job-execution-context");
7
+ const interval_parser_1 = require("./interval-parser");
8
+ class CliJobScheduler {
9
+ _registrations = new Map();
10
+ _storage;
11
+ _broadcastFn = null;
12
+ _running = false;
13
+ constructor(storage) {
14
+ this._storage = storage;
15
+ }
16
+ setBroadcastFn(fn) {
17
+ this._broadcastFn = fn;
18
+ }
19
+ register(job, options) {
20
+ const id = (0, crypto_1.randomUUID)();
21
+ const enabled = options.enabled !== false;
22
+ const reg = {
23
+ id,
24
+ job,
25
+ options: { ...options, enabled },
26
+ status: enabled ? 'active' : 'stopped',
27
+ queue: [],
28
+ };
29
+ this._registrations.set(id, reg);
30
+ return id;
31
+ }
32
+ async start() {
33
+ this._running = true;
34
+ // Load persisted states
35
+ const states = await this._storage.getAllJobStates();
36
+ for (const [id, reg] of this._registrations) {
37
+ const persisted = states.get(id);
38
+ if (persisted) {
39
+ reg.status = persisted.status;
40
+ reg.lastRunAt = persisted.lastRunAt;
41
+ }
42
+ if (reg.status === 'active') {
43
+ this._startTimer(reg);
44
+ }
45
+ }
46
+ }
47
+ async stop() {
48
+ this._running = false;
49
+ // Cancel all running executions and stop timers
50
+ for (const reg of this._registrations.values()) {
51
+ this._stopTimer(reg);
52
+ if (reg.currentAbortController) {
53
+ reg.currentAbortController.abort();
54
+ }
55
+ // Persist state
56
+ await this._storage.saveJobState(reg.id, {
57
+ status: reg.status,
58
+ lastRunAt: reg.lastRunAt,
59
+ updatedAt: new Date().toISOString(),
60
+ });
61
+ }
62
+ }
63
+ getAll() {
64
+ return Array.from(this._registrations.values()).map((reg) => this._toDto(reg));
65
+ }
66
+ get(id) {
67
+ const reg = this._registrations.get(id);
68
+ return reg ? this._toDto(reg) : undefined;
69
+ }
70
+ getRegistration(id) {
71
+ return this._registrations.get(id);
72
+ }
73
+ async triggerAsync(id) {
74
+ const reg = this._registrations.get(id);
75
+ if (!reg)
76
+ throw new JobError('Job not found', 'JOB_NOT_FOUND', 404);
77
+ if (reg.currentExecutionId) {
78
+ const policy = reg.options.overlapPolicy ?? 'skip';
79
+ if (policy === 'skip') {
80
+ throw new JobError('Job is already running', 'JOB_ALREADY_RUNNING', 409);
81
+ }
82
+ if (policy === 'cancel') {
83
+ reg.currentAbortController?.abort();
84
+ // Wait briefly for cancellation
85
+ await new Promise((r) => setTimeout(r, 50));
86
+ }
87
+ if (policy === 'queue') {
88
+ return new Promise((resolve) => {
89
+ reg.queue.push({ resolve });
90
+ });
91
+ }
92
+ }
93
+ await this._executeJobAsync(reg, 0);
94
+ }
95
+ async pauseAsync(id) {
96
+ const reg = this._registrations.get(id);
97
+ if (!reg)
98
+ throw new JobError('Job not found', 'JOB_NOT_FOUND', 404);
99
+ if (reg.status === 'paused')
100
+ throw new JobError('Job is already paused', 'JOB_ALREADY_PAUSED', 409);
101
+ reg.status = 'paused';
102
+ this._stopTimer(reg);
103
+ await this._persistState(reg);
104
+ this._broadcast({ type: 'job:paused', jobId: reg.id });
105
+ }
106
+ async resumeAsync(id) {
107
+ const reg = this._registrations.get(id);
108
+ if (!reg)
109
+ throw new JobError('Job not found', 'JOB_NOT_FOUND', 404);
110
+ if (reg.status !== 'paused')
111
+ throw new JobError('Job is not paused', 'JOB_NOT_PAUSED', 409);
112
+ reg.status = 'active';
113
+ this._startTimer(reg);
114
+ await this._persistState(reg);
115
+ this._broadcast({ type: 'job:resumed', jobId: reg.id });
116
+ }
117
+ async stopJobAsync(id) {
118
+ const reg = this._registrations.get(id);
119
+ if (!reg)
120
+ throw new JobError('Job not found', 'JOB_NOT_FOUND', 404);
121
+ reg.status = 'stopped';
122
+ this._stopTimer(reg);
123
+ if (reg.currentAbortController) {
124
+ reg.currentAbortController.abort();
125
+ }
126
+ await this._persistState(reg);
127
+ this._broadcast({ type: 'job:stopped', jobId: reg.id });
128
+ }
129
+ async cancelCurrentAsync(id) {
130
+ const reg = this._registrations.get(id);
131
+ if (!reg)
132
+ throw new JobError('Job not found', 'JOB_NOT_FOUND', 404);
133
+ if (!reg.currentExecutionId)
134
+ throw new JobError('No execution is running', 'JOB_NOT_RUNNING', 409);
135
+ reg.currentAbortController?.abort();
136
+ }
137
+ async updateOptionsAsync(id, updates) {
138
+ const reg = this._registrations.get(id);
139
+ if (!reg)
140
+ throw new JobError('Job not found', 'JOB_NOT_FOUND', 404);
141
+ // Validate: can't provide both schedule and interval
142
+ if (updates.schedule !== undefined && updates.interval !== undefined && updates.schedule !== null && updates.interval !== null) {
143
+ throw new JobError('Cannot provide both schedule and interval', 'SCHEDULE_CONFLICT', 400);
144
+ }
145
+ // Validate schedule if provided
146
+ if (updates.schedule !== undefined && updates.schedule !== null) {
147
+ try {
148
+ cron_parser_1.CronExpressionParser.parse(updates.schedule);
149
+ }
150
+ catch {
151
+ throw new JobError('Invalid cron expression', 'INVALID_SCHEDULE', 400);
152
+ }
153
+ }
154
+ // Validate interval if provided
155
+ if (updates.interval !== undefined && updates.interval !== null) {
156
+ const ms = (0, interval_parser_1.parseInterval)(updates.interval);
157
+ if (ms === null) {
158
+ throw new JobError('Invalid interval format', 'INVALID_SCHEDULE', 400);
159
+ }
160
+ }
161
+ // Apply updates
162
+ if (updates.description !== undefined)
163
+ reg.options.description = updates.description;
164
+ if (updates.group !== undefined)
165
+ reg.options.group = updates.group;
166
+ if (updates.maxRetries !== undefined)
167
+ reg.options.maxRetries = updates.maxRetries;
168
+ if (updates.retryDelay !== undefined)
169
+ reg.options.retryDelay = updates.retryDelay;
170
+ if (updates.retryStrategy !== undefined)
171
+ reg.options.retryStrategy = updates.retryStrategy;
172
+ if (updates.timeout !== undefined)
173
+ reg.options.timeout = updates.timeout;
174
+ if (updates.overlapPolicy !== undefined)
175
+ reg.options.overlapPolicy = updates.overlapPolicy;
176
+ // Handle schedule/interval changes (setting one clears the other)
177
+ if (updates.schedule !== undefined) {
178
+ if (updates.schedule === null) {
179
+ reg.options.schedule = undefined;
180
+ }
181
+ else {
182
+ reg.options.schedule = updates.schedule;
183
+ reg.options.interval = undefined;
184
+ }
185
+ }
186
+ if (updates.interval !== undefined) {
187
+ if (updates.interval === null) {
188
+ reg.options.interval = undefined;
189
+ }
190
+ else {
191
+ reg.options.interval = updates.interval;
192
+ reg.options.schedule = undefined;
193
+ }
194
+ }
195
+ // Restart timer if active
196
+ if (reg.status === 'active') {
197
+ this._stopTimer(reg);
198
+ this._startTimer(reg);
199
+ }
200
+ }
201
+ get storage() {
202
+ return this._storage;
203
+ }
204
+ // ── Private ────────────────────────────────────────────────────
205
+ _toDto(reg) {
206
+ return {
207
+ id: reg.id,
208
+ name: reg.options.name ?? 'unnamed',
209
+ description: reg.options.description ?? reg.options.name ?? 'unnamed',
210
+ group: reg.options.group,
211
+ status: reg.status,
212
+ schedule: reg.options.schedule,
213
+ interval: reg.options.interval,
214
+ enabled: reg.options.enabled !== false,
215
+ maxRetries: reg.options.maxRetries ?? 1,
216
+ retryDelay: reg.options.retryDelay ?? '5s',
217
+ retryStrategy: reg.options.retryStrategy ?? 'exponential',
218
+ timeout: reg.options.timeout,
219
+ overlapPolicy: reg.options.overlapPolicy ?? 'skip',
220
+ currentExecutionId: reg.currentExecutionId,
221
+ nextRunAt: reg.nextRunAt,
222
+ lastRunAt: reg.lastRunAt,
223
+ lastRunStatus: reg.lastRunStatus,
224
+ lastRunDuration: reg.lastRunDuration,
225
+ };
226
+ }
227
+ _startTimer(reg) {
228
+ if (reg.options.schedule) {
229
+ this._startCronTimer(reg);
230
+ }
231
+ else if (reg.options.interval) {
232
+ this._startIntervalTimer(reg);
233
+ }
234
+ }
235
+ _startCronTimer(reg) {
236
+ const scheduleNext = () => {
237
+ if (!this._running || reg.status !== 'active')
238
+ return;
239
+ try {
240
+ const expr = cron_parser_1.CronExpressionParser.parse(reg.options.schedule);
241
+ const next = expr.next();
242
+ const nextDate = next.toDate();
243
+ reg.nextRunAt = nextDate.toISOString();
244
+ const delay = nextDate.getTime() - Date.now();
245
+ reg.timer = setTimeout(async () => {
246
+ if (reg.status !== 'active' || !this._running)
247
+ return;
248
+ await this._handleTimerFire(reg);
249
+ scheduleNext();
250
+ }, Math.max(delay, 0));
251
+ reg.timerType = 'cron';
252
+ }
253
+ catch {
254
+ // Invalid cron expression — stop scheduling
255
+ }
256
+ };
257
+ scheduleNext();
258
+ }
259
+ _startIntervalTimer(reg) {
260
+ const ms = (0, interval_parser_1.parseInterval)(reg.options.interval);
261
+ if (ms === null)
262
+ return;
263
+ reg.nextRunAt = new Date(Date.now() + ms).toISOString();
264
+ reg.timer = setInterval(async () => {
265
+ if (reg.status !== 'active' || !this._running)
266
+ return;
267
+ await this._handleTimerFire(reg);
268
+ reg.nextRunAt = new Date(Date.now() + ms).toISOString();
269
+ }, ms);
270
+ reg.timerType = 'interval';
271
+ }
272
+ async _handleTimerFire(reg) {
273
+ if (reg.currentExecutionId) {
274
+ const policy = reg.options.overlapPolicy ?? 'skip';
275
+ if (policy === 'skip')
276
+ return;
277
+ if (policy === 'cancel') {
278
+ reg.currentAbortController?.abort();
279
+ await new Promise((r) => setTimeout(r, 50));
280
+ }
281
+ if (policy === 'queue') {
282
+ return new Promise((resolve) => {
283
+ reg.queue.push({ resolve });
284
+ });
285
+ }
286
+ }
287
+ await this._executeJobAsync(reg, 0);
288
+ }
289
+ async _executeJobAsync(reg, retryAttempt) {
290
+ const executionId = (0, crypto_1.randomUUID)();
291
+ const abortController = new AbortController();
292
+ reg.currentExecutionId = executionId;
293
+ reg.currentAbortController = abortController;
294
+ const execution = {
295
+ id: executionId,
296
+ jobId: reg.id,
297
+ jobName: reg.options.name ?? 'unnamed',
298
+ status: 'running',
299
+ startedAt: new Date().toISOString(),
300
+ logs: [],
301
+ retryAttempt,
302
+ };
303
+ await this._storage.saveExecution(execution);
304
+ this._broadcast({
305
+ type: 'job:started',
306
+ jobId: reg.id,
307
+ executionId,
308
+ timestamp: execution.startedAt,
309
+ });
310
+ const context = new cli_job_execution_context_1.CliJobExecutionContext();
311
+ let timeoutTimer;
312
+ // Set up timeout
313
+ if (reg.options.timeout) {
314
+ const timeoutMs = (0, interval_parser_1.parseInterval)(reg.options.timeout);
315
+ if (timeoutMs !== null) {
316
+ timeoutTimer = setTimeout(() => {
317
+ abortController.abort();
318
+ }, timeoutMs);
319
+ }
320
+ }
321
+ let finalStatus = 'completed';
322
+ let error;
323
+ try {
324
+ await reg.job.executeAsync(context, abortController.signal);
325
+ if (abortController.signal.aborted) {
326
+ // Determine if this was a timeout or manual cancel
327
+ finalStatus = timeoutTimer ? 'timed_out' : 'cancelled';
328
+ }
329
+ }
330
+ catch (err) {
331
+ if (abortController.signal.aborted) {
332
+ finalStatus = timeoutTimer ? 'timed_out' : 'cancelled';
333
+ }
334
+ else {
335
+ finalStatus = 'failed';
336
+ error = err instanceof Error ? err.message : String(err);
337
+ }
338
+ }
339
+ finally {
340
+ if (timeoutTimer)
341
+ clearTimeout(timeoutTimer);
342
+ }
343
+ const completedAt = new Date();
344
+ const duration = completedAt.getTime() - new Date(execution.startedAt).getTime();
345
+ execution.status = finalStatus;
346
+ execution.completedAt = completedAt.toISOString();
347
+ execution.duration = duration;
348
+ execution.error = error;
349
+ execution.logs = context.logEntries;
350
+ await this._storage.saveExecution(execution);
351
+ reg.currentExecutionId = undefined;
352
+ reg.currentAbortController = undefined;
353
+ reg.lastRunAt = execution.startedAt;
354
+ reg.lastRunStatus = finalStatus;
355
+ reg.lastRunDuration = duration;
356
+ // Persist state
357
+ await this._persistState(reg);
358
+ // Broadcast completion event
359
+ if (finalStatus === 'completed') {
360
+ this._broadcast({ type: 'job:completed', jobId: reg.id, executionId, duration });
361
+ }
362
+ else if (finalStatus === 'failed') {
363
+ this._broadcast({ type: 'job:failed', jobId: reg.id, executionId, error });
364
+ }
365
+ else if (finalStatus === 'cancelled') {
366
+ this._broadcast({ type: 'job:cancelled', jobId: reg.id, executionId });
367
+ }
368
+ else if (finalStatus === 'timed_out') {
369
+ this._broadcast({ type: 'job:timed_out', jobId: reg.id, executionId, timeout: reg.options.timeout });
370
+ }
371
+ // Handle retry on failure
372
+ if (finalStatus === 'failed' && retryAttempt < (reg.options.maxRetries ?? 1)) {
373
+ const baseDelay = (0, interval_parser_1.parseInterval)(reg.options.retryDelay ?? '5s') ?? 5000;
374
+ const strategy = reg.options.retryStrategy ?? 'exponential';
375
+ const delay = strategy === 'fixed' ? baseDelay
376
+ : strategy === 'linear' ? baseDelay * (retryAttempt + 1)
377
+ : baseDelay * Math.pow(2, retryAttempt);
378
+ this._broadcast({
379
+ type: 'job:retrying',
380
+ jobId: reg.id,
381
+ executionId,
382
+ attempt: retryAttempt + 1,
383
+ maxRetries: reg.options.maxRetries ?? 1,
384
+ delayMs: delay,
385
+ });
386
+ await new Promise(resolve => setTimeout(resolve, delay));
387
+ await this._executeJobAsync(reg, retryAttempt + 1);
388
+ return;
389
+ }
390
+ // Process queue
391
+ if (reg.queue.length > 0) {
392
+ const next = reg.queue.shift();
393
+ next.resolve();
394
+ await this._executeJobAsync(reg, 0);
395
+ }
396
+ }
397
+ _stopTimer(reg) {
398
+ if (reg.timer !== undefined) {
399
+ if (reg.timerType === 'interval') {
400
+ clearInterval(reg.timer);
401
+ }
402
+ else {
403
+ clearTimeout(reg.timer);
404
+ }
405
+ reg.timer = undefined;
406
+ reg.timerType = undefined;
407
+ }
408
+ reg.nextRunAt = undefined;
409
+ }
410
+ async _persistState(reg) {
411
+ await this._storage.saveJobState(reg.id, {
412
+ status: reg.status,
413
+ lastRunAt: reg.lastRunAt,
414
+ updatedAt: new Date().toISOString(),
415
+ });
416
+ }
417
+ _broadcast(message) {
418
+ if (this._broadcastFn) {
419
+ this._broadcastFn(message);
420
+ }
421
+ }
422
+ }
423
+ exports.CliJobScheduler = CliJobScheduler;
424
+ class JobError extends Error {
425
+ code;
426
+ statusCode;
427
+ constructor(message, code, statusCode) {
428
+ super(message);
429
+ this.code = code;
430
+ this.statusCode = statusCode;
431
+ this.name = 'JobError';
432
+ }
433
+ }
434
+ exports.JobError = JobError;
435
+ //# sourceMappingURL=cli-job-scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-job-scheduler.js","sourceRoot":"","sources":["../cli-job-scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import { ICliJob, CliJobOptions, ICliJobStorageProvider } from '@qodalis/cli-server-abstractions';
2
+ import { Router } from 'express';
3
+ import { CliJobScheduler } from './cli-job-scheduler';
4
+ export interface CliJobsPluginResult {
5
+ /** Express router — mount at your preferred path (e.g. `/api/v1/qcli/jobs`). */
6
+ router: Router;
7
+ /** The job scheduler instance. Call `start()` / `stop()` to manage its lifecycle. */
8
+ scheduler: CliJobScheduler;
9
+ }
10
+ /**
11
+ * Fluent builder for configuring the jobs plugin independently of the core CLI server.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { CliJobsBuilder } from '@qodalis/cli-server-plugin-jobs';
16
+ *
17
+ * const jobsPlugin = new CliJobsBuilder()
18
+ * .addJob(new SampleHealthCheckJob(), { name: 'health-check', interval: '30s' })
19
+ * .build((msg) => eventSocketManager.broadcastMessage(msg));
20
+ *
21
+ * app.use('/api/v1/qcli/jobs', jobsPlugin.router);
22
+ * await jobsPlugin.scheduler.start();
23
+ * ```
24
+ */
25
+ export declare class CliJobsBuilder {
26
+ private readonly _jobs;
27
+ private _storageProvider?;
28
+ /**
29
+ * Register a job to be managed by the scheduler.
30
+ */
31
+ addJob(job: ICliJob, options: CliJobOptions): CliJobsBuilder;
32
+ /**
33
+ * Set a custom storage provider for job state and execution history.
34
+ * If not set, an in-memory provider will be used.
35
+ */
36
+ setStorageProvider(provider: ICliJobStorageProvider): CliJobsBuilder;
37
+ /**
38
+ * Build the plugin, returning the Express router and scheduler.
39
+ *
40
+ * @param broadcastFn Optional function to broadcast job events (e.g. via WebSocket).
41
+ */
42
+ build(broadcastFn?: (message: Record<string, unknown>) => void): CliJobsPluginResult;
43
+ }
44
+ //# sourceMappingURL=cli-jobs-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-jobs-builder.d.ts","sourceRoot":"","sources":["../cli-jobs-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAClG,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,WAAW,mBAAmB;IAChC,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,SAAS,EAAE,eAAe,CAAC;CAC9B;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuD;IAC7E,OAAO,CAAC,gBAAgB,CAAC,CAAyB;IAElD;;OAEG;IACH,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,GAAG,cAAc;IAK5D;;;OAGG;IACH,kBAAkB,CAAC,QAAQ,EAAE,sBAAsB,GAAG,cAAc;IAKpE;;;;OAIG;IACH,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,GAAG,mBAAmB;CAgBvF"}
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CliJobsBuilder = void 0;
4
+ const cli_job_scheduler_1 = require("./cli-job-scheduler");
5
+ const in_memory_job_storage_provider_1 = require("./in-memory-job-storage-provider");
6
+ const cli_jobs_controller_1 = require("./cli-jobs-controller");
7
+ /**
8
+ * Fluent builder for configuring the jobs plugin independently of the core CLI server.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { CliJobsBuilder } from '@qodalis/cli-server-plugin-jobs';
13
+ *
14
+ * const jobsPlugin = new CliJobsBuilder()
15
+ * .addJob(new SampleHealthCheckJob(), { name: 'health-check', interval: '30s' })
16
+ * .build((msg) => eventSocketManager.broadcastMessage(msg));
17
+ *
18
+ * app.use('/api/v1/qcli/jobs', jobsPlugin.router);
19
+ * await jobsPlugin.scheduler.start();
20
+ * ```
21
+ */
22
+ class CliJobsBuilder {
23
+ _jobs = [];
24
+ _storageProvider;
25
+ /**
26
+ * Register a job to be managed by the scheduler.
27
+ */
28
+ addJob(job, options) {
29
+ this._jobs.push({ job, options });
30
+ return this;
31
+ }
32
+ /**
33
+ * Set a custom storage provider for job state and execution history.
34
+ * If not set, an in-memory provider will be used.
35
+ */
36
+ setStorageProvider(provider) {
37
+ this._storageProvider = provider;
38
+ return this;
39
+ }
40
+ /**
41
+ * Build the plugin, returning the Express router and scheduler.
42
+ *
43
+ * @param broadcastFn Optional function to broadcast job events (e.g. via WebSocket).
44
+ */
45
+ build(broadcastFn) {
46
+ const storage = this._storageProvider ?? new in_memory_job_storage_provider_1.InMemoryJobStorageProvider();
47
+ const scheduler = new cli_job_scheduler_1.CliJobScheduler(storage);
48
+ for (const { job, options } of this._jobs) {
49
+ scheduler.register(job, options);
50
+ }
51
+ if (broadcastFn) {
52
+ scheduler.setBroadcastFn(broadcastFn);
53
+ }
54
+ const router = (0, cli_jobs_controller_1.createCliJobsController)(scheduler, storage);
55
+ return { router, scheduler };
56
+ }
57
+ }
58
+ exports.CliJobsBuilder = CliJobsBuilder;
59
+ //# sourceMappingURL=cli-jobs-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-jobs-builder.js","sourceRoot":"","sources":["../cli-jobs-builder.ts"],"names":[],"mappings":";;;AAEA,2DAAsD;AACtD,qFAA8E;AAC9E,+DAAgE;AAShE;;;;;;;;;;;;;;GAcG;AACH,MAAa,cAAc;IACN,KAAK,GAAoD,EAAE,CAAC;IACrE,gBAAgB,CAA0B;IAElD;;OAEG;IACH,MAAM,CAAC,GAAY,EAAE,OAAsB;QACvC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;OAGG;IACH,kBAAkB,CAAC,QAAgC;QAC/C,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;QACjC,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,WAAwD;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,IAAI,IAAI,2DAA0B,EAAE,CAAC;QAC1E,MAAM,SAAS,GAAG,IAAI,mCAAe,CAAC,OAAO,CAAC,CAAC;QAE/C,KAAK,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACxC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QACrC,CAAC;QAED,IAAI,WAAW,EAAE,CAAC;YACd,SAAS,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,MAAM,GAAG,IAAA,6CAAuB,EAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAE3D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACjC,CAAC;CACJ;AA1CD,wCA0CC"}
@@ -0,0 +1,5 @@
1
+ import { Router } from 'express';
2
+ import { CliJobScheduler } from './cli-job-scheduler';
3
+ import { ICliJobStorageProvider } from '@qodalis/cli-server-abstractions';
4
+ export declare function createCliJobsController(scheduler: CliJobScheduler, storage: ICliJobStorageProvider): Router;
5
+ //# sourceMappingURL=cli-jobs-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-jobs-controller.d.ts","sourceRoot":"","sources":["../cli-jobs-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,eAAe,EAAY,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAsB,MAAM,kCAAkC,CAAC;AAE9F,wBAAgB,uBAAuB,CACnC,SAAS,EAAE,eAAe,EAC1B,OAAO,EAAE,sBAAsB,GAChC,MAAM,CAqIR"}