# 01. Analyze and document current Expo architecture

meta:
  id: native-business-logic-migration-01
  feature: native-business-logic-migration
  priority: P0
  depends_on: []
  tags: [analysis, documentation]

objective:
- Document the current Expo/TypeScript architecture to understand what needs to be migrated

deliverables:
- Architecture documentation file
- Component dependency diagram
- Data flow diagrams
- List of all services, stores, and utilities to migrate

steps:
- Review all TypeScript source files in src/
- Identify all data models and types
- Map out service dependencies
- Document state management flow (Zustand stores)
- Identify database schema and queries
- Document API endpoints and network calls
- Create migration checklist

acceptance_criteria:
- Architecture document exists with all components listed
- Data flow diagrams created for key features
- Migration checklist complete with all items identified
- All services and their dependencies documented

notes:
- Focus on business logic, not UI components
- Pay attention to async operations and error handling
- Document any platform-specific code that needs special handling

---

# Current Architecture Analysis

## Overview

RSSuper is a multi-platform RSS reader built with **Expo (React Native)** using **TypeScript**. The current architecture follows a service-oriented pattern with Zustand for state management and expo-sqlite for local persistence.

## Technology Stack

| Layer | Technology |
|-------|------------|
| Framework | Expo SDK 55 (canary) |
| Runtime | React Native 0.83.4 |
| Language | TypeScript 5.9 |
| State Management | Zustand 5.x |
| Data Fetching | TanStack Query 5.x |
| HTTP Client | Axios |
| Local Database | expo-sqlite |
| Navigation | React Navigation 7.x |
| XML Parsing | fast-xml-parser |
| Audio | expo-av |

---

## Data Models

### Core Types (`src/types/feed.ts`)

```
FeedItem
├── id: string
├── title: string
├── link?: string
├── description?: string
├── content?: string
├── author?: string
├── published?: Date
├── updated?: Date
├── categories?: string[]
├── enclosure?: { url, type, length? }
└── guid?: string

Feed
├── id: string
├── title: string
├── link?: string
├── description?: string
├── subtitle?: string
├── language?: string
├── lastBuildDate?: Date
├── updated?: Date
├── generator?: string
├── ttl?: number
├── items: FeedItem[]
├── rawUrl: string
├── lastFetchedAt?: Date
└── nextFetchAt?: Date

FeedSubscription
├── id: string
├── url: string
├── title: string
├── category?: string
├── enabled: boolean
├── fetchInterval: number (minutes)
├── createdAt: Date
├── updatedAt: Date
├── lastFetchedAt?: Date
├── nextFetchAt?: Date
├── error?: string
└── httpAuth?: { username, password }

SearchQuery / SearchFilters / SearchResult
```

### Global Types (`src/types/global.d.ts`)

```
NotificationType (enum)
├── NEW_ARTICLE
├── EPISODE_RELEASE
├── CUSTOM_ALERT
└── UPGRADE_PROMO

NotificationConfig
AccountSettings
PushNotificationConfig
```

---

## Services Architecture

### 1. Feed Service (`src/services/feed-service.ts`)

**Responsibilities**: RSS/Atom feed parsing and fetching

```
Functions:
├── parseFeed(url, data) → ParseResult
├── fetchFeed(url, auth?) → ParseResult
└── fetchFeeds(subscriptions) → Map<string, ParseResult>

Dependencies:
├── axios (HTTP)
└── xml2js (XML parsing)

Platform: Pure TypeScript - NO native dependencies
```

### 2. Database Service (`src/services/database.ts`)

**Responsibilities**: SQLite persistence layer

```
Tables:
├── subscriptions
│   ├── id (PRIMARY KEY)
│   ├── url (UNIQUE)
│   ├── title, category
│   ├── enabled, fetch_interval
│   ├── http_auth_username, http_auth_password
│   ├── timestamps (created_at, updated_at, last_fetched_at, next_fetch_at)
│   └── error
│
├── feeds
│   ├── id (PRIMARY KEY)
│   ├── subscription_id (FOREIGN KEY)
│   ├── title, link, description, author
│   ├── published, updated, content
│   ├── guid (UNIQUE)
│   └── created_at
│
├── feeds_fts (FTS5 virtual table)
├── subscriptions_fts (FTS5 virtual table)
└── search_history

Functions:
├── initDatabase() → void
├── saveSubscription(sub) → void
├── getSubscription(id) → FeedSubscription
├── getAllSubscriptions() → FeedSubscription[]
├── deleteSubscription(id) → void
├── saveFeedItems(subscriptionId, items) → void
├── getFeedItems(subscriptionId?, limit, offset) → FeedItem[]
├── getAllFeedItems(limit, offset) → FeedItem[]
└── search history functions

Dependencies: expo-sqlite
```

