@mrjacket/ahko 0.5.0 → 0.6.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/CHANGELOG.md +22 -0
- package/README.md +103 -5
- package/dist/ahko.d.ts +64 -0
- package/dist/events/event-emitter.d.ts +34 -0
- package/dist/events/index.d.ts +1 -0
- package/dist/index.cjs +313 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +313 -3
- package/dist/index.js.map +1 -1
- package/dist/models/events.model.d.ts +50 -0
- package/dist/models/index.d.ts +1 -0
- package/dist/models/stats.model.d.ts +4 -0
- package/dist/scheduler/task-queue.d.ts +30 -0
- package/dist/scheduler/task-runner.d.ts +2 -0
- package/dist/version.d.ts +1 -1
- package/package.json +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.6.0] - 2026-09-23 — Telemetry & DX
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Type-safe lifecycle event emitter (`AhkoEventEmitter`) with dedicated `IAhkoEventMap` events:
|
|
12
|
+
- `task:start`: emitted when a task begins execution with `taskId` and `attempt`.
|
|
13
|
+
- `task:complete`: emitted on task success with `taskId`, `attempt`, `durationMs`, and `result`.
|
|
14
|
+
- `task:fail`: emitted on failure with `taskId`, `attempt`, `error`, and `willRetry` boolean indicator.
|
|
15
|
+
- `task:cancel`: emitted on task cancellation with `taskId` and `reason`.
|
|
16
|
+
- `task:timeout`: emitted when execution exceeds configured deadline with `taskId` and `timeoutMs`.
|
|
17
|
+
- `idle`: emitted when all tasks settle and queue reaches idle state with `timestamp`.
|
|
18
|
+
- Event subscription methods `ahko.on(event, handler)` returning an unsubscribe function, and `ahko.off(event, handler)`.
|
|
19
|
+
- Listener error containment: listener exceptions are safely isolated without crashing the scheduler loop or sibling listeners.
|
|
20
|
+
- Idle lifecycle promises via `ahko.isIdle()`, `ahko.onIdle()`, and chill alias `ahko.chill()`.
|
|
21
|
+
- Queue clearance method `ahko.clear()` to cancel queued, delayed, and coalesced tasks cleanly.
|
|
22
|
+
- Ahko mascot battery telemetry via `ahko.battery()` reporting chill status.
|
|
23
|
+
- Extended telemetry snapshot in `ahko.stats()` with `retriedTasks` and `totalDispatched`.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- Fixed 2 CodeQL security alerts by iterating over map values (`this.entries.values()`) in `DebounceCoordinator.clear()` and `ThrottleCoordinator.clear()`.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
8
30
|
## [0.5.0] - 2026-09-22 — Throttle, Debounce & Rate Limiting
|
|
9
31
|
|
|
10
32
|
### Added
|
package/README.md
CHANGED
|
@@ -27,6 +27,18 @@
|
|
|
27
27
|
<a href="https://github.com/x-name15/ahko/blob/main/LICENSE">
|
|
28
28
|
<img src="https://img.shields.io/npm/l/@mrjacket/ahko.svg" alt="license">
|
|
29
29
|
</a>
|
|
30
|
+
<a href="https://www.npmjs.com/package/@mrjacket/ahko">
|
|
31
|
+
<img src="https://img.shields.io/badge/dependencies-0-success" alt="zero dependencies">
|
|
32
|
+
</a>
|
|
33
|
+
<a href="https://bundlephobia.com/package/@mrjacket/ahko">
|
|
34
|
+
<img src="https://img.shields.io/bundlephobia/minzip/@mrjacket/ahko?color=purple" alt="bundle size">
|
|
35
|
+
</a>
|
|
36
|
+
<a href="https://github.com/x-name15/ahko">
|
|
37
|
+
<img src="https://img.shields.io/badge/TypeScript-Ready-3178C6?logo=typescript&logoColor=white" alt="TypeScript">
|
|
38
|
+
</a>
|
|
39
|
+
<a href="https://github.com/x-name15/ahko/issues">
|
|
40
|
+
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs Welcome">
|
|
41
|
+
</a>
|
|
30
42
|
</p>
|
|
31
43
|
|
|
32
44
|
`ahko` is a low-energy task scheduler for JavaScript and TypeScript.
|
|
@@ -219,10 +231,65 @@ console.log(stats);
|
|
|
219
231
|
// failedTasks: 1,
|
|
220
232
|
// cancelledTasks: 2,
|
|
221
233
|
// timedOutTasks: 1,
|
|
234
|
+
// retriedTasks: 3,
|
|
235
|
+
// totalDispatched: 45,
|
|
222
236
|
// capacity: 3
|
|
223
237
|
// }
|
|
224
238
|
```
|
|
225
239
|
|
|
240
|
+
### 10. Lifecycle Events (`on` / `off`)
|
|
241
|
+
|
|
242
|
+
Listen to typed lifecycle events with isolated callback safety:
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
const unsubscribe = ahko.on("task:start", ({ taskId, attempt }) => {
|
|
246
|
+
console.log(`Task ${taskId} started attempt #${attempt}`);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
ahko.on("task:complete", ({ taskId, durationMs, result }) => {
|
|
250
|
+
console.log(`Task ${taskId} completed in ${durationMs}ms:`, result);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
ahko.on("task:fail", ({ taskId, attempt, error, willRetry }) => {
|
|
254
|
+
console.warn(`Task ${taskId} attempt #${attempt} failed (willRetry: ${willRetry})`, error);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
ahko.on("task:timeout", ({ taskId, timeoutMs }) => {
|
|
258
|
+
console.warn(`Task ${taskId} exceeded ${timeoutMs}ms deadline`);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
ahko.on("task:cancel", ({ taskId, reason }) => {
|
|
262
|
+
console.info(`Task ${taskId} was cancelled:`, reason);
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
ahko.on("idle", ({ timestamp }) => {
|
|
266
|
+
console.log("Scheduler transitioned to idle at", timestamp);
|
|
267
|
+
});
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### 11. Idle & Chill Developer Experience
|
|
271
|
+
|
|
272
|
+
Wait for all work to settle or clear the queue cleanly:
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
// Wait for all active and pending tasks to finish
|
|
276
|
+
await ahko.onIdle();
|
|
277
|
+
// Or use the completely chill alias:
|
|
278
|
+
await ahko.chill();
|
|
279
|
+
|
|
280
|
+
// Check if scheduler is currently idle
|
|
281
|
+
if (ahko.isIdle()) {
|
|
282
|
+
console.log("Completely chill. No tasks running or queued.");
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Clear all queued, delayed, and coalesced tasks
|
|
286
|
+
ahko.clear();
|
|
287
|
+
|
|
288
|
+
// Check Ahko mascot battery telemetry
|
|
289
|
+
console.log(ahko.battery());
|
|
290
|
+
// { level: 3, chill: true, status: "low-energy", quote: "Mwee... my battery is low, but all your tasks are handled completely chill." }
|
|
291
|
+
```
|
|
292
|
+
|
|
226
293
|
---
|
|
227
294
|
|
|
228
295
|
## Documentation
|
|
@@ -231,10 +298,13 @@ Comprehensive guides and technical documentation are available in the [`docs/`](
|
|
|
231
298
|
|
|
232
299
|
| Document | Description |
|
|
233
300
|
|---|---|
|
|
234
|
-
| [**
|
|
235
|
-
| [**
|
|
236
|
-
| [**
|
|
237
|
-
| [**
|
|
301
|
+
| [**Documentation Portal**](./docs/README.md) | Master overview and index of all guides and specifications. |
|
|
302
|
+
| [**Getting Started**](./docs/guides/getting-started.md) | Quickstart guide, installation, and fundamental usage patterns. |
|
|
303
|
+
| [**Library API**](./docs/guides/library.md) | Complete programmatic API reference, TypeScript interfaces, and options. |
|
|
304
|
+
| [**Production Recipes**](./docs/guides/recipes.md) | Battle-tested recipes (paced API client, debounced search, throttled scroll, graceful shutdown). |
|
|
305
|
+
| [**Architecture**](./docs/architecture/ARCHITECTURE.md) | Architectural specifications, lifecycle state machine, and design decisions. |
|
|
306
|
+
| [**Roadmap**](./docs/architecture/ROADMAP.md) | Milestone progression from 0.1.0 through 1.0.0. |
|
|
307
|
+
| [**Engineering Log**](./docs/architecture/LOG.md) | Chronological log of engineering decisions and ADRs. |
|
|
238
308
|
|
|
239
309
|
---
|
|
240
310
|
|
|
@@ -276,9 +346,37 @@ Convenience method scheduling a throttled task with leading execution and coales
|
|
|
276
346
|
|
|
277
347
|
Convenience method scheduling a task under `strategy: "idle"`.
|
|
278
348
|
|
|
349
|
+
### `ahko.on(event, handler)`
|
|
350
|
+
|
|
351
|
+
Subscribes to scheduler lifecycle events (`task:start`, `task:complete`, `task:fail`, `task:cancel`, `task:timeout`, `idle`). Returns an unsubscribe function.
|
|
352
|
+
|
|
353
|
+
### `ahko.off(event, handler)`
|
|
354
|
+
|
|
355
|
+
Unsubscribes an event listener callback.
|
|
356
|
+
|
|
357
|
+
### `ahko.isIdle(): boolean`
|
|
358
|
+
|
|
359
|
+
Returns whether the scheduler is currently idle (no active or pending tasks).
|
|
360
|
+
|
|
361
|
+
### `ahko.onIdle(): Promise<void>`
|
|
362
|
+
|
|
363
|
+
Returns a Promise that resolves when all active and pending tasks have settled.
|
|
364
|
+
|
|
365
|
+
### `ahko.chill(): Promise<void>`
|
|
366
|
+
|
|
367
|
+
Alias for `ahko.onIdle()`.
|
|
368
|
+
|
|
369
|
+
### `ahko.clear(): void`
|
|
370
|
+
|
|
371
|
+
Cancels all pending, delayed, and throttled/debounced tasks cleanly.
|
|
372
|
+
|
|
373
|
+
### `ahko.battery()`
|
|
374
|
+
|
|
375
|
+
Returns mascot battery status and quote.
|
|
376
|
+
|
|
279
377
|
### `ahko.stats(): IAhkoStats`
|
|
280
378
|
|
|
281
|
-
Returns a snapshot of current task counters and queue capacity.
|
|
379
|
+
Returns a snapshot of current task counters, retry counts, total dispatches, and queue capacity.
|
|
282
380
|
|
|
283
381
|
---
|
|
284
382
|
|
package/dist/ahko.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TAhkoEventName, TAhkoEventHandler, TAhkoUnsubscribe } from "./models/events.model.js";
|
|
1
2
|
import type { IAhkoOptions, IScheduleOptions } from "./models/options.model.js";
|
|
2
3
|
import type { IAhkoStats } from "./models/stats.model.js";
|
|
3
4
|
import type { ITask } from "./models/task.model.js";
|
|
@@ -110,4 +111,67 @@ export declare class Ahko {
|
|
|
110
111
|
* ```
|
|
111
112
|
*/
|
|
112
113
|
stats(): IAhkoStats;
|
|
114
|
+
/**
|
|
115
|
+
* Subscribes to a scheduler lifecycle event.
|
|
116
|
+
*
|
|
117
|
+
* @param event - Event name to listen for.
|
|
118
|
+
* @param handler - Callback function invoked when the event is emitted.
|
|
119
|
+
* @returns Unsubscribe function to remove the listener.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const unsubscribe = ahko.on("task:start", ({ taskId, attempt }) => {
|
|
124
|
+
* console.log(`Task ${taskId} started attempt ${attempt}`);
|
|
125
|
+
* });
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
on<K extends TAhkoEventName>(event: K, handler: TAhkoEventHandler<K>): TAhkoUnsubscribe;
|
|
129
|
+
/**
|
|
130
|
+
* Unsubscribes an event listener from a scheduler lifecycle event.
|
|
131
|
+
*
|
|
132
|
+
* @param event - Event name.
|
|
133
|
+
* @param handler - The exact listener callback to remove.
|
|
134
|
+
*/
|
|
135
|
+
off<K extends TAhkoEventName>(event: K, handler: TAhkoEventHandler<K>): void;
|
|
136
|
+
/**
|
|
137
|
+
* Checks whether the scheduler is currently idle (no active runners and no pending tasks).
|
|
138
|
+
*
|
|
139
|
+
* @returns True if completely idle, false otherwise.
|
|
140
|
+
*/
|
|
141
|
+
isIdle(): boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Returns a promise that resolves once the scheduler has completed all tasks and is idle.
|
|
144
|
+
*
|
|
145
|
+
* @returns Promise resolving when the scheduler is idle.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```typescript
|
|
149
|
+
* ahko.schedule(doWork);
|
|
150
|
+
* await ahko.onIdle();
|
|
151
|
+
* console.log("All work finished!");
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
onIdle(): Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* Clears all pending, delayed, and throttled/debounced tasks from the scheduler.
|
|
157
|
+
* In-flight active tasks will continue executing to completion or abort via signal.
|
|
158
|
+
*/
|
|
159
|
+
clear(): void;
|
|
160
|
+
/**
|
|
161
|
+
* Returns the delightful Ahko mascot battery telemetry status.
|
|
162
|
+
*
|
|
163
|
+
* Low energy, completely chill.
|
|
164
|
+
*/
|
|
165
|
+
battery(): {
|
|
166
|
+
level: number;
|
|
167
|
+
chill: boolean;
|
|
168
|
+
status: string;
|
|
169
|
+
quote: string;
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Delightful alias for `onIdle()`: wait for all tasks to settle chill and relaxed.
|
|
173
|
+
*
|
|
174
|
+
* @returns Promise resolving when all tasks have finished.
|
|
175
|
+
*/
|
|
176
|
+
chill(): Promise<void>;
|
|
113
177
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { IAhkoEventMap, TAhkoEventHandler, TAhkoEventName, TAhkoUnsubscribe } from "../models/events.model.js";
|
|
2
|
+
/**
|
|
3
|
+
* Lightweight, zero-dependency typed event emitter with safe error containment.
|
|
4
|
+
*/
|
|
5
|
+
export declare class AhkoEventEmitter {
|
|
6
|
+
private readonly listeners;
|
|
7
|
+
/**
|
|
8
|
+
* Subscribes a listener to a specific Ahko lifecycle event.
|
|
9
|
+
*
|
|
10
|
+
* @param event - The event name to subscribe to.
|
|
11
|
+
* @param handler - The callback function to invoke when the event is emitted.
|
|
12
|
+
* @returns An unsubscribe function to remove the listener.
|
|
13
|
+
*/
|
|
14
|
+
on<K extends TAhkoEventName>(event: K, handler: TAhkoEventHandler<K>): TAhkoUnsubscribe;
|
|
15
|
+
/**
|
|
16
|
+
* Unsubscribes a listener from a specific Ahko lifecycle event.
|
|
17
|
+
*
|
|
18
|
+
* @param event - The event name.
|
|
19
|
+
* @param handler - The callback function to remove.
|
|
20
|
+
*/
|
|
21
|
+
off<K extends TAhkoEventName>(event: K, handler: TAhkoEventHandler<K>): void;
|
|
22
|
+
/**
|
|
23
|
+
* Emits an event with the corresponding typed payload to all subscribed listeners.
|
|
24
|
+
* Listener invocations are safely isolated in try/catch to protect scheduler integrity.
|
|
25
|
+
*
|
|
26
|
+
* @param event - The event name to emit.
|
|
27
|
+
* @param payload - The event-specific payload data.
|
|
28
|
+
*/
|
|
29
|
+
emit<K extends TAhkoEventName>(event: K, payload: IAhkoEventMap[K]): void;
|
|
30
|
+
/**
|
|
31
|
+
* Removes all registered event listeners.
|
|
32
|
+
*/
|
|
33
|
+
clear(): void;
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./event-emitter.js";
|