@lafken/schedule 0.7.0 → 0.8.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @lafken/schedule
2
2
 
3
- `@lafken/schedule` simplifies the creation and management of Amazon EventBridge scheduled rules (Cron jobs) and their integration with AWS Lambda. It provides decorators to define scheduled tasks using standard cron expressions or structured time objects.
3
+ Define Amazon EventBridge scheduled rules using TypeScript decorators. `@lafken/schedule` lets you declare cron-based tasks directly on class methods each one becomes a Lambda function invoked automatically by EventBridge at the specified times.
4
4
 
5
5
  ## Installation
6
6
 
@@ -8,82 +8,144 @@
8
8
  npm install @lafken/schedule
9
9
  ```
10
10
 
11
- ## Configuration
11
+ ## Getting Started
12
12
 
13
- Add the `ScheduleResolver` from the `@lafken/schedule/resolver` library to your application configuration.
13
+ Define a schedule class with `@Schedule`, add `@Cron` methods, and register it through `ScheduleResolver`:
14
14
 
15
15
  ```typescript
16
+ import { createApp, createModule } from '@lafken/main';
16
17
  import { ScheduleResolver } from '@lafken/schedule/resolver';
18
+ import { Schedule, Cron } from '@lafken/schedule/main';
17
19
 
18
- createApp({
19
- name: 'awesome-app',
20
- resolvers: [
21
- new ScheduleResolver(),
22
- ],
23
- ...
24
- });
25
-
26
- // ...
27
-
20
+ // 1. Define scheduled tasks
28
21
  @Schedule()
