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.
Files changed (57) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/CONTRIBUTING.md +4 -3
  3. package/DEVELOPMENT.md +84 -16
  4. package/README.md +71 -5
  5. package/dist/api.js +58 -0
  6. package/dist/api.js.map +1 -0
  7. package/dist/cli.js +454 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/csv.js +64 -0
  10. package/dist/csv.js.map +1 -0
  11. package/dist/format.js +25 -0
  12. package/dist/format.js.map +1 -0
  13. package/dist/gist-router.js +153 -0
  14. package/dist/gist-router.js.map +1 -0
  15. package/dist/gists.js +130 -0
  16. package/dist/gists.js.map +1 -0
  17. package/dist/git.js +67 -0
  18. package/dist/git.js.map +1 -0
  19. package/dist/gitignore.js +34 -0
  20. package/dist/gitignore.js.map +1 -0
  21. package/dist/linkcheck.js +310 -0
  22. package/dist/linkcheck.js.map +1 -0
  23. package/dist/markdown.js +493 -0
  24. package/dist/markdown.js.map +1 -0
  25. package/dist/net.js +10 -0
  26. package/dist/net.js.map +1 -0
  27. package/dist/paths.js +59 -0
  28. package/dist/paths.js.map +1 -0
  29. package/dist/reload.js +55 -0
  30. package/dist/reload.js.map +1 -0
  31. package/dist/repo-context.js +80 -0
  32. package/dist/repo-context.js.map +1 -0
  33. package/dist/repo-router.js +810 -0
  34. package/dist/repo-router.js.map +1 -0
  35. package/dist/review-cli.js +228 -0
  36. package/dist/review-cli.js.map +1 -0
  37. package/dist/server.js +122 -0
  38. package/dist/server.js.map +1 -0
  39. package/dist/session.js +86 -0
  40. package/dist/session.js.map +1 -0
  41. package/dist/types.js +2 -0
  42. package/dist/types.js.map +1 -0
  43. package/dist/views.js +780 -0
  44. package/dist/views.js.map +1 -0
  45. package/package.json +20 -9
  46. package/public/app.css +113 -0
  47. package/public/app.js +26 -3
  48. package/public/gist.js +60 -0
  49. package/public/review.js +9 -6
  50. package/public/session.js +61 -0
  51. package/src/cli.js +0 -91
  52. package/src/gitignore.js +0 -34
  53. package/src/linkcheck.js +0 -312
  54. package/src/markdown.js +0 -518
  55. package/src/review-cli.js +0 -245
  56. package/src/server.js +0 -1126
  57. package/src/views.js +0 -657
