@guren/server 0.2.0-alpha.7 → 1.0.0-rc.9

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 (54) hide show
  1. package/dist/Application-DtWDHXr1.d.ts +2110 -0
  2. package/dist/BroadcastManager-AkIWUGJo.d.ts +466 -0
  3. package/dist/CacheManager-BkvHEOZX.d.ts +244 -0
  4. package/dist/ConsoleKernel-CqCVrdZs.d.ts +207 -0
  5. package/dist/EventManager-CmIoLt7r.d.ts +207 -0
  6. package/dist/Gate-CNkBYf8m.d.ts +268 -0
  7. package/dist/HealthManager-DUyMIzsZ.d.ts +141 -0
  8. package/dist/I18nManager-Dtgzsf5n.d.ts +270 -0
  9. package/dist/LogManager-7mxnkaPM.d.ts +256 -0
  10. package/dist/MailManager-DpMvYiP9.d.ts +292 -0
  11. package/dist/Scheduler-BstvSca7.d.ts +469 -0
  12. package/dist/StorageManager-oZTHqaza.d.ts +337 -0
  13. package/dist/api-token-JOif2CtG.d.ts +1792 -0
  14. package/dist/app-key-CsBfRC_Q.d.ts +214 -0
  15. package/dist/auth/index.d.ts +418 -0
  16. package/dist/auth/index.js +6742 -0
  17. package/dist/authorization/index.d.ts +129 -0
  18. package/dist/authorization/index.js +621 -0
  19. package/dist/broadcasting/index.d.ts +233 -0
  20. package/dist/broadcasting/index.js +907 -0
  21. package/dist/cache/index.d.ts +233 -0
  22. package/dist/cache/index.js +817 -0
  23. package/dist/encryption/index.d.ts +222 -0
  24. package/dist/encryption/index.js +602 -0
  25. package/dist/events/index.d.ts +155 -0
  26. package/dist/events/index.js +330 -0
  27. package/dist/health/index.d.ts +185 -0
  28. package/dist/health/index.js +379 -0
  29. package/dist/i18n/index.d.ts +101 -0
  30. package/dist/i18n/index.js +597 -0
  31. package/dist/index-9_Jzj5jo.d.ts +7 -0
  32. package/dist/index.d.ts +2628 -619
  33. package/dist/index.js +22229 -3116
  34. package/dist/lambda/index.d.ts +156 -0
  35. package/dist/lambda/index.js +91 -0
  36. package/dist/logging/index.d.ts +50 -0
  37. package/dist/logging/index.js +557 -0
  38. package/dist/mail/index.d.ts +288 -0
  39. package/dist/mail/index.js +695 -0
  40. package/dist/mcp/index.d.ts +139 -0
  41. package/dist/mcp/index.js +382 -0
  42. package/dist/notifications/index.d.ts +271 -0
  43. package/dist/notifications/index.js +741 -0
  44. package/dist/queue/index.d.ts +423 -0
  45. package/dist/queue/index.js +958 -0
  46. package/dist/runtime/index.d.ts +93 -0
  47. package/dist/runtime/index.js +834 -0
  48. package/dist/scheduling/index.d.ts +41 -0
  49. package/dist/scheduling/index.js +836 -0
  50. package/dist/storage/index.d.ts +196 -0
  51. package/dist/storage/index.js +832 -0
  52. package/dist/vite/index.js +203 -3
  53. package/package.json +93 -6
  54. package/dist/chunk-FK2XQSBF.js +0 -160