29
- class GreetingSchedule {
30
- // ...
22
+ export class MaintenanceJobs {
23
+ @Cron({ schedule: 'cron(0 3 * * ? *)' })
24
+ cleanupExpiredSessions() {
25
+ // Runs every day at 3:00 AM UTC
26
+ }
27
+
28
+ @Cron({ schedule: { hour: 0, minute: 0, weekDay: 'SUN' } })
29
+ generateWeeklyReport() {
30
+ // Runs every Sunday at midnight UTC
31
+ }
31
32
  }
32
33
 
33
- const greetingModule = createModule({
34
- name: 'greeting',
35
- resources: [
36
- GreetingSchedule
37
- ]
34
+ // 2. Register in a module
35
+ const maintenanceModule = createModule({
36
+ name: 'maintenance',
37
+ resources: [MaintenanceJobs],
38
38
  });
39
39
 
40
+ // 3. Add the resolver to the app
41
+ createApp({
42
+ name: 'my-app',
43
+ resolvers: [new ScheduleResolver()],
44
+ modules: [maintenanceModule],
45
+ });
40
46
  ```
41
47
 
48
+ Each `@Cron` method becomes an independent Lambda function with its own EventBridge rule.
49
+
42
50
  ## Features
43
51
 
44
- ### Defining a Schedule Resource
52
+ ### Schedule Class
45
53
 
46
- Use the `@Schedule` decorator to define a class that contains scheduled tasks.
54
+ Use the `@Schedule` decorator to group related cron tasks in a single class. The class itself holds no schedule logic — it acts as a container for `@Cron` handlers:
47
55
 
48
56
  ```typescript
49
- import { Schedule, Cron } from '@lafken/schedule';
57
+ import { Schedule, Cron } from '@lafken/schedule/main';
50
58
 
51
59
  @Schedule()
52
- export class DataSyncService {
53
- // ... cron handlers
60
+ export class DataPipeline {
61
+ @Cron({ schedule: 'cron(0 6 * * ? *)' })
62
+ ingestData() { }
63
+
64
+ @Cron({ schedule: 'cron(30 6 * * ? *)' })
65
+ transformData() { }
54
66
  }
55
67
  ```
56
68
 
57
- ### Defining Cron Tasks
58
-
59
- Use the `@Cron` decorator to define a method as a scheduled task. You can configure the schedule using a standard cron string or a structured object.
69
+ ### Cron Expression (String)
60
70
 
61
- #### Using Cron Strings
71
+ Pass a standard AWS cron expression as a string. The format follows:
62
72
 
63
- You can use standard AWS cron expressions: `cron(Minutes Hours Day-of-month Month Day-of-week Year)`.
73
+ ```
74
+ cron(Minutes Hours Day-of-month Month Day-of-week Year)
75
+ ```
64
76
 
65
77
  ```typescript
66
- @Cron({
67
- schedule: 'cron(0 12 * * ? *)', // Run every day at 12:00 UTC
68
- })
69
- dailySync() {
70
- console.log('Running daily sync...');
78
+ @Cron({ schedule: 'cron(0 12 * * ? *)' })
79
+ sendDailyDigest() {
80
+ // Every day at 12:00 PM UTC
81
+ }
82
+
83
+ @Cron({ schedule: 'cron(0 9 1 * ? *)' })
84
+ generateMonthlyInvoice() {
85
+ // First day of every month at 9:00 AM UTC
71
86
  }
72
87
  ```
73
88
 
74
- #### Using Structured Schedule Objects
89
+ > [!NOTE]
90
+ > AWS cron expressions require either the day-of-month or day-of-week field to be `?`. You cannot specify both simultaneously. When using a cron string, include the full `cron(...)` wrapper.
75
91
 
76
- You can also define the schedule using a readable object format.
92
+ ### Cron Expression (Object)
93
+
94
+ For a more readable alternative, use the `ScheduleTime` object format. Each field defaults to `'*'` when omitted:
77
95
 
78
96
  ```typescript
79
97
  @Cron({
80
98
  schedule: {
81
- minute: '0',
82
- hour: '8',
99
+ minute: 0,
100
+ hour: 8,
83
101
  weekDay: 'MON-FRI',
84
102
  },
85
103
  })
86
- weekdayStart() {
87
- console.log('Starting weekday operations...');
104
+ startBusinessHours() {
105
+ // Every weekday at 8:00 AM UTC
106
+ }
107
+
108
+ @Cron({
109
+ schedule: {
110
+ minute: 30,
111
+ hour: 22,
112
+ day: 15,
113
+ },
114
+ })
115
+ midMonthAudit() {
116
+ // 15th of every month at 10:30 PM UTC
88
117
  }
89
118
  ```
119
+
120
+ #### ScheduleTime Fields
121
+
122
+ | Field | Type | Default | Description |
123
+ | --------- | --------------------------- | ------- | -------------------- |
124
+ | `minute` | `number \| '*' \| '?'` | `'*'` | Minute (0–59) |
125
+ | `hour` | `number \| '*' \| '?'` | `'*'` | Hour (0–23) |
126
+ | `day` | `number \| '*' \| '?'` | `'*'` | Day of month (1–31) |
127
+ | `month` | `number \| '*' \| '?'` | `'*'` | Month (1–12) |
128
+ | `weekDay` | `number \| string \| '?'` | `'*'` | Day of week (SUN–SAT or 1–7) |
129
+ | `year` | `number \| '*' \| '?'` | `'*'` | Year |
130
+
131
+ When `day` is set to a specific value, `weekDay` is automatically set to `'?'` and vice versa, following the AWS cron constraint.
132
+
133
+ ### Retry Policy
134
+
135
+ Configure how EventBridge handles failed deliveries using `retryAttempts` and `maxEventAge`:
136
+
137
+ ```typescript
138
+ @Cron({
139
+ schedule: 'cron(0 0 * * ? *)',
140
+ retryAttempts: 3,
141
+ maxEventAge: 3600,
142
+ })
143
+ criticalNightlyJob() {
144
+ // Retries up to 3 times, discards events older than 1 hour
145
+ }
146
+ ```
147
+
148
+ | Option | Type | Description |
149
+ | --------------- | -------- | ---------------------------------------------------------- |
150
+ | `retryAttempts` | `number` | Maximum retry attempts if the target invocation fails |
151
+ | `maxEventAge` | `number` | Maximum event age in seconds before the event is discarded |
@@ -1,4 +1,43 @@
1
1
  import type { EventCronProps } from './schedule.types';
2
2
  export declare const RESOURCE_TYPE: "CRON";
3
+ /**
4
+ * Class decorator that registers a class as a scheduled event resource.
5
+ *
6
+ * The decorated class groups one or more `@Cron` handler methods that
7
+ * are invoked on a time-based schedule via Amazon EventBridge.
8
+ *
9
+ * @param props - Optional resource configuration (e.g. a custom `name`).
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * @Schedule()
14
+ * export class MaintenanceJobs {
15
+ * @Cron({ schedule: { hour: 3, minute: 0 } })
16
+ * cleanup() { }
17
+ * }
18
+ * ```
19
+ */
3
20
  export declare const Schedule: (props?: import("@lafken/common").ResourceProps | undefined) => (constructor: Function) => void;
21
+ /**
22
+ * Method decorator that registers a handler to run on a cron schedule.
23
+ *
24
+ * The decorated method becomes a Lambda function invoked automatically
25
+ * by EventBridge at the times defined by the `schedule` option. The
26
+ * schedule can be a standard AWS cron string or a structured
27
+ * `ScheduleTime` object.
28
+ *
29
+ * @param props - Schedule configuration (schedule expression, maxEventAge,
30
+ * retryAttempts).
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * // Using a cron string (every day at midnight UTC)
35
+ * @Cron({ schedule: 'cron(0 0 * * ? *)' })
36
+ * dailyReport() { }
37
+ *
38
+ * // Using a ScheduleTime object (every Monday at 8:30 AM)
39
+ * @Cron({ schedule: { weekDay: 'MON', hour: 8, minute: 30 } })
40
+ * weeklyDigest() { }
41
+ * ```
42
+ */
4
43
  export declare const Cron: (props: EventCronProps) => (target: any, methodName: string, descriptor: PropertyDescriptor) => any;
@@ -3,10 +3,49 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Cron = exports.Schedule = exports.RESOURCE_TYPE = void 0;
4
4
  const common_1 = require("@lafken/common");
5
5
  exports.RESOURCE_TYPE = 'CRON';
6
+ /**
7
+ * Class decorator that registers a class as a scheduled event resource.
8
+ *
9
+ * The decorated class groups one or more `@Cron` handler methods that
10
+ * are invoked on a time-based schedule via Amazon EventBridge.
11
+ *
12
+ * @param props - Optional resource configuration (e.g. a custom `name`).
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * @Schedule()
17
+ * export class MaintenanceJobs {
18
+ * @Cron({ schedule: { hour: 3, minute: 0 } })
19
+ * cleanup() { }
20
+ * }
21
+ * ```
22
+ */
6
23
  exports.Schedule = (0, common_1.createResourceDecorator)({
7
24
  type: exports.RESOURCE_TYPE,
8
25
  callerFileIndex: 5,
9
26
  });
27
+ /**
28
+ * Method decorator that registers a handler to run on a cron schedule.
29
+ *
30
+ * The decorated method becomes a Lambda function invoked automatically
31
+ * by EventBridge at the times defined by the `schedule` option. The
32
+ * schedule can be a standard AWS cron string or a structured
33
+ * `ScheduleTime` object.
34
+ *
35
+ * @param props - Schedule configuration (schedule expression, maxEventAge,
36
+ * retryAttempts).
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * // Using a cron string (every day at midnight UTC)
41
+ * @Cron({ schedule: 'cron(0 0 * * ? *)' })
42
+ * dailyReport() { }
43
+ *
44
+ * // Using a ScheduleTime object (every Monday at 8:30 AM)
45
+ * @Cron({ schedule: { weekDay: 'MON', hour: 8, minute: 30 } })
46
+ * weeklyDigest() { }
47
+ * ```
48
+ */
10
49
  const Cron = (props) => (0, common_1.createLambdaDecorator)({
11
50
  getLambdaMetadata: (props, methodName) => ({
12
51
  ...props,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lafken/schedule",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "private": false,
5
5
  "description": "Define EventBridge scheduled rules and cron jobs using TypeScript decorators with Lafken",
6
6
  "keywords": [
@@ -50,17 +50,19 @@
50
50
  ],
51
51
  "dependencies": {
52
52
  "reflect-metadata": "^0.2.2",
53
- "@lafken/resolver": "0.7.0"
53
+ "@lafken/resolver": "0.8.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@cdktn/provider-aws": "^23.0.0",
57
- "@types/jest": "^30.0.0",
57
+ "@swc/core": "^1.15.11",
58
+ "@swc/helpers": "^0.5.18",
59
+ "@vitest/runner": "^4.0.18",
58
60
  "cdktn": "^0.22.0",
61
+ "cdktn-vitest": "^1.0.0",
59
62
  "constructs": "^10.4.5",
60
- "jest": "^30.2.0",
61
- "ts-jest": "^29.4.6",
62
- "ts-node": "^10.9.2",
63
- "@lafken/common": "0.7.0"
63
+ "unplugin-swc": "^1.5.9",
64
+ "vitest": "^4.0.18",
65
+ "@lafken/common": "0.8.0"
64
66
  },
65
67
  "peerDependencies": {
66
68
  "@cdktn/provider-aws": "^23.0.0",
@@ -76,9 +78,9 @@
76
78
  },
77
79
  "scripts": {
78
80
  "build": "pnpm clean && tsc -p ./tsconfig.build.json",
81
+ "check-types": "tsc --noEmit -p ./tsconfig.build.json",
79
82
  "clean": "rm -rf ./lib",
80
83
  "dev": "tsc -w",
81
- "test": "jest",
82
- "test:coverage": "jest --coverage"
84
+ "test": "vitest"
83
85
  }
84
86
  }