You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Build a comprehensive deadline management module that provides human-readable countdowns in multiple timezones, skips non-business hours when computing "effective" time remaining, fires registered expiry callbacks when a deadline passes, and integrates with the existing watcher.ts polling system.
Acceptance Criteria
Create src/deadlineEngine.ts exporting DeadlineEngine class
When businessHours is set, secondsRemaining counts only business-hours seconds remaining (e.g. a deadline 10 hours away at 5pm Friday = only next Monday morning hours count)
Callbacks are managed via setInterval internally; the interval is shared (one per DeadlineEngine instance), not one per callback
destroy() clears all callbacks and the interval
Exported from src/index.ts
Tests: business-hours calculation across weekend, callback fires after mock time advance, unsubscribe prevents callback, multiple callbacks on same deadline all fire, destroy clears all
Context
isExpired in src/utils.ts is the existing baseline
src/watcher.ts uses polling — DeadlineEngine should be usable standalone or alongside it
Business hours must handle DST correctly using Intl.DateTimeFormat — do not use moment.js or external date libraries
Description
Build a comprehensive deadline management module that provides human-readable countdowns in multiple timezones, skips non-business hours when computing "effective" time remaining, fires registered expiry callbacks when a deadline passes, and integrates with the existing
watcher.tspolling system.Acceptance Criteria
src/deadlineEngine.tsexportingDeadlineEngineclassgetCountdown(deadline: number, options?: CountdownOptions): CountdownResult— returns{ expired: boolean, display: string, secondsRemaining: number, localDisplay: string }CountdownOptionssupports:timezone?: string(IANA, e.g."America/New_York"),businessHours?: { start: number, end: number, days: number[] }businessHoursis set,secondsRemainingcounts only business-hours seconds remaining (e.g. a deadline 10 hours away at 5pm Friday = only next Monday morning hours count)registerExpiryCallback(deadline: number, invoiceId: string, cb: (invoiceId: string) => void): () => void— returns unsubscribe function; callback fires once when deadline passessetIntervalinternally; the interval is shared (one perDeadlineEngineinstance), not one per callbackdestroy()clears all callbacks and the intervalsrc/index.tsContext
isExpiredinsrc/utils.tsis the existing baselinesrc/watcher.tsuses polling —DeadlineEngineshould be usable standalone or alongside itIntl.DateTimeFormat— do not use moment.js or external date libraries