wiki-viewer 1.8.3 → 1.9.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 (77) hide show
  1. package/.next/standalone/.next/BUILD_ID +1 -1
  2. package/.next/standalone/.next/build-manifest.json +3 -3
  3. package/.next/standalone/.next/server/app/_global-error.html +1 -1
  4. package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
  5. package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  6. package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  7. package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  8. package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  9. package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  10. package/.next/standalone/.next/server/app/_not-found.html +1 -1
  11. package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
  12. package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  13. package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  14. package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  15. package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  16. package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  17. package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  18. package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
  19. package/.next/standalone/.next/server/app/index.html +1 -1
  20. package/.next/standalone/.next/server/app/index.rsc +2 -2
  21. package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  22. package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
  23. package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
  24. package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
  25. package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  26. package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
  27. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00lep-u._.js +1 -1
  28. package/.next/standalone/.next/server/chunks/[root-of-the-server]__00qu86p._.js +1 -1
  29. package/.next/standalone/.next/server/chunks/[root-of-the-server]__036mhjp._.js +2 -2
  30. package/.next/standalone/.next/server/chunks/[root-of-the-server]__05t~v6l._.js +1 -1
  31. package/.next/standalone/.next/server/chunks/[root-of-the-server]__09cqzem._.js +1 -1
  32. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0_0_601._.js +1 -1
  33. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ae3dk6._.js +1 -1
  34. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0d7x3e1._.js +1 -1
  35. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0e7vs98._.js +1 -1
  36. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0fxzg4v._.js +1 -1
  37. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0gda_iu._.js +1 -1
  38. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0hu~q20._.js +1 -1
  39. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0l-8clq._.js +1 -1
  40. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0otb8ra._.js +1 -1
  41. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0p0-p__._.js +1 -1
  42. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0piofm3._.js +1 -1
  43. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0rrf-jr._.js +1 -1
  44. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0s6_lzw._.js +1 -1
  45. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0sh13v5._.js +1 -1
  46. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ta~flu._.js +1 -1
  47. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0v4im4p._.js +1 -1
  48. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vatqe-._.js +1 -1
  49. package/.next/standalone/.next/server/chunks/[root-of-the-server]__0vdb2nr._.js +1 -1
  50. package/.next/standalone/.next/server/chunks/[root-of-the-server]__123._fe._.js +1 -1
  51. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1377.79._.js +1 -1
  52. package/.next/standalone/.next/server/chunks/[root-of-the-server]__1378-ox._.js +1 -1
  53. package/.next/standalone/.next/server/chunks/[root-of-the-server]__13hp4tw._.js +2 -2
  54. package/.next/standalone/.next/server/chunks/node_modules__pnpm_0aj5g-w._.js +1 -1
  55. package/.next/standalone/.next/server/chunks/ssr/_0pqaawz._.js +1 -1
  56. package/.next/standalone/.next/server/edge/chunks/0p91_next_dist_0nh.6nc._.js +2 -2
  57. package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
  58. package/.next/standalone/.next/server/middleware-manifest.json +1 -1
  59. package/.next/standalone/.next/server/pages/404.html +1 -1
  60. package/.next/standalone/.next/server/pages/500.html +1 -1
  61. package/.next/standalone/.next/static/chunks/{0d~o0h0ssgra7.js → 125_k3o0s4cid.js} +1 -1
  62. package/.next/standalone/README.md +4 -3
  63. package/.next/standalone/bin/wiki-viewer.js +6 -3
  64. package/.next/standalone/package.json +1 -1
  65. package/.next/standalone/src/app/page.tsx +8 -6
  66. package/.next/standalone/src/lib/auth/admin.ts +8 -0
  67. package/.next/standalone/src/lib/workspace-context.ts +13 -0
  68. package/.next/standalone/src/middleware.ts +5 -0
  69. package/.next/standalone/src/stores/pin-store.ts +1 -0
  70. package/.next/standalone/src/stores/recent-store.ts +1 -0
  71. package/.next/standalone/tsconfig.tsbuildinfo +1 -1
  72. package/README.md +4 -3
  73. package/bin/wiki-viewer.js +6 -3
  74. package/package.json +1 -1
  75. /package/.next/standalone/.next/static/{Pkj31aCfRVk0Zy2rKA1wf → YQHDns_jLqFd_bbnLafs0}/_buildManifest.js +0 -0
  76. /package/.next/standalone/.next/static/{Pkj31aCfRVk0Zy2rKA1wf → YQHDns_jLqFd_bbnLafs0}/_clientMiddlewareManifest.js +0 -0
  77. /package/.next/standalone/.next/static/{Pkj31aCfRVk0Zy2rKA1wf → YQHDns_jLqFd_bbnLafs0}/_ssgManifest.js +0 -0
