@kyo-services/schedulewise 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Timed Job
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,194 @@
1
+ # ScheduleWise
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0.0-blue.svg)](https://www.typescriptlang.org/)
5
+ [![Node Version](https://img.shields.io/node/v/schedulewise)](https://nodejs.org/)
6
+ [![Browser Support](https://img.shields.io/badge/browser-Chrome%20%7C%20Firefox%20%7C%20Safari%20%7C%20Edge-lightgrey)](https://browsersl.ist)
7
+
8
+ A smart and efficient task scheduler for managing periodic jobs with precision timing and intelligent scheduling in both browser and Node.js environments. Built with modern TypeScript features and following best practices for reliable task scheduling.
9
+
10
+ ## 🚀 Features
11
+
12
+ - **Singleton Pattern**: Ensures single scheduler instance across your application
13
+ - **Type-Safe**: Full TypeScript support with type definitions
14
+ - **Flexible Scheduling**: Custom intervals and immediate execution options
15
+ - **Task Management**: Enable, disable, or remove tasks on demand
16
+ - **Execution History**: Track task execution count and timestamps
17
+ - **Zero Dependencies**: No external runtime dependencies
18
+ - **Well Tested**: Comprehensive test coverage
19
+
20
+ ## 📦 Installation
21
+
22
+ ```bash
23
+ npm install @kyo-services/schedulewise
24
+ ```
25
+
26
+ ## 🔧 Usage
27
+
28
+ ### Basic Task Scheduling
29
+
30
+ ```typescript
31
+ import sw from '@kyo-services/schedulewise';
32
+
33
+ // Create a periodic task
34
+ const task = sw.scheduleTask(
35
+ (currentTime: Date, executionCount: number) => {
36
+ console.log(`Task executed at ${currentTime}, count: ${executionCount}`);
37
+ },
38
+ {
39
+ interval: 1000, // Run every second
40
+ name: 'logTask', // Optional task identifier
41
+ immediate: true // Run immediately when created
42
+ }
43
+ );
44
+ ```
45
+
46
+ ### One-Time Task
47
+
48
+ ```typescript
49
+ sw.scheduleTask(
50
+ () => {
51
+ console.log('This task runs only once after 5 seconds');
52
+ },
53
+ {
54
+ interval: 5000,
55
+ once: true
56
+ }
57
+ );
58
+ ```
59
+
60
+ ### Task Management
61
+
62
+ ```typescript
63
+ // Find task by name or ID
64
+ const task = sw.findTask('logTask');
65
+
66
+ // Disable task
67
+ task?.disable();
68
+
69
+ // Enable task
70
+ task?.enable();
71
+
72
+ // Update task configuration
73
+ task?.update({
74
+ interval: 2000,
75
+ immediate: false
76
+ });
77
+
78
+ // Remove specific task
79
+ task?.remove();
80
+ // or
81
+ sw.removeTask('logTask');
82
+
83
+ // Remove all tasks
84
+ sw.clearAllTasks();
85
+ ```
86
+
87
+ ## 📚 API Reference
88
+
89
+ ### TaskOptions
90
+
91
+ ```typescript
92
+ interface TaskOptions {
93
+ interval: number; // Interval in milliseconds
94
+ name?: string; // Optional task identifier
95
+ immediate?: boolean; // Run immediately when created
96
+ once?: boolean; // Run only once
97
+ }
98
+ ```
99
+
100
+ ### Task Methods
101
+
102
+ | Method | Description |
103
+ |--------|-------------|
104
+ | `disable()` | Temporarily disables the task |
105
+ | `enable()` | Re-enables a disabled task |
106
+ | `update(options)` | Updates task configuration |
107
+ | `remove()` | Removes the task from scheduler |
108
+
109
+ ### Task Properties
110
+
111
+ | Property | Type | Description |
112
+ |----------|------|-------------|
113
+ | `id` | `number` | Unique task identifier |
114
+ | `name` | `string \| undefined` | Optional task name |
115
+ | `lastExecutionTime` | `Date` | Last execution timestamp |
116
+ | `executionCount` | `number` | Number of executions |
117
+ | `isEnabled` | `boolean` | Current enabled status |
118
+
119
+ ### Scheduler Methods
120
+
121
+ | Method | Description |
122
+ |--------|-------------|
123
+ | `scheduleTask(callback, options)` | Creates a new task |
124
+ | `findTask(identifier)` | Finds task by ID or name |
125
+ | `removeTask(identifier)` | Removes a specific task |
126
+ | `clearAllTasks()` | Removes all tasks |
127
+ | `getAllTasks()` | Gets all scheduled tasks |
128
+
129
+ ## 🧪 Testing
130
+
131
+ ```bash
132
+ # Run tests
133
+ npm test
134
+
135
+ # Run tests with coverage
136
+ npm test -- --coverage
137
+ ```
138
+
139
+ ## 🤝 Contributing
140
+
141
+ 1. Fork the repository
142
+ 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
143
+ 3. Commit your changes using conventional commits (`git commit -m 'feat: add amazing feature'`)
144
+ 4. Push to the branch (`git push origin feature/amazing-feature`)
145
+ 5. Open a Pull Request
146
+
147
+ ## 📝 License
148
+
149
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
150
+
151
+ ## ⚡ Best Practices
152
+
153
+ 1. **Task Naming**: Use descriptive names for better task management
154
+ ```typescript
155
+ sw.scheduleTask(sendEmail, { name: 'dailyNewsletterTask' });
156
+ ```
157
+
158
+ 2. **Error Handling**: Always handle task errors
159
+ ```typescript
160
+ sw.scheduleTask(async () => {
161
+ try {
162
+ await riskyOperation();
163
+ } catch (error) {
164
+ console.error('Task failed:', error);
165
+ }
166
+ }, { interval: 1000 });
167
+ ```
168
+
169
+ 3. **Resource Cleanup**: Remove tasks when no longer needed
170
+ ```typescript
171
+ // In component unmount or cleanup
172
+ task.remove();
173
+ // or for all tasks
174
+ sw.clearAllTasks();
175
+ ```
176
+
177
+ 4. **Interval Selection**: Choose appropriate intervals
178
+ ```typescript
179
+ // Good: Clear intention
180
+ const MINUTE = 60 * 1000;
181
+ sw.scheduleTask(task, { interval: 5 * MINUTE });
182
+
183
+ // Avoid: Magic numbers
184
+ sw.scheduleTask(task, { interval: 300000 });
185
+ ```
186
+
187
+ 5. **Type Safety**: Leverage TypeScript types
188
+ ```typescript
189
+ import type { TaskCallback, TaskOptions } from '@kyo-services/schedulewise';
190
+
191
+ const callback: TaskCallback = (time: Date, count: number) => {
192
+ // Type-safe callback
193
+ };
194
+ ```
package/dist/Task.d.ts ADDED
@@ -0,0 +1,74 @@
1
+ import { TaskCallback } from './types';
2
+ import { TaskScheduler } from './TaskScheduler';
3
+ /**
4
+ * Represents a scheduled task in the system
5
+ * @class Task
6
+ */
7
+ export declare class Task {
8
+ readonly name: string | undefined;
9
+ readonly id: number;
10
+ private callback;
11
+ private interval;
12
+ private executeImmediately;
13
+ private isOneTime;
14
+ private scheduler;
15
+ lastExecutionTime: Date;
16
+ executionCount: number;
17
+ isEnabled: boolean;
18
+ /**
19
+ * Creates a new Task instance
20
+ * @param {TaskScheduler} scheduler - Reference to the scheduler instance
21
+ * @param {string} [name] - Optional name to identify the task
22
+ * @param {number} id - Unique identifier for the task
23
+ * @param {TaskCallback} callback - Function to be executed
24
+ * @param {number} interval - Time interval in milliseconds between executions
25
+ * @param {boolean} executeImmediately - Whether to execute immediately
26
+ * @param {boolean} isOneTime - Whether to execute only once
27
+ */
28
+ constructor(scheduler: TaskScheduler, name: string | undefined, id: number, callback: TaskCallback, interval: number, executeImmediately: boolean, isOneTime: boolean);
29
+ /**
30
+ * Executes the task callback
31
+ * @param {Date} currentTime - Current timestamp
32
+ */
33
+ execute(currentTime: Date): void;
34
+ /**
35
+ * Enables the task
36
+ * @returns {Task} The task instance for chaining
37
+ */
38
+ enable(): Task;
39
+ /**
40
+ * Disables the task
41
+ * @returns {Task} The task instance for chaining
42
+ */
43
+ disable(): Task;
44
+ /**
45
+ * Updates the task configuration
46
+ * @param {TaskOptions} options - New configuration options
47
+ * @param {TaskCallback} [newCallback] - Optional new callback function
48
+ * @returns {Task} The task instance for chaining
49
+ */
50
+ update(options: {
51
+ interval: number;
52
+ immediate?: boolean;
53
+ }, newCallback?: TaskCallback): Task;
54
+ /**
55
+ * Removes the task from the scheduler
56
+ */
57
+ remove(): void;
58
+ /**
59
+ * Gets the task's interval
60
+ * @returns {number} The interval in milliseconds
61
+ */
62
+ getInterval(): number;
63
+ /**
64
+ * Checks if the task is ready to execute
65
+ * @param {number} elapsedTime - Time elapsed since last execution
66
+ * @returns {boolean} Whether the task should execute
67
+ */
68
+ shouldExecute(elapsedTime: number): boolean;
69
+ /**
70
+ * Checks if the task should be removed after execution
71
+ * @returns {boolean} Whether the task is one-time
72
+ */
73
+ shouldRemove(): boolean;
74
+ }
package/dist/Task.js ADDED
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Represents a scheduled task in the system
3
+ * @class Task
4
+ */
5
+ export class Task {
6
+ name;
7
+ id;
8
+ callback;
9
+ interval;
10
+ executeImmediately;
11
+ isOneTime;
12
+ scheduler;
13
+ lastExecutionTime;
14
+ executionCount;
15
+ isEnabled;
16
+ /**
17
+ * Creates a new Task instance
18
+ * @param {TaskScheduler} scheduler - Reference to the scheduler instance
19
+ * @param {string} [name] - Optional name to identify the task
20
+ * @param {number} id - Unique identifier for the task
21
+ * @param {TaskCallback} callback - Function to be executed
22
+ * @param {number} interval - Time interval in milliseconds between executions
23
+ * @param {boolean} executeImmediately - Whether to execute immediately
24
+ * @param {boolean} isOneTime - Whether to execute only once
25
+ */
26
+ constructor(scheduler, name, id, callback, interval, executeImmediately, isOneTime) {
27
+ this.name = name;
28
+ this.id = id;
29
+ this.callback = callback;
30
+ this.interval = interval;
31
+ this.executeImmediately = executeImmediately;
32
+ this.isOneTime = isOneTime;
33
+ this.scheduler = scheduler;
34
+ this.executionCount = 0;
35
+ this.isEnabled = true;
36
+ this.lastExecutionTime = new Date(0);
37
+ }
38
+ /**
39
+ * Executes the task callback
40
+ * @param {Date} currentTime - Current timestamp
41
+ */
42
+ execute(currentTime) {
43
+ this.callback(currentTime, this.executionCount + 1);
44
+ this.lastExecutionTime = currentTime;
45
+ this.executionCount++;
46
+ }
47
+ /**
48
+ * Enables the task
49
+ * @returns {Task} The task instance for chaining
50
+ */
51
+ enable() {
52
+ this.isEnabled = true;
53
+ return this;
54
+ }
55
+ /**
56
+ * Disables the task
57
+ * @returns {Task} The task instance for chaining
58
+ */
59
+ disable() {
60
+ this.isEnabled = false;
61
+ return this;
62
+ }
63
+ /**
64
+ * Updates the task configuration
65
+ * @param {TaskOptions} options - New configuration options
66
+ * @param {TaskCallback} [newCallback] - Optional new callback function
67
+ * @returns {Task} The task instance for chaining
68
+ */
69
+ update(options, newCallback) {
70
+ this.interval = options.interval;
71
+ this.executeImmediately = options.immediate || false;
72
+ if (newCallback)
73
+ this.callback = newCallback;
74
+ return this;
75
+ }
76
+ /**
77
+ * Removes the task from the scheduler
78
+ */
79
+ remove() {
80
+ this.scheduler.removeTask(this.id);
81
+ }
82
+ /**
83
+ * Gets the task's interval
84
+ * @returns {number} The interval in milliseconds
85
+ */
86
+ getInterval() {
87
+ return this.interval;
88
+ }
89
+ /**
90
+ * Checks if the task is ready to execute
91
+ * @param {number} elapsedTime - Time elapsed since last execution
92
+ * @returns {boolean} Whether the task should execute
93
+ */
94
+ shouldExecute(elapsedTime) {
95
+ return elapsedTime >= this.interval && this.isEnabled;
96
+ }
97
+ /**
98
+ * Checks if the task should be removed after execution
99
+ * @returns {boolean} Whether the task is one-time
100
+ */
101
+ shouldRemove() {
102
+ return this.isOneTime;
103
+ }
104
+ }
105
+ //# sourceMappingURL=Task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Task.js","sourceRoot":"","sources":["../src/Task.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,OAAO,IAAI;IAkBO;IACA;IACR;IACA;IACA;IACA;IAtBJ,SAAS,CAAgB;IAC1B,iBAAiB,CAAO;IACxB,cAAc,CAAS;IACvB,SAAS,CAAU;IAE1B;;;;;;;;;OASG;IACH,YACI,SAAwB,EACR,IAAwB,EACxB,EAAU,EAClB,QAAsB,EACtB,QAAgB,EAChB,kBAA2B,EAC3B,SAAkB;QALV,SAAI,GAAJ,IAAI,CAAoB;QACxB,OAAE,GAAF,EAAE,CAAQ;QAClB,aAAQ,GAAR,QAAQ,CAAc;QACtB,aAAQ,GAAR,QAAQ,CAAQ;QAChB,uBAAkB,GAAlB,kBAAkB,CAAS;QAC3B,cAAS,GAAT,SAAS,CAAS;QAE1B,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,iBAAiB,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACI,OAAO,CAAC,WAAiB;QAC5B,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC;QACrC,IAAI,CAAC,cAAc,EAAE,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACI,MAAM;QACT,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;OAGG;IACI,OAAO;QACV,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,OAAkD,EAAE,WAA0B;QACxF,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QACjC,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC,SAAS,IAAI,KAAK,CAAC;QACrD,IAAI,WAAW;YAAE,IAAI,CAAC,QAAQ,GAAG,WAAW,CAAC;QAC7C,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACI,MAAM;QACT,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC;IAED;;;OAGG;IACI,WAAW;QACd,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED;;;;OAIG;IACI,aAAa,CAAC,WAAmB;QACpC,OAAO,WAAW,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC;IAC1D,CAAC;IAED;;;OAGG;IACI,YAAY;QACf,OAAO,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;CACJ"}
@@ -0,0 +1,55 @@
1
+ import { Task } from './Task';
2
+ import { TaskCallback, TaskOptions } from './types';
3
+ /**
4
+ * A singleton class that manages scheduled tasks in the system
5
+ * @class TaskScheduler
6
+ */
7
+ export declare class TaskScheduler {
8
+ private static instance;
9
+ private currentTimestamp;
10
+ private scheduledTasks;
11
+ private schedulerInterval;
12
+ private constructor();
13
+ /**
14
+ * Gets the singleton instance of TaskScheduler
15
+ * @returns {TaskScheduler} The singleton instance
16
+ */
17
+ static getInstance(): TaskScheduler;
18
+ /**
19
+ * Finds a task by its identifier (id or name)
20
+ * @param {number | string} identifier - The task's ID or name
21
+ * @returns {Task | undefined} The found task or undefined
22
+ */
23
+ findTask(identifier: number | string): Task | undefined;
24
+ /**
25
+ * Gets all scheduled tasks in the system
26
+ * @returns {Task[]} Array of all scheduled tasks
27
+ */
28
+ getAllTasks(): Task[];
29
+ /**
30
+ * Creates and schedules a new task
31
+ * @param {TaskCallback} callback - Function to be executed
32
+ * @param {TaskOptions} options - Configuration options for the task
33
+ * @returns {Task} The created task instance
34
+ */
35
+ scheduleTask(callback: TaskCallback, options: TaskOptions): Task;
36
+ /**
37
+ * Removes a task from the scheduler
38
+ * @param {number | string} identifier - The task's ID or name
39
+ */
40
+ removeTask(identifier: number | string): void;
41
+ /**
42
+ * Removes all tasks and stops the scheduler
43
+ */
44
+ clearAllTasks(): void;
45
+ /**
46
+ * Updates current timestamp and processes tasks
47
+ * @internal For testing purposes
48
+ */
49
+ processTasksNow(): void;
50
+ /**
51
+ * Starts the task processor that executes scheduled tasks
52
+ * @private
53
+ */
54
+ private startTaskProcessor;
55
+ }
@@ -0,0 +1,110 @@
1
+ import { Task } from './Task';
2
+ /**
3
+ * A singleton class that manages scheduled tasks in the system
4
+ * @class TaskScheduler
5
+ */
6
+ export class TaskScheduler {
7
+ static instance;
8
+ currentTimestamp;
9
+ scheduledTasks = new Map();
10
+ schedulerInterval = null;
11
+ constructor() {
12
+ this.currentTimestamp = new Date();
13
+ this.startTaskProcessor();
14
+ }
15
+ /**
16
+ * Gets the singleton instance of TaskScheduler
17
+ * @returns {TaskScheduler} The singleton instance
18
+ */
19
+ static getInstance() {
20
+ if (!TaskScheduler.instance)
21
+ TaskScheduler.instance = new TaskScheduler();
22
+ return TaskScheduler.instance;
23
+ }
24
+ /**
25
+ * Finds a task by its identifier (id or name)
26
+ * @param {number | string} identifier - The task's ID or name
27
+ * @returns {Task | undefined} The found task or undefined
28
+ */
29
+ findTask(identifier) {
30
+ return this.scheduledTasks.get(identifier);
31
+ }
32
+ /**
33
+ * Gets all scheduled tasks in the system
34
+ * @returns {Task[]} Array of all scheduled tasks
35
+ */
36
+ getAllTasks() {
37
+ return Array.from(this.scheduledTasks.values());
38
+ }
39
+ /**
40
+ * Creates and schedules a new task
41
+ * @param {TaskCallback} callback - Function to be executed
42
+ * @param {TaskOptions} options - Configuration options for the task
43
+ * @returns {Task} The created task instance
44
+ */
45
+ scheduleTask(callback, options) {
46
+ const taskId = Math.floor(Math.random() * 1000000);
47
+ const task = new Task(this, options.name, taskId, callback, options.interval, false, options.once || false);
48
+ this.scheduledTasks.set(taskId, task);
49
+ if (options.name)
50
+ this.scheduledTasks.set(options.name, task);
51
+ if (options.immediate) {
52
+ task.execute(this.currentTimestamp);
53
+ task.lastExecutionTime = this.currentTimestamp;
54
+ }
55
+ return task;
56
+ }
57
+ /**
58
+ * Removes a task from the scheduler
59
+ * @param {number | string} identifier - The task's ID or name
60
+ */
61
+ removeTask(identifier) {
62
+ const task = this.findTask(identifier);
63
+ if (!task)
64
+ return;
65
+ this.scheduledTasks.delete(task.id);
66
+ if (task.name)
67
+ this.scheduledTasks.delete(task.name);
68
+ }
69
+ /**
70
+ * Removes all tasks and stops the scheduler
71
+ */
72
+ clearAllTasks() {
73
+ if (this.schedulerInterval) {
74
+ clearInterval(this.schedulerInterval);
75
+ this.schedulerInterval = null;
76
+ }
77
+ this.scheduledTasks.clear();
78
+ }
79
+ /**
80
+ * Updates current timestamp and processes tasks
81
+ * @internal For testing purposes
82
+ */
83
+ processTasksNow() {
84
+ const previousTimestamp = this.currentTimestamp;
85
+ this.currentTimestamp = new Date();
86
+ for (const task of this.scheduledTasks.values()) {
87
+ const elapsedTime = task.getInterval(); // Bir interval süresi geçmiş varsayalım
88
+ const shouldRun = task.shouldExecute(elapsedTime) &&
89
+ task.lastExecutionTime.getTime() <= previousTimestamp.getTime();
90
+ if (!shouldRun)
91
+ continue;
92
+ task.execute(this.currentTimestamp);
93
+ if (task.shouldRemove()) {
94
+ this.removeTask(task.id);
95
+ }
96
+ }
97
+ }
98
+ /**
99
+ * Starts the task processor that executes scheduled tasks
100
+ * @private
101
+ */
102
+ startTaskProcessor() {
103
+ if (this.schedulerInterval)
104
+ clearInterval(this.schedulerInterval);
105
+ this.schedulerInterval = setInterval(() => {
106
+ this.processTasksNow();
107
+ }, 100);
108
+ }
109
+ }
110
+ //# sourceMappingURL=TaskScheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TaskScheduler.js","sourceRoot":"","sources":["../src/TaskScheduler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B;;;GAGG;AACH,MAAM,OAAO,aAAa;IACd,MAAM,CAAC,QAAQ,CAAgB;IAC/B,gBAAgB,CAAO;IACvB,cAAc,GAA+B,IAAI,GAAG,EAAE,CAAC;IACvD,iBAAiB,GAA0C,IAAI,CAAC;IAExE;QACI,IAAI,CAAC,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,WAAW;QACrB,IAAI,CAAC,aAAa,CAAC,QAAQ;YAAE,aAAa,CAAC,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAC1E,OAAO,aAAa,CAAC,QAAQ,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACI,QAAQ,CAAC,UAA2B;QACvC,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED;;;OAGG;IACI,WAAW;QACd,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;IAED;;;;;OAKG;IACI,YAAY,CAAC,QAAsB,EAAE,OAAoB;QAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,IAAI,CACjB,IAAI,EACJ,OAAO,CAAC,IAAI,EACZ,MAAM,EACN,QAAQ,EACR,OAAO,CAAC,QAAQ,EAChB,KAAK,EACL,OAAO,CAAC,IAAI,IAAI,KAAK,CACxB,CAAC;QAEF,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,OAAO,CAAC,IAAI;YAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAE9D,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACpB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACnD,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;OAGG;IACI,UAAU,CAAC,UAA2B;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI;YAAE,OAAO;QAElB,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,IAAI;YAAE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC;IAED;;OAEG;IACI,aAAa;QAChB,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACtC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAClC,CAAC;QACD,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;IAChC,CAAC;IAED;;;OAGG;IACI,eAAe;QAClB,MAAM,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAChD,IAAI,CAAC,gBAAgB,GAAG,IAAI,IAAI,EAAE,CAAC;QAEnC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;YAC9C,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,wCAAwC;YAChF,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC;gBACjC,IAAI,CAAC,iBAAiB,CAAC,OAAO,EAAE,IAAI,iBAAiB,CAAC,OAAO,EAAE,CAAC;YAEhF,IAAI,CAAC,SAAS;gBAAE,SAAS;YAEzB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACpC,IAAI,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC;gBACtB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7B,CAAC;QACL,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,kBAAkB;QACtB,IAAI,IAAI,CAAC,iBAAiB;YAAE,aAAa,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAElE,IAAI,CAAC,iBAAiB,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,eAAe,EAAE,CAAC;QAC3B,CAAC,EAAE,GAAG,CAAC,CAAC;IACZ,CAAC;CACJ"}
@@ -0,0 +1,4 @@
1
+ import { TaskScheduler } from './TaskScheduler';
2
+ export { TaskCallback, TaskOptions } from './types';
3
+ declare const _default: TaskScheduler;
4
+ export default _default;
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import { TaskScheduler } from './TaskScheduler';
2
+ export default TaskScheduler.getInstance();
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,eAAe,aAAa,CAAC,WAAW,EAAE,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Callback function type for scheduled tasks
3
+ * @callback TaskCallback
4
+ * @param {Date} [executionTime] - Timestamp when the task was executed
5
+ * @param {number} [executionCount] - Number of times the task has been executed
6
+ * @returns {void}
7
+ */
8
+ export type TaskCallback = (executionTime?: Date, executionCount?: number) => void;
9
+ /**
10
+ * Configuration options for creating a scheduled task
11
+ * @typedef {Object} TaskOptions
12
+ * @property {string} [name] - Optional name to identify the task
13
+ * @property {number} interval - Time interval in milliseconds between executions
14
+ * @property {boolean} [immediate] - Whether to execute the task immediately upon creation
15
+ * @property {boolean} [once] - Whether the task should only execute once
16
+ */
17
+ export type TaskOptions = {
18
+ name?: string;
19
+ interval: number;
20
+ immediate?: boolean;
21
+ once?: boolean;
22
+ };
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@kyo-services/schedulewise",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "engines": {
6
+ "node": ">=18.0.0"
7
+ },
8
+ "description": "A smart and efficient task scheduler for managing periodic jobs with precision timing and intelligent scheduling in both browser and Node.js environments",
9
+ "main": "dist/main.js",
10
+ "types": "dist/main.d.ts",
11
+ "scripts": {
12
+ "build": "tsc --project tsconfig.json",
13
+ "test": "jest --config jest.config.cjs",
14
+ "test:watch": "jest --config jest.config.cjs --watch",
15
+ "prepare": "husky install && npm run build",
16
+ "lint": "eslint . --ext .ts",
17
+ "lint:fix": "eslint . --ext .ts --fix",
18
+ "prepublishOnly": "npm run build && npm test"
19
+ },
20
+ "keywords": [
21
+ "task",
22
+ "scheduler",
23
+ "job",
24
+ "periodic",
25
+ "interval",
26
+ "timer",
27
+ "cron",
28
+ "typescript"
29
+ ],
30
+ "author": "",
31
+ "license": "MIT",
32
+ "devDependencies": {
33
+ "@commitlint/cli": "^19.8.1",
34
+ "@commitlint/config-conventional": "^19.8.1",
35
+ "@types/jest": "^29.5.14",
36
+ "@typescript-eslint/eslint-plugin": "^8.38.0",
37
+ "@typescript-eslint/parser": "^8.38.0",
38
+ "eslint": "^9.32.0",
39
+ "husky": "^9.1.7",
40
+ "jest": "^29.7.0",
41
+ "lint-staged": "^16.1.2",
42
+ "ts-jest": "^29.4.0",
43
+ "typescript": "^5.0.0",
44
+ "typescript-eslint": "^8.38.0"
45
+ },
46
+ "files": [
47
+ "dist/*.js",
48
+ "dist/*.d.ts",
49
+ "dist/*.map",
50
+ "src"
51
+ ],
52
+ "repository": {
53
+ "type": "git",
54
+ "url": "git+https://github.com/kyo-services/schedulewise.git"
55
+ },
56
+ "bugs": {
57
+ "url": "https://github.com/kyo-services/schedulewise/issues"
58
+ },
59
+ "homepage": "https://github.com/kyo-services/schedulewise#readme",
60
+ "lint-staged": {
61
+ "*.ts": [
62
+ "eslint --fix",
63
+ "jest --findRelatedTests"
64
+ ]
65
+ }
66
+ }
package/src/Task.ts ADDED
@@ -0,0 +1,111 @@
1
+ import { TaskCallback } from './types';
2
+ import { TaskScheduler } from './TaskScheduler';
3
+
4
+ /**
5
+ * Represents a scheduled task in the system
6
+ * @class Task
7
+ */
8
+ export class Task {
9
+ private scheduler: TaskScheduler;
10
+ public lastExecutionTime: Date;
11
+ public executionCount: number;
12
+ public isEnabled: boolean;
13
+
14
+ /**
15
+ * Creates a new Task instance
16
+ * @param {TaskScheduler} scheduler - Reference to the scheduler instance
17
+ * @param {string} [name] - Optional name to identify the task
18
+ * @param {number} id - Unique identifier for the task
19
+ * @param {TaskCallback} callback - Function to be executed
20
+ * @param {number} interval - Time interval in milliseconds between executions
21
+ * @param {boolean} executeImmediately - Whether to execute immediately
22
+ * @param {boolean} isOneTime - Whether to execute only once
23
+ */
24
+ constructor(
25
+ scheduler: TaskScheduler,
26
+ public readonly name: string | undefined,
27
+ public readonly id: number,
28
+ private callback: TaskCallback,
29
+ private interval: number,
30
+ private executeImmediately: boolean,
31
+ private isOneTime: boolean
32
+ ) {
33
+ this.scheduler = scheduler;
34
+ this.executionCount = 0;
35
+ this.isEnabled = true;
36
+ this.lastExecutionTime = new Date(0);
37
+ }
38
+
39
+ /**
40
+ * Executes the task callback
41
+ * @param {Date} currentTime - Current timestamp
42
+ */
43
+ public execute(currentTime: Date): void {
44
+ this.callback(currentTime, this.executionCount + 1);
45
+ this.lastExecutionTime = currentTime;
46
+ this.executionCount++;
47
+ }
48
+
49
+ /**
50
+ * Enables the task
51
+ * @returns {Task} The task instance for chaining
52
+ */
53
+ public enable(): Task {
54
+ this.isEnabled = true;
55
+ return this;
56
+ }
57
+
58
+ /**
59
+ * Disables the task
60
+ * @returns {Task} The task instance for chaining
61
+ */
62
+ public disable(): Task {
63
+ this.isEnabled = false;
64
+ return this;
65
+ }
66
+
67
+ /**
68
+ * Updates the task configuration
69
+ * @param {TaskOptions} options - New configuration options
70
+ * @param {TaskCallback} [newCallback] - Optional new callback function
71
+ * @returns {Task} The task instance for chaining
72
+ */
73
+ public update(options: { interval: number, immediate?: boolean }, newCallback?: TaskCallback): Task {
74
+ this.interval = options.interval;
75
+ this.executeImmediately = options.immediate || false;
76
+ if (newCallback) this.callback = newCallback;
77
+ return this;
78
+ }
79
+
80
+ /**
81
+ * Removes the task from the scheduler
82
+ */
83
+ public remove(): void {
84
+ this.scheduler.removeTask(this.id);
85
+ }
86
+
87
+ /**
88
+ * Gets the task's interval
89
+ * @returns {number} The interval in milliseconds
90
+ */
91
+ public getInterval(): number {
92
+ return this.interval;
93
+ }
94
+
95
+ /**
96
+ * Checks if the task is ready to execute
97
+ * @param {number} elapsedTime - Time elapsed since last execution
98
+ * @returns {boolean} Whether the task should execute
99
+ */
100
+ public shouldExecute(elapsedTime: number): boolean {
101
+ return elapsedTime >= this.interval && this.isEnabled;
102
+ }
103
+
104
+ /**
105
+ * Checks if the task should be removed after execution
106
+ * @returns {boolean} Whether the task is one-time
107
+ */
108
+ public shouldRemove(): boolean {
109
+ return this.isOneTime;
110
+ }
111
+ }
@@ -0,0 +1,130 @@
1
+ import { Task } from './Task';
2
+ import { TaskCallback, TaskOptions } from './types';
3
+
4
+ /**
5
+ * A singleton class that manages scheduled tasks in the system
6
+ * @class TaskScheduler
7
+ */
8
+ export class TaskScheduler {
9
+ private static instance: TaskScheduler;
10
+ private currentTimestamp: Date;
11
+ private scheduledTasks: Map<number | string, Task> = new Map();
12
+ private schedulerInterval: ReturnType<typeof setInterval> | null = null;
13
+
14
+ private constructor() {
15
+ this.currentTimestamp = new Date();
16
+ this.startTaskProcessor();
17
+ }
18
+
19
+ /**
20
+ * Gets the singleton instance of TaskScheduler
21
+ * @returns {TaskScheduler} The singleton instance
22
+ */
23
+ public static getInstance(): TaskScheduler {
24
+ if (!TaskScheduler.instance) TaskScheduler.instance = new TaskScheduler();
25
+ return TaskScheduler.instance;
26
+ }
27
+
28
+ /**
29
+ * Finds a task by its identifier (id or name)
30
+ * @param {number | string} identifier - The task's ID or name
31
+ * @returns {Task | undefined} The found task or undefined
32
+ */
33
+ public findTask(identifier: number | string): Task | undefined {
34
+ return this.scheduledTasks.get(identifier);
35
+ }
36
+
37
+ /**
38
+ * Gets all scheduled tasks in the system
39
+ * @returns {Task[]} Array of all scheduled tasks
40
+ */
41
+ public getAllTasks(): Task[] {
42
+ return Array.from(this.scheduledTasks.values());
43
+ }
44
+
45
+ /**
46
+ * Creates and schedules a new task
47
+ * @param {TaskCallback} callback - Function to be executed
48
+ * @param {TaskOptions} options - Configuration options for the task
49
+ * @returns {Task} The created task instance
50
+ */
51
+ public scheduleTask(callback: TaskCallback, options: TaskOptions): Task {
52
+ const taskId = Math.floor(Math.random() * 1000000);
53
+ const task = new Task(
54
+ this,
55
+ options.name,
56
+ taskId,
57
+ callback,
58
+ options.interval,
59
+ false,
60
+ options.once || false
61
+ );
62
+
63
+ this.scheduledTasks.set(taskId, task);
64
+ if (options.name) this.scheduledTasks.set(options.name, task);
65
+
66
+ if (options.immediate) {
67
+ task.execute(this.currentTimestamp);
68
+ task.lastExecutionTime = this.currentTimestamp;
69
+ }
70
+
71
+ return task;
72
+ }
73
+
74
+ /**
75
+ * Removes a task from the scheduler
76
+ * @param {number | string} identifier - The task's ID or name
77
+ */
78
+ public removeTask(identifier: number | string): void {
79
+ const task = this.findTask(identifier);
80
+ if (!task) return;
81
+
82
+ this.scheduledTasks.delete(task.id);
83
+ if (task.name) this.scheduledTasks.delete(task.name);
84
+ }
85
+
86
+ /**
87
+ * Removes all tasks and stops the scheduler
88
+ */
89
+ public clearAllTasks(): void {
90
+ if (this.schedulerInterval) {
91
+ clearInterval(this.schedulerInterval);
92
+ this.schedulerInterval = null;
93
+ }
94
+ this.scheduledTasks.clear();
95
+ }
96
+
97
+ /**
98
+ * Updates current timestamp and processes tasks
99
+ * @internal For testing purposes
100
+ */
101
+ public processTasksNow(): void {
102
+ const previousTimestamp = this.currentTimestamp;
103
+ this.currentTimestamp = new Date();
104
+
105
+ for (const task of this.scheduledTasks.values()) {
106
+ const elapsedTime = task.getInterval(); // Bir interval süresi geçmiş varsayalım
107
+ const shouldRun = task.shouldExecute(elapsedTime) &&
108
+ task.lastExecutionTime.getTime() <= previousTimestamp.getTime();
109
+
110
+ if (!shouldRun) continue;
111
+
112
+ task.execute(this.currentTimestamp);
113
+ if (task.shouldRemove()) {
114
+ this.removeTask(task.id);
115
+ }
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Starts the task processor that executes scheduled tasks
121
+ * @private
122
+ */
123
+ private startTaskProcessor(): void {
124
+ if (this.schedulerInterval) clearInterval(this.schedulerInterval);
125
+
126
+ this.schedulerInterval = setInterval(() => {
127
+ this.processTasksNow();
128
+ }, 100);
129
+ }
130
+ }
@@ -0,0 +1,46 @@
1
+ import { setupTest, cleanupTest } from "./testUtils";
2
+ import { TaskScheduler } from "../TaskScheduler";
3
+
4
+ describe("Task Creation", () => {
5
+ let scheduler: TaskScheduler;
6
+
7
+ beforeEach(() => {
8
+ scheduler = setupTest();
9
+ });
10
+
11
+ afterEach(() => {
12
+ cleanupTest();
13
+ });
14
+
15
+ it("should create a task with basic configuration", () => {
16
+ const callback = jest.fn();
17
+ const task = scheduler.scheduleTask(callback, { interval: 1000 });
18
+
19
+ expect(task).toBeDefined();
20
+ expect(task.getInterval()).toBe(1000);
21
+ expect(task.isEnabled).toBe(true);
22
+ expect(task.executionCount).toBe(0);
23
+ });
24
+
25
+ it("should create a task with immediate execution", () => {
26
+ const callback = jest.fn();
27
+ const task = scheduler.scheduleTask(callback, {
28
+ interval: 1000,
29
+ immediate: true,
30
+ });
31
+
32
+ expect(callback).toHaveBeenCalledTimes(1);
33
+ expect(task.executionCount).toBe(1);
34
+ });
35
+
36
+ it("should create a task with a name", () => {
37
+ const callback = jest.fn();
38
+ const task = scheduler.scheduleTask(callback, {
39
+ interval: 1000,
40
+ name: "testTask",
41
+ });
42
+
43
+ expect(task.name).toBe("testTask");
44
+ expect(scheduler.findTask("testTask")).toBe(task);
45
+ });
46
+ });
@@ -0,0 +1,69 @@
1
+ import { setupTest, cleanupTest } from "./testUtils";
2
+ import { TaskScheduler } from "../TaskScheduler";
3
+
4
+ describe("Task Execution", () => {
5
+ let scheduler: TaskScheduler;
6
+
7
+ beforeEach(() => {
8
+ scheduler = setupTest();
9
+ });
10
+
11
+ afterEach(() => {
12
+ cleanupTest();
13
+ });
14
+
15
+ it("should execute task at regular intervals", () => {
16
+ const callback = jest.fn();
17
+ scheduler.scheduleTask(callback, { interval: 1000 });
18
+
19
+ // İlk çalıştırma
20
+ scheduler.processTasksNow();
21
+ expect(callback).toHaveBeenCalledTimes(1);
22
+
23
+ // İkinci çalıştırma
24
+ scheduler.processTasksNow();
25
+ expect(callback).toHaveBeenCalledTimes(2);
26
+
27
+ // Üçüncü çalıştırma
28
+ scheduler.processTasksNow();
29
+ expect(callback).toHaveBeenCalledTimes(3);
30
+ });
31
+
32
+ it("should execute task only once when configured", () => {
33
+ const callback = jest.fn();
34
+ scheduler.scheduleTask(callback, {
35
+ interval: 1000,
36
+ once: true,
37
+ });
38
+
39
+ // İlk çalıştırma
40
+ scheduler.processTasksNow();
41
+ expect(callback).toHaveBeenCalledTimes(1);
42
+
43
+ // İkinci çalıştırma - çağrılmamalı
44
+ scheduler.processTasksNow();
45
+ expect(callback).toHaveBeenCalledTimes(1);
46
+
47
+ // Üçüncü çalıştırma - çağrılmamalı
48
+ scheduler.processTasksNow();
49
+ expect(callback).toHaveBeenCalledTimes(1);
50
+ });
51
+
52
+ it("should not execute disabled tasks", () => {
53
+ const callback = jest.fn();
54
+ const task = scheduler.scheduleTask(callback, { interval: 1000 });
55
+ task.disable();
56
+
57
+ // İlk çalıştırma
58
+ scheduler.processTasksNow();
59
+ expect(callback).toHaveBeenCalledTimes(0);
60
+
61
+ // İkinci çalıştırma
62
+ scheduler.processTasksNow();
63
+ expect(callback).toHaveBeenCalledTimes(0);
64
+
65
+ // Üçüncü çalıştırma
66
+ scheduler.processTasksNow();
67
+ expect(callback).toHaveBeenCalledTimes(0);
68
+ });
69
+ });
@@ -0,0 +1,75 @@
1
+ import { setupTest, cleanupTest } from "./testUtils";
2
+ import { TaskScheduler } from "../TaskScheduler";
3
+
4
+ describe("Task Management", () => {
5
+ let scheduler: TaskScheduler;
6
+
7
+ beforeEach(() => {
8
+ scheduler = setupTest();
9
+ });
10
+
11
+ afterEach(() => {
12
+ cleanupTest();
13
+ });
14
+
15
+ it("should enable and disable tasks", () => {
16
+ const callback = jest.fn();
17
+ const task = scheduler.scheduleTask(callback, { interval: 1000 });
18
+
19
+ // İlk çalıştırma - aktif
20
+ scheduler.processTasksNow();
21
+ expect(callback).toHaveBeenCalledTimes(1);
22
+
23
+ task.disable();
24
+ scheduler.processTasksNow();
25
+ expect(callback).toHaveBeenCalledTimes(1);
26
+
27
+ task.enable();
28
+ scheduler.processTasksNow();
29
+ expect(callback).toHaveBeenCalledTimes(2);
30
+ });
31
+
32
+ it("should remove tasks", () => {
33
+ const callback = jest.fn();
34
+ const task = scheduler.scheduleTask(callback, {
35
+ interval: 1000,
36
+ name: "testTask",
37
+ });
38
+
39
+ // İlk çalıştırma
40
+ scheduler.processTasksNow();
41
+ expect(callback).toHaveBeenCalledTimes(1);
42
+
43
+ task.remove();
44
+
45
+ expect(scheduler.findTask(task.id)).toBeUndefined();
46
+ expect(scheduler.findTask("testTask")).toBeUndefined();
47
+
48
+ // Task silindiği için çağrılmamalı
49
+ scheduler.processTasksNow();
50
+ expect(callback).toHaveBeenCalledTimes(1);
51
+
52
+ scheduler.processTasksNow();
53
+ expect(callback).toHaveBeenCalledTimes(1);
54
+ });
55
+
56
+ it("should clear all tasks", () => {
57
+ const callback1 = jest.fn();
58
+ const callback2 = jest.fn();
59
+
60
+ scheduler.scheduleTask(callback1, { interval: 1000 });
61
+ scheduler.scheduleTask(callback2, { interval: 1000 });
62
+
63
+ scheduler.clearAllTasks();
64
+
65
+ // Tüm tasklar silindiği için çağrılmamalı
66
+ scheduler.processTasksNow();
67
+ expect(callback1).not.toHaveBeenCalled();
68
+
69
+ scheduler.processTasksNow();
70
+ expect(callback2).not.toHaveBeenCalled();
71
+
72
+ // Task listesi boş olmalı
73
+ expect(scheduler.getAllTasks()).toHaveLength(0);
74
+ });
75
+ });
@@ -0,0 +1,38 @@
1
+ import { TaskScheduler } from "../TaskScheduler";
2
+
3
+ let scheduler: TaskScheduler;
4
+ let OriginalDate: DateConstructor;
5
+
6
+ export const mockDate = (date: Date): void => {
7
+ OriginalDate = global.Date;
8
+ const MockDate = class extends OriginalDate {
9
+ constructor(...args: ConstructorParameters<typeof Date>) {
10
+ super(...args);
11
+ return date;
12
+ }
13
+ static now(): number {
14
+ return date.getTime();
15
+ }
16
+ } as unknown as DateConstructor;
17
+ global.Date = MockDate;
18
+ jest.useFakeTimers();
19
+ };
20
+
21
+ export const restoreDate = (): void => {
22
+ jest.useRealTimers();
23
+ global.Date = OriginalDate;
24
+ };
25
+
26
+ export const setupTest = (): TaskScheduler => {
27
+ const now = new Date();
28
+ mockDate(now);
29
+ scheduler = TaskScheduler.getInstance();
30
+ return scheduler;
31
+ };
32
+
33
+ export const cleanupTest = (): void => {
34
+ restoreDate();
35
+ if (scheduler) {
36
+ scheduler.clearAllTasks();
37
+ }
38
+ };
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ import { TaskScheduler } from './TaskScheduler';
2
+ export { TaskCallback, TaskOptions } from './types';
3
+
4
+ export default TaskScheduler.getInstance();
package/src/types.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Callback function type for scheduled tasks
3
+ * @callback TaskCallback
4
+ * @param {Date} [executionTime] - Timestamp when the task was executed
5
+ * @param {number} [executionCount] - Number of times the task has been executed
6
+ * @returns {void}
7
+ */
8
+ export type TaskCallback = (executionTime?: Date, executionCount?: number) => void;
9
+
10
+ /**
11
+ * Configuration options for creating a scheduled task
12
+ * @typedef {Object} TaskOptions
13
+ * @property {string} [name] - Optional name to identify the task
14
+ * @property {number} interval - Time interval in milliseconds between executions
15
+ * @property {boolean} [immediate] - Whether to execute the task immediately upon creation
16
+ * @property {boolean} [once] - Whether the task should only execute once
17
+ */
18
+ export type TaskOptions = {
19
+ name?: string;
20
+ interval: number;
21
+ immediate?: boolean;
22
+ once?: boolean;
23
+ };