package/dist/reload.js ADDED
@@ -0,0 +1,55 @@
1
+ /** Parent directory of a repo-relative posix path ("" for a top-level file). */
2
+ function dirOf(p) {
3
+ const i = p.lastIndexOf("/");
4
+ return i === -1 ? "" : p.slice(0, i);
5
+ }
6
+ function scopeMatches(scope, changedPaths) {
7
+ switch (scope.type) {
8
+ case "all":
9
+ return true;
10
+ case "file":
11
+ return changedPaths.includes(scope.path);
12
+ case "dir":
13
+ return changedPaths.some((p) => dirOf(p) === scope.path);
14
+ }
15
+ }
16
+ export function createReloadHub() {
17
+ const clients = new Map();
18
+ let revision = 0;
19
+ return {
20
+ add(res, scope = { type: "all" }) {
21
+ clients.set(res, scope);
22
+ res.on("close", () => clients.delete(res));
23
+ },
24
+ notify(changedPaths) {
25
+ // Bump the revision unconditionally so the polling fallback (/rev) still
26
+ // detects changes, even though SSE delivery is scoped per client.
27
+ revision++;
28
+ const payload = `event: reload\ndata: ${Date.now()}\n\n`;
29
+ for (const [res, scope] of clients) {
30
+ if (scopeMatches(scope, changedPaths))
31
+ res.write(payload);
32
+ }
33
+ },
34
+ getRevision() {
35
+ return revision;
36
+ },
37
+ broadcastPing() {
38
+ const payload = `event: ping\ndata: ${Date.now()}\n\n`;
39
+ for (const res of clients.keys())
40
+ res.write(payload);
41
+ },
42
+ close() {
43
+ for (const res of clients.keys()) {
44
+ try {
45
+ res.end();
46
+ }
47
+ catch {
48
+ // ignore
49
+ }
50
+ }
51
+ clients.clear();
52
+ },
53
+ };
54
+ }
55
+ //# sourceMappingURL=reload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reload.js","sourceRoot":"","sources":["../src/reload.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,SAAS,KAAK,CAAC,CAAS;IACtB,MAAM,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,YAAY,CAAC,KAAkB,EAAE,YAAsB;IAC9D,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,KAAK;YACR,OAAO,IAAI,CAAC;QACd,KAAK,MAAM;YACT,OAAO,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3C,KAAK,KAAK;YACR,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;IAClD,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,OAAO;QACL,GAAG,CAAC,GAAG,EAAE,KAAK,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE;YAC9B,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YACxB,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,MAAM,CAAC,YAAY;YACjB,yEAAyE;YACzE,kEAAkE;YAClE,QAAQ,EAAE,CAAC;YACX,MAAM,OAAO,GAAG,wBAAwB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;YACzD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,OAAO,EAAE,CAAC;gBACnC,IAAI,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC;oBAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QACD,WAAW;YACT,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,aAAa;YACX,MAAM,OAAO,GAAG,sBAAsB,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;YACvD,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE;gBAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACvD,CAAC;QACD,KAAK;YACH,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;gBACjC,IAAI,CAAC;oBACH,GAAG,CAAC,GAAG,EAAE,CAAC;gBACZ,CAAC;gBAAC,MAAM,CAAC;oBACP,SAAS;gBACX,CAAC;YACH,CAAC;YACD,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,80 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import chokidar from "chokidar";
4
+ import { loadGitIgnoreMatcher } from "./gitignore.js";
5
+ import { createRepoLinkScanner } from "./linkcheck.js";
6
+ import { getGitInfo } from "./git.js";
7
+ import { createReloadHub } from "./reload.js";
8
+ import { toPosixPath } from "./paths.js";
9
+ /**
10
+ * Build the per-repo runtime state. Each context owns its own git info,
11
+ * gitignore matcher, link scanner, review dir, reload hub and (optionally) a
12
+ * filesystem watcher. The markdown renderer is shared across repos and passed in.
13
+ */
14
+ export async function createRepoContext({ id, repoRoot, md, watch = true, }) {
15
+ const repoRootReal = await fs.realpath(repoRoot);
16
+ const repoName = path.basename(repoRootReal);
17
+ const gitInfo = await getGitInfo(repoRootReal);
18
+ const reloadHub = createReloadHub();
19
+ const reviewDir = path.join(repoRootReal, ".repoview", "reviews");
20
+ const ctx = {
21
+ id: id ?? repoName,
22
+ repoRootReal,
23
+ repoName,
24
+ gitInfo,
25
+ reloadHub,
26
+ reviewDir,
27
+ md,
28
+ ignoreMatcher: await loadGitIgnoreMatcher(repoRootReal),
29
+ isIgnored: () => false,
30
+ linkScanner: undefined,
31
+ watcher: null,
32
+ close: async () => { },
33
+ };
34
+ ctx.isIgnored = (relPosix, opts) => ctx.ignoreMatcher.ignores(relPosix, opts);
35
+ ctx.linkScanner = createRepoLinkScanner({
36
+ repoRootReal,
37
+ markdownRenderer: md,
38
+ isIgnored: ctx.isIgnored,
39
+ });
40
+ void ctx.linkScanner.triggerScan();
41
+ if (watch) {
42
+ const watcher = chokidar.watch(repoRootReal, {
43
+ ignored: [
44
+ /(^|[/\\])\.git([/\\]|$)/,
45
+ /(^|[/\\])node_modules([/\\]|$)/,
46
+ /(^|[/\\])\.repoview([/\\]|$)/,
47
+ ],
48
+ ignoreInitial: true,
49
+ ignorePermissionErrors: true,
50
+ });
51
+ watcher.on("error", () => {
52
+ // Silently ignore watch errors (e.g., permission denied)
53
+ });
54
+ let pending = null;
55
+ const changed = new Set();
56
+ watcher.on("all", (_event, changedPath) => {
57
+ if (typeof changedPath === "string") {
58
+ changed.add(toPosixPath(path.relative(repoRootReal, changedPath)));
59
+ }
60
+ if (pending)
61
+ return;
62
+ pending = setTimeout(() => {
63
+ pending = null;
64
+ const paths = [...changed];
65
+ changed.clear();
66
+ reloadHub.notify(paths);
67
+ void loadGitIgnoreMatcher(repoRootReal).then((m) => (ctx.ignoreMatcher = m));
68
+ void ctx.linkScanner.triggerScan();
69
+ }, 100);
70
+ });
71
+ ctx.watcher = watcher;
72
+ }
73
+ ctx.close = async () => {
74
+ reloadHub.close();
75
+ if (ctx.watcher)
76
+ await ctx.watcher.close();
77
+ };
78
+ return ctx;
79
+ }
80
+ //# sourceMappingURL=repo-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-context.js","sourceRoot":"","sources":["../src/repo-context.ts"],"names":[],"mappings":"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"}