-
-
Notifications
You must be signed in to change notification settings - Fork 438
Description
@wxt-dev/alarms API Proposal
Overview
This proposal outlines a simple wrapper for Chrome’s native browser.alarms API, available as @wxt-dev/alarms. The goal is to provide an asynchronous, promise-based interface that aligns with our existing API design patterns. The new design centers on a single function, defineAlarm, which returns an object with helper methods to manage an alarm instance.
Objectives
- Consistency: Provide a uniform, promise-based API similar to our other modules.
- Simplicity: Encapsulate alarm management within a defined object.
- Extensibility: Lay the groundwork for future enhancements, such as snapshotting and restoration of alarms.
Proposed API Design
1. defineAlarm
This function defines an alarm, automatically initializing and registering it if it does not already exist. It returns an object with methods to retrieve, reschedule, clear, and watch the alarm. By handling the registration of the alarm listener internally, this design eliminates the need for manually adding a listener via browser.alarms.onAlarm.addListener for each alarm, thereby reducing boilerplate and potential errors.
/**
* Defines an alarm with a specified name and configuration.
* Returns an object with helper methods to manage the alarm instance.
*
* @param {string} name - The name of the alarm.
* @param {browser.alarms.AlarmCreateInfo} options - The scheduling options for the alarm.
* @returns {DefinedAlarm} An object representing the defined alarm.
*/
function defineAlarm(name: string, options: browser.alarms.AlarmCreateInfo): DefinedAlarm;The returned DefinedAlarm object has the following interface:
interface DefinedAlarm {
/**
* Retrieves the current alarm configuration.
*
* @returns {Promise<browser.alarms.Alarm | null>} A promise that resolves to the alarm object, or null if not found.
*/
getAlarm(): Promise<browser.alarms.Alarm | null>;
/**
* Reschedules the alarm with new scheduling options.
*
* @param {browser.alarms.AlarmCreateInfo} options - The new scheduling options.
* @returns {Promise<void>} A promise that resolves once the alarm is rescheduled.
*/
reschedule(options: browser.alarms.AlarmCreateInfo): Promise<void>;
/**
* Clears the alarm. Note: This only temporarily disables the alarm until the extension is reloaded or `defineAlarm` is run again.
*
* @returns {Promise<boolean>} A promise that resolves to true if the alarm was cleared successfully.
*/
clear(): Promise<boolean>;
/**
* Registers a callback to listen for alarm triggers.
*
* @param {(alarm: browser.alarms.Alarm) => void} callback - The callback function to invoke when the alarm triggers.
* @returns {() => void} A function to unwatch the alarm.
*/
watch(callback: (alarm: browser.alarms.Alarm) => void): () => void;
}Example Usage
import { alarms } from '@wxt-dev/alarms';
// Define a new alarm and store it in a variable
const dailyReminder = alarms.defineAlarm('dailyReminder', { delayInMinutes: 1440, periodInMinutes: 1440 });
// Retrieve the alarm details when needed
const alarmDetails = await dailyReminder.getAlarm();
console.log('Alarm details:', alarmDetails);
// Reschedule the alarm if necessary
await dailyReminder.reschedule({ delayInMinutes: 1440, periodInMinutes: 1440 });
// Set up a listener for the alarm trigger
const unwatch = dailyReminder.watch((triggeredAlarm) => {
console.log('Alarm triggered:', triggeredAlarm);
});
// Clear the alarm when needed (this temporarily disables the alarm until the extension is reloaded or `defineAlarm` is run again)
await dailyReminder.clear();
// Remove the watch listener if it's no longer required
unwatch();Alternative Scheduling Options
The API is designed with flexibility in mind. In addition to using browser.alarms for scheduling, it can be extended to support alternative scheduling mechanisms such as cron-based scheduling or even setInterval for simpler use cases. Developers may configure the scheduling method via options, enabling a more versatile approach to alarm management.
Why is this API Beneficial?
Using the traditional approach, you would need to manually add an event listener for each alarm, as shown below:
browser.alarms.onAlarm.addListener((alarm) => {
if (alarm.name === 'dailyReminder') {
// Handle the alarm trigger
console.log('Alarm triggered:', alarm);
}
});This approach requires you to check the alarm name each time an alarm is triggered. With our proposed API, this boilerplate code is encapsulated within the defineAlarm method. The API automatically registers a listener for the specified alarm and provides a dedicated watch method, simplifying your code to just:
const unwatch = dailyReminder.watch((triggeredAlarm) => {
console.log('Alarm triggered:', triggeredAlarm);
});This not only improves code clarity and maintainability but also reduces the risk of errors from manual listener management.
Conclusion
This proposal outlines a straightforward and useful interface for working with Chrome alarms in an asynchronous and consistent manner. By returning an object from defineAlarm, developers can manage a specific alarm instance with its own methods, improving code clarity and encapsulation. This approach streamlines alarm management and reduces boilerplate code, making it easier to integrate and maintain alarm functionality within the extension.