@karmaniverous/jeeves-server 3.0.0-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.
- package/.env.local +13 -0
- package/.env.local.template +13 -0
- package/.tsbuildinfo +1 -0
- package/CHANGELOG.md +450 -0
- package/about.md +82 -0
- package/client/README.md +73 -0
- package/client/eslint.config.js +23 -0
- package/client/index.html +14 -0
- package/client/package-lock.json +5181 -0
- package/client/package.json +60 -0
- package/client/public/vite.svg +1 -0
- package/client/src/App.tsx +22 -0
- package/client/src/components/AccountMenu.tsx +167 -0
- package/client/src/components/ActionDropdown.tsx +120 -0
- package/client/src/components/CodeEditor.tsx +143 -0
- package/client/src/components/CodeViewer.tsx +113 -0
- package/client/src/components/ConfirmDialog.tsx +32 -0
- package/client/src/components/DirectoryRow.tsx +62 -0
- package/client/src/components/DirectoryTable.tsx +42 -0
- package/client/src/components/DownloadDropdown.tsx +116 -0
- package/client/src/components/DriveList.tsx +54 -0
- package/client/src/components/EmbeddedDiagramPanzoom.ts +28 -0
- package/client/src/components/FileContentView.tsx +155 -0
- package/client/src/components/InlineSvgPanzoom.ts +60 -0
- package/client/src/components/LazyDiagram.ts +93 -0
- package/client/src/components/LinkDropdown.tsx +134 -0
- package/client/src/components/MarkdownView.tsx +115 -0
- package/client/src/components/MermaidViewer.tsx +21 -0
- package/client/src/components/PlantUmlViewer.tsx +21 -0
- package/client/src/components/SearchModal.tsx +424 -0
- package/client/src/components/SvgViewer.tsx +107 -0
- package/client/src/components/TabBar.tsx +96 -0
- package/client/src/components/layout/Header.tsx +270 -0
- package/client/src/components/panzoom.ts +203 -0
- package/client/src/components/renderableUtils.ts +15 -0
- package/client/src/components/runner/JobTable.tsx +153 -0
- package/client/src/components/runner/RunHistory.tsx +140 -0
- package/client/src/components/runner/StatsBar.tsx +43 -0
- package/client/src/components/runner/StatusPill.tsx +27 -0
- package/client/src/components/runner/jobTableUtils.ts +65 -0
- package/client/src/components/scrollUtils.ts +39 -0
- package/client/src/components/ui/alert-dialog.tsx +107 -0
- package/client/src/components/ui/button.tsx +40 -0
- package/client/src/components/ui/dropdown-menu.tsx +79 -0
- package/client/src/components/ui/input.tsx +26 -0
- package/client/src/components/useActionState.ts +43 -0
- package/client/src/hooks/useFileBrowser.ts +102 -0
- package/client/src/hooks/useFileData.ts +78 -0
- package/client/src/hooks/useScrollAnchor.ts +70 -0
- package/client/src/hooks/useShareSettings.ts +22 -0
- package/client/src/hooks/useTopBar.ts +27 -0
- package/client/src/index.css +281 -0
- package/client/src/lib/AuthContext.ts +27 -0
- package/client/src/lib/api.ts +239 -0
- package/client/src/lib/auth.tsx +50 -0
- package/client/src/lib/codeBlockCm6.ts +129 -0
- package/client/src/lib/codeBlockCopy.ts +43 -0
- package/client/src/lib/codemirror.ts +77 -0
- package/client/src/lib/runner-api.ts +172 -0
- package/client/src/lib/svg.ts +50 -0
- package/client/src/lib/theme.ts +34 -0
- package/client/src/lib/utils.ts +6 -0
- package/client/src/main.tsx +11 -0
- package/client/src/pages/FileBrowser.tsx +135 -0
- package/client/src/pages/Home.tsx +46 -0
- package/client/src/pages/Runner.tsx +151 -0
- package/client/src/pages/RunnerJob.tsx +170 -0
- package/client/tsconfig.app.json +32 -0
- package/client/tsconfig.json +7 -0
- package/client/tsconfig.node.json +26 -0
- package/client/vite.config.ts +35 -0
- package/content/privacy.md +61 -0
- package/content/terms.md +41 -0
- package/dist/client/assets/CodeEditor-0XHVI8Nu.js +1 -0
- package/dist/client/assets/CodeViewer-CykMVsfX.js +1 -0
- package/dist/client/assets/index--MBieNJA.js +1 -0
- package/dist/client/assets/index-BENeXQI_.js +1 -0
- package/dist/client/assets/index-BbBpoOxz.js +1 -0
- package/dist/client/assets/index-BdV9g5AM.js +6 -0
- package/dist/client/assets/index-BjAilRri.js +2 -0
- package/dist/client/assets/index-BqbhWo2I.js +3 -0
- package/dist/client/assets/index-CVbycZ0H.js +1 -0
- package/dist/client/assets/index-Cs5oz2oJ.js +5 -0
- package/dist/client/assets/index-D8KZVveX.js +1 -0
- package/dist/client/assets/index-DC4HMHxY.js +13 -0
- package/dist/client/assets/index-DbMebkkd.css +1 -0
- package/dist/client/assets/index-DcY2RXqX.js +1 -0
- package/dist/client/assets/index-Duy-tZYV.js +1 -0
- package/dist/client/assets/index-Dw7rDFmE.js +7 -0
- package/dist/client/assets/index-FlCUvrjv.js +2 -0
- package/dist/client/assets/index-K6OVmfhg.js +1 -0
- package/dist/client/assets/index-LjwgzZ7F.js +62 -0
- package/dist/client/assets/index-MLwyFRN0.js +1 -0
- package/dist/client/assets/index-OpqBpSjn.js +1 -0
- package/dist/client/assets/index-SsHei0HE.js +1 -0
- package/dist/client/assets/index-uQa2yckk.js +1 -0
- package/dist/client/assets/index-udkXoIER.js +1 -0
- package/dist/client/index.html +15 -0
- package/dist/client/vite.svg +1 -0
- package/dist/src/auth/google.js +57 -0
- package/dist/src/auth/keys.js +185 -0
- package/dist/src/auth/resolve.js +102 -0
- package/dist/src/auth/session.js +57 -0
- package/dist/src/cli/commands/config.js +100 -0
- package/dist/src/cli/commands/config.test.js +84 -0
- package/dist/src/cli/commands/service.js +93 -0
- package/dist/src/cli/commands/start.js +24 -0
- package/dist/src/cli/index.js +20 -0
- package/dist/src/config/index.js +90 -0
- package/dist/src/config/loadConfig.test.js +127 -0
- package/dist/src/config/resolve.js +134 -0
- package/dist/src/config/resolve.test.js +148 -0
- package/dist/src/config/schema.js +159 -0
- package/dist/src/config/substituteEnvVars.js +45 -0
- package/dist/src/config/substituteEnvVars.test.js +51 -0
- package/dist/src/config/types.js +5 -0
- package/dist/src/routes/api/auth-status.js +56 -0
- package/dist/src/routes/api/diagrams.js +35 -0
- package/dist/src/routes/api/directory.js +93 -0
- package/dist/src/routes/api/drives.js +15 -0
- package/dist/src/routes/api/export.js +218 -0
- package/dist/src/routes/api/fileContent.js +286 -0
- package/dist/src/routes/api/index.js +33 -0
- package/dist/src/routes/api/linkInfo.js +71 -0
- package/dist/src/routes/api/linkInfo.test.js +104 -0
- package/dist/src/routes/api/middleware.js +117 -0
- package/dist/src/routes/api/raw.js +38 -0
- package/dist/src/routes/api/runner.js +59 -0
- package/dist/src/routes/api/search.js +236 -0
- package/dist/src/routes/api/sharing.js +203 -0
- package/dist/src/routes/api/status.js +68 -0
- package/dist/src/routes/api/status.test.js +62 -0
- package/dist/src/routes/auth.js +99 -0
- package/dist/src/routes/event.js +77 -0
- package/dist/src/routes/event.test.js +206 -0
- package/dist/src/routes/health.js +10 -0
- package/dist/src/routes/keys.js +129 -0
- package/dist/src/routes/path/index.js +17 -0
- package/dist/src/routes/static.js +30 -0
- package/dist/src/server.js +90 -0
- package/dist/src/services/deepShareLinks.js +163 -0
- package/dist/src/services/diagramCache.js +104 -0
- package/dist/src/services/embeddedDiagrams.js +136 -0
- package/dist/src/services/eventLog.js +55 -0
- package/dist/src/services/eventLog.test.js +113 -0
- package/dist/src/services/eventQueue.js +154 -0
- package/dist/src/services/eventQueue.test.js +104 -0
- package/dist/src/services/export.js +220 -0
- package/dist/src/services/exportCache.js +196 -0
- package/dist/src/services/markdown.js +147 -0
- package/dist/src/services/mermaid.js +97 -0
- package/dist/src/services/plantuml.js +145 -0
- package/dist/src/services/puppeteer.js +156 -0
- package/dist/src/util/breadcrumbs.js +22 -0
- package/dist/src/util/crypto.js +56 -0
- package/dist/src/util/crypto.test.js +99 -0
- package/dist/src/util/fileDetection.js +66 -0
- package/dist/src/util/fileDetection.test.js +89 -0
- package/dist/src/util/formatters.js +43 -0
- package/dist/src/util/formatters.test.js +83 -0
- package/dist/src/util/packageVersion.js +25 -0
- package/dist/src/util/platform.js +148 -0
- package/dist/src/util/state.js +46 -0
- package/dist/vitest.config.js +12 -0
- package/favicon.svg +3 -0
- package/guides/access-decision-flow.mmd +24 -0
- package/guides/access-decision-flow.svg +1 -0
- package/guides/api-integration.md +236 -0
- package/guides/deployment.md +287 -0
- package/guides/event-gateway.md +204 -0
- package/guides/event-gateway.mmd +17 -0
- package/guides/event-gateway.svg +1 -0
- package/guides/exports.md +239 -0
- package/guides/setup.md +313 -0
- package/guides/sharing.md +204 -0
- package/jeeves-server.config.template.json +25 -0
- package/package.json +124 -0
- package/scripts/download-plantuml.js +70 -0
- package/src/auth/google.ts +93 -0
- package/src/auth/keys.ts +252 -0
- package/src/auth/resolve.ts +157 -0
- package/src/auth/session.ts +77 -0
- package/src/cli/commands/config.test.ts +107 -0
- package/src/cli/commands/config.ts +113 -0
- package/src/cli/commands/service.ts +129 -0
- package/src/cli/commands/start.ts +27 -0
- package/src/cli/index.ts +25 -0
- package/src/config/index.ts +113 -0
- package/src/config/loadConfig.test.ts +155 -0
- package/src/config/resolve.test.ts +192 -0
- package/src/config/resolve.ts +173 -0
- package/src/config/schema.ts +179 -0
- package/src/config/substituteEnvVars.test.ts +64 -0
- package/src/config/substituteEnvVars.ts +52 -0
- package/src/config/types.ts +129 -0
- package/src/routes/api/auth-status.ts +85 -0
- package/src/routes/api/diagrams.ts +53 -0
- package/src/routes/api/directory.ts +123 -0
- package/src/routes/api/drives.ts +23 -0
- package/src/routes/api/export.ts +314 -0
- package/src/routes/api/fileContent.ts +414 -0
- package/src/routes/api/index.ts +37 -0
- package/src/routes/api/linkInfo.test.ts +132 -0
- package/src/routes/api/linkInfo.ts +83 -0
- package/src/routes/api/middleware.ts +156 -0
- package/src/routes/api/raw.ts +54 -0
- package/src/routes/api/runner.ts +107 -0
- package/src/routes/api/search.ts +321 -0
- package/src/routes/api/sharing.ts +259 -0
- package/src/routes/api/status.test.ts +72 -0
- package/src/routes/api/status.ts +82 -0
- package/src/routes/auth.ts +143 -0
- package/src/routes/event.test.ts +248 -0
- package/src/routes/event.ts +109 -0
- package/src/routes/health.ts +13 -0
- package/src/routes/keys.ts +192 -0
- package/src/routes/path/index.ts +24 -0
- package/src/routes/static.ts +54 -0
- package/src/server.ts +104 -0
- package/src/services/deepShareLinks.ts +203 -0
- package/src/services/diagramCache.ts +128 -0
- package/src/services/embeddedDiagrams.ts +168 -0
- package/src/services/eventLog.test.ts +144 -0
- package/src/services/eventLog.ts +68 -0
- package/src/services/eventQueue.test.ts +127 -0
- package/src/services/eventQueue.ts +196 -0
- package/src/services/export.ts +267 -0
- package/src/services/exportCache.ts +216 -0
- package/src/services/markdown.ts +189 -0
- package/src/services/mermaid.ts +113 -0
- package/src/services/plantuml.ts +172 -0
- package/src/services/puppeteer.ts +188 -0
- package/src/types/fastify.d.ts +13 -0
- package/src/types/jsonmap.d.ts +10 -0
- package/src/types/plantuml-encoder.d.ts +4 -0
- package/src/util/breadcrumbs.ts +33 -0
- package/src/util/crypto.test.ts +132 -0
- package/src/util/crypto.ts +79 -0
- package/src/util/fileDetection.test.ts +115 -0
- package/src/util/fileDetection.ts +70 -0
- package/src/util/formatters.test.ts +105 -0
- package/src/util/formatters.ts +44 -0
- package/src/util/packageVersion.ts +30 -0
- package/src/util/platform.ts +178 -0
- package/src/util/state.ts +55 -0
- package/test-docs/diagram-retry-test.md +18 -0
- package/test-docs/embedded-diagrams.md +52 -0
- package/test-docs/lazy-diagrams-test.md +333 -0
- package/test-docs/page-a.md +7 -0
- package/test-docs/page-b.md +7 -0
- package/test-docs/page-c.md +7 -0
- package/test-docs/sub/page-d.md +7 -0
- package/test-docs/test-diagram.puml +13 -0
- package/test-docs/validate-deep-share.js +318 -0
- package/tsconfig.json +37 -0
- package/tsdoc.json +13 -0
- package/vendor/.plantuml-version +1 -0
- package/vendor/plantuml.jar +0 -0
- package/vitest.config.js +12 -0
- package/vitest.config.ts +13 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# Exporting & Downloads
|
|
2
|
+
|
|
3
|
+
Jeeves Server can export files as PDF, DOCX, or ZIP — turning Markdown into business-ready documents with one click.
|
|
4
|
+
|
|
5
|
+
## Export Types
|
|
6
|
+
|
|
7
|
+
| Format | Available For | How It Works |
|
|
8
|
+
|--------|--------------|--------------|
|
|
9
|
+
| **PDF** | Markdown, Mermaid, PlantUML | Puppeteer (Markdown) or diagram renderer (Mermaid/PlantUML) |
|
|
10
|
+
| **DOCX** | Markdown files | HTML converted via `@turbodocx/html-to-docx` |
|
|
11
|
+
| **SVG** | Mermaid (`.mmd`), PlantUML (`.puml`, `.pu`, `.plantuml`) | Rendered via Mermaid CLI or PlantUML jar/server |
|
|
12
|
+
| **PNG** | Mermaid, PlantUML | Rendered via Mermaid CLI or PlantUML jar/server |
|
|
13
|
+
| **EPS** | PlantUML (jar only) | Vector export via PlantUML jar |
|
|
14
|
+
| **ZIP** | Directories | Entire directory tree compressed via [`archiver`](https://github.com/archiverjs/node-archiver) |
|
|
15
|
+
| **Raw** | Any file | Direct file download |
|
|
16
|
+
|
|
17
|
+
## Using Exports
|
|
18
|
+
|
|
19
|
+
### From the UI
|
|
20
|
+
|
|
21
|
+
The **Download dropdown** (⬇️ icon) in the header shows available export options based on the current file type. Click an option and the file downloads directly — a spinner shows during generation, replaced by a checkmark on completion.
|
|
22
|
+
|
|
23
|
+
### Via URL Parameters
|
|
24
|
+
|
|
25
|
+
Append to any file URL:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
# PDF export
|
|
29
|
+
/browse/d/docs/design.md?export=pdf
|
|
30
|
+
|
|
31
|
+
# DOCX export
|
|
32
|
+
/browse/d/docs/design.md?export=docx
|
|
33
|
+
|
|
34
|
+
# Raw file download
|
|
35
|
+
/browse/d/docs/design.md?raw=1
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
These work with both insider keys (`?key=<insider-key>&export=pdf`) and outsider share links.
|
|
39
|
+
|
|
40
|
+
### Programmatic Access
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Download PDF via curl
|
|
44
|
+
curl -o design.pdf "https://jeeves.example.com/path/d/docs/design.md?key=<key>&export=pdf"
|
|
45
|
+
|
|
46
|
+
# Download DOCX
|
|
47
|
+
curl -o design.docx "https://jeeves.example.com/path/d/docs/design.md?key=<key>&export=docx"
|
|
48
|
+
|
|
49
|
+
# Download raw file
|
|
50
|
+
curl -o design.md "https://jeeves.example.com/path/d/docs/design.md?key=<key>&raw=1"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## PDF Export
|
|
54
|
+
|
|
55
|
+
PDF generation uses [**Puppeteer**](https://github.com/puppeteer/puppeteer) with your installed Chrome/Chromium. The server:
|
|
56
|
+
|
|
57
|
+
1. Launches headless Chrome
|
|
58
|
+
2. Loads the rendered markdown page (authenticating with the `_internal` key)
|
|
59
|
+
3. Prints to PDF with print-quality settings
|
|
60
|
+
4. Returns the PDF as a download
|
|
61
|
+
|
|
62
|
+
### Requirements
|
|
63
|
+
|
|
64
|
+
- **Chrome/Chromium** must be installed on the server
|
|
65
|
+
- **`chromePath`** must point to the executable in `jeeves.config.ts`
|
|
66
|
+
- **`_internal` key** must be configured (Puppeteer uses it to authenticate)
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
chromePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
70
|
+
keys: {
|
|
71
|
+
_internal: 'random-seed-string', // Required for PDF/DOCX export
|
|
72
|
+
},
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### What you see is what you get
|
|
76
|
+
|
|
77
|
+
PDFs render from the same HTML as the browser view, but:
|
|
78
|
+
- **Prose width setting is ignored** — exports always use full width
|
|
79
|
+
- **Dark mode is ignored** — exports always render in light mode
|
|
80
|
+
- **TOC sidebar is excluded** — the document stands alone
|
|
81
|
+
- **Code blocks retain syntax highlighting** — colors print correctly
|
|
82
|
+
|
|
83
|
+
### Troubleshooting
|
|
84
|
+
|
|
85
|
+
**"Export failed" error:**
|
|
86
|
+
- Verify `chromePath` points to a valid Chrome/Chromium executable
|
|
87
|
+
- Ensure the `_internal` key is configured in `keys`
|
|
88
|
+
- Check server logs for Puppeteer errors
|
|
89
|
+
|
|
90
|
+
**Blank or login page in PDF:**
|
|
91
|
+
- The `_internal` key's derived insider key must be valid
|
|
92
|
+
- Verify with: `curl -s "http://localhost:<port>/insider-key" -H "X-API-Key: <_internal-seed>"`
|
|
93
|
+
|
|
94
|
+
**Timeout on large documents:**
|
|
95
|
+
- Large markdown files with many code blocks or diagrams take longer to render
|
|
96
|
+
- The server has a default timeout; very large documents may need optimization
|
|
97
|
+
|
|
98
|
+
## DOCX Export
|
|
99
|
+
|
|
100
|
+
DOCX generation converts the rendered HTML to a Word document using [`@turbodocx/html-to-docx`](https://github.com/nickmessing/turbodocx). This happens server-side without Chrome.
|
|
101
|
+
|
|
102
|
+
DOCX exports:
|
|
103
|
+
- Preserve headings, tables, lists, and basic formatting
|
|
104
|
+
- Include code blocks (without syntax highlighting colors)
|
|
105
|
+
- Embed images as inline content
|
|
106
|
+
- Work independently of the `_internal` key (no Puppeteer needed)
|
|
107
|
+
|
|
108
|
+
## Mermaid Export
|
|
109
|
+
|
|
110
|
+
Mermaid diagrams (`.mmd` files) can be exported as SVG, PNG, or PDF via the [Mermaid CLI](https://github.com/mermaid-js/mermaid-cli) (`mmdc`).
|
|
111
|
+
|
|
112
|
+
### Requirements
|
|
113
|
+
|
|
114
|
+
- **Mermaid CLI** must be installed (via npm)
|
|
115
|
+
- **`mermaidCliPath`** must point to the `mmdc` binary in `jeeves.config.ts`
|
|
116
|
+
- **Puppeteer/Chrome** is required by Mermaid CLI for rendering
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
mermaidCliPath: '/usr/local/bin/mmdc',
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Export endpoint
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
GET /api/mermaid-export/<path>?format=svg|png|pdf
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## PlantUML Export
|
|
129
|
+
|
|
130
|
+
PlantUML files (`.puml`, `.pu`, `.plantuml`) can be exported as SVG, PNG, PDF, or EPS.
|
|
131
|
+
|
|
132
|
+
### Rendering pipeline
|
|
133
|
+
|
|
134
|
+
PlantUML uses a **fallback rendering pipeline** — each method is tried in order until one succeeds:
|
|
135
|
+
|
|
136
|
+
1. **Local Java jar** — fastest, supports `!include` directives for complex diagrams with shared libraries. Requires Java and the PlantUML jar.
|
|
137
|
+
2. **Configured PlantUML servers** — self-hosted or private PlantUML server instances, tried in order.
|
|
138
|
+
3. **Public community server** (`plantuml.com`) — always appended as the last resort. Cannot resolve `!include` directives.
|
|
139
|
+
|
|
140
|
+
### Configuration
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
plantuml: {
|
|
144
|
+
jarPath: '/opt/plantuml/plantuml.jar', // Local jar path (optional)
|
|
145
|
+
javaPath: '/usr/bin/java', // Java binary (optional, defaults to 'java')
|
|
146
|
+
servers: ['https://internal.plantuml.example.com/plantuml'], // Private servers (optional)
|
|
147
|
+
},
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
If `plantuml` is omitted entirely, only the public community server is used.
|
|
151
|
+
|
|
152
|
+
### Export formats
|
|
153
|
+
|
|
154
|
+
| Format | Jar | Server |
|
|
155
|
+
|--------|-----|--------|
|
|
156
|
+
| SVG | ✅ | ✅ |
|
|
157
|
+
| PNG | ✅ | ✅ |
|
|
158
|
+
| PDF | ✅ | ❌ |
|
|
159
|
+
| EPS | ✅ | ❌ |
|
|
160
|
+
|
|
161
|
+
### Export endpoint
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
GET /api/plantuml-export/<path>?format=svg|png|pdf|eps
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### `!include` support
|
|
168
|
+
|
|
169
|
+
Only the **local jar** method resolves `!include` directives. If your diagrams reference shared PlantUML libraries (e.g., AWS icons, company style files), you must configure `jarPath`. The jar runs with `cwd` set to the diagram's parent directory, so relative includes resolve naturally.
|
|
170
|
+
|
|
171
|
+
## Embedded Diagrams in Markdown
|
|
172
|
+
|
|
173
|
+
Markdown files can contain **inline diagram source** in fenced code blocks. Following the [GitHub convention](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/), code blocks tagged `mermaid` or `plantuml` (also `puml`) are rendered as inline SVG diagrams when the page is displayed.
|
|
174
|
+
|
|
175
|
+
````markdown
|
|
176
|
+
```mermaid
|
|
177
|
+
graph TD
|
|
178
|
+
A[Start] --> B{Decision}
|
|
179
|
+
B -->|Yes| C[Do it]
|
|
180
|
+
B -->|No| D[Skip]
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```plantuml
|
|
184
|
+
@startuml
|
|
185
|
+
Alice -> Bob: Hello
|
|
186
|
+
Bob --> Alice: Hi!
|
|
187
|
+
@enduml
|
|
188
|
+
```
|
|
189
|
+
````
|
|
190
|
+
|
|
191
|
+
### How it works
|
|
192
|
+
|
|
193
|
+
Diagram blocks are detected during markdown parsing, replaced with placeholders, and rendered server-side after HTML generation:
|
|
194
|
+
- **Mermaid** — rendered via Mermaid CLI (`mmdc`) to SVG
|
|
195
|
+
- **PlantUML** — rendered via the same fallback pipeline as `.puml` files (jar → servers → community)
|
|
196
|
+
|
|
197
|
+
If rendering fails, the source code is displayed with a small error label.
|
|
198
|
+
|
|
199
|
+
### Showing source instead of rendering
|
|
200
|
+
|
|
201
|
+
To display diagram source as a code block (without rendering), use a different language hint:
|
|
202
|
+
|
|
203
|
+
````markdown
|
|
204
|
+
```text
|
|
205
|
+
graph TD
|
|
206
|
+
A --> B
|
|
207
|
+
```
|
|
208
|
+
````
|
|
209
|
+
|
|
210
|
+
### PDF/DOCX export
|
|
211
|
+
|
|
212
|
+
Embedded diagrams appear in PDF and DOCX exports as rendered SVGs — what you see in the browser is what you get in the export.
|
|
213
|
+
|
|
214
|
+
## ZIP Export
|
|
215
|
+
|
|
216
|
+
Directories can be downloaded as ZIP archives. The header shows a ZIP download option when viewing a directory.
|
|
217
|
+
|
|
218
|
+
### Size limit
|
|
219
|
+
|
|
220
|
+
The `maxZipSizeMb` config setting (default: 100 MB) prevents accidentally zipping enormous directories:
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
maxZipSizeMb: 100, // Refuse ZIP for directories larger than this
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
When the total directory size exceeds this limit, the ZIP option is disabled with a message explaining why.
|
|
227
|
+
|
|
228
|
+
### What's included
|
|
229
|
+
|
|
230
|
+
The ZIP contains the entire directory tree — all files and subdirectories. No files are excluded.
|
|
231
|
+
|
|
232
|
+
## Export for Outsiders
|
|
233
|
+
|
|
234
|
+
Outsiders (people using share links) can also export files:
|
|
235
|
+
- **PDF and DOCX** exports work on shared markdown files
|
|
236
|
+
- **Raw download** works on any shared file
|
|
237
|
+
- **ZIP** works on shared directories (within the size limit)
|
|
238
|
+
|
|
239
|
+
The share link's authentication covers the export — no additional credentials needed.
|
package/guides/setup.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# Setup & Configuration
|
|
2
|
+
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
- **Node.js** ≥ 18
|
|
6
|
+
- **Chrome or Chromium** — required for PDF export (Puppeteer uses it headlessly)
|
|
7
|
+
- **A domain or IP** where the server will be accessible (for Google OAuth callbacks)
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
git clone https://github.com/karmaniverous/jeeves-server.git
|
|
13
|
+
cd jeeves-server
|
|
14
|
+
npm install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Configuration
|
|
18
|
+
|
|
19
|
+
Jeeves Server uses a **TypeScript configuration file** validated at startup by a [Zod](https://github.com/colinhacks/zod) schema. The schema at `src/config/schema.ts` is the single source of truth — all types are derived from it.
|
|
20
|
+
|
|
21
|
+
### Create your config
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cp jeeves.config.template.ts jeeves.config.ts
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Edit `jeeves.config.ts` with your values. This file is **gitignored** — it contains secrets and is never committed.
|
|
28
|
+
|
|
29
|
+
### Config structure
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import type { JeevesConfig } from './src/config/schema.js';
|
|
33
|
+
|
|
34
|
+
export default {
|
|
35
|
+
port: 1934,
|
|
36
|
+
chromePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
37
|
+
auth: { ... },
|
|
38
|
+
insiders: { ... },
|
|
39
|
+
keys: { ... },
|
|
40
|
+
events: { ... },
|
|
41
|
+
} satisfies JeevesConfig;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The `satisfies` keyword gives you type checking without losing literal types — your editor will autocomplete and validate as you type.
|
|
45
|
+
|
|
46
|
+
### Platform-specific settings
|
|
47
|
+
|
|
48
|
+
**Windows** — drives are auto-discovered; no `roots` config needed:
|
|
49
|
+
```typescript
|
|
50
|
+
chromePath: 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Linux** — configure filesystem roots for the file browser:
|
|
54
|
+
```typescript
|
|
55
|
+
chromePath: '/usr/bin/chromium-browser',
|
|
56
|
+
roots: {
|
|
57
|
+
home: '/home',
|
|
58
|
+
projects: '/opt/projects',
|
|
59
|
+
},
|
|
60
|
+
mermaidCliPath: '/opt/mermaid-cli', // optional
|
|
61
|
+
plantuml: { // optional
|
|
62
|
+
jarPath: '/opt/plantuml/plantuml.jar',
|
|
63
|
+
javaPath: '/usr/bin/java', // defaults to 'java' on PATH
|
|
64
|
+
servers: [], // private servers; community server always appended
|
|
65
|
+
},
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
On Windows, `roots` is ignored. On Linux, if omitted, it defaults to `{ root: '/' }`.
|
|
69
|
+
|
|
70
|
+
### Config is immutable at runtime
|
|
71
|
+
|
|
72
|
+
Once the server starts, the config is loaded once and never written to. Mutable state (like auto-generated insider keys) lives in a separate `state.json` file that the server manages itself.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Authentication Modes
|
|
77
|
+
|
|
78
|
+
Jeeves Server supports two authentication methods, configured via `auth.modes`:
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
auth: {
|
|
82
|
+
modes: ['google', 'keys'], // Active modes, in priority order
|
|
83
|
+
// ...
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
You can enable one or both. The order matters — modes are checked in the order listed.
|
|
88
|
+
|
|
89
|
+
### Google OAuth (`'google'`)
|
|
90
|
+
|
|
91
|
+
**Best for:** Teams where insiders log in via browser.
|
|
92
|
+
|
|
93
|
+
Users authenticate with their Google account. The server checks their email against the `insiders` map to determine access.
|
|
94
|
+
|
|
95
|
+
**Requirements when enabled:**
|
|
96
|
+
- `auth.google.clientId` and `auth.google.clientSecret` — from [Google Cloud Console](https://console.cloud.google.com/apis/credentials)
|
|
97
|
+
- `auth.sessionSecret` — a random string for signing session cookies
|
|
98
|
+
- At least one entry in `insiders`
|
|
99
|
+
|
|
100
|
+
**Google Cloud setup:**
|
|
101
|
+
1. Create a project (or use an existing one)
|
|
102
|
+
2. Go to **APIs & Services → Credentials → Create Credentials → OAuth client ID**
|
|
103
|
+
3. Application type: **Web application**
|
|
104
|
+
4. Authorized redirect URI: `https://your-domain.com/auth/google/callback`
|
|
105
|
+
5. Copy the client ID and client secret into your config
|
|
106
|
+
|
|
107
|
+
**Session secret generation:**
|
|
108
|
+
```bash
|
|
109
|
+
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Key-Based Auth (`'keys'`)
|
|
113
|
+
|
|
114
|
+
**Best for:** Headless access, bot integrations, simple setups without Google.
|
|
115
|
+
|
|
116
|
+
Users authenticate by appending `?key=<value>` to any URL. The server derives keys from configured seeds using HMAC-SHA256 and checks the provided key against all known derived keys.
|
|
117
|
+
|
|
118
|
+
**Requirements when enabled:**
|
|
119
|
+
- At least one entry in `keys`
|
|
120
|
+
|
|
121
|
+
**How keys work:** You configure a **seed** (a random secret string). The server derives the actual insider key from it via HMAC. You never put the derived key in the config — only the seed. To get the derived key for use in URLs:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Via the API (requires X-API-Key header with any seed)
|
|
125
|
+
curl -H "X-API-Key: <seed>" https://your-domain.com/insider-key
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Both Modes Together
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
auth: {
|
|
132
|
+
modes: ['keys', 'google'], // Keys checked first
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
When both are active:
|
|
137
|
+
- Browser users can log in with Google for a session-based experience
|
|
138
|
+
- Bots and scripts can use `?key=` for stateless access
|
|
139
|
+
- Both methods work on every endpoint
|
|
140
|
+
|
|
141
|
+
### Choosing a Mode
|
|
142
|
+
|
|
143
|
+
| Scenario | Recommended |
|
|
144
|
+
|----------|-------------|
|
|
145
|
+
| Team of humans accessing via browser | `['google']` |
|
|
146
|
+
| Bot/script access only | `['keys']` |
|
|
147
|
+
| Humans + bots on the same server | `['google', 'keys']` |
|
|
148
|
+
| Quick local setup, no Google credentials | `['keys']` |
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Insiders
|
|
153
|
+
|
|
154
|
+
The `insiders` map defines **who** has full browsing access. Each entry is an email address with optional path scopes:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
insiders: {
|
|
158
|
+
// Full access
|
|
159
|
+
'alice@example.com': {},
|
|
160
|
+
|
|
161
|
+
// Restricted to specific paths (allow-only)
|
|
162
|
+
'contractor@example.com': {
|
|
163
|
+
scopes: ['/d/projects/client-x/*'],
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
// Broad access with cutouts (allow/deny)
|
|
167
|
+
'team-member@example.com': {
|
|
168
|
+
scopes: {
|
|
169
|
+
allow: ['/d/*'],
|
|
170
|
+
deny: ['/d/secrets/*', '/d/.private/*'],
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
With Google auth, insiders log in via OAuth and the server checks their email. With key auth, each insider gets a derived URL key.
|
|
177
|
+
|
|
178
|
+
See the [Insiders, Outsiders & Sharing](sharing.md) guide for the full access model.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Keys
|
|
183
|
+
|
|
184
|
+
The `keys` map defines **named API keys** for machine access:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
keys: {
|
|
188
|
+
// Unscoped — full access to all paths
|
|
189
|
+
primary: 'a-random-64-char-hex-string',
|
|
190
|
+
|
|
191
|
+
// Scoped — restricted to specific paths
|
|
192
|
+
'webhook-notion': {
|
|
193
|
+
key: 'another-random-hex-string',
|
|
194
|
+
scopes: ['/event'],
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
// Reserved: internal server operations (Puppeteer export)
|
|
198
|
+
_internal: 'yet-another-random-hex-string',
|
|
199
|
+
},
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**Generate seeds with:**
|
|
203
|
+
```bash
|
|
204
|
+
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### The `_internal` key
|
|
208
|
+
|
|
209
|
+
The `_internal` key is reserved for the server's own use — specifically, Puppeteer uses it to authenticate when rendering PDFs and DOCX files. It **must not** have scopes (enforced by the schema).
|
|
210
|
+
|
|
211
|
+
If you don't configure `_internal`, PDF/DOCX export will not work.
|
|
212
|
+
|
|
213
|
+
### Key names
|
|
214
|
+
|
|
215
|
+
Key names are used for logging and identification. Choose meaningful names: `primary`, `webhook-notion`, `ci-bot`, etc.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Event Gateway
|
|
220
|
+
|
|
221
|
+
The event gateway receives webhooks at `POST /event`, validates them against JSON Schema rules, and dispatches matched events to shell commands via a durable JSONL queue.
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
events: {
|
|
225
|
+
'notion-page-update': {
|
|
226
|
+
// JSON Schema to match against incoming body
|
|
227
|
+
schema: {
|
|
228
|
+
type: 'object',
|
|
229
|
+
properties: { type: { const: 'page.content_updated' } },
|
|
230
|
+
required: ['type'],
|
|
231
|
+
},
|
|
232
|
+
// Command to execute when matched
|
|
233
|
+
cmd: 'node /path/to/handler.js',
|
|
234
|
+
// Optional: transform body before passing to command
|
|
235
|
+
map: {
|
|
236
|
+
pageId: { '$': { method: '$.lib._.get', params: ['$.input', 'data.page_id'] } },
|
|
237
|
+
},
|
|
238
|
+
// Optional: override default timeout
|
|
239
|
+
timeoutMs: 60000,
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Webhook callers authenticate with a scoped key:
|
|
245
|
+
```bash
|
|
246
|
+
curl -X POST "https://your-domain.com/event?key=<webhook-key>" \
|
|
247
|
+
-H "Content-Type: application/json" \
|
|
248
|
+
-d '{"type": "page.content_updated", "data": {"page_id": "abc123"}}'
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Building
|
|
254
|
+
|
|
255
|
+
```bash
|
|
256
|
+
# Full build (server TypeScript + React client)
|
|
257
|
+
npm run build # Compiles server → dist/
|
|
258
|
+
cd client && npx vite build --outDir ../dist/client && cd .. # Builds React SPA → dist/client/
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
> ⚠️ `npm run build` deletes the entire `dist/` directory (including `dist/client/`). Always rebuild the client after the server.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Running
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
node dist/server.js
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
### As a Windows service
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
nssm install JeevesServer "node" "/path/to/dist/server.js"
|
|
275
|
+
nssm start JeevesServer
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Health check
|
|
279
|
+
|
|
280
|
+
```
|
|
281
|
+
GET /health
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
Returns `200 OK` with no authentication required.
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## File Layout
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
jeeves-server/
|
|
292
|
+
├── jeeves.config.ts # Your config (gitignored)
|
|
293
|
+
├── jeeves.config.template.ts # Config template (committed)
|
|
294
|
+
├── state.json # Runtime state (gitignored, auto-managed)
|
|
295
|
+
├── src/ # Server source (TypeScript)
|
|
296
|
+
│ ├── config/
|
|
297
|
+
│ │ ├── schema.ts # Zod schema (source of truth)
|
|
298
|
+
│ │ ├── index.ts # Config loader (jiti for TS)
|
|
299
|
+
│ │ └── types.ts # Runtime types
|
|
300
|
+
│ ├── auth/ # Google OAuth + key verification
|
|
301
|
+
│ ├── routes/ # Fastify route handlers
|
|
302
|
+
│ ├── services/ # Export, markdown, event queue
|
|
303
|
+
│ └── server.ts # Entry point
|
|
304
|
+
├── client/ # React SPA source
|
|
305
|
+
│ └── src/
|
|
306
|
+
│ ├── pages/ # FileBrowser, FileViewer, About
|
|
307
|
+
│ ├── components/ # Header, dropdowns, viewers
|
|
308
|
+
│ └── lib/ # API client, auth, theme
|
|
309
|
+
├── dist/ # Compiled output (gitignored)
|
|
310
|
+
│ ├── server.js # Compiled server
|
|
311
|
+
│ └── client/ # Built React SPA
|
|
312
|
+
└── guides/ # Documentation
|
|
313
|
+
```
|