@@ -32,6 +32,7 @@ function printUsage() {
32
32
  console.error(" -p, --port <port> Port to listen on (default: 3000)");
33
33
  console.error(" -H, --host <host> Host to bind to (default: localhost)");
34
34
  console.error(" --https Enable HTTPS (self-signed cert, enables service workers)");
35
+ console.error(" --no-auth Run without authentication — no sign-in, no session check");
35
36
  console.error("");
36
37
  console.error(" -e, --env <KEY=VALUE> Set an app env var (repeatable; persisted with service install)");
37
38
  console.error("");
@@ -67,6 +68,7 @@ function parseServeArgs(args) {
67
68
  let useHttps;
68
69
  let userSpecifiedPort = false;
69
70
  let rootDir;
71
+ let noAuth;
70
72
 
71
73
  for (let i = 0; i < args.length; i++) {
72
74
  const a = args[i];
@@ -74,10 +76,11 @@ function parseServeArgs(args) {
74
76
  else if (a === "-H" || a === "--host") host = args[++i] ?? host;
75
77
  else if (a === "-e" || a === "--env") { i++; } // consumed by parseEnvFlags
76
78
  else if (a === "--https") useHttps = true;
79
+ else if (a === "--no-auth") noAuth = true;
77
80
  else if (!a.startsWith("-") && rootDir === undefined) rootDir = a;
78
81
  }
79
82
 
80
- return { rootDir, port, host, useHttps, userSpecifiedPort };
83
+ return { rootDir, port, host, useHttps, userSpecifiedPort, noAuth: Boolean(noAuth) };
81
84
  }
82
85
 
83
86
  // ── config file ────────────────────────────────────────────────────────────
@@ -111,7 +114,7 @@ function resolveServeOptions(args) {
111
114
  useHttps: Boolean(cli.useHttps),
112
115
  userSpecifiedPort: cli.userSpecifiedPort,
113
116
  // App env: config.env as base, ad-hoc --env flags override per run.
114
- configEnv: { ...(cfg.env ?? {}), ...parseEnvFlags(args) },
117
+ configEnv: { ...(cfg.env ?? {}), ...(cli.noAuth ? { WIKI_NO_AUTH: "1" } : {}), ...parseEnvFlags(args) },
115
118
  };
116
119
  }
117
120
 
@@ -135,7 +138,7 @@ function resolveRunOptions(args) {
135
138
  host,
136
139
  useHttps: Boolean(useHttps),
137
140
  userSpecifiedPort,
138
- configEnv: { ...(cfg.env ?? {}), ...parseEnvFlags(args) },
141
+ configEnv: { ...(cfg.env ?? {}), ...(cli.noAuth ? { WIKI_NO_AUTH: "1" } : {}), ...parseEnvFlags(args) },
139
142
  };
140
143
  }
141
144
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-viewer",
3
- "version": "1.8.3",
3
+ "version": "1.9.0",
4
4
  "description": "Local file viewer and wiki — view markdown, HTML, PDFs, notebooks, office docs, and more from any directory",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -292,7 +292,7 @@ export default function Page() {
292
292
  // Recent files
293
293
  const recents = useRecentStore((s) => s.recents);
294
294
  const [pinnedCollapsed, setPinnedCollapsed] = useState(false);
295
- const [recentCollapsed, setRecentCollapsed] = useState(false);
295
+ const [recentCollapsed, setRecentCollapsed] = useState(true);
296
296
 
297
297
  // Pins
298
298
  const pins = usePinStore((s) => s.pins);
@@ -1350,7 +1350,7 @@ export default function Page() {
1350
1350
  onClick={() =>
1351
1351
  usePinStore
1352
1352
  .getState()
1353
- .toggle({ path: node.path, name: node.name }, activeWorkspaceId)
1353
+ .toggle({ path: node.path, name: node.name, type: (node.type === "dir" ? "file" : node.type) as "file" | "app" | "node-app" }, activeWorkspaceId)
1354
1354
  }
1355
1355
  >
1356
1356
  <Star className={cn("mr-2 h-3.5 w-3.5", isNodePinned && "fill-current text-amber-400")} />
@@ -1783,6 +1783,7 @@ export default function Page() {
1783
1783
  {pinnedCollapsed ? <ChevronRight className="h-3 w-3" /> : <ChevronDown className="h-3 w-3" />}
1784
1784
  <Pin className="h-3 w-3" />
1785
1785
  Pinned
1786
+ <span className="ml-auto text-[9px] tabular-nums opacity-60">{pins.length}</span>
1786
1787
  </button>
1787
1788
  {!pinnedCollapsed && pins.map((p) => (
1788
1789
  <div
@@ -1793,8 +1794,8 @@ export default function Page() {
1793
1794
  "group flex items-center gap-1.5 rounded-sm px-2 py-1 text-sm cursor-pointer transition-colors select-none",
1794
1795
  openFile?.path === p.path ? "bg-accent-soft text-foreground font-medium" : "hover:bg-muted",
1795
1796
  )}
1796
- onClick={() => void openViewer({ path: p.path, name: p.name, type: "file", modifiedAt: "" } as TreeNode)}
1797
- onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); void openViewer({ path: p.path, name: p.name, type: "file", modifiedAt: "" } as TreeNode); } }}
1797
+ onClick={() => void openViewer({ path: p.path, name: p.name, type: (p.type ?? "file") as TreeNode["type"], modifiedAt: "" } as TreeNode)}
1798
+ onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); void openViewer({ path: p.path, name: p.name, type: (p.type ?? "file") as TreeNode["type"], modifiedAt: "" } as TreeNode); } }}
1798
1799
  >
