@commandkit/tasks 0.0.0-dev.20250724145623

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,79 @@
1
+ import { CommandKitPluginRuntime, RuntimePlugin, Collection, CommandKitHMREvent } from 'commandkit';
2
+ import { Task } from './task';
3
+ /**
4
+ * Configuration options for the tasks plugin.
5
+ *
6
+ * Currently, the plugin uses default settings for task loading and HMR.
7
+ * Future versions may support customizing the tasks directory path and HMR behavior.
8
+ */
9
+ export interface TasksPluginOptions {
10
+ }
11
+ /**
12
+ * CommandKit plugin that provides task management capabilities.
13
+ *
14
+ * This plugin automatically loads task definitions from the `src/app/tasks` directory
15
+ * and manages their execution through configured drivers. It supports hot module
16
+ * replacement (HMR) for development workflows.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * import { tasks } from '@commandkit/tasks';
21
+ *
22
+ * export default {
23
+ * plugins: [
24
+ * tasks(),
25
+ * ],
26
+ * };
27
+ * ```
28
+ */
29
+ export declare class TasksPlugin extends RuntimePlugin<TasksPluginOptions> {
30
+ /** The plugin name identifier */
31
+ readonly name = "tasks";
32
+ /** Collection of loaded task instances indexed by task name */
33
+ readonly tasks: Collection<string, Task<Record<string, any>>>;
34
+ /**
35
+ * Activates the tasks plugin.
36
+ *
37
+ * This method:
38
+ * 1. Sets up the task execution runner
39
+ * 2. Loads all task definitions from the tasks directory
40
+ * 3. Schedules tasks that have defined schedules
41
+ *
42
+ * @param ctx - The CommandKit plugin runtime context
43
+ */
44
+ activate(ctx: CommandKitPluginRuntime): Promise<void>;
45
+ /**
46
+ * Deactivates the tasks plugin.
47
+ *
48
+ * Clears all loaded tasks from memory.
49
+ *
50
+ * @param ctx - The CommandKit plugin runtime context
51
+ */
52
+ deactivate(ctx: CommandKitPluginRuntime): Promise<void>;
53
+ /**
54
+ * Gets the default tasks directory path.
55
+ *
56
+ * @returns The absolute path to the tasks directory
57
+ */
58
+ private getTaskDirectory;
59
+ /**
60
+ * Loads all task definitions from the tasks directory.
61
+ *
62
+ * This method scans the tasks directory for TypeScript/JavaScript files and
63
+ * imports them as task definitions. It validates that each export is a valid
64
+ * Task instance and schedules tasks that have defined schedules.
65
+ *
66
+ * @param commandkit - The CommandKit instance
67
+ */
68
+ private loadTasks;
69
+ /**
70
+ * Handles hot module replacement (HMR) for task files.
71
+ *
72
+ * When a task file is modified during development, this method reloads the
73
+ * task definition and updates the scheduler accordingly.
74
+ *
75
+ * @param ctx - The CommandKit plugin runtime context
76
+ * @param event - The HMR event containing file change information
77
+ */
78
+ performHMR(ctx: CommandKitPluginRuntime, event: CommandKitHMREvent): Promise<void>;
79
+ }
package/dist/plugin.js ADDED
@@ -0,0 +1,223 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TasksPlugin = void 0;
37
+ const commandkit_1 = require("commandkit");
38
+ const promises_1 = require("node:fs/promises");
39
+ const node_path_1 = __importStar(require("node:path"));
40
+ const task_1 = require("./task");
41
+ const node_process_1 = require("node:process");
42
+ const driver_manager_1 = require("./driver-manager");
43
+ const context_1 = require("./context");
44
+ const node_fs_1 = require("node:fs");
45
+ /**
46
+ * CommandKit plugin that provides task management capabilities.
47
+ *
48
+ * This plugin automatically loads task definitions from the `src/app/tasks` directory
49
+ * and manages their execution through configured drivers. It supports hot module
50
+ * replacement (HMR) for development workflows.
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * import { tasks } from '@commandkit/tasks';
55
+ *
56
+ * export default {
57
+ * plugins: [
58
+ * tasks(),
59
+ * ],
60
+ * };
61
+ * ```
62
+ */
63
+ class TasksPlugin extends commandkit_1.RuntimePlugin {
64
+ constructor() {
65
+ super(...arguments);
66
+ /** The plugin name identifier */
67
+ this.name = 'tasks';
68
+ /** Collection of loaded task instances indexed by task name */
69
+ this.tasks = new commandkit_1.Collection();
70
+ }
71
+ /**
72
+ * Activates the tasks plugin.
73
+ *
74
+ * This method:
75
+ * 1. Sets up the task execution runner
76
+ * 2. Loads all task definitions from the tasks directory
77
+ * 3. Schedules tasks that have defined schedules
78
+ *
79
+ * @param ctx - The CommandKit plugin runtime context
80
+ */
81
+ async activate(ctx) {
82
+ driver_manager_1.taskDriverManager.setTaskRunner(async (task) => {
83
+ try {
84
+ const taskInstance = this.tasks.get(task.name);
85
+ if (!taskInstance) {
86
+ // task does not exist so we delete it
87
+ await driver_manager_1.taskDriverManager.deleteTask(task.name);
88
+ return;
89
+ }
90
+ const context = new context_1.TaskContext({
91
+ task: taskInstance,
92
+ data: task.data,
93
+ commandkit: ctx.commandkit,
94
+ });
95
+ const prepared = await taskInstance.prepare(context);
96
+ if (!prepared)
97
+ return;
98
+ await taskInstance.execute(context);
99
+ }
100
+ catch (e) {
101
+ commandkit_1.Logger.error(`Error executing task: ${e?.stack ?? e}`);
102
+ }
103
+ });
104
+ await this.loadTasks();
105
+ commandkit_1.Logger.info('Tasks plugin activated!');
106
+ }
107
+ /**
108
+ * Deactivates the tasks plugin.
109
+ *
110
+ * Clears all loaded tasks from memory.
111
+ *
112
+ * @param ctx - The CommandKit plugin runtime context
113
+ */
114
+ async deactivate(ctx) {
115
+ this.tasks.clear();
116
+ commandkit_1.Logger.info('Tasks plugin deactivated!');
117
+ }
118
+ /**
119
+ * Gets the default tasks directory path.
120
+ *
121
+ * @returns The absolute path to the tasks directory
122
+ */
123
+ getTaskDirectory() {
124
+ return node_path_1.default.join((0, commandkit_1.getCurrentDirectory)(), 'app', 'tasks');
125
+ }
126
+ /**
127
+ * Loads all task definitions from the tasks directory.
128
+ *
129
+ * This method scans the tasks directory for TypeScript/JavaScript files and
130
+ * imports them as task definitions. It validates that each export is a valid
131
+ * Task instance and schedules tasks that have defined schedules.
132
+ *
133
+ * @param commandkit - The CommandKit instance
134
+ */
135
+ async loadTasks() {
136
+ const taskDirectory = this.getTaskDirectory();
137
+ if (!(0, node_fs_1.existsSync)(taskDirectory))
138
+ return;
139
+ const files = await (0, promises_1.readdir)(taskDirectory, { withFileTypes: true });
140
+ for (const file of files) {
141
+ if (file.isDirectory() ||
142
+ file.name.startsWith('_') ||
143
+ !/\.(c|m)?(j|t)sx?$/.test(file.name)) {
144
+ continue;
145
+ }
146
+ const taskPath = node_path_1.default.join(file.parentPath, file.name);
147
+ const task = await import((0, commandkit_1.toFileURL)(taskPath, true))
148
+ .then((m) => m.default || m)
149
+ .catch((e) => {
150
+ commandkit_1.Logger.error(`Error loading task file: ${e?.stack ?? e}`);
151
+ return null;
152
+ });
153
+ if (!task || !(task instanceof task_1.Task)) {
154
+ continue;
155
+ }
156
+ if (this.tasks.has(task.name)) {
157
+ commandkit_1.Logger.error(`Duplicate task found: ${task.name} at src/app/tasks/${file.name}`);
158
+ continue;
159
+ }
160
+ if (task.schedule) {
161
+ await driver_manager_1.taskDriverManager.createTask({
162
+ name: task.name,
163
+ data: {},
164
+ schedule: task.schedule,
165
+ });
166
+ }
167
+ this.tasks.set(task.name, task);
168
+ commandkit_1.Logger.info(`Loaded task: ${task.name}`);
169
+ }
170
+ commandkit_1.Logger.info(`Loaded ${this.tasks.size} tasks`);
171
+ }
172
+ /**
173
+ * Handles hot module replacement (HMR) for task files.
174
+ *
175
+ * When a task file is modified during development, this method reloads the
176
+ * task definition and updates the scheduler accordingly.
177
+ *
178
+ * @param ctx - The CommandKit plugin runtime context
179
+ * @param event - The HMR event containing file change information
180
+ */
181
+ async performHMR(ctx, event) {
182
+ if (event.event !== 'unknown')
183
+ return;
184
+ if (!event.path.startsWith((0, node_path_1.join)((0, node_process_1.cwd)(), 'src', 'app', 'tasks'))) {
185
+ return;
186
+ }
187
+ event.preventDefault();
188
+ event.accept();
189
+ const taskData = await import((0, commandkit_1.toFileURL)(event.path, true))
190
+ .then((t) => t.default || t)
191
+ .catch((e) => {
192
+ commandkit_1.Logger.error(`Error loading task file: ${e?.stack ?? e}`);
193
+ return null;
194
+ });
195
+ if (!taskData || !(taskData instanceof task_1.Task))
196
+ return;
197
+ if (this.tasks.has(taskData.name)) {
198
+ commandkit_1.Logger.info(`Reloading task: ${taskData.name}`);
199
+ await driver_manager_1.taskDriverManager.deleteTask(taskData.name);
200
+ this.tasks.set(taskData.name, taskData);
201
+ if (taskData.schedule) {
202
+ await driver_manager_1.taskDriverManager.createTask({
203
+ name: taskData.name,
204
+ data: {},
205
+ schedule: taskData.schedule,
206
+ });
207
+ }
208
+ }
209
+ else {
210
+ commandkit_1.Logger.info(`Loading task: ${taskData.name}`);
211
+ this.tasks.set(taskData.name, taskData);
212
+ if (taskData.schedule) {
213
+ await driver_manager_1.taskDriverManager.createTask({
214
+ name: taskData.name,
215
+ data: {},
216
+ schedule: taskData.schedule,
217
+ });
218
+ }
219
+ }
220
+ }
221
+ }
222
+ exports.TasksPlugin = TasksPlugin;
223
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwyQ0FTb0I7QUFDcEIsK0NBQTJDO0FBQzNDLHVEQUF1QztBQUN2QyxpQ0FBOEI7QUFDOUIsK0NBQW1DO0FBQ25DLHFEQUFxRDtBQUNyRCx1Q0FBd0M7QUFDeEMscUNBQXFDO0FBY3JDOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQWEsV0FBWSxTQUFRLDBCQUFpQztJQUFsRTs7UUFDRSxpQ0FBaUM7UUFDakIsU0FBSSxHQUFHLE9BQU8sQ0FBQztRQUUvQiwrREFBK0Q7UUFDL0MsVUFBSyxHQUFHLElBQUksdUJBQVUsRUFBZ0IsQ0FBQztJQWtMekQsQ0FBQztJQWhMQzs7Ozs7Ozs7O09BU0c7SUFDSSxLQUFLLENBQUMsUUFBUSxDQUFDLEdBQTRCO1FBQ2hELGtDQUFpQixDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEVBQUU7WUFDN0MsSUFBSSxDQUFDO2dCQUNILE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFFL0MsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO29CQUNsQixzQ0FBc0M7b0JBQ3RDLE1BQU0sa0NBQWlCLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztvQkFDOUMsT0FBTztnQkFDVCxDQUFDO2dCQUVELE1BQU0sT0FBTyxHQUFHLElBQUkscUJBQVcsQ0FBQztvQkFDOUIsSUFBSSxFQUFFLFlBQVk7b0JBQ2xCLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtvQkFDZixVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVU7aUJBQzNCLENBQUMsQ0FBQztnQkFFSCxNQUFNLFFBQVEsR0FBRyxNQUFNLFlBQVksQ0FB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
package/dist/task.d.ts ADDED
@@ -0,0 +1,108 @@
1
+ import { TaskContext } from './context';
2
+ import { TaskDefinition, TaskSchedule } from './types';
3
+ /**
4
+ * Represents a task instance with execution logic and metadata.
5
+ *
6
+ * Tasks can be scheduled to run at specific times or intervals using cron expressions
7
+ * or date-based scheduling. They support preparation logic to conditionally execute
8
+ * and provide a context for accessing CommandKit and Discord.js functionality.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { task } from '@commandkit/tasks';
13
+ *
14
+ * export const cleanupTask = task({
15
+ * name: 'cleanup-old-data',
16
+ * schedule: { type: 'cron', value: '0 2 * * *' }, // Daily at 2 AM
17
+ * async prepare(ctx) {
18
+ * // Only run if there's old data to clean
19
+ * return await hasOldData();
20
+ * },
21
+ * async execute(ctx) {
22
+ * await cleanupOldRecords();
23
+ * await ctx.commandkit.client.channels.cache
24
+ * .get('log-channel')?.send('Cleanup completed!');
25
+ * },
26
+ * });
27
+ * ```
28
+ */
29
+ export declare class Task<T extends Record<string, any> = Record<string, any>> {
30
+ private data;
31
+ /**
32
+ * Creates a new task instance.
33
+ *
34
+ * @param data - The task definition containing name, schedule, and execution logic
35
+ */
36
+ constructor(data: TaskDefinition<T>);
37
+ /**
38
+ * Whether this task should run immediately when created.
39
+ * Only applicable to cron tasks, defaults to false.
40
+ */
41
+ get immediate(): boolean;
42
+ /**
43
+ * The unique identifier for this task.
44
+ */
45
+ get name(): string;
46
+ /**
47
+ * The schedule configuration for this task.
48
+ * Returns null if no schedule is defined (manual execution only).
49
+ */
50
+ get schedule(): TaskSchedule | null;
51
+ /**
52
+ * Checks if this task uses cron-based scheduling.
53
+ *
54
+ * @returns true if the task has a cron schedule
55
+ */
56
+ isCron(): boolean;
57
+ /**
58
+ * Checks if this task uses date-based scheduling.
59
+ *
60
+ * @returns true if the task has a date schedule
61
+ */
62
+ isDate(): boolean;
63
+ /**
64
+ * Determines if the task is ready to be executed.
65
+ *
66
+ * This method calls the optional prepare function if defined. If no prepare
67
+ * function is provided, the task is always ready to execute.
68
+ *
69
+ * @param ctx - The task execution context
70
+ * @returns true if the task should execute, false to skip this run
71
+ */
72
+ prepare(ctx: TaskContext<T>): Promise<boolean>;
73
+ /**
74
+ * Executes the task's main logic.
75
+ *
76
+ * This method calls the execute function defined in the task definition.
77
+ * It provides access to the CommandKit instance, Discord.js client, and
78
+ * any custom data passed to the task.
79
+ *
80
+ * @param ctx - The task execution context containing CommandKit, client, and data
81
+ */
82
+ execute(ctx: TaskContext<T>): Promise<void>;
83
+ }
84
+ /**
85
+ * Creates a new task definition.
86
+ *
87
+ * This is the main function for defining tasks in your application. Tasks can be
88
+ * scheduled using cron expressions or specific dates, and can include preparation
89
+ * logic to conditionally execute based on runtime conditions.
90
+ *
91
+ * @example
92
+ * ```ts
93
+ * import { task } from '@commandkit/tasks';
94
+ *
95
+ * // Simple scheduled task
96
+ * export const dailyBackup = task({
97
+ * name: 'daily-backup',
98
+ * schedule: { type: 'cron', value: '0 0 * * *' },
99
+ * async execute(ctx) {
100
+ * await performBackup();
101
+ * },
102
+ * });
103
+ * ```
104
+ *
105
+ * @param data - The task definition containing name, schedule, and execution logic
106
+ * @returns A configured Task instance
107
+ */
108
+ export declare function task<T extends Record<string, any> = Record<string, any>>(data: TaskDefinition<T>): Task<T>;
package/dist/task.js ADDED
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Task = void 0;
4
+ exports.task = task;
5
+ /**
6
+ * Represents a task instance with execution logic and metadata.
7
+ *
8
+ * Tasks can be scheduled to run at specific times or intervals using cron expressions
9
+ * or date-based scheduling. They support preparation logic to conditionally execute
10
+ * and provide a context for accessing CommandKit and Discord.js functionality.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * import { task } from '@commandkit/tasks';
15
+ *
16
+ * export const cleanupTask = task({
17
+ * name: 'cleanup-old-data',
18
+ * schedule: { type: 'cron', value: '0 2 * * *' }, // Daily at 2 AM
19
+ * async prepare(ctx) {
20
+ * // Only run if there's old data to clean
21
+ * return await hasOldData();
22
+ * },
23
+ * async execute(ctx) {
24
+ * await cleanupOldRecords();
25
+ * await ctx.commandkit.client.channels.cache
26
+ * .get('log-channel')?.send('Cleanup completed!');
27
+ * },
28
+ * });
29
+ * ```
30
+ */
31
+ class Task {
32
+ /**
33
+ * Creates a new task instance.
34
+ *
35
+ * @param data - The task definition containing name, schedule, and execution logic
36
+ */
37
+ constructor(data) {
38
+ this.data = data;
39
+ }
40
+ /**
41
+ * Whether this task should run immediately when created.
42
+ * Only applicable to cron tasks, defaults to false.
43
+ */
44
+ get immediate() {
45
+ return this.data.immediate ?? false;
46
+ }
47
+ /**
48
+ * The unique identifier for this task.
49
+ */
50
+ get name() {
51
+ return this.data.name;
52
+ }
53
+ /**
54
+ * The schedule configuration for this task.
55
+ * Returns null if no schedule is defined (manual execution only).
56
+ */
57
+ get schedule() {
58
+ return this.data.schedule ?? null;
59
+ }
60
+ /**
61
+ * Checks if this task uses cron-based scheduling.
62
+ *
63
+ * @returns true if the task has a cron schedule
64
+ */
65
+ isCron() {
66
+ return this.schedule?.type === 'cron';
67
+ }
68
+ /**
69
+ * Checks if this task uses date-based scheduling.
70
+ *
71
+ * @returns true if the task has a date schedule
72
+ */
73
+ isDate() {
74
+ return this.schedule?.type === 'date';
75
+ }
76
+ /**
77
+ * Determines if the task is ready to be executed.
78
+ *
79
+ * This method calls the optional prepare function if defined. If no prepare
80
+ * function is provided, the task is always ready to execute.
81
+ *
82
+ * @param ctx - The task execution context
83
+ * @returns true if the task should execute, false to skip this run
84
+ */
85
+ async prepare(ctx) {
86
+ return this.data.prepare?.(ctx) ?? true;
87
+ }
88
+ /**
89
+ * Executes the task's main logic.
90
+ *
91
+ * This method calls the execute function defined in the task definition.
92
+ * It provides access to the CommandKit instance, Discord.js client, and
93
+ * any custom data passed to the task.
94
+ *
95
+ * @param ctx - The task execution context containing CommandKit, client, and data
96
+ */
97
+ async execute(ctx) {
98
+ await this.data.execute(ctx);
99
+ }
100
+ }
101
+ exports.Task = Task;
102
+ /**
103
+ * Creates a new task definition.
104
+ *
105
+ * This is the main function for defining tasks in your application. Tasks can be
106
+ * scheduled using cron expressions or specific dates, and can include preparation
107
+ * logic to conditionally execute based on runtime conditions.
108
+ *
109
+ * @example
110
+ * ```ts
111
+ * import { task } from '@commandkit/tasks';
112
+ *
113
+ * // Simple scheduled task
114
+ * export const dailyBackup = task({
115
+ * name: 'daily-backup',
116
+ * schedule: { type: 'cron', value: '0 0 * * *' },
117
+ * async execute(ctx) {
118
+ * await performBackup();
119
+ * },
120
+ * });
121
+ * ```
122
+ *
123
+ * @param data - The task definition containing name, schedule, and execution logic
124
+ * @returns A configured Task instance
125
+ */
126
+ function task(data) {
127
+ return new Task(data);
128
+ }
129
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy90YXNrLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWlJQSxvQkFJQztBQWxJRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlCRztBQUNILE1BQWEsSUFBSTtJQUNmOzs7O09BSUc7SUFDSCxZQUEyQixJQUF1QjtRQUF2QixTQUFJLEdBQUosSUFBSSxDQUFtQjtJQUFHLENBQUM7SUFFdEQ7OztPQUdHO0lBQ0gsSUFBVyxTQUFTO1FBQ2xCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsSUFBSTtRQUNiLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQVcsUUFBUTtRQUNqQixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQztJQUNwQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU07UUFDWCxPQUFPLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxLQUFLLE1BQU0sQ0FBQztJQUN4QyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU07UUFDWCxPQUFPLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxLQUFLLE1BQU0sQ0FBQztJQUN4QyxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQW1CO1FBQ3RDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLENBQUM7SUFDMUMsQ0FBQztJQUVEOzs7Ozs7OztPQVFHO0lBQ0ksS0FBSyxDQUFDLE9BQU8sQ0FBQyxHQUFtQjtRQUN0QyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9CLENBQUM7Q0FDRjtBQTFFRCxvQkEwRUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFDSCxTQUFnQixJQUFJLENBQ2xCLElBQXVCO0lBRXZCLE9BQU8sSUFBSSxJQUFJLENBQUksSUFBSSxDQUFDLENBQUM7QUFDM0IsQ0FBQyJ9
@@ -0,0 +1,77 @@
1
+ import { TaskContext } from './context';
2
+ /**
3
+ * Represents a task schedule configuration.
4
+ *
5
+ * Tasks can be scheduled using either cron expressions or specific dates/timestamps.
6
+ * The timezone is optional and defaults to the system timezone.
7
+ */
8
+ export type TaskSchedule = {
9
+ /** Schedule type using cron expressions */
10
+ type: 'cron';
11
+ /** Optional timezone for the cron schedule (e.g., 'UTC', 'America/New_York') */
12
+ timezone?: string;
13
+ /** Cron expression (e.g., '0 0 * * *' for daily at midnight) */
14
+ value: string;
15
+ } | {
16
+ /** Schedule type using a specific date or timestamp */
17
+ type: 'date';
18
+ /** Optional timezone for the date schedule */
19
+ timezone?: string;
20
+ /** Date object or Unix timestamp in milliseconds */
21
+ value: Date | number;
22
+ };
23
+ /**
24
+ * Defines a task with its execution logic and scheduling.
25
+ *
26
+ * Tasks can have optional preparation logic that determines whether the task should run,
27
+ * and required execution logic that performs the actual task work.
28
+ */
29
+ export interface TaskDefinition<T extends Record<string, any> = Record<string, any>> {
30
+ /** Unique identifier for the task */
31
+ name: string;
32
+ /** Optional schedule configuration for recurring or delayed execution */
33
+ schedule?: TaskSchedule;
34
+ /** Whether the task should run immediately when created (only for cron tasks) */
35
+ immediate?: boolean;
36
+ /**
37
+ * Optional preparation function that determines if the task should execute.
38
+ * Return false to skip execution for this run.
39
+ */
40
+ prepare?: (ctx: TaskContext<T>) => Promise<boolean>;
41
+ /**
42
+ * The main execution function that performs the task work.
43
+ * This is called when the task is scheduled to run.
44
+ */
45
+ execute: (ctx: TaskContext<T>) => Promise<void>;
46
+ }
47
+ /**
48
+ * Represents the data structure for a task instance.
49
+ *
50
+ * This includes the task metadata and any custom data passed to the task.
51
+ */
52
+ export interface TaskData<T extends Record<string, any> = Record<string, any>> {
53
+ /** The name of the task definition to execute */
54
+ name: string;
55
+ /** Custom data passed to the task execution context */
56
+ data: T;
57
+ /** Schedule configuration for when the task should run */
58
+ schedule: TaskSchedule;
59
+ /** Whether the task should run immediately when created */
60
+ immediate?: boolean;
61
+ }
62
+ /**
63
+ * Partial task data for creating tasks with optional fields.
64
+ *
65
+ * Useful when you want to create a task with only some fields specified.
66
+ */
67
+ export type PartialTaskData<T extends Record<string, any> = Record<string, any>> = Partial<TaskData<T>>;
68
+ /**
69
+ * Data structure passed to task execution handlers.
70
+ *
71
+ * This includes the task metadata and execution timestamp, but excludes
72
+ * scheduling information since the task is already being executed.
73
+ */
74
+ export type TaskExecutionData = Omit<TaskData, 'schedule' | 'immediate'> & {
75
+ /** Unix timestamp when the task execution started */
76
+ timestamp: number;
77
+ };
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9