import { loadState, saveState, sumMonthUsages, projectedMonthEnd } from './storage' const ALARM_NAME = 'costdev_budget_check' chrome.runtime.onInstalled.addListener(async () => { await chrome.alarms.create(ALARM_NAME, { periodInMinutes: 60 }) }) chrome.alarms.onAlarm.addListener(async (alarm) => { if (alarm.name !== ALARM_NAME) return const state = await loadState() if (!state.budget.enabled || state.budget.monthlyLimit <= 0) return const spent = sumMonthUsages(state.usages) const limit = state.budget.monthlyLimit const threshold = limit * state.budget.alertThreshold if (spent >= threshold && spent < limit) { const last = state.lastAlertAt ?? 0 if (Date.now() - last > 24 * 60 * 60 * 1000) { chrome.notifications.create('costdev-warning', { type: 'basic', iconUrl: 'icons/icon128.png', title: 'Cost.dev — Budget Alert', message: `You've spent $${spent.toFixed(2)} of your $${limit.toFixed(2)} monthly budget.`, priority: 1, }) state.lastAlertAt = Date.now() await saveState(state) } } if (spent >= limit) { const last = state.lastAlertAt ?? 0 if (Date.now() - last > 24 * 60 * 60 * 1000) { chrome.notifications.create('costdev-over', { type: 'basic', iconUrl: 'icons/icon128.png', title: 'Cost.dev — Budget Overrun', message: `You've exceeded your $${limit.toFixed(2)} monthly budget! Current spend: $${spent.toFixed(2)}.`, priority: 2, }) state.lastAlertAt = Date.now() await saveState(state) } } }) chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => { ;(async () => { if (message.type === 'budget-check') { const state = await loadState() const spent = sumMonthUsages(state.usages) const limit = state.budget.monthlyLimit const projected = projectedMonthEnd(spent) sendResponse({ spent, limit, projected, enabled: state.budget.enabled }) } else { sendResponse({ ok: false }) } })() return true })