|
2 | 2 |
|
3 | 3 | This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
4 | 4 |
|
5 | | -## Project Overview |
| 5 | +## What this is |
6 | 6 |
|
7 | | -This is an rssCloud Server implementation in Node.js - a notification protocol server that allows RSS feeds to notify subscribers when they are updated. The server handles subscription management and real-time notifications for RSS/feed updates. |
| 7 | +An [rssCloud](http://rsscloud.org/) notification protocol server. Subscribers register a callback URL via `/pleaseNotify`; publishers `/ping` when feeds update; the server fans notifications out to subscribers. Implementation lives in `apps/server/`. |
8 | 8 |
|
9 | | -## Monorepo Structure |
| 9 | +## Data storage |
10 | 10 |
|
11 | | -This project is a pnpm workspace monorepo orchestrated by [Turborepo](https://turborepo.com/). |
| 11 | +State (resources and subscriptions) is held in memory and persisted atomically to a JSON file (default `./data/subscriptions.json`, configurable via `DATA_FILE_PATH`). The flush happens on an interval, at shutdown, and on unexpected exit. There is no external database. |
12 | 12 |
|
13 | | -``` |
14 | | -/ # Workspace root |
15 | | -├── apps/ |
16 | | -│ ├── server/ # rssCloud Server application |
17 | | -│ │ ├── app.js # Express entry point |
18 | | -│ │ ├── config.js # Configuration from env vars |
19 | | -│ │ ├── controllers/ # Route handlers |
20 | | -│ │ ├── services/ # Business logic |
21 | | -│ │ ├── views/ # Handlebars templates |
22 | | -│ │ ├── public/ # Static assets |
23 | | -│ │ └── Dockerfile # Lean production image |
24 | | -│ └── e2e/ # End-to-end test suite (private) |
25 | | -│ ├── test/ # Mocha/Chai tests + mock servers |
26 | | -│ ├── Dockerfile # Test-runner image (mocha + dockerize) |
27 | | -│ └── docker-compose.yml # Orchestrates server + e2e containers |
28 | | -├── packages/ |
29 | | -│ └── core/ # @rsscloud/core: shared primitives (TS, tsup) |
30 | | -├── pnpm-workspace.yaml # Workspace definition |
31 | | -└── turbo.json # Task orchestration + caching |
32 | | -``` |
| 13 | +## End-to-end tests |
33 | 14 |
|
34 | | -## Development Commands |
| 15 | +`apps/e2e/` is a private workspace package holding a full mocha suite. Tests talk to the server over HTTP via `APP_URL` and spin up their own mock servers on ports 8002/8003. |
35 | 16 |
|
36 | | -This project uses pnpm with corepack. Run `corepack enable` to set up pnpm automatically. |
| 17 | +A handful of server-internal helpers (RPC builders, dayjs wrapper, `init-subscription`, three config keys) are **intentionally duplicated** in `apps/e2e/test/helpers/` rather than imported across the workspace boundary. This preserves the e2e package as an independent consumer of the server's HTTP+RPC protocol, at the cost of some maintenance overhead if those helpers' wire-shape ever changes. If you find yourself adding a new `require('../...')` in a test file, prefer copying the dependency into `helpers/` instead. |
37 | 18 |
|
38 | | -### Start Development (from repo root) |
| 19 | +## Releases |
39 | 20 |
|
40 | | -- `pnpm start` - Start server with nodemon (auto-reload on changes) |
41 | | -- `pnpm run client` - Start client with nodemon |
| 21 | +Conventional Commits are enforced by commitlint (via husky). Pushes to `main` trigger [release-please](https://github.com/googleapis/release-please) which opens or updates a Release PR per tracked package (`apps/server`, `packages/core`). `apps/e2e` is private and not tracked. Merging the Release PR cuts the release and git tag. |
42 | 22 |
|
43 | | -### Testing & Quality (from repo root, all routed through turbo) |
44 | | - |
45 | | -- `pnpm test` - Run docker-based end-to-end tests via `apps/e2e/docker-compose.yml` (MacOS tested) |
46 | | -- `pnpm run test:unit` - Run unit tests across all packages (just `@rsscloud/core`'s vitest today) |
47 | | -- `pnpm run build` - Build all packages (just `@rsscloud/core`'s tsup today) |
48 | | -- `pnpm run lint` - Run ESLint across all packages |
49 | | -- `pnpm run typecheck` - Run TypeScript typecheck across all packages |
50 | | -- `pnpm run format` - Run Prettier on the entire repo |
51 | | - |
52 | | -## Architecture |
53 | | - |
54 | | -### Core Application Structure (apps/server/) |
55 | | - |
56 | | -- **app.js** - Main Express application entry point, sets up middleware, loads jsonStore from disk, and starts server |
57 | | -- **config.js** - Configuration management reading from env vars with defaults |
58 | | -- **controllers/** - Express route handlers for API endpoints |
59 | | -- **services/** - Business logic modules for core functionality |
60 | | -- **views/** - Handlebars templates for web interface |
61 | | - |
62 | | -### Key Services |
63 | | - |
64 | | -- **services/json-store.js** - Disk-backed in-memory store; the sole source of truth for resources and subscriptions. Flushes atomically to `./data/subscriptions.json` on an interval and at shutdown. |
65 | | -- **services/notify-\*.js** - Notification system for subscribers |
66 | | -- **services/ping.js** - RSS feed update detection and processing |
67 | | -- **services/please-notify.js** - Subscription management |
68 | | - |
69 | | -### API Endpoints (defined in controllers/index.js) |
70 | | - |
71 | | -- `/pleaseNotify` - Subscribe to RSS feed notifications |
72 | | -- `/ping` - Notify server of RSS feed updates |
73 | | -- `/viewLog` - Event log viewer for debugging |
74 | | -- `/RPC2` - XML-RPC endpoint |
75 | | -- Web forms available at `/pleaseNotifyForm` and `/pingForm` |
76 | | - |
77 | | -### Configuration |
78 | | - |
79 | | -Environment variables (with defaults in apps/server/config.js): |
80 | | - |
81 | | -- `DOMAIN` (default: localhost) |
82 | | -- `PORT` (default: 5337) |
83 | | -- `DATA_FILE_PATH` (default: `./data/subscriptions.json`) |
84 | | -- Resource limits: MAX_RESOURCE_SIZE, REQUEST_TIMEOUT, etc. |
85 | | - |
86 | | -### Data Storage |
87 | | - |
88 | | -State is persisted to a JSON file (default `./data/subscriptions.json`) managed by services/json-store.js. The store loads into memory at startup and flushes atomically on an interval and at shutdown. No external database is required. |
89 | | - |
90 | | -### Testing |
91 | | - |
92 | | -- End-to-end tests live in `apps/e2e/test/` (separate workspace package, `@rsscloud/e2e`) |
93 | | -- Tests use Mocha/Chai, orchestrated via `apps/e2e/docker-compose.yml` |
94 | | -- Mock servers spin up on ports 8002/8003; SSL certs in `apps/e2e/test/keys/` |
95 | | -- Server-internal helpers used by tests (RPC builders, dayjs wrapper, init-subscription, config) are duplicated under `apps/e2e/test/helpers/` to keep the suite decoupled from `apps/server` internals |
96 | | - |
97 | | -## Commits and Releases |
98 | | - |
99 | | -This project uses [Conventional Commits](https://www.conventionalcommits.org/) enforced by commitlint via husky git hooks. |
100 | | - |
101 | | -### Commit Format |
102 | | - |
103 | | -``` |
104 | | -type: description |
105 | | -
|
106 | | -[optional body] |
107 | | -``` |
108 | | - |
109 | | -### Commit Types |
110 | | - |
111 | | -**Trigger releases:** |
112 | | - |
113 | | -- `fix:` - Bug fixes → patch release |
114 | | -- `feat:` - New features → minor release |
115 | | -- `feat!:` or `BREAKING CHANGE:` → major release |
116 | | - |
117 | | -**No release triggered:** |
118 | | - |
119 | | -- `chore:` - Maintenance tasks, dependencies |
120 | | -- `docs:` - Documentation only |
121 | | -- `style:` - Code style/formatting |
122 | | -- `refactor:` - Code refactoring |
123 | | -- `test:` - Adding/updating tests |
124 | | -- `ci:` - CI/CD changes |
125 | | -- `build:` - Build system changes |
126 | | - |
127 | | -### Release Workflow |
128 | | - |
129 | | -1. Push commits to `main` |
130 | | -2. release-please automatically creates/updates a Release PR |
131 | | -3. Review the Release PR (contains changelog and version bump) |
132 | | -4. Merge the Release PR when ready to release |
133 | | -5. release-please creates GitHub Release and git tag |
| 23 | +`fix:` → patch, `feat:` → minor, `feat!:` / `BREAKING CHANGE:` → major. Other types (`chore:`, `docs:`, `style:`, `refactor:`, `test:`, `ci:`, `build:`) don't trigger releases. |
0 commit comments