repoimage 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/AGENTS.md +28 -0
  3. package/PROJECT-AGENTS.md +55 -0
  4. package/README.md +153 -0
  5. package/TODO.md +132 -0
  6. package/client/index.html +12 -0
  7. package/client/package.json +23 -0
  8. package/client/src/App.tsx +599 -0
  9. package/client/src/components/FsBrowser.tsx +210 -0
  10. package/client/src/components/Settings.tsx +81 -0
  11. package/client/src/index.css +797 -0
  12. package/client/src/lib/api.ts +69 -0
  13. package/client/src/lib/collect.ts +204 -0
  14. package/client/src/lib/format.ts +96 -0
  15. package/client/src/lib/session.ts +58 -0
  16. package/client/src/main.tsx +10 -0
  17. package/client/src/vite-env.d.ts +1 -0
  18. package/client/tsconfig.json +18 -0
  19. package/client/vite.config.ts +27 -0
  20. package/docs/README.md +28 -0
  21. package/docs/api/overview.md +65 -0
  22. package/docs/api/scan.md +188 -0
  23. package/docs/architecture.md +155 -0
  24. package/docs/design/invariants.md +19 -0
  25. package/docs/design/role-system.md +50 -0
  26. package/docs/development/README.md +94 -0
  27. package/docs/features/README.md +21 -0
  28. package/docs/features/compression-score.md +75 -0
  29. package/docs/features/exclusions.md +63 -0
  30. package/docs/features/session.md +64 -0
  31. package/package.json +37 -0
  32. package/server/dist/cli.d.ts +3 -0
  33. package/server/dist/cli.d.ts.map +1 -0
  34. package/server/dist/cli.js +54 -0
  35. package/server/dist/cli.js.map +1 -0
  36. package/server/dist/fs-list.d.ts +3 -0
  37. package/server/dist/fs-list.d.ts.map +1 -0
  38. package/server/dist/fs-list.js +73 -0
  39. package/server/dist/fs-list.js.map +1 -0
  40. package/server/dist/paths.d.ts +3 -0
  41. package/server/dist/paths.d.ts.map +1 -0
  42. package/server/dist/paths.js +12 -0
  43. package/server/dist/paths.js.map +1 -0
  44. package/server/dist/scan.d.ts +16 -0
  45. package/server/dist/scan.d.ts.map +1 -0
  46. package/server/dist/scan.js +158 -0
  47. package/server/dist/scan.js.map +1 -0
  48. package/server/dist/server.d.ts +6 -0
  49. package/server/dist/server.d.ts.map +1 -0
  50. package/server/dist/server.js +313 -0
  51. package/server/dist/server.js.map +1 -0
  52. package/server/package.json +22 -0
  53. package/server/src/cli.ts +63 -0
  54. package/server/src/fs-list.ts +70 -0
  55. package/server/src/paths.ts +6 -0
  56. package/server/src/scan.ts +203 -0
  57. package/server/src/server.ts +356 -0
  58. package/server/tsconfig.json +9 -0
  59. package/shared/package.json +10 -0
  60. package/shared/src/constants.ts +37 -0
  61. package/shared/src/index.ts +4 -0
  62. package/shared/src/role-guess.ts +103 -0
  63. package/shared/src/schema.ts +18 -0
  64. package/shared/src/types.ts +36 -0
  65. package/shared/tsconfig.json +9 -0
  66. package/test/cli.test.js +56 -0
  67. package/test/fs-list.test.js +39 -0
  68. package/test/role-guess.test.js +50 -0
  69. package/test/scan.test.js +150 -0
  70. package/test/server.test.js +308 -0
  71. package/tsconfig.base.json +14 -0
