codeburn/app/electron/preload.ts
iamtoruk d0ce20e49c feat(app): working periods, detected-provider dropdown, drag-select date range
- Period seg now uses the 5 real CLI periods (Today/7D/30D/Month/6M);
  6M maps to 'all' (matches the menubar).
- Provider control is a real dropdown listing only DETECTED providers
  (accumulated from current.providers so it never shrinks) + All.
- New RangeCalendar: month grid with click-and-drag range selection
  (+ two-click fallback, future-date disabling) behind a calendar button;
  commits a custom {from,to} threaded to Overview/Spend/Models/Optimize
  via new --from/--to CLI args (Plans/Settings stay period-only).
- typecheck clean, 87 vitest pass.
2026-07-11 09:14:54 -07:00

35 lines
1.8 KiB
TypeScript

import { contextBridge, ipcRenderer } from 'electron'
// Handlers resolve with { ok, value } | { ok, error } so the structured error
// `kind` survives the contextBridge boundary. `import type` is erased at build,
// so this shares main.ts's declaration without pulling its runtime in.
import type { Envelope } from './main'
type DateRange = { from: string; to: string }
async function invoke<T>(channel: string, ...args: unknown[]): Promise<T> {
const res = (await ipcRenderer.invoke(channel, ...args)) as Envelope<T>
if (res.ok) return res.value
// Reject with a plain object so `kind` is preserved (Error subclasses lose
// custom fields when cloned across worlds).
return Promise.reject(res.error)
}
// Shape matches CodeburnBridge (app/renderer/lib/types.ts); typing is enforced
// renderer-side where `window.codeburn` is declared as CodeburnBridge.
const bridge = {
getOverview: (period: string, provider: string, range?: DateRange) => invoke('codeburn:getOverview', period, provider, range),
getPlans: (period: string) => invoke('codeburn:getPlans', period),
getActReport: () => invoke('codeburn:getActReport'),
getModels: (period: string, provider: string, byTask: boolean, range?: DateRange) => invoke('codeburn:getModels', period, provider, byTask, range),
getYield: (period: string, range?: DateRange) => invoke('codeburn:getYield', period, range),
getSpendFlow: (period: string, provider: string, range?: DateRange) => invoke('codeburn:getSpendFlow', period, provider, range),
getDevices: (period: string) => invoke('codeburn:getDevices', period),
getDevicesScan: () => invoke('codeburn:getDevicesScan'),
getShareStatus: () => invoke('codeburn:getShareStatus'),
getIdentity: () => invoke('codeburn:getIdentity'),
cliStatus: () => invoke('codeburn:cliStatus'),
platform: process.platform,
}
contextBridge.exposeInMainWorld('codeburn', bridge)