### 3. Search Service (`src/services/search-service.ts`)

**Responsibilities**: Full-text search using SQLite FTS5

```
Functions:
├── searchArticles(query, options) → SearchResult[]
├── searchFeeds(query, limit) → SearchResult[]
└── combinedSearch(query, options) → { articles, feeds }

Search Features:
├── FTS5 full-text search (primary)
├── LIKE fallback search
├── Date filters
├── Feed filters
├── Author filters
├── Content type filters
└── Multiple sort options

Dependencies: database service
```

### 4. Sync Service (`src/services/sync-service.ts`)

**Responsibilities**: Feed synchronization orchestration

```
Functions:
├── syncFeed(subscription) → { success, itemsSynced }
├── syncAllFeeds() → { success, totalItemsSynced }
├── getFeedsDueForSync() → FeedSubscription[]
├── getLocalFeedItems(...) → FeedItem[]
├── getAllLocalFeedItems(limit) → FeedItem[]
├── hasLocalData() → boolean
└── resolveConflict(options) → FeedItem

Conflict Resolution Strategies:
├── newer
├── older
├── local
└── remote

Dependencies: feed-service, database, feed-store
```

### 5. Background Sync Service (`src/services/background-sync.ts`)

**Responsibilities**: Background task management

```
Task: BACKGROUND_SYNC_TASK
├── Uses expo-task-manager
├── Registers background fetch task
└── Syncs all enabled feeds

Functions:
├── registerBackgroundSync() → boolean
├── unregisterBackgroundSync() → void
└── isBackgroundSyncRegistered() → boolean

Dependencies: expo-task-manager, sync-service, feed-store
```

### 6. Notification Service (`src/services/notification-service.ts`)

**Responsibilities**: Push and local notifications

```
Functions:
├── registerNotificationChannels() → void (Android)
├── requestNotificationPermissions() → boolean
├── getPermissionStatus() → status
├── scheduleNotification(config) → string | null
├── scheduleNotificationAtTime(config, date) → string | null
├── cancelNotification(id) → void
├── cancelAllNotifications() → void
├── getScheduledNotifications() → NotificationRequest[]
├── showNotification(config) → void
├── setBadgeCount(count) → void
├── getBadgeCount() → number
├── addNotificationListener(callback) → unsubscribe
└── addNotificationResponseListener(callback) → unsubscribe

Android Channels:
├── default
├── new-articles
├── episode-releases
└── custom-alerts

Dependencies: expo-notifications, settings-store
```

### 7. Audio Player Service (`src/services/audio-player.ts`)

**Responsibilities**: Podcast/audio playback

```
Class: AudioPlayerService
├── initialize() → void
├── subscribe(callback) → unsubscribe
├── play(item) → void
├── pause() → void
├── resume() → void
├── stop() → void
├── seekTo(positionMs) → void
├── setPlaybackSpeed(speed) → void
├── skipForward(seconds) → void
├── skipBackward(seconds) → void
└── getState() → PlayerState

Playback States: idle | loading | playing | paused | error
Playback Speeds: 0.5 | 0.75 | 1 | 1.25 | 1.5 | 1.75 | 2

Dependencies: expo-av
```

### 8. API Service (`src/services/api.ts`)

**Responsibilities**: HTTP client setup (currently minimal)

```
Setup:
├── Axios instance with baseURL
├── Request interceptor (auth token placeholder)
└── Response interceptor (error handling)

Note: Not actively used - TODO for future cloud sync
```

---

## State Management (Zustand Stores)

### 1. Feed Store (`src/stores/feed-store.ts`)