@@ -0,0 +1,8 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npm test *)",
5
+ "Bash(npm run *)"
6
+ ]
7
+ }
8
+ }
package/AGENTS.md ADDED
@@ -0,0 +1,28 @@
1
+ # Agent instructions
2
+
3
+ **Note:** This file is generic and transferable across projects. For RepoImage-specific policies, see [PROJECT-AGENTS.md](PROJECT-AGENTS.md).
4
+
5
+ ## Questions are informational only
6
+
7
+ When the user asks a **question** (including “how”, “what”, “why”, “can”, “does”, “is there”, “should I”, or any phrasing that seeks information, explanation, or advice rather than a direct change request):
8
+
9
+ - Treat it **only** as a request for information.
10
+ - **Do not** edit, create, or delete files.
11
+ - **Do not** run commands that modify the project (no installs, commits, refactors, or “helpful” fixes unless the user explicitly asks you to make a change in that same message).
12
+
13
+ If the user wants changes after your answer, they will say so explicitly (e.g. “implement that”, “add this”, “fix it”, “update the README”).
14
+
15
+ When in doubt whether a message is a question or a task, **assume it is a question** and respond without altering code.
16
+
17
+ ## Tests and documentation
18
+
19
+ **Policy:** Every TODO item must include tests and documentation updates. This is compulsory, not optional.
20
+
21
+ - After changing project code, run `npm test` and report the result (pass or fail with a short summary of failing tests).
22
+ - Do not treat a failing suite as an automatic mandate to make tests pass. Decide whether the implementation or the tests should change based on the user’s request.
23
+ - When the user asked for intentional behavior or API changes, update or add tests to match; explain what you changed.
24
+ - Do not weaken, delete, or bypass assertions just to get a green run unless the user explicitly asked for that.
25
+ - If it is unclear whether code or tests are wrong, report the failures and your recommendation; do not guess by silently “fixing” whichever is easier.
26
+ - Tests with fixed input/output expectations (fixtures) may fail after deliberate rule changes; those failures may be expected until expectations are updated with the user’s agreement.
27
+ - When completing a TODO item, update the `docs/` folder with relevant documentation (API endpoints, features, examples, etc.) — this is required before marking as done.
28
+ - If documentation is already present and complete, note this; only add or update docs when the feature is new or behavior has changed.
@@ -0,0 +1,55 @@
1
+ # Project-Specific Agent Guidelines
2
+
3
+ This document extends [AGENTS.md](AGENTS.md) with RepoImage-specific policies. Use this alongside the main AGENTS.md when working on this project.
4
+
5
+ ## Design Principles
6
+
7
+ All work must respect the [Global Invariants](docs/design/invariants.md). Before implementing a feature or fix, check if any invariants apply. If your change would violate an invariant, escalate to the user.
8
+
9
+ ## Testing Strategy
10
+
11
+ When implementing a TODO section, tests should focus on:
12
+
13
+ | Area | Focus |
14
+ |------|-------|
15
+ | `shared` / `role-guess` | Fixture table; `unknown` when weak; valid roles only |
16
+ | `server` / config | Load, merge, save, invariants |
17
+ | `server` / scan | `roleGuess`, `role: null`, path `..` rejected |
18
+ | `client` | Extracted banner/save helpers (not full E2E v1) |
19
+ | Integration | API + CLI + config file |
20
+
21
+ **No test is exempt.** Every TODO item must include tests as a prerequisite to completion (see [AGENTS.md](AGENTS.md) policy). Tests verify both happy path and invariant violations.
22
+
23
+ ## Documentation Requirements
24
+
25
+ Every completed TODO item must include documentation updates in `docs/`. Specifically:
26
+
27
+ - API changes → update `docs/api/` (endpoints, params, responses)
28
+ - Features → update `docs/features/` (user guide, examples)
29
+ - Architectural changes → update `docs/architecture.md` or `docs/design/`
30
+ - CLI changes → document in `docs/development/` or feature docs
31
+
32
+ See [B.docs TODO](TODO.md#bdocs--documentation-structure) for the docs folder structure.
33
+
34
+ ## Path Security
35
+
36
+ Paths are a security boundary. Always validate:
37
+ - No `..` segments
38
+ - Normalized to project root
39
+ - Reject attempts to escape (see [Invariant #6](docs/design/invariants.md))
40
+
41
+ ## Role Semantics
42
+
43
+ Role values are enumerated: `hero`, `content`, `thumbnail`, `unknown`.
44
+
45
+ - **Guesses** (`roleGuess`) are ephemeral; never persisted.
46
+ - **Confirmed roles** (`role`) in `.repoimage.json` are authoritative and survive re-scans.
47
+ - See [Invariants #1, #2, #3, #7](docs/design/invariants.md) for the full contract.
48
+
49
+ ## Config File Stability
50
+
51
+ The `.repoimage.json` sidecar is user-editable and may contain manual changes. Treat it as a partial, user-curated document:
52
+
53
+ - Load with validation (reject stale paths, invalid roles)
54
+ - Never overwrite confirmed roles during re-scan ([Invariant #4](docs/design/invariants.md))
55
+ - Always set `_generator` on write ([Invariant #5](docs/design/invariants.md))
package/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # RepoImage
2
+
3
+ Scan a project (or any folder tree) for image files, measure dimensions and file size, and estimate how well each image is compressed. Useful for finding oversized or poorly compressed assets in a repository.
4
+
5
+ The **web GUI** is a React app (Vite). A **CLI** is available for scripts and quick terminal scans. The repo uses **npm workspaces**: `shared/`, `server/`, and `client/`.
6
+
7
+ **For developers:** See [docs/](docs/) for architecture, API reference, and development guides.
8
+
9
+ ## Requirements
10
+
11
+ - [Node.js](https://nodejs.org/) v18+
12
+
13
+ ## Quick start (production GUI)
14
+
15
+ ```bash
16
+ git clone <repo-url> repoimage
17
+ cd repoimage
18
+ npm install
19
+ npm run build
20
+ npm run gui
21
+ ```
22
+
23
+ The server prints a URL, for example:
24
+
25
+ ```text
26
+ RepoImage GUI: http://127.0.0.1:3847/
27
+ ```
28
+
29
+ Open that URL in your browser. Do not open `client/index.html` directly (`file://`); folder browse and scanning need the API server.
30
+
31
+ ## Development
32
+
33
+ Run the API server and Vite dev client together (client proxies `/api` to port `3847`):
34
+
35
+ ```bash
36
+ npm install
37
+ npm run dev
38
+ ```
39
+
40
+ - **GUI:** http://127.0.0.1:5173/
41
+ - **API:** http://127.0.0.1:3847/
42
+
43
+ Build everything and run tests:
44
+
45
+ ```bash
46
+ npm run build
47
+ npm test
48
+ ```
49
+
50
+ ## Using the GUI
51
+
52
+ 1. Start with `npm run gui` (production) or `npm run dev` (development).
53
+ 2. Open the URL shown (production: port **3847**; dev: port **5173**).
54
+ 3. **Choose a project root:** type an absolute path, or **Browse…** (server folder browser or system folder dialog).
55
+ 4. Review the table: path, file size, dimensions, estimated uncompressed size, compression score (0–10), and a visual bar.
56
+ 5. Use **Sort by**, **Filter path**, and **Min/Max score** to focus on the worst offenders.
57
+
58
+ Compression score is higher when the file is large relative to an estimated uncompressed size (roughly `width × height × bytes-per-pixel`). SVG files are listed but do not get a score.
59
+
60
+ ### Environment variables
61
+
62
+ | Variable | Default | Purpose |
63
+ |----------|---------|---------|
64
+ | `PORT` | `3847` | HTTP port (server / `npm run gui`) |
65
+ | `REPOIMAGE_BIND` | `127.0.0.1` | Bind address (`0.0.0.0` for all interfaces) |
66
+ | `REPOIMAGE_FS_TRUST_REMOTE` | (unset) | Set to `1` to allow non-loopback clients to use `/api/fs/*` (not recommended) |
67
+ | `REPOIMAGE_API_PORT` | `3847` | API port targeted by the Vite dev proxy |
68
+
69
+ Examples:
70
+
71
+ ```bash
72
+ PORT=8080 npm run gui
73
+ REPOIMAGE_BIND=0.0.0.0 npm run gui
74
+ ```
75
+
76
+ Filesystem listing APIs (`/api/fs/list`, `/api/fs/home`) are restricted to loopback clients unless `REPOIMAGE_FS_TRUST_REMOTE=1`.
77
+
78
+ ## Command line
79
+
80
+ ```bash
81
+ npm start -- /path/to/project
82
+ # or after build:
83
+ node server/dist/cli.js --json /path/to/repo
84
+ # or:
85
+ npx repoimage --json /path/to/repo
86
+ ```
87
+
88
+ | Flag | Description |
89
+ |------|-------------|
90
+ | `--json` | Print `{ images, issues }` as JSON on stdout |
91
+ | `--sort-by-score` | Order results by compression score (worst first) |
92
+
93
+ Install globally from the repo root (optional):
94
+
95
+ ```bash
96
+ npm install -g .
97
+ repoimage /path/to/project
98
+ ```
99
+
100
+ ## Image role suggestions
101
+
102
+ Each scanned image includes a **heuristic suggested role** (not saved to disk):
103
+
104
+ | Field | Meaning |
105
+ |-------|---------|
106
+ | `roleGuess` | One of `hero`, `content`, `thumbnail`, or `unknown` |
107
+ | `roleGuessReason` | Short explanation when the guess is not `unknown` |
108
+ | `role` | Always `null` for now — confirmed roles will use `.repoimage.json` (see [TODO.md](TODO.md)) |
109
+
110
+ Guesses use path segments, small dimension suffixes in filenames, and image dimensions. They are **hints only**.
111
+
112
+ ### Example `--json` row
113
+
114
+ ```json
115
+ {
116
+ "path": "public/hero-banner.jpg",
117
+ "size": 245000,
118
+ "width": 1600,
119
+ "height": 900,
120
+ "uncompressedSize": 4320000,
121
+ "compressionRatio": "4.1",
122
+ "role": null,
123
+ "roleGuess": "hero",
124
+ "roleGuessReason": "path suggests hero or banner"
125
+ }
126
+ ```
127
+
128
+ ## Project layout
129
+
130
+ | Path | Role |
131
+ |------|------|
132
+ | `shared/` | TypeScript types, role schema, `guessRole` heuristics |
133
+ | `server/` | Scan, FS APIs, HTTP server, CLI (`tsc` → `dist/`) |
134
+ | `client/` | Vite + React + TypeScript GUI (`vite build` → `dist/`) |
135
+ | `test/` | Node test runner suites (run after server/shared build) |
136
+
137
+ ## Scripts
138
+
139
+ | Script | Description |
140
+ |--------|-------------|
141
+ | `npm run build` | Build shared, server, and client |
142
+ | `npm run dev` | Server watch + Vite dev server |
143
+ | `npm run gui` | Build and start production server (serves `client/dist`) |
144
+ | `npm start -- <folders>` | CLI scan |
145
+ | `npm test` | Build shared/server and run tests |
146
+
147
+ ## Supported image types
148
+
149
+ `.jpg`, `.jpeg`, `.png`, `.gif`, `.bmp`, `.tiff`, `.tif`, `.webp`, `.svg`, `.ico`, `.raw`, `.heic`, `.heif`, `.avif`
150
+
151
+ ## License
152
+
153
+ MIT
package/TODO.md ADDED
@@ -0,0 +1,132 @@
1
+ # RepoImage TODO
2
+
3
+ Phased plan for the repo. Completed work is documented in [README.md](README.md). Run `npm test` after code changes; see [AGENTS.md](AGENTS.md) for how to handle failures.
4
+
5
+ ---
6
+
7
+ ## A — Load and merge `.repoimage.json`
8
+
9
+ **Goal:** Read sidecar at project root; merged scan output shows confirmed `role` + `roleGuess`.
10
+
11
+ **Reference:** [docs/design/role-system.md](docs/design/role-system.md) — role system design decisions.
12
+
13
+ **⚠️ Invariants:** Never write `roleGuess` to disk (invariant #1). Re-scan must not overwrite confirmed roles (invariant #4). Config `role` wins over guess in output (invariant #3).
14
+
15
+ - [ ] `server` (or `shared` + server): `loadConfig`, `mergeRoles`
16
+ - [ ] Validate paths and roles; stale config paths reported
17
+ - [ ] `/api/scan`, `/api/scan-entries` (when root known), CLI `--json`: `hasConfigFile`, `confirmedCount`, `totalImages`
18
+ - [ ] Update `docs/api/` with `.repoimage.json` loading contract and response changes
19
+ - [ ] Update `docs/features/` documenting config file format and partial catalog concept
20
+
21
+ **Tests:** `repoimage-config` tests; extend server/scan/cli tests.
22
+
23
+ **Done when:** Scan JSON includes manual `role` where configured; catalog stats correct.
24
+
25
+ ---
26
+
27
+ ## B — Save confirmed roles (API)
28
+
29
+ **Goal:** Persist only on explicit save from UI (or future CLI command).
30
+
31
+ **Reference:** [docs/design/role-system.md](docs/design/role-system.md) — role system design decisions.
32
+
33
+ **⚠️ Invariants:** Never write `roleGuess` to disk (invariant #1). Only confirmed roles in `images` (invariant #2). Valid roles only (invariant #7). Always set `_generator` and `version` (invariant #5). Reject paths outside root (invariant #6).
34
+
35
+ - [ ] `POST /api/repoimage` — `updates`, `remove`; read-modify-write; never write guesses
36
+ - [ ] Maintain `version` + `_generator` on every write
37
+ - [ ] Same path trust rules as scan / fs APIs
38
+ - [ ] Update `docs/api/config.md` documenting save endpoint, payload, and write semantics
39
+
40
+ **Tests:** create, update, unconfirm, `_generator` insert/replace, security cases.
41
+
42
+ **Done when:** Sidecar writable via API without GUI.
43
+
44
+ ---
45
+
46
+ ## C — Role review UI (React)
47
+
48
+ **Goal:** Review guesses and confirm roles in the client.
49
+
50
+ **Reference:** [docs/design/role-system.md](docs/design/role-system.md) — role system design decisions.
51
+
52
+ **⚠️ Invariant:** No one-click guess → confirm (invariant #8). Users must explicitly choose and confirm; accept-guess is forbidden.
53
+
54
+ - [ ] Banner (no file vs partial catalog)
55
+ - [ ] Columns: suggested role (+ reason tooltip), confirmed role ("—" if none)
56
+ - [ ] Row control → popover: suggested (read-only), role select, Save/Cancel, Clear
57
+ - [ ] Filters: e.g. unreviewed only
58
+ - [ ] Stale config entries (path in JSON, file missing) — visible warning
59
+ - [ ] Extract testable helpers (`bannerMessage`, save payload builder) — unit test in `client` or `shared`
60
+ - [ ] Update `docs/features/` documenting role workflow and UI patterns
61
+
62
+ **Done when:** Full confirm/unconfirm loop; no accept-guess shortcut.
63
+
64
+ ---
65
+
66
+ ## D — CLI and docs polish
67
+
68
+ - [ ] CLI `--json` documents role + catalog fields (default with `--json`)
69
+ - [ ] README: reference to `.repoimage.json` format in docs/
70
+ - [ ] Re-scan never overwrites confirmed roles on disk
71
+ - [ ] Update `docs/` as needed for CLI behavior and any remaining features
72
+
73
+ **Tests:** CLI integration with config file; save → CLI sees confirmed role.
74
+
75
+ ---
76
+
77
+ ## E — Role guess tuning (optional)
78
+
79
+ - [ ] Tune `role-guess` rules from real repos
80
+ - [ ] Richer reasons in UI; sort/filter by suggestion; unreviewed + low score worklist
81
+ - [ ] Update guess fixtures intentionally when rules change
82
+ - [ ] Document updated guessing heuristics in `docs/features/`
83
+
84
+ ---
85
+
86
+ ## F — GUI walkthrough and screenshots
87
+
88
+ **Goal:** User-friendly walkthrough documentation with screenshots of the GUI and feature workflows.
89
+
90
+ - [ ] Screenshot: main scan interface (folder selection, results table)
91
+ - [ ] Screenshot: sort/filter controls
92
+ - [ ] Screenshot: compression score tooltip
93
+ - [ ] Screenshot: settings dropdown
94
+ - [ ] Screenshot: role confirmation popover
95
+ - [ ] Write `docs/features/gui-walkthrough.md` with annotated screenshots and user workflows
96
+ - [ ] Update `docs/features/README.md` to link to the walkthrough
97
+
98
+ **Done when:** Users can understand core features visually before diving into docs.
99
+
100
+ ---
101
+
102
+ ## G — CONTRIBUTING.md
103
+
104
+ **Goal:** Welcome open source contributors with clear guidelines.
105
+
106
+ - [ ] Create `CONTRIBUTING.md` at repo root
107
+ - [ ] Link to developer setup (`docs/development/`)
108
+ - [ ] Explain the development process (pick a TODO, read PROJECT-AGENTS.md, tests + docs required)
109
+ - [ ] Link to invariants and design principles
110
+ - [ ] Code of conduct or basic courtesy guidelines
111
+ - [ ] How to submit PRs (tests must pass, docs must be updated)
112
+
113
+ **Done when:** New contributors know where to start and what's expected.
114
+
115
+ ---
116
+
117
+ ## Suggested order
118
+
119
+ 1. **A** → **B** → **C** → **D** — roles backend, API, UI, CLI (next: start with A)
120
+ 2. **E** — role guess tuning (optional, as needed)
121
+ 3. **F** — GUI walkthrough and screenshots (after main features complete)
122
+ 4. **G** — CONTRIBUTING.md (when ready to invite contributors)
123
+
124
+ **Gate:** `npm test` after each section; see [AGENTS.md](AGENTS.md) if failures need human review.
125
+
126
+ ---
127
+
128
+ ## Out of scope for v1
129
+
130
+ - Playwright E2E (optional later)
131
+ - Visual/CSS regression tests
132
+ - Proving heuristic "correctness" on real sites — only fixture-documented rules
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>RepoImage — Repository Image Analyser</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/src/main.tsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@repoimage/client",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "vite",
8
+ "build": "vite build",
9
+ "preview": "vite preview"
10
+ },
11
+ "dependencies": {
12
+ "@repoimage/shared": "*",
13
+ "react": "^19.0.0",
14
+ "react-dom": "^19.0.0"
15
+ },
16
+ "devDependencies": {
17
+ "@types/react": "^19.0.0",
18
+ "@types/react-dom": "^19.0.0",
19
+ "@vitejs/plugin-react": "^4.3.4",
20
+ "typescript": "^5.7.2",
21
+ "vite": "^6.0.3"
22
+ }
23
+ }