repoview 0.5.1 → 0.6.1
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.
- package/CHANGELOG.md +87 -0
- package/CONTRIBUTING.md +4 -3
- package/DEVELOPMENT.md +84 -16
- package/README.md +71 -5
- package/dist/api.js +58 -0
- package/dist/api.js.map +1 -0
- package/dist/cli.js +454 -0
- package/dist/cli.js.map +1 -0
- package/dist/csv.js +64 -0
- package/dist/csv.js.map +1 -0
- package/dist/format.js +25 -0
- package/dist/format.js.map +1 -0
- package/dist/gist-router.js +153 -0
- package/dist/gist-router.js.map +1 -0
- package/dist/gists.js +130 -0
- package/dist/gists.js.map +1 -0
- package/dist/git.js +67 -0
- package/dist/git.js.map +1 -0
- package/dist/gitignore.js +34 -0
- package/dist/gitignore.js.map +1 -0
- package/dist/linkcheck.js +310 -0
- package/dist/linkcheck.js.map +1 -0
- package/dist/markdown.js +493 -0
- package/dist/markdown.js.map +1 -0
- package/dist/net.js +10 -0
- package/dist/net.js.map +1 -0
- package/dist/paths.js +59 -0
- package/dist/paths.js.map +1 -0
- package/dist/reload.js +55 -0
- package/dist/reload.js.map +1 -0
- package/dist/repo-context.js +80 -0
- package/dist/repo-context.js.map +1 -0
- package/dist/repo-router.js +810 -0
- package/dist/repo-router.js.map +1 -0
- package/dist/review-cli.js +228 -0
- package/dist/review-cli.js.map +1 -0
- package/dist/server.js +122 -0
- package/dist/server.js.map +1 -0
- package/dist/session.js +86 -0
- package/dist/session.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/views.js +780 -0
- package/dist/views.js.map +1 -0
- package/package.json +20 -9
- package/public/app.css +113 -0
- package/public/app.js +26 -3
- package/public/gist.js +60 -0
- package/public/review.js +9 -6
- package/public/session.js +61 -0
- package/src/cli.js +0 -91
- package/src/gitignore.js +0 -34
- package/src/linkcheck.js +0 -312
- package/src/markdown.js +0 -518
- package/src/review-cli.js +0 -245
- package/src/server.js +0 -1126
- package/src/views.js +0 -657
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. This project adheres to
|
|
4
|
+
[Semantic Versioning](https://semver.org/).
|
|
5
|
+
|
|
6
|
+
## 0.6.1 — 2026-06-27
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- **Ephemeral gists.** Publish an arbitrary file (usually Markdown) to a running
|
|
10
|
+
session and get a shareable preview URL — for agents that generate a doc and
|
|
11
|
+
want the user to read it.
|
|
12
|
+
- `POST /api/gists` `{content, filename?, title?, ttlSeconds?}` → `{id, url, rawUrl, expiresAt}`
|
|
13
|
+
- `GET /gist/:id` (rendered preview), `GET /gist/:id/raw`, `GET /gists` (list)
|
|
14
|
+
- **Editable & deletable** (GitHub-gist-shaped): `PATCH /api/gists/:id`,
|
|
15
|
+
`DELETE /api/gists/:id`, `GET /api/gists` (JSON list), an `/gist/:id/edit`
|
|
16
|
+
form, and Edit/Delete buttons on the preview page.
|
|
17
|
+
- CLI: `repoview gist <file>` (create) plus `gist edit <id> [file]`,
|
|
18
|
+
`gist delete <id>`, `gist list` — all also work via `--url` against a remote
|
|
19
|
+
server. Create/edit read from a file or stdin.
|
|
20
|
+
- Gists are **in memory only** (don't survive a restart) and expire after a TTL
|
|
21
|
+
(default 24h, clamped 1m–7d); capped at 1 MB / 500 gists.
|
|
22
|
+
- **`REPOVIEW_BASE_URL`** env var sets the absolute origin used in returned gist
|
|
23
|
+
URLs (so a remotely-running server returns clickable links). Falls back to the
|
|
24
|
+
request `Host` header.
|
|
25
|
+
- A **Gists** link in the top bar (and on the session page) → the `/gists` list.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- **Scoped live reload.** A page now reloads only for changes relevant to it: a
|
|
29
|
+
file view reloads on its exact file, a directory view on its direct children,
|
|
30
|
+
and repo-wide views (diff, broken-links) on any change. Previously any edit
|
|
31
|
+
reloaded every open page of that repo. Gist/session pages no longer live-reload
|
|
32
|
+
(their content is static), which also removes spurious reloads of open gist
|
|
33
|
+
tabs when the default repo changed.
|
|
34
|
+
- **Rewrote `--help`** to be comprehensive and agent-friendly: documents the
|
|
35
|
+
daemon lifecycle (first run is the foreground server; later runs exit), all
|
|
36
|
+
subcommands and their daemon/`--repo` requirements, the HTTP control + gist API
|
|
37
|
+
with example payloads, the page map, and env vars (incl. that
|
|
38
|
+
`REPOVIEW_BASE_URL` is read by the server, not the client).
|
|
39
|
+
|
|
40
|
+
## 0.6.0 — 2026-06-04
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
- **Shared multi-repo sessions (tmux-style).** Multiple `repoview` invocations on
|
|
44
|
+
the same port now join one server instead of each starting its own. The first
|
|
45
|
+
run starts the daemon; later runs register their repo and exit immediately — no
|
|
46
|
+
more remembering a port per repo. Each repo is served at `/r/<id>/…`.
|
|
47
|
+
- **Repo switcher** in the topbar and a **`/session` management page** to open,
|
|
48
|
+
add, and remove repos from the browser.
|
|
49
|
+
- **CLI session commands:** `repoview ls`, `repoview rm <id|path>`, `repoview stop`.
|
|
50
|
+
- **Control API:** `GET /api/session`, `GET/POST /api/repos`,
|
|
51
|
+
`DELETE /api/repos/:id`, `POST /api/shutdown` (mutations restricted to loopback).
|
|
52
|
+
- HTTP integration test suite (`npm test`, `node:test`) — runs without a browser.
|
|
53
|
+
|
|
54
|
+
### Changed
|
|
55
|
+
- **Default port is now `7376`** ("REPO" on a phone keypad) instead of `3000`, to
|
|
56
|
+
avoid colliding with common dev servers. Override with `--port` or `$PORT`.
|
|
57
|
+
- **Migrated the codebase to TypeScript** (strict). Sources compile to `dist/`;
|
|
58
|
+
the published package ships `dist/` and `bin` points at `dist/cli.js`.
|
|
59
|
+
- `startServer` was refactored into a session + per-repo context/router design;
|
|
60
|
+
each repo owns its own git info, gitignore matcher, link scanner, reload hub,
|
|
61
|
+
and file watcher.
|
|
62
|
+
- Playwright moved to `npm run test:e2e`; `npm test` is the browser-free suite.
|
|
63
|
+
|
|
64
|
+
### Security
|
|
65
|
+
- The session binds `0.0.0.0` by default, exposing every added repo to the
|
|
66
|
+
network. The server now **warns at startup** when bound to a non-loopback host,
|
|
67
|
+
and the `/session` page is **read-only** for non-loopback viewers. Use
|
|
68
|
+
`--host 127.0.0.1` to keep a session fully local.
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
- Markdown content links are prefixed with the repo base exactly once (guards a
|
|
72
|
+
double-rewrite during sanitization).
|
|
73
|
+
- Repo switcher dropdown stays on-screen on narrow viewports (left-anchored).
|
|
74
|
+
|
|
75
|
+
### Upgrade notes (0.5.x → 0.6.0)
|
|
76
|
+
- **Default port changed** from `3000` to `7376`. If you relied on the old
|
|
77
|
+
default, pass `--port 3000` (or set `$PORT`).
|
|
78
|
+
- **URLs are now repo-prefixed** (`/r/<id>/…`). Old bookmarks to `/tree/…`,
|
|
79
|
+
`/blob/…`, etc. still work — they redirect to the default repo — but the
|
|
80
|
+
canonical URL now includes the repo id.
|
|
81
|
+
- No data migration is needed; review threads under `.repoview/` are unchanged.
|
|
82
|
+
|
|
83
|
+
## 0.5.1
|
|
84
|
+
|
|
85
|
+
- Render Markdown frontmatter as a styled header.
|
|
86
|
+
- Inline code review threads; Playwright end-to-end suite.
|
|
87
|
+
</content>
|
package/CONTRIBUTING.md
CHANGED
|
@@ -11,13 +11,14 @@ npm install
|
|
|
11
11
|
## Run
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm start -- --repo /path/to/repo --port
|
|
14
|
+
npm start -- --repo /path/to/repo --port 7376
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
## Lint
|
|
17
|
+
## Lint & test
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
npm run lint
|
|
20
|
+
npm run lint # tsc --noEmit (strict type-check)
|
|
21
|
+
npm test # build + node:test HTTP integration suite
|
|
21
22
|
```
|
|
22
23
|
|
|
23
24
|
## What to work on
|
package/DEVELOPMENT.md
CHANGED
|
@@ -4,43 +4,94 @@ This doc collects the “how it works” details so `README.md` can stay product
|
|
|
4
4
|
|
|
5
5
|
## Project layout
|
|
6
6
|
|
|
7
|
-
- `src/server.
|
|
8
|
-
- `src/
|
|
9
|
-
- `src/
|
|
10
|
-
- `src/
|
|
11
|
-
- `src/
|
|
12
|
-
- `
|
|
7
|
+
- `src/server.ts`: Express app wiring — vendor static mounts, the control API, the `/r/:repoId` repos router, the `/session` page, and legacy redirects
|
|
8
|
+
- `src/session.ts`: a session owning multiple repos (add/remove/list, slug ids, default repo)
|
|
9
|
+
- `src/api.ts`: control API router (`/api/session`, `/api/repos`, `/api/shutdown`); mutations loopback-guarded
|
|
10
|
+
- `src/repo-context.ts`: per-repo runtime state (git info, gitignore matcher, link scanner, reload hub, file watcher)
|
|
11
|
+
- `src/repo-router.ts`: the per-repo routes (`/tree`, `/blob`, `/raw`, `/diff`, `/review`, `/events`, …) as a router that resolves `/r/:repoId` → a per-repo child router
|
|
12
|
+
- `src/net.ts`: loopback helpers (control-endpoint guard, bind-host check)
|
|
13
|
+
- `src/gists.ts` / `src/gist-router.ts`: in-memory ephemeral gist store (TTL, expiry sweeper) and its routes
|
|
14
|
+
- `src/types.ts`: shared interfaces (`RepoContext`, `Session`/`RepoSummary`, `GitInfo`, `MarkdownRenderer`, `LinkScanner`, …)
|
|
15
|
+
- `src/git.ts` / `src/paths.ts` / `src/format.ts` / `src/csv.ts` / `src/reload.ts`: extracted helpers (git CLI, path safety, byte/date formatting, CSV parsing, SSE reload hub)
|
|
16
|
+
- `src/markdown.ts`: Markdown rendering + link/image rewriting (repo-prefixed) + sanitization
|
|
17
|
+
- `src/linkcheck.ts`: broken-link scanner (Markdown → rendered HTML → internal link validation)
|
|
18
|
+
- `src/gitignore.ts`: `.gitignore` matcher (used for hiding + scanner noise reduction)
|
|
19
|
+
- `src/views.ts`: HTML templates (mobile-first top bar + repo switcher + GitHub-style Markdown shell)
|
|
20
|
+
- `public/`: CSS + client JS (live reload, KaTeX render, Mermaid render, diff collapse, query preservation, session management)
|
|
21
|
+
|
|
22
|
+
> See `docs/multi-repo-session.md` for the full multi-repo session design.
|
|
23
|
+
|
|
24
|
+
## TypeScript
|
|
25
|
+
|
|
26
|
+
The source is TypeScript (`src/*.ts`, `strict` mode). It compiles to `dist/` via
|
|
27
|
+
`tsc` and the published package ships `dist/` (the `bin` points at `dist/cli.js`).
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm run build # tsc → dist/
|
|
31
|
+
npm run lint # tsc --noEmit (type-check only)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`dist/` is git-ignored and rebuilt on `prepack` (so `npm pack` / `npm publish`
|
|
35
|
+
always ship a fresh build).
|
|
13
36
|
|
|
14
37
|
## Running locally
|
|
15
38
|
|
|
16
39
|
```bash
|
|
17
40
|
npm install
|
|
18
|
-
npm start -- --repo /path/to/repo --port
|
|
41
|
+
npm start -- --repo /path/to/repo --port 7376 # runs src via tsx (no build needed)
|
|
42
|
+
# or, after a build:
|
|
43
|
+
node dist/cli.js --repo /path/to/repo --port 7376
|
|
19
44
|
```
|
|
20
45
|
|
|
46
|
+
`npm start` / `npm run dev` use `tsx` to run the TypeScript directly for fast
|
|
47
|
+
iteration; `npm run build` produces the runnable `dist/` for publishing.
|
|
48
|
+
|
|
21
49
|
Useful flags:
|
|
22
50
|
- `--watch` / `--no-watch` (watch is on by default)
|
|
23
51
|
- `--host 127.0.0.1` to bind locally only
|
|
24
52
|
|
|
25
53
|
## Routes
|
|
26
54
|
|
|
55
|
+
Every repo is served behind a `/r/<id>` prefix (the repo's slug id). Legacy
|
|
56
|
+
non-prefixed paths (`/`, `/tree`, `/blob`, `/raw`, `/diff`, `/review`,
|
|
57
|
+
`/broken-links`, `/events`, `/rev`) redirect to the default (first) repo.
|
|
58
|
+
|
|
59
|
+
Per-repo routes (under `/r/<id>`):
|
|
27
60
|
- `GET /tree/<path>`: directory listing (applies `.gitignore` by default; `?ignored=1` shows ignored)
|
|
28
61
|
- `GET /blob/<path>`: file view (Markdown rendered; non-Markdown shown as highlighted text)
|
|
29
62
|
- `GET /raw/<path>`: raw bytes (used for images and downloads)
|
|
30
|
-
- `GET /events`: Server-Sent Events stream for live reload
|
|
63
|
+
- `GET /events`: Server-Sent Events stream for live reload (`GET /rev` is the polling fallback)
|
|
31
64
|
- `GET /diff`: diff view — compare working tree against a base ref (`?base=HEAD` default; accepts branches, tags)
|
|
32
|
-
- `GET /
|
|
33
|
-
- `GET /broken-links.json`:
|
|
65
|
+
- `GET /review/…`: code review threads
|
|
66
|
+
- `GET /broken-links[.json]`: broken internal link report
|
|
67
|
+
|
|
68
|
+
Session-level routes:
|
|
69
|
+
- `GET /session`: manage repos (open / add / remove); read-only for non-loopback clients
|
|
70
|
+
- `GET /api/session`: session signature + repo list (also the join handshake)
|
|
71
|
+
- `GET /api/repos`, `POST /api/repos`, `DELETE /api/repos/:id`, `POST /api/shutdown`: control API (mutations are loopback-only)
|
|
72
|
+
|
|
73
|
+
Gist routes (ephemeral published files, in-memory, default 24h TTL):
|
|
74
|
+
- `GET /api/gists`: list gists as JSON
|
|
75
|
+
- `POST /api/gists`: publish `{content, filename?, title?, ttlSeconds?}` → `{id, url, rawUrl, expiresAt}`
|
|
76
|
+
- `PATCH /api/gists/:id`: edit `{content?, filename?, title?, ttlSeconds?}` → updated gist
|
|
77
|
+
- `DELETE /api/gists/:id`: delete
|
|
78
|
+
- `GET /gist/:id`: rendered preview (Markdown or highlighted code) with Edit/Delete
|
|
79
|
+
- `GET /gist/:id/edit`: edit form
|
|
80
|
+
- `GET /gist/:id/raw`: raw source
|
|
81
|
+
- `GET /gists`: list of active gists
|
|
82
|
+
|
|
83
|
+
`REPOVIEW_BASE_URL` sets the absolute origin used in returned gist URLs (falls
|
|
84
|
+
back to the request `Host` header).
|
|
34
85
|
|
|
35
86
|
## Link rewriting rules
|
|
36
87
|
|
|
37
|
-
`src/markdown.
|
|
88
|
+
`src/markdown.ts` rewrites relative Markdown links so they stay inside the repo UI:
|
|
38
89
|
|
|
39
|
-
- Links →
|
|
40
|
-
- Images →
|
|
90
|
+
- Links → `<repoBase>/blob/<path>` (or `<repoBase>/tree/<path>` when the link ends with `/`), where `repoBase` is `/r/<id>`
|
|
91
|
+
- Images → `<repoBase>/raw/<path>`
|
|
41
92
|
- Same rewriting is applied to HTML inside Markdown (`<a href>`, `<img src>`) after sanitization.
|
|
42
93
|
- Paths that would escape the repo root (leading `../`) are clamped to the repo root (GitHub-like).
|
|
43
|
-
- Already-internal links (`/blob/…`, `/tree/…`, `/raw/…`, `/static
|
|
94
|
+
- Already-internal links (`/blob/…`, `/tree/…`, `/raw/…`, `/static/…`, and anything already under `repoBase`) are not rewritten again.
|
|
44
95
|
|
|
45
96
|
## Markdown “GitHub-like” features
|
|
46
97
|
|
|
@@ -65,9 +116,26 @@ Notes:
|
|
|
65
116
|
## Lint
|
|
66
117
|
|
|
67
118
|
```bash
|
|
68
|
-
npm run lint
|
|
119
|
+
npm run lint # tsc --noEmit — full strict type-check
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Tests
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npm test # build + node:test HTTP integration suite (no browser needed)
|
|
126
|
+
npm run test:e2e # Playwright browser suite (requires installed browsers)
|
|
69
127
|
```
|
|
70
128
|
|
|
129
|
+
- `tests/integration/*.test.mjs` boots the server in-process (from `dist/`) and
|
|
130
|
+
drives it over HTTP — covering the session API, `/r/<id>` routing, legacy
|
|
131
|
+
redirects, repo registration/idempotency/slug-disambiguation, the session
|
|
132
|
+
page, and the unknown-repo fallback. This is the default `npm test` and runs
|
|
133
|
+
anywhere.
|
|
134
|
+
- The Playwright suite (`tests/frontend.spec.js`) covers the rich browsing/review
|
|
135
|
+
UI in a real browser; it needs `npx playwright install` and is run as
|
|
136
|
+
`test:e2e`. New multi-repo flows are exercised via the Chrome DevTools MCP
|
|
137
|
+
(see `docs/multi-repo-session.md`).
|
|
138
|
+
|
|
71
139
|
## Release checklist
|
|
72
140
|
|
|
73
141
|
Before publishing to npm, run a quick smoke test from a clean install context (this catches issues where the server accidentally serves assets from the *repo* instead of the installed package):
|
|
@@ -83,5 +151,5 @@ npm init -y
|
|
|
83
151
|
npm install /path/to/repoview-*.tgz
|
|
84
152
|
|
|
85
153
|
# serve any repo and verify vendor assets load (no ENOENT)
|
|
86
|
-
node ./node_modules/.bin/repoview --repo /path/to/repo --port
|
|
154
|
+
node ./node_modules/.bin/repoview --repo /path/to/repo --port 7376
|
|
87
155
|
```
|
package/README.md
CHANGED
|
@@ -14,28 +14,94 @@ Not affiliated with GitHub.
|
|
|
14
14
|
- Live reload when files change (SSE with polling fallback)
|
|
15
15
|
- Broken internal link discovery for docs (`/broken-links`)
|
|
16
16
|
- Respects `.gitignore` by default (toggleable)
|
|
17
|
+
- Shared sessions (like tmux): run `repoview` in several repos on the same port and browse them all from one server, switching between them in the UI
|
|
17
18
|
|
|
18
19
|
## Quick start (from source)
|
|
19
20
|
|
|
20
21
|
```bash
|
|
21
22
|
npm install
|
|
22
|
-
npm start -- --repo /path/to/your/repo --port
|
|
23
|
+
npm start -- --repo /path/to/your/repo --port 7376
|
|
23
24
|
```
|
|
24
25
|
|
|
25
|
-
Then open `http://localhost:
|
|
26
|
+
Then open `http://localhost:7376`.
|
|
26
27
|
|
|
27
28
|
## Quick start (npx)
|
|
28
29
|
|
|
29
30
|
From anywhere:
|
|
30
31
|
|
|
31
32
|
```bash
|
|
32
|
-
npx repoview --repo /path/to/your/repo --port
|
|
33
|
+
npx repoview --repo /path/to/your/repo --port 7376
|
|
33
34
|
```
|
|
34
35
|
|
|
35
36
|
By default, `repoview` binds to `0.0.0.0` (LAN-accessible). For localhost-only:
|
|
36
37
|
|
|
37
38
|
```bash
|
|
38
|
-
npx repoview --repo /path/to/your/repo --host 127.0.0.1 --port
|
|
39
|
+
npx repoview --repo /path/to/your/repo --host 127.0.0.1 --port 7376
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Shared sessions (multi-repo)
|
|
43
|
+
|
|
44
|
+
The first `repoview` on a port starts a server; later runs on the **same port**
|
|
45
|
+
join it instead of failing — they register their repo and exit immediately
|
|
46
|
+
(no need to remember a port per repo):
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
cd ~/work/api && repoview # starts the session on :7376
|
|
50
|
+
cd ~/work/web && repoview # joins :7376, registers, exits
|
|
51
|
+
cd ~/work/docs && repoview # joins :7376, registers, exits
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Each repo is served at `/r/<id>/…`; switch between them from the dropdown in the
|
|
55
|
+
top bar, or open **Manage repos…** (the `/session` page) to add/remove repos
|
|
56
|
+
from the browser. Manage the session from the CLI too:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
repoview ls # list repos in the session
|
|
60
|
+
repoview rm <id|path> # unregister a repo
|
|
61
|
+
repoview stop # shut the session down
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Use `--port` to run independent sessions side by side.
|
|
65
|
+
|
|
66
|
+
> **Note:** by default the session binds `0.0.0.0`, so **every repo you add is
|
|
67
|
+
> browsable by anyone on the network** (you'll see a warning at startup). Session
|
|
68
|
+
> control endpoints (register / remove / stop) are restricted to localhost, and
|
|
69
|
+
> the `/session` page is read-only for remote viewers. Use `--host 127.0.0.1` to
|
|
70
|
+
> keep a session fully local.
|
|
71
|
+
|
|
72
|
+
## Gists (ephemeral file previews)
|
|
73
|
+
|
|
74
|
+
Publish an arbitrary file (usually Markdown) to a running session and get a
|
|
75
|
+
shareable preview URL — handy for agents that generate a doc and want the user to
|
|
76
|
+
read it. Gists live **in memory only** (they don't survive a restart) and expire
|
|
77
|
+
after a TTL (default **24h**).
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
repoview gist NOTES.md --title "Release plan" # prints a preview URL
|
|
81
|
+
cat report.md | repoview gist --filename report.md # from stdin
|
|
82
|
+
repoview gist out.md --ttl 2h # custom TTL (1m–7d)
|
|
83
|
+
repoview gist edit <id> NOTES.md # replace content
|
|
84
|
+
repoview gist delete <id> # delete
|
|
85
|
+
repoview gist list # list active gists
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Gists are **editable and deletable** (like GitHub gists): the preview page has
|
|
89
|
+
Edit/Delete buttons, and the HTTP API supports `PATCH`/`DELETE /api/gists/:id`.
|
|
90
|
+
|
|
91
|
+
Or over HTTP (e.g. from a remote agent):
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
curl -X POST "$BASE/api/gists" -H 'content-type: application/json' \
|
|
95
|
+
-d '{"content":"# Hi","filename":"hi.md","ttlSeconds":3600}'
|
|
96
|
+
# → { "url": "…/gist/<id>", "rawUrl": "…/gist/<id>/raw", "expiresAt": "…" }
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
All gists are listed at **`/gists`** (linked from the top bar) so the user can
|
|
100
|
+
always find them. Set **`REPOVIEW_BASE_URL`** so a remotely-running server returns
|
|
101
|
+
absolute, clickable URLs:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
REPOVIEW_BASE_URL=https://repoview.example.com repoview --host 0.0.0.0
|
|
39
105
|
```
|
|
40
106
|
|
|
41
107
|
## Why
|
|
@@ -47,7 +113,7 @@ npx repoview --repo /path/to/your/repo --host 127.0.0.1 --port 3000
|
|
|
47
113
|
## Usage
|
|
48
114
|
|
|
49
115
|
```bash
|
|
50
|
-
npm start -- [--repo /path/to/repo] [--host 0.0.0.0] [--port
|
|
116
|
+
npm start -- [--repo /path/to/repo] [--host 0.0.0.0] [--port 7376] [--no-watch]
|
|
51
117
|
```
|
|
52
118
|
|
|
53
119
|
Common flags:
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { isLoopbackAddress } from "./net.js";
|
|
3
|
+
/** Restrict a mutating control endpoint to loopback clients. */
|
|
4
|
+
function requireLoopback(req, res, next) {
|
|
5
|
+
if (isLoopbackAddress(req.socket.remoteAddress))
|
|
6
|
+
return next();
|
|
7
|
+
res.status(403).json({ error: "Control endpoints are restricted to localhost" });
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The session control API. `GET /api/session` doubles as the join-handshake
|
|
11
|
+
* signature; mutating routes (register/unregister/shutdown) are loopback-only.
|
|
12
|
+
*/
|
|
13
|
+
export function createApiRouter(session, { version, onShutdown }) {
|
|
14
|
+
const router = express.Router();
|
|
15
|
+
router.get("/session", (req, res) => {
|
|
16
|
+
res.json({ app: "repoview", version, repos: session.listRepos() });
|
|
17
|
+
});
|
|
18
|
+
router.get("/repos", (req, res) => {
|
|
19
|
+
res.json({ repos: session.listRepos() });
|
|
20
|
+
});
|
|
21
|
+
router.post("/repos", requireLoopback, express.json(), async (req, res) => {
|
|
22
|
+
try {
|
|
23
|
+
const repoRoot = req.body?.path;
|
|
24
|
+
if (!repoRoot || typeof repoRoot !== "string") {
|
|
25
|
+
return res.status(400).json({ error: "path is required" });
|
|
26
|
+
}
|
|
27
|
+
const watch = req.body?.watch !== false;
|
|
28
|
+
const ctx = await session.addRepo({ repoRoot, watch });
|
|
29
|
+
res.status(201).json({
|
|
30
|
+
id: ctx.id,
|
|
31
|
+
name: ctx.repoName,
|
|
32
|
+
path: ctx.repoRootReal,
|
|
33
|
+
url: `/r/${ctx.id}/tree/`,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
catch (e) {
|
|
37
|
+
res.status(500).json({ error: e.message });
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
router.delete("/repos/:id", requireLoopback, async (req, res) => {
|
|
41
|
+
try {
|
|
42
|
+
const removed = await session.removeRepo(req.params.id);
|
|
43
|
+
if (!removed)
|
|
44
|
+
return res.status(404).json({ error: "Repo not found" });
|
|
45
|
+
res.json({ ok: true, id: removed.id });
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
res.status(500).json({ error: e.message });
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
router.post("/shutdown", requireLoopback, (req, res) => {
|
|
52
|
+
res.json({ ok: true });
|
|
53
|
+
// Defer so the response flushes before the process tears down.
|
|
54
|
+
setTimeout(onShutdown, 50);
|
|
55
|
+
});
|
|
56
|
+
return router;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|