```
State:
├── subscriptions: FeedSubscription[]
├── feedItems: FeedItem[]
├── loading: boolean
└── error: string | null

Actions:
├── addSubscription(subscription) → Promise<void>
├── updateSubscription(id, updates) → void
├── removeSubscription(id) → Promise<void>
├── loadSubscriptions() → Promise<void>
├── loadFeedItems(subscriptionId?, limit?, offset?) → Promise<void>
├── setLoading(loading) → void
├── setError(error) → void
└── clearError() → void
```

### 2. Settings Store (`src/stores/settings-store.ts`)

```
State:
├── syncInterval: SyncInterval
├── theme: 'system' | 'light' | 'dark'
├── notificationPreferences: NotificationPreferences
├── readingPreferences: ReadingPreferences
└── accountSettings: AccountSettings

Actions:
├── setSyncInterval(interval) → void
├── setTheme(theme) → void
├── setNotificationPreferences(prefs) → void
├── setReadingPreferences(prefs) → void
├── setAccountSettings(settings) → void
└── resetSettings() → void

Persistence: AsyncStorage (via zustand persist)
Storage Key: rssuper-settings
```

### 3. Bookmark Store (`src/stores/bookmark-store.ts`)

```
State:
└── bookmarkedIds: Set<string>

Actions:
├── addBookmark(articleId) → void
├── removeBookmark(articleId) → void
├── toggleBookmark(articleId) → void
├── isBookmarked(articleId) → boolean
└── getBookmarks() → string[]

Persistence: AsyncStorage (via zustand persist)
Storage Key: rssuper-bookmarks
```

### 4. Search Store (`src/stores/search-store.ts`)

```
State:
├── query: string
├── filters: SearchFilters
├── sort: SearchSortOption
├── page: number
├── pageSize: number
├── loading: boolean
├── error: string | null
└── searchHistory: SearchHistoryItem[]

Actions:
├── setQuery(query) → void
├── setFilters(filters) → void
├── setSort(sort) → void
├── setPage(page) → void
├── setLoading(loading) → void
├── setError(error) → void
├── clearSearch() → void
├── addToHistory(query) → Promise<void>
├── loadHistory() → Promise<void>
├── clearHistory() → Promise<void>
├── removeFromHistory(query) → Promise<void>
└── resetSearch() → void
```

---

## Component Dependencies

```
┌─────────────────────────────────────────────────────────────────────────┐
│                           UI Components                                  │
│  (feed-item-card, article-card, search-filters, etc.)                  │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                         React Hooks                                      │
│  use-feed-list, use-theme, use-color-scheme, use-offline               │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                        Zustand Stores                                    │
│  feed-store, settings-store, bookmark-store, search-store              │
└─────────────────────────────────────────────────────────────────────────┘
            │                   │                   │                   │
            ▼                   ▼                   ▼                   ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                          Services Layer                                  │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌───────────┐ │
│  │feed-service  │  │search-service│  │ sync-service │  │  api.ts   │ │
│  └──────────────┘  └──────────────┘  └──────────────┘  └───────────┘ │
│  ┌──────────────────────┐  ┌──────────────────────┐                    │
│  │background-sync.ts    │  │notification-service  │                    │
│  └──────────────────────┘  └──────────────────────┘                    │
└─────────────────────────────────────────────────────────────────────────┘
            │                   │
            ▼                   ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                      Data Layer                                          │
│  ┌──────────────────────────────────────────────────────────────────┐   │
│  │                    database.ts (expo-sqlite)                      │   │
│  │  - subscriptions table                                            │   │
│  │  - feeds table                                                    │   │
│  │  - FTS5 virtual tables                                            │   │
│  │  - search_history table                                           │   │
│  └──────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                    Expo Modules (Native)                                 │
│  expo-sqlite, expo-task-manager, expo-notifications, expo-av           │
└─────────────────────────────────────────────────────────────────────────┘
```

---

## Data Flow Diagrams

### Feed Sync Flow