1799
1800
  <Star className="h-3 w-3 shrink-0 fill-current text-amber-400" />
1800
1801
  <span className="min-w-0 flex-1 truncate text-xs">{p.name}</span>
@@ -1826,6 +1827,7 @@ export default function Page() {
1826
1827
  >
1827
1828
  {recentCollapsed ? <ChevronRight className="h-3 w-3" /> : <ChevronDown className="h-3 w-3" />}
1828
1829
  Recent
1830
+ <span className="ml-auto text-[9px] tabular-nums opacity-60">{recents.length}</span>
1829
1831
  </button>
1830
1832
  {!recentCollapsed && recents.slice(0, 8).map((r) => (
1831
1833
  <div
@@ -1836,8 +1838,8 @@ export default function Page() {
1836
1838
  "flex items-center gap-1.5 rounded-sm px-2 py-1 text-sm cursor-pointer transition-colors select-none",
1837
1839
  openFile?.path === r.path ? "bg-accent-soft text-foreground font-medium" : "hover:bg-muted",
1838
1840
  )}
1839
- onClick={() => void openViewer({ path: r.path, name: r.name, type: "file", modifiedAt: "" } as TreeNode)}
1840
- onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); void openViewer({ path: r.path, name: r.name, type: "file", modifiedAt: "" } as TreeNode); } }}
1841
+ onClick={() => void openViewer({ path: r.path, name: r.name, type: (r.type ?? "file") as TreeNode["type"], modifiedAt: "" } as TreeNode)}
1842
+ onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); void openViewer({ path: r.path, name: r.name, type: (r.type ?? "file") as TreeNode["type"], modifiedAt: "" } as TreeNode); } }}
1841
1843
  >
1842
1844
  <FileText className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
1843
1845
  <span className="flex-1 truncate text-xs">{r.name}</span>
@@ -102,6 +102,14 @@ export async function requireAdmin(
102
102
  | { ok: true; user: { id: string; email: string; name: string } }
103
103
  | { ok: false; status: number; code: string }
104
104
  > {
105
+ // --no-auth bypass
106
+ if (process.env.WIKI_NO_AUTH === "1") {
107
+ return {
108
+ ok: true,
109
+ user: { id: "local", email: "local@localhost", name: "local" },
110
+ };
111
+ }
112
+
105
113
  const auth = await requireUser(req);
106
114
  if (!auth.ok) return { ok: false, status: 401, code: "UNAUTHORIZED" };
107
115
 
@@ -85,6 +85,19 @@ export interface WorkspaceError {
85
85
  export async function resolveWorkspaceForUser(
86
86
  req: Request,
87
87
  ): Promise<WorkspaceContext | WorkspaceError> {
88
+ // --no-auth bypass
89
+ if (process.env.WIKI_NO_AUTH === "1") {
90
+ const ws = await pickWorkspace(req);
91
+ if (!ws) {
92
+ return {
93
+ ok: false,
94
+ status: 400,
95
+ code: "WORKSPACE_REQUIRED",
96
+ };
97
+ }
98
+ return { ok: true, ws, rootDir: ws.rootDir, userId: "local", isAdmin: true };
99
+ }
100
+
88
101
  // Authenticate
89
102
  const auth = await requireUser(req);
90
103
  if (!auth.ok) return { ok: false, status: 401, code: "UNAUTHORIZED" };
@@ -18,6 +18,11 @@ export function middleware(req: NextRequest): NextResponse {
18
18
  return NextResponse.next();
19
19
  }
20
20
 
21
+ // --no-auth skip
22
+ if (process.env.WIKI_NO_AUTH === "1") {
23
+ return NextResponse.next();
24
+ }
25
+
21
26
  // Cheap presence check; real session validation happens in individual routes.
22
27
  // Cookie name from better-auth default: "better-auth.session_token"
23
28
  const sessionCookie =
@@ -4,6 +4,7 @@ import { create } from "zustand";
4
4
  export interface PinnedEntry {
5
5
  path: string;
6
6
  name: string;
7
+ type?: "file" | "app" | "node-app";
7
8
  }
8
9
 
9
10
  interface PinState {
@@ -4,6 +4,7 @@ import { create } from "zustand";
4
4
  export interface RecentEntry {
5
5
  path: string;
6
6
  name: string;
7
+ type?: "file" | "app" | "node-app";
7
8
  }
8
9
 
9
10
  interface RecentState {