@@ -0,0 +1,836 @@
1
+ // src/scheduling/CronParser.ts
2
+ function parseField(field, min, max) {
3
+ const values = /* @__PURE__ */ new Set();
4
+ const parts = field.split(",");
5
+ for (const part of parts) {
6
+ const stepMatch = part.match(/^(.+)\/(\d+)$/);
7
+ let range;
8
+ let step = 1;
9
+ if (stepMatch) {
10
+ range = stepMatch[1];
11
+ step = parseInt(stepMatch[2], 10);
12
+ } else {
13
+ range = part;
14
+ }
15
+ if (range === "*") {
16
+ for (let i = min; i <= max; i += step) {
17
+ values.add(i);
18
+ }
19
+ continue;
20
+ }
21
+ const rangeMatch = range.match(/^(\d+)-(\d+)$/);
22
+ if (rangeMatch) {
23
+ const start = parseInt(rangeMatch[1], 10);
24
+ const end = parseInt(rangeMatch[2], 10);
25
+ for (let i = start; i <= end; i += step) {
26
+ if (i >= min && i <= max) {
27
+ values.add(i);
28
+ }
29
+ }
30
+ continue;
31
+ }
32
+ const value = parseInt(range, 10);
33
+ if (!isNaN(value) && value >= min && value <= max) {
34
+ values.add(value);
35
+ }
36
+ }
37
+ return Array.from(values).sort((a, b) => a - b);
38
+ }
39
+ function parseCron(expression) {
40
+ const parts = expression.trim().split(/\s+/);
41
+ if (parts.length !== 5) {
42
+ throw new Error(`Invalid cron expression: ${expression}. Expected 5 fields.`);
43
+ }
44
+ return {
45
+ minute: parseField(parts[0], 0, 59),
46
+ hour: parseField(parts[1], 0, 23),
47
+ dayOfMonth: parseField(parts[2], 1, 31),
48
+ month: parseField(parts[3], 1, 12),
49
+ dayOfWeek: parseField(parts[4], 0, 6)
50
+ // 0 = Sunday
51
+ };
52
+ }
53
+ function matchesCron(date, cron) {
54
+ const minute = date.getMinutes();
55
+ const hour = date.getHours();
56
+ const dayOfMonth = date.getDate();
57
+ const month = date.getMonth() + 1;
58
+ const dayOfWeek = date.getDay();
59
+ return cron.minute.includes(minute) && cron.hour.includes(hour) && cron.dayOfMonth.includes(dayOfMonth) && cron.month.includes(month) && cron.dayOfWeek.includes(dayOfWeek);
60
+ }
61
+ function getNextOccurrence(expression, from = /* @__PURE__ */ new Date()) {
62
+ const cron = parseCron(expression);
63
+ const next = new Date(from);
64
+ next.setSeconds(0);
65
+ next.setMilliseconds(0);
66
+ next.setMinutes(next.getMinutes() + 1);
67
+ const maxIterations = 525600;
68
+ let iterations = 0;
69
+ while (iterations < maxIterations) {
70
+ if (matchesCron(next, cron)) {
71
+ return next;
72
+ }
73
+ next.setMinutes(next.getMinutes() + 1);
74
+ iterations++;
75
+ }
76
+ throw new Error(`Could not find next occurrence for: ${expression}`);
77
+ }
78
+ function isDue(expression, date = /* @__PURE__ */ new Date()) {
79
+ const cron = parseCron(expression);
80
+ return matchesCron(date, cron);
81
+ }
82
+ function getNextOccurrences(expression, count, from = /* @__PURE__ */ new Date()) {
83
+ const occurrences = [];
84
+ let current = from;
85
+ for (let i = 0; i < count; i++) {
86
+ const next = getNextOccurrence(expression, current);
87
+ occurrences.push(next);
88
+ current = next;
89
+ }
90
+ return occurrences;
91
+ }
92
+ function toTimezone(date, timezone) {
93
+ const options = {
94
+ timeZone: timezone,
95
+ year: "numeric",
96
+ month: "2-digit",
97
+ day: "2-digit",
98
+ hour: "2-digit",
99
+ minute: "2-digit",
100
+ second: "2-digit",
101
+ hour12: false
102
+ };
103
+ const formatter = new Intl.DateTimeFormat("en-US", options);
104
+ const parts = formatter.formatToParts(date);
105
+ const get = (type) => parts.find((p) => p.type === type)?.value ?? "0";
106
+ const year = parseInt(get("year"), 10);
107
+ const month = parseInt(get("month"), 10) - 1;
108
+ const day = parseInt(get("day"), 10);
109
+ const hour = parseInt(get("hour"), 10);
110
+ const minute = parseInt(get("minute"), 10);
111
+ const second = parseInt(get("second"), 10);
112
+ return new Date(year, month, day, hour, minute, second);
113
+ }
114
+ function isDueInTimezone(expression, timezone, date = /* @__PURE__ */ new Date()) {
115
+ const localDate = toTimezone(date, timezone);
116
+ return isDue(expression, localDate);
117
+ }
118
+
119
+ // src/scheduling/ScheduledTask.ts
120
+ var ScheduledTask = class {
121
+ definition;
122
+ lastRun = null;
123
+ isRunning = false;
124
+ constructor(definition) {
125
+ this.definition = definition;
126
+ }
127
+ /**
128
+ * Get the task name.
129
+ */
130
+ getName() {
131
+ return this.definition.name ?? "anonymous";
132
+ }
133
+ /**
134
+ * Get the cron expression.
135
+ */
136
+ getExpression() {
137
+ return this.definition.expression;
138
+ }
139
+ /**
140
+ * Get the timezone.
141
+ */
142
+ getTimezone() {
143
+ return this.definition.timezone;
144
+ }
145
+ /**
146
+ * Check if the task is due.
147
+ */
148
+ isDue(date = /* @__PURE__ */ new Date()) {
149
+ if (this.definition.timezone) {
150
+ return isDueInTimezone(this.definition.expression, this.definition.timezone, date);
151
+ }
152
+ return isDue(this.definition.expression, date);
153
+ }
154
+ /**
155
+ * Check if the task should run based on conditions.
156
+ * Note: Overlap checking is handled separately in run() to prevent race conditions.
157
+ */
158
+ async shouldRun() {
159
+ if (this.definition.when) {
160
+ const result = await this.definition.when();
161
+ if (!result) {
162
+ return false;
163
+ }
164
+ }
165
+ if (this.definition.skip) {
166
+ const result = await this.definition.skip();
167
+ if (result) {
168
+ return false;
169
+ }
170
+ }
171
+ return true;
172
+ }
173
+ /**
174
+ * Run the task.
175
+ */
176
+ async run() {
177
+ if (this.definition.withoutOverlapping) {
178
+ if (this.isRunning) {
179
+ return;
180
+ }
181
+ this.isRunning = true;
182
+ }
183
+ if (!await this.shouldRun()) {
184
+ if (this.definition.withoutOverlapping) {
185
+ this.isRunning = false;
186
+ }
187
+ return;
188
+ }
189
+ if (!this.definition.withoutOverlapping) {
190
+ this.isRunning = true;
191
+ }
192
+ let error = null;
193
+ try {
194
+ if (this.definition.before) {
195
+ await this.definition.before();
196
+ }
197
+ await this.definition.callback();
198
+ this.lastRun = /* @__PURE__ */ new Date();
199
+ if (this.definition.onSuccess) {
200
+ await this.definition.onSuccess();
201
+ }
202
+ } catch (err) {
203
+ error = err instanceof Error ? err : new Error(String(err));
204
+ if (this.definition.onFailure) {
205
+ await this.definition.onFailure(error);
206
+ }
207
+ } finally {
208
+ this.isRunning = false;
209
+ if (this.definition.after) {
210
+ await this.definition.after();
211
+ }
212
+ }
213
+ if (error) {
214
+ throw error;
215
+ }
216
+ }
217
+ /**
218
+ * Get the last run time.
219
+ */
220
+ getLastRun() {
221
+ return this.lastRun;
222
+ }
223
+ /**
224
+ * Check if the task is currently running.
225
+ */
226
+ isCurrentlyRunning() {
227
+ return this.isRunning;
228
+ }
229
+ /**
230
+ * Get the task definition.
231
+ */
232
+ getDefinition() {
233
+ return { ...this.definition };
234
+ }
235
+ };
236
+
237
+ // src/scheduling/Schedule.ts
238
+ var PendingSchedule = class {
239
+ constructor(callback) {
240
+ this.callback = callback;
241
+ }
242
+ expression = "* * * * *";
243
+ timezone;
244
+ taskName;
245
+ withoutOverlapping = false;
246
+ overlapExpiresAt;
247
+ onOneServer = false;
248
+ whenCallback;
249
+ skipCallback;
250
+ beforeCallback;
251
+ afterCallback;
252
+ successCallback;
253
+ failureCallback;
254
+ // ===== Frequency Methods =====
255
+ /**
256
+ * Run every minute.
257
+ */
258
+ everyMinute() {
259
+ this.expression = "* * * * *";
260
+ return this;
261
+ }
262
+ /**
263
+ * Run every two minutes.
264
+ */
265
+ everyTwoMinutes() {
266
+ this.expression = "*/2 * * * *";
267
+ return this;
268
+ }
269
+ /**
270
+ * Run every three minutes.
271
+ */
272
+ everyThreeMinutes() {
273
+ this.expression = "*/3 * * * *";
274
+ return this;
275
+ }
276
+ /**
277
+ * Run every four minutes.
278
+ */
279
+ everyFourMinutes() {
280
+ this.expression = "*/4 * * * *";
281
+ return this;
282
+ }
283
+ /**
284
+ * Run every five minutes.
285
+ */
286
+ everyFiveMinutes() {
287
+ this.expression = "*/5 * * * *";
288
+ return this;
289
+ }
290
+ /**
291
+ * Run every ten minutes.
292
+ */
293
+ everyTenMinutes() {
294
+ this.expression = "*/10 * * * *";
295
+ return this;
296
+ }
297
+ /**
298
+ * Run every fifteen minutes.
299
+ */
300
+ everyFifteenMinutes() {
301
+ this.expression = "*/15 * * * *";
302
+ return this;
303
+ }
304
+ /**
305
+ * Run every thirty minutes.
306
+ */
307
+ everyThirtyMinutes() {
308
+ this.expression = "*/30 * * * *";
309
+ return this;
310
+ }
311
+ /**
312
+ * Run hourly.
313
+ */
314
+ hourly() {
315
+ this.expression = "0 * * * *";
316
+ return this;
317
+ }
318
+ /**
319
+ * Run hourly at a specific minute.
320
+ */
321
+ hourlyAt(minute) {
322
+ this.expression = `${minute} * * * *`;
323
+ return this;
324
+ }
325
+ /**
326
+ * Run every two hours.
327
+ */
328
+ everyTwoHours() {
329
+ this.expression = "0 */2 * * *";
330
+ return this;
331
+ }
332
+ /**
333
+ * Run every three hours.
334
+ */
335
+ everyThreeHours() {
336
+ this.expression = "0 */3 * * *";
337
+ return this;
338
+ }
339
+ /**
340
+ * Run every four hours.
341
+ */
342
+ everyFourHours() {
343
+ this.expression = "0 */4 * * *";
344
+ return this;
345
+ }
346
+ /**
347
+ * Run every six hours.
348
+ */
349
+ everySixHours() {
350
+ this.expression = "0 */6 * * *";
351
+ return this;
352
+ }
353
+ /**
354
+ * Run daily at midnight.
355
+ */
356
+ daily() {
357
+ this.expression = "0 0 * * *";
358
+ return this;
359
+ }
360
+ /**
361
+ * Run daily at a specific time.
362
+ * @param time Time in HH:MM format
363
+ */
364
+ dailyAt(time) {
365
+ const [hour, minute] = time.split(":").map((n) => parseInt(n, 10));
366
+ this.expression = `${minute ?? 0} ${hour ?? 0} * * *`;
367
+ return this;
368
+ }
369
+ /**
370
+ * Alias for dailyAt.
371
+ */
372
+ at(time) {
373
+ return this.dailyAt(time);
374
+ }
375
+ /**
376
+ * Run twice daily.
377
+ */
378
+ twiceDaily(firstHour = 1, secondHour = 13) {
379
+ this.expression = `0 ${firstHour},${secondHour} * * *`;
380
+ return this;
381
+ }
382
+ /**
383
+ * Run weekly on Sunday at midnight.
384
+ */
385
+ weekly() {
386
+ this.expression = "0 0 * * 0";
387
+ return this;
388
+ }
389
+ /**
390
+ * Run weekly on a specific day at a specific time.
391
+ * @param day Day of week (0 = Sunday, 6 = Saturday)
392
+ * @param time Time in HH:MM format
393
+ */
394
+ weeklyOn(day, time = "00:00") {
395
+ const [hour, minute] = time.split(":").map((n) => parseInt(n, 10));
396
+ this.expression = `${minute ?? 0} ${hour ?? 0} * * ${day}`;
397
+ return this;
398
+ }
399
+ // Day of week shortcuts
400
+ sundays() {
401
+ const parts = this.expression.split(" ");
402
+ parts[4] = "0";
403
+ this.expression = parts.join(" ");
404
+ return this;
405
+ }
406
+ mondays() {
407
+ const parts = this.expression.split(" ");
408
+ parts[4] = "1";
409
+ this.expression = parts.join(" ");
410
+ return this;
411
+ }
412
+ tuesdays() {
413
+ const parts = this.expression.split(" ");
414
+ parts[4] = "2";
415
+ this.expression = parts.join(" ");
416
+ return this;
417
+ }
418
+ wednesdays() {
419
+ const parts = this.expression.split(" ");
420
+ parts[4] = "3";
421
+ this.expression = parts.join(" ");
422
+ return this;
423
+ }
424
+ thursdays() {
425
+ const parts = this.expression.split(" ");
426
+ parts[4] = "4";
427
+ this.expression = parts.join(" ");
428
+ return this;
429
+ }
430
+ fridays() {
431
+ const parts = this.expression.split(" ");
432
+ parts[4] = "5";
433
+ this.expression = parts.join(" ");
434
+ return this;
435
+ }
436
+ saturdays() {
437
+ const parts = this.expression.split(" ");
438
+ parts[4] = "6";
439
+ this.expression = parts.join(" ");
440
+ return this;
441
+ }
442
+ /**
443
+ * Run on weekdays (Monday-Friday).
444
+ */
445
+ weekdays() {
446
+ const parts = this.expression.split(" ");
447
+ parts[4] = "1-5";
448
+ this.expression = parts.join(" ");
449
+ return this;
450
+ }
451
+ /**
452
+ * Run on weekends (Saturday-Sunday).
453
+ */
454
+ weekends() {
455
+ const parts = this.expression.split(" ");
456
+ parts[4] = "0,6";
457
+ this.expression = parts.join(" ");
458
+ return this;
459
+ }
460
+ /**
461
+ * Run monthly on the first day at midnight.
462
+ */
463
+ monthly() {
464
+ this.expression = "0 0 1 * *";
465
+ return this;
466
+ }
467
+ /**
468
+ * Run monthly on a specific day at a specific time.
469
+ */
470
+ monthlyOn(day, time = "00:00") {
471
+ const [hour, minute] = time.split(":").map((n) => parseInt(n, 10));
472
+ this.expression = `${minute ?? 0} ${hour ?? 0} ${day} * *`;
473
+ return this;
474
+ }
475
+ /**
476
+ * Run on the last day of the month.
477
+ */
478
+ lastDayOfMonth(time = "00:00") {
479
+ const [hour, minute] = time.split(":").map((n) => parseInt(n, 10));
480
+ this.expression = `${minute ?? 0} ${hour ?? 0} 28-31 * *`;
481
+ return this;
482
+ }
483
+ /**
484
+ * Run quarterly.
485
+ */
486
+ quarterly() {
487
+ this.expression = "0 0 1 1,4,7,10 *";
488
+ return this;
489
+ }
490
+ /**
491
+ * Run yearly on January 1st at midnight.
492
+ */
493
+ yearly() {
494
+ this.expression = "0 0 1 1 *";
495
+ return this;
496
+ }
497
+ /**
498
+ * Run yearly on a specific date.
499
+ */
500
+ yearlyOn(month, day, time = "00:00") {
501
+ const [hour, minute] = time.split(":").map((n) => parseInt(n, 10));
502
+ this.expression = `${minute ?? 0} ${hour ?? 0} ${day} ${month} *`;
503
+ return this;
504
+ }
505
+ /**
506
+ * Set a custom cron expression.
507
+ */
508
+ cron(expression) {
509
+ this.expression = expression;
510
+ return this;
511
+ }
512
+ // ===== Configuration Methods =====
513
+ /**
514
+ * Set the task name.
515
+ */
516
+ name(name) {
517
+ this.taskName = name;
518
+ return this;
519
+ }
520
+ /**
521
+ * Set the timezone.
522
+ */
523
+ tz(timezone) {
524
+ this.timezone = timezone;
525
+ return this;
526
+ }
527
+ /**
528
+ * Alias for tz().
529
+ */
530
+ setTimezone(timezone) {
531
+ return this.tz(timezone);
532
+ }
533
+ /**
534
+ * Prevent overlapping executions.
535
+ */
536
+ preventOverlapping(expiresAt) {
537
+ this.withoutOverlapping = true;
538
+ this.overlapExpiresAt = expiresAt;
539
+ return this;
540
+ }
541
+ /**
542
+ * Alias for preventOverlapping().
543
+ */
544
+ withoutOverlaps(expiresAt) {
545
+ return this.preventOverlapping(expiresAt);
546
+ }
547
+ /**
548
+ * Only run on one server.
549
+ */
550
+ runOnOneServer() {
551
+ this.onOneServer = true;
552
+ return this;
553
+ }
554
+ /**
555
+ * Set a condition for running.
556
+ */
557
+ when(callback) {
558
+ this.whenCallback = callback;
559
+ return this;
560
+ }
561
+ /**
562
+ * Set a condition to skip execution.
563
+ */
564
+ skip(callback) {
565
+ this.skipCallback = callback;
566
+ return this;
567
+ }
568
+ /**
569
+ * Set a before callback.
570
+ */
571
+ before(callback) {
572
+ this.beforeCallback = callback;
573
+ return this;
574
+ }
575
+ /**
576
+ * Set an after callback.
577
+ */
578
+ after(callback) {
579
+ this.afterCallback = callback;
580
+ return this;
581
+ }
582
+ /**
583
+ * Set a success callback.
584
+ */
585
+ onSuccess(callback) {
586
+ this.successCallback = callback;
587
+ return this;
588
+ }
589
+ /**
590
+ * Set a failure callback.
591
+ */
592
+ onFailure(callback) {
593
+ this.failureCallback = callback;
594
+ return this;
595
+ }
596
+ // ===== Build Method =====
597
+ /**
598
+ * Build the task definition.
599
+ */
600
+ build() {
601
+ return {
602
+ name: this.taskName,
603
+ expression: this.expression,
604
+ timezone: this.timezone,
605
+ callback: this.callback,
606
+ withoutOverlapping: this.withoutOverlapping,
607
+ overlapExpiresAt: this.overlapExpiresAt,
608
+ onOneServer: this.onOneServer,
609
+ when: this.whenCallback,
610
+ skip: this.skipCallback,
611
+ before: this.beforeCallback,
612
+ after: this.afterCallback,
613
+ onSuccess: this.successCallback,
614
+ onFailure: this.failureCallback
615
+ };
616
+ }
617
+ /**
618
+ * Build as a ScheduledTask.
619
+ */
620
+ toTask() {
621
+ return new ScheduledTask(this.build());
622
+ }
623
+ };
624
+ var Schedule = class {
625
+ tasks = [];
626
+ /**
627
+ * Schedule a callback.
628
+ */
629
+ call(callback) {
630
+ const pending = new PendingSchedule(callback);
631
+ this.tasks.push(pending);
632
+ return pending;
633
+ }
634
+ /**
635
+ * Schedule a job.
636
+ */
637
+ job(jobClass, payload) {
638
+ return this.call(async () => {
639
+ await jobClass.dispatch(payload);
640
+ });
641
+ }
642
+ /**
643
+ * Schedule a shell command.
644
+ */
645
+ command(cmd) {
646
+ return this.call(async () => {
647
+ const { exec } = await import("child_process");
648
+ const { promisify } = await import("util");
649
+ const execAsync = promisify(exec);
650
+ await execAsync(cmd);
651
+ });
652
+ }
653
+ /**
654
+ * Get all pending schedules.
655
+ */
656
+ getPendingSchedules() {
657
+ return [...this.tasks];
658
+ }
659
+ /**
660
+ * Build all tasks.
661
+ */
662
+ buildTasks() {
663
+ return this.tasks.map((pending) => pending.toTask());
664
+ }
665
+ };
666
+
667
+ // src/scheduling/Scheduler.ts
668
+ var Scheduler = class {
669
+ tasks = [];
670
+ options;
671
+ interval = null;
672
+ isRunning = false;
673
+ lastCheck = null;
674
+ constructor(options = {}) {
675
+ this.options = {
676
+ timezone: options.timezone ?? "UTC",
677
+ checkInterval: options.checkInterval ?? 6e4,
678
+ logger: options.logger ?? (() => {
679
+ })
680
+ };
681
+ }
682
+ /**
683
+ * Define schedules using a callback.
684
+ */
685
+ schedule(definer) {
686
+ const schedule = new Schedule();
687
+ definer(schedule);
688
+ this.tasks.push(...schedule.buildTasks());
689
+ }
690
+ /**
691
+ * Add a pre-built task.
692
+ */
693
+ addTask(task) {
694
+ this.tasks.push(task);
695
+ }
696
+ /**
697
+ * Get all scheduled tasks.
698
+ */
699
+ getTasks() {
700
+ return [...this.tasks];
701
+ }
702
+ /**
703
+ * Get tasks that are due now.
704
+ */
705
+ getDueTasks(date = /* @__PURE__ */ new Date()) {
706
+ return this.tasks.filter((task) => task.isDue(date));
707
+ }
708
+ /**
709
+ * Run all due tasks.
710
+ */
711
+ async runDueTasks(date = /* @__PURE__ */ new Date()) {
712
+ const dueTasks = this.getDueTasks(date);
713
+ for (const task of dueTasks) {
714
+ this.options.logger(`Running task: ${task.getName()}`);
715
+ try {
716
+ await task.run();
717
+ this.options.logger(`Task completed: ${task.getName()}`);
718
+ } catch (error) {
719
+ const message = error instanceof Error ? error.message : String(error);
720
+ this.options.logger(`Task failed: ${task.getName()} - ${message}`);
721
+ }
722
+ }
723
+ }
724
+ /**
725
+ * Start the scheduler.
726
+ */
727
+ start() {
728
+ if (this.isRunning) {
729
+ return;
730
+ }
731
+ this.isRunning = true;
732
+ this.options.logger("Scheduler started");
733
+ this.tick();
734
+ this.interval = setInterval(() => {
735
+ this.tick();
736
+ }, this.options.checkInterval);
737
+ if (this.interval.unref) {
738
+ this.interval.unref();
739
+ }
740
+ }
741
+ /**
742
+ * Stop the scheduler.
743
+ */
744
+ stop() {
745
+ if (!this.isRunning) {
746
+ return;
747
+ }
748
+ if (this.interval) {
749
+ clearInterval(this.interval);
750
+ this.interval = null;
751
+ }
752
+ this.isRunning = false;
753
+ this.options.logger("Scheduler stopped");
754
+ }
755
+ /**
756
+ * Check and run due tasks.
757
+ */
758
+ tick() {
759
+ const now = /* @__PURE__ */ new Date();
760
+ if (this.lastCheck) {
761
+ const lastMinute = Math.floor(this.lastCheck.getTime() / 6e4);
762
+ const currentMinute = Math.floor(now.getTime() / 6e4);
763
+ if (lastMinute === currentMinute) {
764
+ return;
765
+ }
766
+ }
767
+ this.lastCheck = now;
768
+ this.runDueTasks(now).catch((error) => {
769
+ this.options.logger(`Scheduler error: ${error}`);
770
+ });
771
+ }
772
+ /**
773
+ * Check if the scheduler is running.
774
+ */
775
+ getIsRunning() {
776
+ return this.isRunning;
777
+ }
778
+ /**
779
+ * Get the check interval.
780
+ */
781
+ getCheckInterval() {
782
+ return this.options.checkInterval;
783
+ }
784
+ /**
785
+ * Get the default timezone.
786
+ */
787
+ getTimezone() {
788
+ return this.options.timezone;
789
+ }
790
+ /**
791
+ * Clear all tasks.
792
+ */
793
+ clear() {
794
+ this.tasks = [];
795
+ }
796
+ /**
797
+ * Get the number of tasks.
798
+ */
799
+ count() {
800
+ return this.tasks.length;
801
+ }
802
+ /**
803
+ * Get task by name.
804
+ */
805
+ getTask(name) {
806
+ return this.tasks.find((task) => task.getName() === name);
807
+ }
808
+ /**
809
+ * Remove a task by name.
810
+ */
811
+ removeTask(name) {
812
+ const index = this.tasks.findIndex((task) => task.getName() === name);
813
+ if (index !== -1) {
814
+ this.tasks.splice(index, 1);
815
+ return true;
816
+ }
817
+ return false;
818
+ }
819
+ };
820
+ function createScheduler(options) {
821
+ return new Scheduler(options);
822
+ }
823
+ export {
824
+ PendingSchedule,
825
+ Schedule,
826
+ ScheduledTask,
827
+ Scheduler,
828
+ createScheduler,
829
+ getNextOccurrence,
830
+ getNextOccurrences,
831
+ isDue,
832
+ isDueInTimezone,
833
+ matchesCron,
834
+ parseCron,
835
+ toTimezone
836
+ };