```
User adds subscription
        │
        ▼
┌───────────────────┐
│ feed-store        │
│ addSubscription() │
└─────────┬─────────┘
          │
          ▼
┌───────────────────┐     ┌───────────────────┐
│ database.ts       │     │ settings-store    │
│ saveSubscription()│     │ (check intervals) │
└─────────┬─────────┘     └───────────────────┘
          │
          ▼ (manual or background)
┌───────────────────┐
│ sync-service      │
│ syncFeed()        │
└─────────┬─────────┘
          │
          ▼
┌───────────────────┐     ┌───────────────────┐
│ feed-service      │     │ feed-store        │
│ fetchFeed()       │     │ updateSubscription│
│ parseFeed()       │     └─────────┬─────────┘
└─────────┬─────────┘               │
          │                         ▼
          │               ┌───────────────────┐
          │               │ database.ts       │
          │               │ saveFeedItems()   │
          │               └─────────┬─────────┘
          │                         │
          ▼                         ▼
┌───────────────────┐     ┌───────────────────┐
│ axios.get()      │     │ UI updates        │
│ (HTTP request)   │     │ via Zustand       │
└───────────────────┘     └───────────────────┘
```

### Search Flow

```
User enters search query
        │
        ▼
┌───────────────────┐
│ search-store      │
│ setQuery()        │
└─────────┬─────────┘
          │
          ▼
┌───────────────────┐
│ search-service    │
│ searchArticles()  │
└─────────┬─────────┘
          │
          ▼
┌───────────────────┐     ┌───────────────────┐
│ database.ts       │     │ FTS5 or LIKE      │
│ getDb()           │────▶│ fallback search   │
└─────────┬─────────┘     └───────────────────┘
          │
          ▼
┌───────────────────┐
│ SearchResult[]    │
└─────────┬─────────┘
          │
          ▼
┌───────────────────┐
│ UI renders        │
│ search-results    │
└───────────────────┘
```

---

## Migration Checklist

### Services to Migrate (Pure TypeScript)

| Service | File | Native Deps | Priority |
|---------|------|-------------|----------|
| Feed Service | `feed-service.ts` | None | P0 |
| Search Service | `search-service.ts` | None | P0 |
| Sync Service | `sync-service.ts` | None | P0 |
| API Service | `api.ts` | None | P1 |

### Services with Native Dependencies

| Service | File | Native Deps | Priority |
|---------|------|-------------|----------|
| Database | `database.ts` | expo-sqlite | P0 |
| Background Sync | `background-sync.ts` | expo-task-manager | P0 |
| Notifications | `notification-service.ts` | expo-notifications | P0 |
| Audio Player | `audio-player.ts` | expo-av | P1 |

### Stores to Migrate

| Store | File | Persistence | Priority |
|-------|------|-------------|----------|
| Feed Store | `feed-store.ts` | None | P0 |
| Settings Store | `settings-store.ts` | AsyncStorage | P0 |
| Bookmark Store | `bookmark-store.ts` | AsyncStorage | P0 |
| Search Store | `search-store.ts` | None | P0 |

### Types to Migrate

| Types | File | Priority |
|-------|------|----------|
| Feed Types | `types/feed.ts` | P0 |
| Global Types | `types/global.d.ts` | P0 |

---

## Key Findings

1. **Pure TypeScript Services** (can be shared across all platforms):
   - Feed parsing (RSS/Atom)
   - Search logic
   - Sync orchestration
   - Conflict resolution

2. **Native Module Dependencies**:
   - `expo-sqlite` → SQLite database
   - `expo-task-manager` → Background tasks
   - `expo-notifications` → Push/local notifications
   - `expo-av` → Audio playback

3. **State Management**:
   - All stores use Zustand
   - Settings and bookmarks persist to AsyncStorage
   - Database serves as source of truth for feeds/subscriptions

4. **Error Handling**:
   - Most services return `{ success: boolean; error?: string }`
   - Try-catch blocks with meaningful error messages
   - Fallback strategies (e.g., FTS → LIKE search)

5. **Platform-Specific Code**:
   - `hooks/use-color-scheme.web.ts` - Web-specific color scheme
   - `components/animated-icon.web.tsx` - Web-specific icon animation
   - `components/app-tabs.web.tsx` - Web-specific tabs

---

## Migration Priorities

1. **Phase 1**: Data models and types (shared)
2. **Phase 2**: Pure TypeScript services (feed, search, sync)
3. **Phase 3**: Database layer with expo-sqlite
4. **Phase 4**: Background sync with expo-task-manager
5. **Phase 5**: Notifications with expo-notifications
6. **Phase 6**: Audio player with expo-av
7. **Phase 7**: State management integration