diff --git a/client/components/admin/BankSyncAdminCard.jsx b/client/components/admin/BankSyncAdminCard.jsx
index 38e62bb..1706f3c 100644
--- a/client/components/admin/BankSyncAdminCard.jsx
+++ b/client/components/admin/BankSyncAdminCard.jsx
@@ -25,12 +25,13 @@ function timeUntil(iso) {
}
export default function BankSyncAdminCard() {
- const [config, setConfig] = useState(null);
- const [loading, setLoading] = useState(true);
- const [loadError, setLoadError] = useState('');
- const [saving, setSaving] = useState(false);
- const [enabled, setEnabled] = useState(false);
+ const [config, setConfig] = useState(null);
+ const [loading, setLoading] = useState(true);
+ const [loadError, setLoadError] = useState('');
+ const [saving, setSaving] = useState(false);
+ const [enabled, setEnabled] = useState(false);
const [syncInterval, setSyncInterval] = useState(4);
+ const [syncDays, setSyncDays] = useState(90);
useEffect(() => {
api.bankSyncConfig()
@@ -38,6 +39,7 @@ export default function BankSyncAdminCard() {
setConfig(d);
setEnabled(!!d.enabled);
setSyncInterval(d.sync_interval_hours ?? 4);
+ setSyncDays(d.sync_days ?? 90);
})
.catch(err => setLoadError(err.message || 'Failed to load bank sync config'))
.finally(() => setLoading(false));
@@ -45,16 +47,22 @@ export default function BankSyncAdminCard() {
const handleSave = async () => {
const hours = parseFloat(syncInterval);
+ const days = parseInt(syncDays, 10);
if (!Number.isFinite(hours) || hours < 0.5 || hours > 168) {
toast.error('Sync interval must be between 0.5 and 168 hours.');
return;
}
+ if (!Number.isFinite(days) || days < 1 || days > 730) {
+ toast.error('Transaction history must be between 1 and 730 days.');
+ return;
+ }
setSaving(true);
try {
- const result = await api.setBankSyncConfig({ enabled, sync_interval_hours: hours });
+ const result = await api.setBankSyncConfig({ enabled, sync_interval_hours: hours, sync_days: days });
setConfig(result);
setEnabled(!!result.enabled);
setSyncInterval(result.sync_interval_hours ?? 4);
+ setSyncDays(result.sync_days ?? 90);
toast.success('Bank sync settings saved.');
} catch (err) {
toast.error(err.message || 'Failed to update bank sync setting.');
@@ -83,7 +91,9 @@ export default function BankSyncAdminCard() {
);
}
- const changed = enabled !== !!config?.enabled || parseFloat(syncInterval) !== config?.sync_interval_hours;
+ const changed = enabled !== !!config?.enabled
+ || parseFloat(syncInterval) !== config?.sync_interval_hours
+ || parseInt(syncDays, 10) !== config?.sync_days;
const worker = config?.worker;
return (
@@ -135,6 +145,28 @@ export default function BankSyncAdminCard() {
+ {/* Transaction history lookback */}
+
+
+
Transaction history
+
+ How far back to fetch on first connect. Re-syncs only fetch recent activity.
+
+
+
+ setSyncDays(e.target.value)}
+ className="w-20 text-sm text-right"
+ />
+ days
+
+
+
{/* Auto-sync worker status */}
{config?.enabled && worker && (
diff --git a/docs/top_200_us_subscriptions.csv b/docs/top_200_us_subscriptions.csv
new file mode 100644
index 0000000..0d5ef20
--- /dev/null
+++ b/docs/top_200_us_subscriptions.csv
@@ -0,0 +1,201 @@
+Rank,Service,Category,Subcategory,Subscription_or_Plan,US_Availability,Website,Source_URL,Ranking_Basis
+1,Netflix,Video Streaming,SVOD,Netflix subscription,United States,https://www.netflix.com/,https://www.netflix.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+2,Amazon Prime Video,Video Streaming,SVOD / Prime benefit,Prime Video / Amazon Prime,United States,https://www.primevideo.com/,https://www.primevideo.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+3,Hulu,Video Streaming,SVOD / Live TV,Hulu,United States,https://www.hulu.com/,https://www.hulu.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+4,Disney+,Video Streaming,SVOD,Disney+,United States,https://www.disneyplus.com/,https://www.disneyplus.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+5,Max,Video Streaming,SVOD,Max,United States,https://www.max.com/,https://www.max.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+6,Peacock,Video Streaming,SVOD / live sports,Peacock Premium,United States,https://www.peacocktv.com/,https://www.peacocktv.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+7,Paramount+,Video Streaming,SVOD / live sports,Paramount+,United States,https://www.paramountplus.com/,https://www.paramountplus.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+8,Apple TV+,Video Streaming,SVOD,Apple TV+,United States,https://tv.apple.com/,https://tv.apple.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+9,YouTube Premium,Video Streaming,Ad-free video / music bundle,YouTube Premium,United States,https://www.youtube.com/premium,https://www.youtube.com/premium,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+10,ESPN+,Sports Streaming,Live sports,ESPN+,United States,https://plus.espn.com/,https://plus.espn.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+11,YouTube TV,Live TV Streaming,Virtual MVPD,YouTube TV,United States,https://tv.youtube.com/,https://tv.youtube.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+12,Sling TV,Live TV Streaming,Virtual MVPD,Sling TV,United States,https://www.sling.com/,https://www.sling.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+13,Fubo,Live TV Streaming,Sports-focused live TV,Fubo,United States,https://www.fubo.tv/,https://www.fubo.tv/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+14,DirecTV Stream,Live TV Streaming,Virtual MVPD,DirecTV Stream,United States,https://streamtv.directv.com/,https://streamtv.directv.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+15,Philo,Live TV Streaming,Entertainment live TV,Philo,United States,https://www.philo.com/,https://www.philo.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+16,Starz,Video Streaming,Premium network,Starz,United States,https://www.starz.com/,https://www.starz.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+17,MGM+,Video Streaming,Premium network,MGM+,United States,https://www.mgmplus.com/,https://www.mgmplus.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+18,AMC+,Video Streaming,Premium network bundle,AMC+,United States,https://www.amcplus.com/,https://www.amcplus.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+19,BET+,Video Streaming,Black entertainment,BET+,United States,https://www.bet.plus/,https://www.bet.plus/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+20,Crunchyroll,Video Streaming,Anime,Crunchyroll Premium,United States,https://www.crunchyroll.com/,https://www.crunchyroll.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+21,HIDIVE,Video Streaming,Anime,HIDIVE,United States,https://www.hidive.com/,https://www.hidive.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+22,Shudder,Video Streaming,Horror,Shudder,United States,https://www.shudder.com/,https://www.shudder.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+23,Acorn TV,Video Streaming,British/International TV,Acorn TV,United States,https://acorn.tv/,https://acorn.tv/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+24,BritBox,Video Streaming,British TV,BritBox,United States,https://www.britbox.com/,https://www.britbox.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+25,The Criterion Channel,Video Streaming,Classic/arthouse film,Criterion Channel,United States,https://www.criterionchannel.com/,https://www.criterionchannel.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+26,MUBI,Video Streaming,Curated film,MUBI,United States,https://mubi.com/,https://mubi.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+27,Discovery+,Video Streaming,Lifestyle / factual,Discovery+,United States,https://www.discoveryplus.com/,https://www.discoveryplus.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+28,Hallmark+,Video Streaming,Family/romance,Hallmark+,United States,https://www.hallmarkplus.com/,https://www.hallmarkplus.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+29,PBS Passport,Video Streaming,Public television,PBS Passport,United States,https://www.pbs.org/passport/,https://www.pbs.org/passport/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+30,MagellanTV,Video Streaming,Documentaries,MagellanTV,United States,https://www.magellantv.com/,https://www.magellantv.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+31,Curiosity Stream,Video Streaming,Documentaries,Curiosity Stream,United States,https://curiositystream.com/,https://curiositystream.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+32,Nebula,Video Streaming,Creator video,Nebula,United States,https://nebula.tv/,https://nebula.tv/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+33,WOW Presents Plus,Video Streaming,LGBTQ+ entertainment,WOW Presents Plus,United States,https://www.wowpresentsplus.com/,https://www.wowpresentsplus.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+34,ViX Premium,Video Streaming,Spanish-language entertainment,ViX Premium,United States,https://vix.com/,https://vix.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+35,FloSports,Sports Streaming,Niche live sports,FloSports,United States,https://www.flosports.tv/,https://www.flosports.tv/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+36,DAZN,Sports Streaming,Combat sports / live sports,DAZN,United States,https://www.dazn.com/,https://www.dazn.com/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+37,MLB.TV,Sports Streaming,Baseball,MLB.TV,United States,https://www.mlb.com/live-stream-games/subscribe,https://www.mlb.com/live-stream-games/subscribe,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+38,NBA League Pass,Sports Streaming,Basketball,NBA League Pass,United States,https://www.nba.com/watch/league-pass-stream,https://www.nba.com/watch/league-pass-stream,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+39,NHL Power Play on ESPN+,Sports Streaming,Hockey,NHL Power Play,United States,https://www.espn.com/espnplus/catalog/nhl,https://www.espn.com/espnplus/catalog/nhl,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+40,NFL+,Sports Streaming,Football,NFL+,United States,https://www.nfl.com/plus/,https://www.nfl.com/plus/,U.S. SVOD prominence; Parks/industry lists where applicable; curated within category
+41,Spotify Premium,Music & Audio,Music streaming,Spotify Premium,United States,https://www.spotify.com/premium/,https://www.spotify.com/premium/,U.S. paid audio and audiobook prominence; curated within category
+42,Apple Music,Music & Audio,Music streaming,Apple Music,United States,https://www.apple.com/apple-music/,https://www.apple.com/apple-music/,U.S. paid audio and audiobook prominence; curated within category
+43,Amazon Music Unlimited,Music & Audio,Music streaming,Amazon Music Unlimited,United States,https://music.amazon.com/,https://music.amazon.com/,U.S. paid audio and audiobook prominence; curated within category
+44,Pandora Premium,Music & Audio,Music streaming / radio,Pandora Premium,United States,https://www.pandora.com/upgrade,https://www.pandora.com/upgrade,U.S. paid audio and audiobook prominence; curated within category
+45,SiriusXM,Music & Audio,Satellite radio / streaming,SiriusXM,United States,https://www.siriusxm.com/,https://www.siriusxm.com/,U.S. paid audio and audiobook prominence; curated within category
+46,TIDAL,Music & Audio,Hi-fi music streaming,TIDAL,United States,https://tidal.com/,https://tidal.com/,U.S. paid audio and audiobook prominence; curated within category
+47,Qobuz,Music & Audio,Hi-res music streaming,Qobuz,United States,https://www.qobuz.com/us-en/music/streaming/offers,https://www.qobuz.com/us-en/music/streaming/offers,U.S. paid audio and audiobook prominence; curated within category
+48,SoundCloud Go+,Music & Audio,Music / creators,SoundCloud Go+,United States,https://soundcloud.com/go,https://soundcloud.com/go,U.S. paid audio and audiobook prominence; curated within category
+49,Deezer,Music & Audio,Music streaming,Deezer Premium,United States,https://www.deezer.com/us/offers,https://www.deezer.com/us/offers,U.S. paid audio and audiobook prominence; curated within category
+50,iHeartRadio Plus,Music & Audio,Radio / music,iHeartRadio Plus,United States,https://www.iheart.com/plus/,https://www.iheart.com/plus/,U.S. paid audio and audiobook prominence; curated within category
+51,Audible,Audiobooks,Audiobooks,Audible Premium Plus,United States,https://www.audible.com/,https://www.audible.com/,U.S. paid audio and audiobook prominence; curated within category
+52,Spotify Audiobooks,Audiobooks,Audiobooks,Spotify Audiobooks access,United States,https://www.spotify.com/us/audiobooks/,https://www.spotify.com/us/audiobooks/,U.S. paid audio and audiobook prominence; curated within category
+53,Everand,Audiobooks & Ebooks,Books / audiobooks,Everand,United States,https://www.everand.com/,https://www.everand.com/,U.S. paid audio and audiobook prominence; curated within category
+54,Scribd,Documents & Ebooks,Documents / books,Scribd,United States,https://www.scribd.com/,https://www.scribd.com/,U.S. paid audio and audiobook prominence; curated within category
+55,Kindle Unlimited,Ebooks,Ebooks,Kindle Unlimited,United States,https://www.amazon.com/kindle-dbs/hz/subscribe/ku,https://www.amazon.com/kindle-dbs/hz/subscribe/ku,U.S. paid audio and audiobook prominence; curated within category
+56,Kobo Plus,Ebooks & Audiobooks,Books / audiobooks,Kobo Plus,United States,https://www.kobo.com/us/en/plus,https://www.kobo.com/us/en/plus,U.S. paid audio and audiobook prominence; curated within category
+57,Libro.fm,Audiobooks,Audiobooks,Libro.fm membership,United States,https://libro.fm/,https://libro.fm/,U.S. paid audio and audiobook prominence; curated within category
+58,Blinkist,Books & Learning,Book summaries,Blinkist Premium,United States,https://www.blinkist.com/,https://www.blinkist.com/,U.S. paid audio and audiobook prominence; curated within category
+59,Pocket Casts Plus,Podcasts,Podcast app,Pocket Casts Plus,United States,https://pocketcasts.com/plus/,https://pocketcasts.com/plus/,U.S. paid audio and audiobook prominence; curated within category
+60,Wondery+,Podcasts,Podcast network,Wondery+,United States,https://wondery.com/plus/,https://wondery.com/plus/,U.S. paid audio and audiobook prominence; curated within category
+61,The New York Times,News & Magazines,National news,NYT All Access,United States,https://www.nytimes.com/subscription,https://www.nytimes.com/subscription,Major U.S. news and magazine subscriptions; curated within category
+62,The Wall Street Journal,News & Magazines,Business news,WSJ Digital,United States,https://www.wsj.com/news/subscribe,https://www.wsj.com/news/subscribe,Major U.S. news and magazine subscriptions; curated within category
+63,The Washington Post,News & Magazines,National news,Digital subscription,United States,https://subscribe.washingtonpost.com/,https://subscribe.washingtonpost.com/,Major U.S. news and magazine subscriptions; curated within category
+64,The Atlantic,News & Magazines,Magazine,The Atlantic subscription,United States,https://www.theatlantic.com/subscribe/,https://www.theatlantic.com/subscribe/,Major U.S. news and magazine subscriptions; curated within category
+65,The New Yorker,News & Magazines,Magazine,The New Yorker subscription,United States,https://www.newyorker.com/subscribe,https://www.newyorker.com/subscribe,Major U.S. news and magazine subscriptions; curated within category
+66,Bloomberg.com,News & Magazines,Business news,Bloomberg Digital,United States,https://www.bloomberg.com/subscriptions,https://www.bloomberg.com/subscriptions,Major U.S. news and magazine subscriptions; curated within category
+67,Financial Times,News & Magazines,Business news,FT Digital,United States,https://www.ft.com/products,https://www.ft.com/products,Major U.S. news and magazine subscriptions; curated within category
+68,The Economist,News & Magazines,Global news magazine,The Economist subscription,United States,https://www.economist.com/subscribe,https://www.economist.com/subscribe,Major U.S. news and magazine subscriptions; curated within category
+69,TIME,News & Magazines,Magazine,TIME subscription,United States,https://time.com/subscribe/,https://time.com/subscribe/,Major U.S. news and magazine subscriptions; curated within category
+70,WIRED,News & Magazines,Technology magazine,WIRED subscription,United States,https://www.wired.com/subscribe/,https://www.wired.com/subscribe/,Major U.S. news and magazine subscriptions; curated within category
+71,Consumer Reports,News & Magazines,Product reviews,Consumer Reports membership,United States,https://www.consumerreports.org/join/,https://www.consumerreports.org/join/,Major U.S. news and magazine subscriptions; curated within category
+72,Politico Pro,News & Magazines,Policy intelligence,Politico Pro,United States,https://www.politicopro.com/,https://www.politicopro.com/,Major U.S. news and magazine subscriptions; curated within category
+73,The Athletic,Sports Media,Sports journalism,The Athletic subscription,United States,https://theathletic.com/,https://theathletic.com/,Major U.S. news and magazine subscriptions; curated within category
+74,Substack,Creator Media,Newsletter subscriptions,Substack paid subscriptions,United States,https://substack.com/,https://substack.com/,Major U.S. news and magazine subscriptions; curated within category
+75,Medium,Creator Media,Publishing platform,Medium Membership,United States,https://medium.com/membership,https://medium.com/membership,Major U.S. news and magazine subscriptions; curated within category
+76,Patreon,Creator Media,Creator memberships,Patreon memberships,United States,https://www.patreon.com/,https://www.patreon.com/,Major U.S. news and magazine subscriptions; curated within category
+77,Apple News+,News & Magazines,News bundle,Apple News+,United States,https://www.apple.com/apple-news/,https://www.apple.com/apple-news/,Major U.S. news and magazine subscriptions; curated within category
+78,Readly,News & Magazines,Magazine bundle,Readly,United States,https://us.readly.com/,https://us.readly.com/,Major U.S. news and magazine subscriptions; curated within category
+79,PressReader,News & Magazines,Newspaper/magazine bundle,PressReader Premium,United States,https://www.pressreader.com/,https://www.pressreader.com/,Major U.S. news and magazine subscriptions; curated within category
+80,The Information,News & Magazines,Technology/business news,The Information subscription,United States,https://www.theinformation.com/subscribe,https://www.theinformation.com/subscribe,Major U.S. news and magazine subscriptions; curated within category
+81,Microsoft 365,Software & Productivity,Office suite,Microsoft 365,United States,https://www.microsoft.com/microsoft-365,https://www.microsoft.com/microsoft-365,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+82,Google One,Cloud & Storage,Cloud storage,Google One,United States,https://one.google.com/,https://one.google.com/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+83,iCloud+,Cloud & Storage,Cloud storage,iCloud+,United States,https://www.apple.com/icloud/,https://www.apple.com/icloud/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+84,Dropbox,Cloud & Storage,Cloud storage,Dropbox plans,United States,https://www.dropbox.com/plans,https://www.dropbox.com/plans,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+85,Box,Cloud & Storage,Cloud content management,Box plans,United States,https://www.box.com/pricing,https://www.box.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+86,Adobe Creative Cloud,Software & Design,Creative software,Creative Cloud,United States,https://www.adobe.com/creativecloud.html,https://www.adobe.com/creativecloud.html,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+87,Canva Pro,Software & Design,Design platform,Canva Pro,United States,https://www.canva.com/pro/,https://www.canva.com/pro/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+88,Figma,Software & Design,Design/collaboration,Figma plans,United States,https://www.figma.com/pricing/,https://www.figma.com/pricing/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+89,Notion,Software & Productivity,Workspace / notes,Notion Plus,United States,https://www.notion.so/pricing,https://www.notion.so/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+90,Evernote,Software & Productivity,Notes,Evernote plans,United States,https://evernote.com/compare-plans,https://evernote.com/compare-plans,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+91,Todoist,Software & Productivity,Task management,Todoist Pro,United States,https://todoist.com/pricing,https://todoist.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+92,Grammarly,Writing & AI,Writing assistant,Grammarly Pro,United States,https://www.grammarly.com/plans,https://www.grammarly.com/plans,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+93,ChatGPT,AI,AI assistant,ChatGPT Plus / Pro,United States,https://chatgpt.com/pricing,https://chatgpt.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+94,Claude,AI,AI assistant,Claude Pro,United States,https://claude.ai/upgrade,https://claude.ai/upgrade,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+95,Perplexity,AI,AI search,Perplexity Pro,United States,https://www.perplexity.ai/pro,https://www.perplexity.ai/pro,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+96,Gemini Advanced,AI,AI assistant / Google One AI,Google AI plans,United States,https://one.google.com/about/google-ai-plans/,https://one.google.com/about/google-ai-plans/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+97,GitHub Copilot,Developer Tools,AI coding,GitHub Copilot,United States,https://github.com/features/copilot/plans,https://github.com/features/copilot/plans,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+98,Cursor,Developer Tools,AI coding,Cursor Pro,United States,https://www.cursor.com/pricing,https://www.cursor.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+99,Replit,Developer Tools,Cloud coding,Replit Core,United States,https://replit.com/pricing,https://replit.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+100,Setapp,Software & Productivity,Mac app bundle,Setapp,United States,https://setapp.com/,https://setapp.com/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+101,1Password,Security,Password manager,1Password,United States,https://1password.com/pricing,https://1password.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+102,Dashlane,Security,Password manager,Dashlane,United States,https://www.dashlane.com/pricing,https://www.dashlane.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+103,NordVPN,Security,VPN,NordVPN,United States,https://nordvpn.com/pricing/,https://nordvpn.com/pricing/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+104,ExpressVPN,Security,VPN,ExpressVPN,United States,https://www.expressvpn.com/,https://www.expressvpn.com/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+105,Surfshark,Security,VPN,Surfshark,United States,https://surfshark.com/pricing,https://surfshark.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+106,Norton 360,Security,Device security,Norton 360,United States,https://us.norton.com/products,https://us.norton.com/products,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+107,McAfee+,Security,Device security,McAfee+,United States,https://www.mcafee.com/en-us/consumer-support/pricing.html,https://www.mcafee.com/en-us/consumer-support/pricing.html,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+108,QuickBooks Online,Finance Software,Small business accounting,QuickBooks Online,United States,https://quickbooks.intuit.com/pricing/,https://quickbooks.intuit.com/pricing/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+109,TurboTax Live,Finance Software,Tax filing support,TurboTax Live,United States,https://turbotax.intuit.com/personal-taxes/online/live/,https://turbotax.intuit.com/personal-taxes/online/live/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+110,YNAB,Finance Software,Budgeting,YNAB,United States,https://www.ynab.com/pricing,https://www.ynab.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+111,Rocket Money Premium,Finance Software,Personal finance,Rocket Money Premium,United States,https://www.rocketmoney.com/premium,https://www.rocketmoney.com/premium,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+112,Copilot Money,Finance Software,Personal finance,Copilot Money,United States,https://copilot.money/,https://copilot.money/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+113,Calendly,Software & Productivity,Scheduling,Calendly plans,United States,https://calendly.com/pricing,https://calendly.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+114,Zoom Workplace,Software & Productivity,Video meetings,Zoom plans,United States,https://www.zoom.com/en/pricing/,https://www.zoom.com/en/pricing/,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+115,Slack,Software & Productivity,Team messaging,Slack Pro / Business+,United States,https://slack.com/pricing,https://slack.com/pricing,Major U.S. consumer/professional software subscriptions; app revenue and SaaS prominence where applicable; curated
+116,Xbox Game Pass,Gaming,Game subscription,Xbox Game Pass,United States,https://www.xbox.com/en-US/xbox-game-pass,https://www.xbox.com/en-US/xbox-game-pass,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+117,PlayStation Plus,Gaming,Game subscription,PlayStation Plus,United States,https://www.playstation.com/en-us/ps-plus/,https://www.playstation.com/en-us/ps-plus/,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+118,Nintendo Switch Online,Gaming,Online/game library,Nintendo Switch Online,United States,https://www.nintendo.com/us/switch/online/,https://www.nintendo.com/us/switch/online/,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+119,Apple Arcade,Gaming,Mobile games,Apple Arcade,United States,https://www.apple.com/apple-arcade/,https://www.apple.com/apple-arcade/,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+120,EA Play,Gaming,Game subscription,EA Play,United States,https://www.ea.com/ea-play,https://www.ea.com/ea-play,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+121,Ubisoft+,Gaming,Game subscription,Ubisoft+,United States,https://www.ubisoft.com/en-us/ubisoft-plus,https://www.ubisoft.com/en-us/ubisoft-plus,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+122,NVIDIA GeForce NOW,Gaming,Cloud gaming,GeForce NOW,United States,https://www.nvidia.com/en-us/geforce-now/memberships/,https://www.nvidia.com/en-us/geforce-now/memberships/,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+123,Roblox Premium,Gaming,Creator/game currency membership,Roblox Premium,United States,https://www.roblox.com/premium/membership,https://www.roblox.com/premium/membership,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+124,Fortnite Crew,Gaming,Game membership,Fortnite Crew,United States,https://www.fortnite.com/fortnite-crew-subscription,https://www.fortnite.com/fortnite-crew-subscription,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+125,Minecraft Realms,Gaming,Private server subscription,Minecraft Realms,United States,https://www.minecraft.net/realms,https://www.minecraft.net/realms,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+126,Twitch Turbo,Creator & Social,Ad-free streaming,Twitch Turbo,United States,https://www.twitch.tv/turbo,https://www.twitch.tv/turbo,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+127,Discord Nitro,Creator & Social,Social / gaming chat,Discord Nitro,United States,https://discord.com/nitro,https://discord.com/nitro,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+128,X Premium,Creator & Social,Social network subscription,X Premium,United States,https://help.x.com/en/using-x/x-premium,https://help.x.com/en/using-x/x-premium,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+129,Snapchat+,Creator & Social,Social network subscription,Snapchat+,United States,https://www.snapchat.com/plus,https://www.snapchat.com/plus,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+130,TikTok Live Subscription,Creator & Social,Creator memberships,TikTok LIVE Subscription,United States,https://www.tiktok.com/live/creators/en-US/subscription/,https://www.tiktok.com/live/creators/en-US/subscription/,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+131,Meta Verified,Creator & Social,Creator/business verification,Meta Verified,United States,https://about.meta.com/technologies/meta-verified/,https://about.meta.com/technologies/meta-verified/,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+132,LinkedIn Premium,Career & Social,Professional network,LinkedIn Premium,United States,https://premium.linkedin.com/,https://premium.linkedin.com/,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+133,Tinder Gold,Dating,Dating app,Tinder Gold,United States,https://tinder.com/feature/plus,https://tinder.com/feature/plus,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+134,Bumble Premium,Dating,Dating app,Bumble Premium,United States,https://bumble.com/en/the-buzz/bumble-premium,https://bumble.com/en/the-buzz/bumble-premium,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+135,Hinge+,Dating,Dating app,Hinge+,United States,https://hinge.co/hinge-plus,https://hinge.co/hinge-plus,"Major U.S. gaming, creator, and social paid memberships; curated within category"
+136,Amazon Prime,Shopping & Delivery,Retail membership,Amazon Prime,United States,https://www.amazon.com/amazonprime,https://www.amazon.com/amazonprime,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+137,Walmart+,Shopping & Delivery,Retail membership,Walmart+,United States,https://www.walmart.com/plus,https://www.walmart.com/plus,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+138,Target Circle 360,Shopping & Delivery,Retail membership,Target Circle 360,United States,https://www.target.com/circle/target-circle-360,https://www.target.com/circle/target-circle-360,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+139,Costco,Warehouse Clubs,Retail membership,Costco Membership,United States,https://www.costco.com/join-costco.html,https://www.costco.com/join-costco.html,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+140,Sam's Club,Warehouse Clubs,Retail membership,Sam's Club Membership,United States,https://www.samsclub.com/join,https://www.samsclub.com/join,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+141,BJ's Wholesale Club,Warehouse Clubs,Retail membership,BJ's Membership,United States,https://www.bjs.com/membership,https://www.bjs.com/membership,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+142,Instacart+,Grocery & Delivery,Grocery delivery,Instacart+,United States,https://www.instacart.com/instacart-plus,https://www.instacart.com/instacart-plus,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+143,DoorDash DashPass,Food Delivery,Delivery membership,DashPass,United States,https://www.doordash.com/dashpass/,https://www.doordash.com/dashpass/,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+144,Uber One,Food & Rides,Delivery/rides membership,Uber One,United States,https://www.uber.com/us/en/u/uber-one/,https://www.uber.com/us/en/u/uber-one/,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+145,Grubhub+,Food Delivery,Delivery membership,Grubhub+,United States,https://www.grubhub.com/plus,https://www.grubhub.com/plus,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+146,Shipt,Grocery & Delivery,Same-day delivery,Shipt membership,United States,https://www.shipt.com/membership/,https://www.shipt.com/membership/,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+147,Kroger Boost,Grocery & Delivery,Grocery delivery,Kroger Boost,United States,https://www.kroger.com/pr/boost,https://www.kroger.com/pr/boost,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+148,Thrive Market,Grocery & Delivery,Online grocery,Thrive Market membership,United States,https://thrivemarket.com/,https://thrivemarket.com/,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+149,Misfits Market,Grocery & Delivery,Produce/grocery box,Misfits Market,United States,https://www.misfitsmarket.com/,https://www.misfitsmarket.com/,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+150,Imperfect Foods,Grocery & Delivery,Grocery delivery,Imperfect Foods,United States,https://www.imperfectfoods.com/,https://www.imperfectfoods.com/,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+151,Chewy Autoship,Pet Retail,Pet product autoship,Chewy Autoship,United States,https://www.chewy.com/app/content/autoship,https://www.chewy.com/app/content/autoship,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+152,Petco Vital Care Premier,Pet Retail,Pet care membership,Vital Care Premier,United States,https://www.petco.com/shop/en/petcostore/c/vitalcare,https://www.petco.com/shop/en/petcostore/c/vitalcare,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+153,PetSmart Treats Rewards VIPP,Pet Retail,Pet care membership,Treats Rewards VIPP,United States,https://www.petsmart.com/treats-rewards-vipp.html,https://www.petsmart.com/treats-rewards-vipp.html,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+154,GameStop Pro,Retail Memberships,Gaming retail,GameStop Pro,United States,https://www.gamestop.com/pro/,https://www.gamestop.com/pro/,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+155,Barnes & Noble Membership,Retail Memberships,Books retail,B&N Membership,United States,https://www.barnesandnoble.com/membership,https://www.barnesandnoble.com/membership,"Major U.S. shopping, grocery, and delivery memberships; curated within category"
+156,HelloFresh,Food & Meal Kits,Meal kits,HelloFresh,United States,https://www.hellofresh.com/,https://www.hellofresh.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+157,Blue Apron,Food & Meal Kits,Meal kits,Blue Apron,United States,https://www.blueapron.com/,https://www.blueapron.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+158,Home Chef,Food & Meal Kits,Meal kits,Home Chef,United States,https://www.homechef.com/,https://www.homechef.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+159,Marley Spoon,Food & Meal Kits,Meal kits,Marley Spoon,United States,https://marleyspoon.com/,https://marleyspoon.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+160,Dinnerly,Food & Meal Kits,Budget meal kits,Dinnerly,United States,https://dinnerly.com/,https://dinnerly.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+161,EveryPlate,Food & Meal Kits,Budget meal kits,EveryPlate,United States,https://www.everyplate.com/,https://www.everyplate.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+162,Green Chef,Food & Meal Kits,Meal kits,Green Chef,United States,https://www.greenchef.com/,https://www.greenchef.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+163,Purple Carrot,Food & Meal Kits,Plant-based meal kits,Purple Carrot,United States,https://www.purplecarrot.com/,https://www.purplecarrot.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+164,Sunbasket,Food & Meal Kits,Meal kits,Sunbasket,United States,https://sunbasket.com/,https://sunbasket.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+165,Factor,Prepared Meals,Prepared meals,Factor,United States,https://www.factor75.com/,https://www.factor75.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+166,CookUnity,Prepared Meals,Prepared meals,CookUnity,United States,https://www.cookunity.com/,https://www.cookunity.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+167,Fresh N Lean,Prepared Meals,Prepared meals,Fresh N Lean,United States,https://www.freshnlean.com/,https://www.freshnlean.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+168,Hungryroot,Food & Meal Kits,Groceries/meal planning,Hungryroot,United States,https://www.hungryroot.com/,https://www.hungryroot.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+169,Daily Harvest,Prepared Meals,Frozen plant-based food,Daily Harvest,United States,https://www.daily-harvest.com/,https://www.daily-harvest.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+170,Tovala,Prepared Meals,Smart oven meals,Tovala meals,United States,https://www.tovala.com/,https://www.tovala.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+171,MistoBox,Coffee & Tea,Coffee subscription,MistoBox,United States,https://mistobox.com/,https://mistobox.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+172,Trade Coffee,Coffee & Tea,Coffee subscription,Trade Coffee,United States,https://www.drinktrade.com/,https://www.drinktrade.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+173,Atlas Coffee Club,Coffee & Tea,Coffee subscription,Atlas Coffee Club,United States,https://atlascoffeeclub.com/,https://atlascoffeeclub.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+174,Bean Box,Coffee & Tea,Coffee subscription,Bean Box,United States,https://beanbox.com/,https://beanbox.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+175,Universal Yums,Snacks,International snack box,Universal Yums,United States,https://www.universalyums.com/,https://www.universalyums.com/,"U.S. meal kit, prepared food, coffee, and snack subscriptions; curated from current editorial/brand sources"
+176,Peloton App,Fitness & Wellness,Connected fitness,Peloton App,United States,https://www.onepeloton.com/app,https://www.onepeloton.com/app,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+177,ClassPass,Fitness & Wellness,Fitness class credits,ClassPass,United States,https://classpass.com/,https://classpass.com/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+178,Apple Fitness+,Fitness & Wellness,Workout streaming,Apple Fitness+,United States,https://www.apple.com/apple-fitness-plus/,https://www.apple.com/apple-fitness-plus/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+179,Strava,Fitness & Wellness,Fitness tracking,Strava Subscription,United States,https://www.strava.com/subscribe,https://www.strava.com/subscribe,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+180,Fitbit Premium,Fitness & Wellness,Fitness/health insights,Fitbit Premium,United States,https://www.fitbit.com/global/us/products/services/premium,https://www.fitbit.com/global/us/products/services/premium,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+181,MyFitnessPal Premium,Fitness & Wellness,Nutrition tracking,MyFitnessPal Premium,United States,https://www.myfitnesspal.com/premium,https://www.myfitnesspal.com/premium,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+182,Noom,Fitness & Wellness,Weight management,Noom,United States,https://www.noom.com/,https://www.noom.com/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+183,WW,Fitness & Wellness,Weight management,WeightWatchers membership,United States,https://www.weightwatchers.com/us/plans,https://www.weightwatchers.com/us/plans,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+184,Headspace,Meditation & Wellness,Meditation,Headspace,United States,https://www.headspace.com/,https://www.headspace.com/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+185,Calm,Meditation & Wellness,Meditation/sleep,Calm Premium,United States,https://www.calm.com/premium,https://www.calm.com/premium,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+186,Sleep Cycle Premium,Sleep & Wellness,Sleep tracking,Sleep Cycle Premium,United States,https://www.sleepcycle.com/premium/,https://www.sleepcycle.com/premium/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+187,Oura Membership,Fitness & Wellness,Wearable insights,Oura Membership,United States,https://ouraring.com/membership,https://ouraring.com/membership,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+188,Whoop,Fitness & Wellness,Wearable membership,Whoop Membership,United States,https://www.whoop.com/us/en/membership/,https://www.whoop.com/us/en/membership/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+189,Aaptiv,Fitness & Wellness,Workout app,Aaptiv,United States,https://aaptiv.com/,https://aaptiv.com/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+190,Fitbod,Fitness & Wellness,Strength training app,Fitbod Elite,United States,https://fitbod.me/pricing/,https://fitbod.me/pricing/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+191,Alo Moves,Fitness & Wellness,Yoga/fitness streaming,Alo Moves,United States,https://www.alomoves.com/,https://www.alomoves.com/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+192,Obé Fitness,Fitness & Wellness,Workout streaming,Obé Fitness,United States,https://obefitness.com/,https://obefitness.com/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+193,Centr,Fitness & Wellness,Fitness/wellness app,Centr,United States,https://centr.com/,https://centr.com/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+194,Future,Fitness & Wellness,Remote personal training,Future,United States,https://www.future.co/,https://www.future.co/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+195,Tonal Membership,Fitness & Wellness,Connected strength training,Tonal Membership,United States,https://www.tonal.com/membership/,https://www.tonal.com/membership/,"Major U.S. fitness, wellness, and health app subscriptions; curated within category"
+196,Duolingo Super,Education,Language learning,Super Duolingo,United States,https://www.duolingo.com/super,https://www.duolingo.com/super,Major U.S. education and family subscriptions; curated within category
+197,MasterClass,Education,Online classes,MasterClass,United States,https://www.masterclass.com/,https://www.masterclass.com/,Major U.S. education and family subscriptions; curated within category
+198,Coursera Plus,Education,Online courses,Coursera Plus,United States,https://www.coursera.org/courseraplus,https://www.coursera.org/courseraplus,Major U.S. education and family subscriptions; curated within category
+199,Skillshare,Education,Creative/business courses,Skillshare membership,United States,https://www.skillshare.com/,https://www.skillshare.com/,Major U.S. education and family subscriptions; curated within category
+200,Book of the Month,Books & Subscription Boxes,Book box,Book of the Month,United States,https://www.bookofthemonth.com/,https://www.bookofthemonth.com/,Major U.S. subscription boxes and recurring memberships; curated from editorial/brand sources
diff --git a/package.json b/package.json
index 31bbc2c..5eb7d18 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "bill-tracker",
- "version": "0.33.0",
+ "version": "0.33.1",
"description": "Monthly bill tracking system",
"main": "server.js",
"scripts": {
diff --git a/routes/admin.js b/routes/admin.js
index be5cc71..773e40a 100644
--- a/routes/admin.js
+++ b/routes/admin.js
@@ -1,7 +1,7 @@
const express = require('express');
const router = express.Router();
const { getDb, rollbackMigration } = require('../db/database');
-const { getBankSyncConfig, setBankSyncEnabled, setSyncIntervalHours } = require('../services/bankSyncConfigService');
+const { getBankSyncConfig, setBankSyncEnabled, setSyncIntervalHours, setSyncDays } = require('../services/bankSyncConfigService');
const { getStatus: getBankSyncWorkerStatus } = require('../services/bankSyncWorker');
const { hashPassword } = require('../services/authService');
const { logAudit } = require('../services/auditService');
@@ -407,15 +407,12 @@ router.get('/bank-sync-config', (req, res) => {
// PUT /api/admin/bank-sync-config
router.put('/bank-sync-config', (req, res) => {
- const { enabled, sync_interval_hours } = req.body || {};
+ const { enabled, sync_interval_hours, sync_days } = req.body || {};
try {
let config = getBankSyncConfig();
- if (typeof enabled === 'boolean') {
- config = setBankSyncEnabled(enabled);
- }
- if (sync_interval_hours !== undefined) {
- config = setSyncIntervalHours(sync_interval_hours);
- }
+ if (typeof enabled === 'boolean') config = setBankSyncEnabled(enabled);
+ if (sync_interval_hours !== undefined) config = setSyncIntervalHours(sync_interval_hours);
+ if (sync_days !== undefined) config = setSyncDays(sync_days);
res.json(config);
} catch (err) {
res.status(err.status || 500).json({ error: err.message || 'Failed to update bank sync config' });
diff --git a/services/bankSyncConfigService.js b/services/bankSyncConfigService.js
index f96b632..99629bb 100644
--- a/services/bankSyncConfigService.js
+++ b/services/bankSyncConfigService.js
@@ -55,4 +55,13 @@ function setSyncIntervalHours(hours) {
return getBankSyncConfig();
}
-module.exports = { getBankSyncConfig, setBankSyncEnabled, setSyncIntervalHours };
+function setSyncDays(days) {
+ const n = parseInt(days, 10);
+ if (!Number.isFinite(n) || n < 1 || n > 730) {
+ throw Object.assign(new Error('sync_days must be between 1 and 730'), { status: 400 });
+ }
+ setSetting('simplefin_sync_days', String(n));
+ return getBankSyncConfig();
+}
+
+module.exports = { getBankSyncConfig, setBankSyncEnabled, setSyncIntervalHours, setSyncDays };
diff --git a/services/bankSyncService.js b/services/bankSyncService.js
index 6e21f14..df75ac4 100644
--- a/services/bankSyncService.js
+++ b/services/bankSyncService.js
@@ -8,22 +8,17 @@ const {
normalizeTransaction,
sanitizeErrorMessage,
} = require('./simplefinService');
+const { getBankSyncConfig } = require('./bankSyncConfigService');
const { decorateDataSource } = require('./transactionService');
-const SYNC_DAYS_DEFAULT = 90;
-
-function syncDaysBack() {
- const n = parseInt(process.env.SIMPLEFIN_SYNC_DAYS, 10);
- return Number.isFinite(n) && n > 0 ? n : SYNC_DAYS_DEFAULT;
-}
-
function sinceEpoch(dataSource) {
if (dataSource.last_sync_at) {
// Overlap by 2 days to catch late-posted transactions
const ts = new Date(dataSource.last_sync_at).getTime();
if (Number.isFinite(ts)) return Math.floor((ts - 2 * 86400 * 1000) / 1000);
}
- return Math.floor((Date.now() - syncDaysBack() * 86400 * 1000) / 1000);
+ const { sync_days } = getBankSyncConfig();
+ return Math.floor((Date.now() - sync_days * 86400 * 1000) / 1000);
}
function safeErrorMessage(err) {
@@ -94,6 +89,10 @@ async function runSync(db, userId, dataSource) {
const raw = await fetchAccountsAndTransactions(accessUrl, since);
const accounts = Array.isArray(raw.accounts) ? raw.accounts : [];
+ if (raw._errlistSummary) {
+ console.warn(`[bankSync] errlist for source ${dataSource.id}: ${raw._errlistSummary}`);
+ }
+
let accountsUpserted = 0;
let transactionsNew = 0;
let transactionsSkip = 0;
@@ -113,13 +112,18 @@ async function runSync(db, userId, dataSource) {
}
}
+ // Store any errlist warnings alongside a successful sync so users can see them
+ const partialError = raw._errlistSummary
+ ? sanitizeErrorMessage(`Partial sync — some connections failed: ${raw._errlistSummary}`)
+ : null;
+
db.prepare(`
UPDATE data_sources
- SET last_sync_at = datetime('now'), last_error = NULL, status = 'active', updated_at = datetime('now')
+ SET last_sync_at = datetime('now'), last_error = ?, status = 'active', updated_at = datetime('now')
WHERE id = ? AND user_id = ?
- `).run(dataSource.id, userId);
+ `).run(partialError, dataSource.id, userId);
- return { accountsUpserted, transactionsNew, transactionsSkip };
+ return { accountsUpserted, transactionsNew, transactionsSkip, errlist: raw._errlistSummary || null };
}
// ─── Public API ───────────────────────────────────────────────────────────────
diff --git a/services/simplefinService.js b/services/simplefinService.js
index d962bf5..728ed92 100644
--- a/services/simplefinService.js
+++ b/services/simplefinService.js
@@ -93,7 +93,7 @@ async function fetchAccountsAndTransactions(accessUrl, sinceEpoch) {
const basicAuth = Buffer.from(`${url.username}:${url.password}`).toString('base64');
const baseUrl = `${url.protocol}//${url.host}${url.pathname.replace(/\/?$/, '')}`;
- const endpoint = `${baseUrl}/accounts?start-date=${Math.floor(sinceEpoch)}`;
+ const endpoint = `${baseUrl}/accounts?start-date=${Math.floor(sinceEpoch)}&version=2`;
let data;
try {
@@ -111,6 +111,14 @@ async function fetchAccountsAndTransactions(accessUrl, sinceEpoch) {
throw sanitizeError(err);
}
+ // Surface any connection-level errors from the errlist so callers can log them
+ if (Array.isArray(data.errlist) && data.errlist.length > 0) {
+ const msgs = data.errlist
+ .map(e => sanitizeErrorMessage(e.message || e.msg || e.code || 'Unknown error'))
+ .join('; ');
+ data._errlistSummary = msgs;
+ }
+
return data;
}
@@ -123,7 +131,7 @@ function normalizeAccount(rawAccount, dataSourceId, userId) {
data_source_id: dataSourceId,
provider_account_id: String(rawAccount.id),
name: String(rawAccount.name || 'Account').slice(0, 255),
- org_name: rawAccount.org?.name ? String(rawAccount.org.name).slice(0, 255) : null,
+ org_name: (rawAccount.org?.name || rawAccount.conn_name) ? String(rawAccount.org?.name || rawAccount.conn_name).slice(0, 255) : null,
account_type: null,
currency: rawAccount.currency ? String(rawAccount.currency).slice(0, 10) : 'USD',
balance: Number.isFinite(balance) ? balance : null,