
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
eternal-timer
Advanced tools
A simple and persistent timer library for Node.js. Timers are saved to a file and maintain their state even after process restart.
expired, created, removed, and updated through an event system.npm install eternal-timer
You can choose between two manager classes depending on the desired storage format.
JSONLTimersManager (JSON Lines)Use this manager to store timers in a .jsonl file, which allows for storing extra data.
import { JSONLTimersManager } from 'eternal-timer';
async function main() {
// By default, timers are stored in '.timers.jsonl' in the project root.
const manager = new JSONLTimersManager();
// Create a timer (5 seconds) with a title and description
const timerId = await manager.createTimer({length: 5000, extra: { title: 'My Timer', description: 'This is a test timer.' }});
console.log('Timer created:', timerId);
// Start monitoring for expired timers
const interval = await manager.checkStart();
// Listen for 'expired' events
manager.on('expired', (timer) => {
console.log('Timer expired:', timer.id, timer.extra?.title);
});
// Display all timers
const timers = await manager.showTimers();
console.log('Active timers:', timers);
// To stop monitoring, for example after 10 seconds
setTimeout(() => {
clearInterval(interval);
console.log('Stopped monitoring timers.');
}, 10000);
}
main();
PlainTextTimersManager (Plain Text)Use this manager for a more lightweight plain-text format.
import { PlainTextTimersManager } from 'eternal-timer';
async function main() {
// By default, timers are stored in '.timers' in the project root.
const manager = new PlainTextTimersManager();
// Create a timer (5 seconds)
const timerId = await manager.createTimer(5000);
console.log('Timer created:', timerId);
// Start monitoring for expired timers
const interval = await manager.checkStart();
// Listen for 'expired' events
manager.on('expired', (timer) => {
console.log('Timer expired:', timer.id);
});
// Display all timers
const timers = await manager.showTimers();
console.log('Active timers:', timers);
// Stop monitoring after a while
setTimeout(() => {
clearInterval(interval);
console.log('Stopped monitoring for timers.');
}, 10000);
}
main();
JSONLTimersManagerconstructor(timerfiledir?: string)Creates a manager for timers stored in JSON Lines format.
timerfiledir (optional, string): Path to the timer file. Defaults to .timers.jsonl in the project root.changeExtra(id: string, newExtra: Extra): Promise<void>Changes the extra data of an existing timer.
id: The ID of the timer to modify.newExtra: The new extra object for the timer.Returns: A Promise<void> that resolves when the timer's extra data has been updated.
Throws: An error if: the timer with the specified ID is not found, or a file operation fails.
Extra Type ParameterThe JSONLTimersManager is a generic class that accepts a type parameter Extra. This allows you to define the structure of the extra object that will be stored with your timers. By default, Extra is an empty object {}.
Example: Defining and using a custom Extra type
import { JSONLTimersManager } from 'eternal-timer';
interface MyTimerExtra {
title?: string;
description?: string;
category?: string;
}
async function main() {
// Specify MyTimerExtra as the type argument for JSONLTimersManager
const manager = new JSONLTimersManager<MyTimerExtra>();
// Create a timer with custom extra data
const timerId = await manager.createTimer({
length: 10000,
extra: {
title: 'Project Alpha Deadline',
description: 'Final submission for project Alpha.',
category: 'Work'
}
});
console.log('Timer created:', timerId);
// Retrieve and access the custom extra data
const timers = await manager.showTimers();
const myTimer = timers.find(t => t.id === timerId);
if (myTimer) {
console.log('Timer title:', myTimer.extra?.title);
console.log('Timer category:', myTimer.extra?.category);
}
}
main();
PlainTextTimersManagerconstructor(timerfiledir?: string)Creates a manager for timers stored in plain-text format.
timerfiledir (optional, string): Path to the timer file. Defaults to .timers in the project root.createTimer(options: CreateTimerOptions<T, Extra>): Promise<string>Creates a new timer and saves it to the file.
options (CreateTimerOptions<T, Extra>)
PlainTextTimersManager (type PlainText):
number — The timer's duration in milliseconds.JSONLTimersManager (type JSONL):
{ length: number; extra?: Extra }
length (number): The timer's duration in milliseconds.extra (optional, Extra object): An object containing arbitrary user-defined metadata for the timer.Returns A Promise<string> that resolves to the timer's unique ID (UUID).
Throws An error if: length is invalid (e.g., negative) or a file operation fails.
Examples:
// For PlainTextTimersManager with a custom Extra type
import { PlainTextTimersManager } from 'eternal-timer';
// For PlainTextTimersManager
const manager = new PlainTextTimersManager();
const newTimerId = await manager.createTimer(5000); // Create a 5-second timer
console.log('Created PlainText timer with ID:', newTimerId);
// For JSONLTimersManager with a custom Extra type
import { JSONLTimersManager } from 'eternal-timer';
interface MyCustomExtra {
purpose: string;
userId: string;
}
const jsonlManager = new JSONLTimersManager<MyCustomExtra>();
const jsonlTimerId = await jsonlManager.createTimer({
length: 10000, // 10 seconds
extra: {
purpose: "Session Timeout",
userId: "user-123"
}
});
console.log('Created JSONL timer with ID:', jsonlTimerId);
removeTimer(id: string): Promise<void>Removes a timer by its ID.
id: The ID of the timer to remove.Returns: A Promise that resolves when the timer is removed.
Throws: An error if the timer with the specified ID is not found or if a file operation fails.
checkStart(interval?: number): Promise<NodeJS.Timeout>Starts the timer checking loop. This method should be called once after creating an instance of a TimersManager to begin detecting expired timers. Events like expired, errored, created, removed, and updated are emitted, which can be listened to using the on method.
interval (optional, number): Polling interval in milliseconds (default: 200ms)Returns: The interval ID which can be used to stop the loop with clearInterval().
Throws: If file operation fails during checking.
on<K extends keyof TimerEvents<T, Extra>>(event: K, listener: (payload: TimerEvents<T, Extra>[K]) => void | Promise<void>): voidRegisters an event listener for a specific timer event.
event: The name of the event to listen for (e.g., 'expired', 'created', 'removed', 'updated', 'errored').listener: The callback function to execute when the event is emitted. It receives the event payload as an argument.Returns: void
Example:
manager.on('expired', (timer) => {
console.log(`Timer ${timer.id} expired!`);
});
manager.on('errored', (error) => {
console.error('Timer event error:', error);
});
once<K extends keyof TimerEvents<T, Extra>>(event: K, listener: (payload: TimerEvents<T, Extra>[K]) => void | Promise<void>): voidRegisters a one-time event listener for a specific timer event. The listener will be invoked only once for the specified event, after which it will be automatically removed.
event: The name of the event to listen for.listener: The callback function to execute when the event is emitted.Returns: void
off<K extends keyof TimerEvents<T, Extra>>(event: K, listener: (payload: TimerEvents<T, Extra>[K]) => void | Promise<void>): voidRemoves a specific event listener for a given event.
event: The name of the event from which to remove the listener.listener: The listener function to remove.Returns: void
offAll<K extends keyof TimerEvents<T, Extra>>(event: K): voidRemoves all event listeners for a specific event.
event: The name of the event for which to remove all listeners.Returns: void
showTimers(): Promise<Timer[]>Retrieves all active timers.
Returns: A Promise that resolves to an array of Timer objects.
Throws: An error if a file operation fails.
adjustRemainingTime(id: string, delay: number): Promise<void>Adjusts the remaining time of a specified timer. This can be used to extend or shorten a timer's duration.
id: The ID of the timer to modify.delay: The amount of time in milliseconds to add to (if positive) or subtract from (if negative) the timer's remaining duration.Returns: A Promise<void> that resolves when the timer's remaining time has been adjusted.
Throws: An error if: the timer with the specified ID is not found, the resulting remaining time would be negative, or a file operation fails.
Example:
// Assuming 'timerId' is the ID of an existing timer
await manager.adjustRemainingTime(timerId, 60000); // Add 1 minute to the timer
await manager.adjustRemainingTime(timerId, -30000); // Subtract 30 seconds from the timer
checkStop(): Promise<void>Asynchronously checks for any running checkStart intervals and clears them if found. This effectively stops the timer monitoring process.
Returns: A Promise<void> that resolves when all intervals have been cleared.
Throws: An error if any underlying file operation fails during the process of checking and stopping.
isBusy: booleanA getter that returns true if the manager is currently monitoring for expired timers (i.e., checkStart has been called and checkStop has not yet been called), and false otherwise.
Returns: boolean - true if monitoring, false otherwise.
The StorageType has the following structure:
type StorageType = "JSONL" | "PlainText"
The Timer object has the following structure:
type Timer<T extends StorageType, Extra extends object> =
T extends "JSONL"
? {
id: string;
start: number;
stop: number;
extra: Extra
}
: {
id: string;
start: number;
stop: number;
};
Extra is a generic type parameter that represents an object containing arbitrary user-defined metadata for JSONL timers. By default, it's object. For example, it can be { title?: string; description?: string }.
The CreateTimerOptions type is used when creating new timers:
type CreateTimerOptions<T extends StorageType, Extra extends object> = T extends "JSONL"
? {
length: number;
extra: Extra
}
: T extends "PlainText"
? number
: never;
The TimerEvents type defines the events emitted by TimersManager:
type TimerEvents<T extends StorageType, Extra extends object> = {
expired: Timer<T, Extra>
errored: Error
interval: void
created: Timer<T, Extra>
removed: Timer<T, Extra>
updated: { old: Timer<T, Extra>, new: Timer<T, Extra> }
}
npm run build: Compile TypeScriptnpm run test: Test the compiled codenpm run lint: Lint all codesnpm run lint:fix: Lint all codes and fixYou can choose between two storage formats by selecting the appropriate manager class.
JSONLTimersManager)This is the recommended format for storing rich metadata.
title and description. Improved memory efficiency due to line-by-line file reading..timers.jsonl{"id":"...","start":1678886400000,"stop":1678886405000,"title":"My Timer","description":"..."}
PlainTextTimersManager)This format is more lightweight and slightly faster.
title or description..timers{id} {start_timestamp} {stop_timestamp}
Apache-2.0
Licensed under the Apache License, Version 2.0. See the LICENSE file for details.
FAQs
timer for node.js package
The npm package eternal-timer receives a total of 372 weekly downloads. As such, eternal-timer popularity was classified as not popular.
We found that eternal-timer demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.