logseq-graph-living-atlas 0.1.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.example +29 -0
- package/CHANGELOG.md +38 -0
- package/CODE_OF_CONDUCT.md +33 -0
- package/CONTRIBUTING.md +116 -0
- package/GOVERNANCE.md +40 -0
- package/LICENSE +21 -0
- package/MAINTAINERS.md +34 -0
- package/README.md +370 -0
- package/ROADMAP.md +38 -0
- package/SECURITY.md +43 -0
- package/SUPPORT.md +31 -0
- package/dist/assets/AtlasCanvas-p-Pb_C3p.js +172 -0
- package/dist/assets/index-Cb0dgkF5.css +1 -0
- package/dist/assets/index-D-LUf-q7.js +12 -0
- package/dist/assets/three-DQCgX68K.js +3947 -0
- package/dist/index.html +13 -0
- package/docs/ADAPTERS.md +48 -0
- package/docs/API.md +145 -0
- package/docs/ARCHITECTURE.md +93 -0
- package/docs/CONCEPTS.md +62 -0
- package/docs/MCP.md +74 -0
- package/docs/RELEASE.md +65 -0
- package/docs/REPO_GUIDE.md +92 -0
- package/docs/TROUBLESHOOTING.md +138 -0
- package/docs/assets/living-atlas-demo.png +0 -0
- package/docs/assets/living-atlas-pathfinder.png +0 -0
- package/docs/assets/living-atlas-radar.png +0 -0
- package/docs/assets/living-atlas-source-detail.png +0 -0
- package/package.json +102 -0
- package/server/brain-service.mjs +201 -0
- package/server/contracts.mjs +346 -0
- package/server/fixture/create-fixture-graph.mjs +115 -0
- package/server/graph/pathfinding.mjs +155 -0
- package/server/graph/quality.mjs +11 -0
- package/server/graph/utils.mjs +25 -0
- package/server/graph-index.mjs +920 -0
- package/server/logseq/parser.mjs +121 -0
- package/server/logseq/source-adapter.mjs +147 -0
- package/server/redaction.mjs +89 -0
- package/server/service.mjs +777 -0
- package/server/source-adapter-contract.d.ts +46 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Troubleshooting
|
|
2
|
+
|
|
3
|
+
## `npx logseq-graph-living-atlas` Is Not Found
|
|
4
|
+
|
|
5
|
+
Confirm npm can see the package:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm view logseq-graph-living-atlas version
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
If the package is not available yet, run from source:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/johnschieferleuhlenbrock/logseq-graph-living-atlas.git
|
|
15
|
+
cd logseq-graph-living-atlas
|
|
16
|
+
npm install
|
|
17
|
+
npm run demo
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Missing `pages/`
|
|
21
|
+
|
|
22
|
+
`--root` must point at the Logseq graph folder, not the `pages/` folder:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
my-logseq-graph/
|
|
26
|
+
pages/
|
|
27
|
+
journals/
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Check it with:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
ls /absolute/path/to/my-logseq-graph/pages
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Port Already In Use
|
|
37
|
+
|
|
38
|
+
Use another local port:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
living-atlas --root /absolute/path/to/logseq --port 8790
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## `401` From `/api/*`
|
|
45
|
+
|
|
46
|
+
Real graph reads are token-protected by default. Open the `#token=...` URL printed by the service, or provide your own:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
LIVING_ATLAS_TOKEN=<random-local-token> living-atlas --root /absolute/path/to/logseq
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
PowerShell:
|
|
53
|
+
|
|
54
|
+
```powershell
|
|
55
|
+
$env:LIVING_ATLAS_TOKEN = "<random-local-token>"
|
|
56
|
+
living-atlas --root "D:\LogseqGraph"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
For fixture-only local experiments, you can opt out:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
living-atlas --root /path/to/public-fixture --allow-unauthenticated-read
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Split Dev CORS
|
|
66
|
+
|
|
67
|
+
When running Vite and the API separately, allow the local Vite origin and open the token URL:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
LIVING_ATLAS_TOKEN=<random-local-token> npm run dev:api -- --root /absolute/path/to/logseq --allowed-origin http://127.0.0.1:5177
|
|
71
|
+
npm run dev
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Open `http://127.0.0.1:5177/#token=<random-local-token>`.
|
|
75
|
+
|
|
76
|
+
PowerShell:
|
|
77
|
+
|
|
78
|
+
```powershell
|
|
79
|
+
$env:LIVING_ATLAS_TOKEN = "<random-local-token>"
|
|
80
|
+
npm run dev:api -- --root "D:\LogseqGraph" --allowed-origin http://127.0.0.1:5177
|
|
81
|
+
npm run dev
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## MCP Changes Do Not Appear In Atlas
|
|
85
|
+
|
|
86
|
+
Confirm both processes point at the same graph root:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
living-atlas --root /absolute/path/to/logseq
|
|
90
|
+
npx logseq-graph-mcp --root /absolute/path/to/logseq --readonly
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Atlas does not subscribe to the MCP protocol directly. It sees MCP writes as filesystem changes, so either keep Atlas running with `--watch` or call `POST /api/reindex` after a guarded MCP write. If you use a custom cache path, keep the cache outside the graph folder.
|
|
94
|
+
|
|
95
|
+
Run the public compatibility smoke when debugging install or path issues:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm run smoke:mcp
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Blank Or Unsupported WebGL
|
|
102
|
+
|
|
103
|
+
Living Atlas needs WebGL for the cinematic field. If WebGL is unavailable, the app should show the fallback graph-inspection panel with totals, top regions, and high-signal pages.
|
|
104
|
+
|
|
105
|
+
Try another browser, disable low-power/restricted graphics settings, or run the fixture smoke path:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npm run demo
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## UI Smoke Test Browser Missing
|
|
112
|
+
|
|
113
|
+
Install the Playwright browser once:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npx playwright install chromium
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
On Linux CI-like systems:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
npx playwright install --with-deps chromium
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Safe Bug Reports
|
|
126
|
+
|
|
127
|
+
Do not attach real graph files, private screenshots, cache files, token URLs, or terminal output containing local paths. Reproduce with the public fixture whenever possible:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npm run demo
|
|
131
|
+
npm run test:ui
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
For API-shaped bug reports from a real graph, request redacted JSON:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
curl -H "Authorization: Bearer <token>" "http://127.0.0.1:8787/api/snapshot?redact=1"
|
|
138
|
+
```
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "logseq-graph-living-atlas",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Local-only cinematic 3D atlas and read-only index service for Logseq markdown graphs.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=20.19.0"
|
|
9
|
+
},
|
|
10
|
+
"packageManager": "npm@10.8.2",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"logseq",
|
|
13
|
+
"knowledge-graph",
|
|
14
|
+
"threejs",
|
|
15
|
+
"visualization",
|
|
16
|
+
"local-first"
|
|
17
|
+
],
|
|
18
|
+
"homepage": "https://github.com/johnschieferleuhlenbrock/logseq-graph-living-atlas#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/johnschieferleuhlenbrock/logseq-graph-living-atlas/issues"
|
|
21
|
+
},
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "git+https://github.com/johnschieferleuhlenbrock/logseq-graph-living-atlas.git"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"living-atlas": "server/brain-service.mjs",
|
|
31
|
+
"logseq-graph-living-atlas": "server/brain-service.mjs"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist/",
|
|
35
|
+
"server/",
|
|
36
|
+
"docs/API.md",
|
|
37
|
+
"docs/ADAPTERS.md",
|
|
38
|
+
"docs/ARCHITECTURE.md",
|
|
39
|
+
"docs/CONCEPTS.md",
|
|
40
|
+
"docs/MCP.md",
|
|
41
|
+
"docs/RELEASE.md",
|
|
42
|
+
"docs/REPO_GUIDE.md",
|
|
43
|
+
"docs/TROUBLESHOOTING.md",
|
|
44
|
+
"docs/assets/living-atlas-demo.png",
|
|
45
|
+
"docs/assets/living-atlas-pathfinder.png",
|
|
46
|
+
"docs/assets/living-atlas-radar.png",
|
|
47
|
+
"docs/assets/living-atlas-source-detail.png",
|
|
48
|
+
"README.md",
|
|
49
|
+
"CONTRIBUTING.md",
|
|
50
|
+
"CODE_OF_CONDUCT.md",
|
|
51
|
+
"CHANGELOG.md",
|
|
52
|
+
"SECURITY.md",
|
|
53
|
+
"SUPPORT.md",
|
|
54
|
+
"MAINTAINERS.md",
|
|
55
|
+
"GOVERNANCE.md",
|
|
56
|
+
"ROADMAP.md",
|
|
57
|
+
".env.example",
|
|
58
|
+
"LICENSE"
|
|
59
|
+
],
|
|
60
|
+
"scripts": {
|
|
61
|
+
"dev": "vite --host 127.0.0.1 --port 5177",
|
|
62
|
+
"dev:api": "node server/brain-service.mjs --watch --no-static --port 8787",
|
|
63
|
+
"build": "vite build",
|
|
64
|
+
"start": "npm run demo",
|
|
65
|
+
"serve": "node server/brain-service.mjs --watch --static dist --port 8787",
|
|
66
|
+
"serve:env": "npm run build && node --env-file=.env.local server/brain-service.mjs --watch --static dist --port 8787",
|
|
67
|
+
"demo": "npm run build && node scripts/demo.mjs",
|
|
68
|
+
"dev:fixture": "node scripts/dev-fixture.mjs",
|
|
69
|
+
"capture:demo": "npm run build && node scripts/capture-demo.mjs",
|
|
70
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.test.json --noEmit",
|
|
71
|
+
"check:runtime": "node scripts/runtime-check.mjs",
|
|
72
|
+
"test": "node --test tests/*.test.mjs && npm run test:frontend && npm run typecheck && npm run check:runtime && npm run build",
|
|
73
|
+
"test:frontend": "tsx --test tests/frontend/*.test.ts",
|
|
74
|
+
"test:ui": "npm run build && node tests/ui-smoke.mjs",
|
|
75
|
+
"test:ui:scale": "npm run build && node tests/ui-scale-smoke.mjs",
|
|
76
|
+
"eval": "node tests/scale-eval.mjs && node tests/service-scale-eval.mjs",
|
|
77
|
+
"eval:service:100k": "node tests/service-scale-eval.mjs --size=100000 --watch",
|
|
78
|
+
"smoke:mcp": "node scripts/mcp-compat-smoke.mjs",
|
|
79
|
+
"smoke:package": "node scripts/package-smoke.mjs",
|
|
80
|
+
"check:public": "node scripts/public-readiness.mjs",
|
|
81
|
+
"check:release": "node scripts/release-readiness.mjs",
|
|
82
|
+
"clean": "node scripts/clean.mjs",
|
|
83
|
+
"prepack": "npm run build",
|
|
84
|
+
"prepublishOnly": "npm run check:release && npm run validate && npm run smoke:package",
|
|
85
|
+
"validate": "npm test && npm run eval && npm run test:ui && npm run test:ui:scale && npm run check:public"
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@types/node": "^24.10.1",
|
|
89
|
+
"@types/react": "^19.2.7",
|
|
90
|
+
"@types/react-dom": "^19.2.3",
|
|
91
|
+
"@types/three": "^0.181.0",
|
|
92
|
+
"@vitejs/plugin-react": "^5.0.4",
|
|
93
|
+
"playwright": "^1.60.0",
|
|
94
|
+
"pngjs": "^7.0.0",
|
|
95
|
+
"react": "^19.2.0",
|
|
96
|
+
"react-dom": "^19.2.0",
|
|
97
|
+
"three": "^0.181.2",
|
|
98
|
+
"tsx": "^4.22.4",
|
|
99
|
+
"typescript": "^5.9.3",
|
|
100
|
+
"vite": "^7.2.4"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import crypto from "node:crypto";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { DEFAULT_LOGSEQ_ROOT } from "./logseq/source-adapter.mjs";
|
|
8
|
+
import { createBrainService } from "./service.mjs";
|
|
9
|
+
import { createFixtureGraph } from "./fixture/create-fixture-graph.mjs";
|
|
10
|
+
|
|
11
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const packageJson = JSON.parse(fs.readFileSync(path.resolve(__dirname, "..", "package.json"), "utf8"));
|
|
13
|
+
|
|
14
|
+
if (process.argv[1] && fs.realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
15
|
+
await main(process.argv.slice(2));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function main(argv = []) {
|
|
19
|
+
const args = parseArgs(argv);
|
|
20
|
+
if (args.help) {
|
|
21
|
+
printHelp();
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (args.version) {
|
|
25
|
+
console.log(packageJson.version);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const port = Number(args.port || process.env.LIVING_ATLAS_PORT || process.env.BRAIN_ATLAS_PORT || 8787);
|
|
30
|
+
const demoMode = Boolean(args.demo);
|
|
31
|
+
const rootInput = demoMode
|
|
32
|
+
? createDemoGraphRoot()
|
|
33
|
+
: args.root || process.env.LOGSEQ_ROOT || DEFAULT_LOGSEQ_ROOT;
|
|
34
|
+
if (!rootInput) {
|
|
35
|
+
console.error("[living-atlas] LOGSEQ_ROOT or --root is required. Point it at a Logseq graph folder containing pages/.");
|
|
36
|
+
console.error("[living-atlas] Example: npx logseq-graph-living-atlas --root /path/to/logseq");
|
|
37
|
+
console.error("[living-atlas] Or try a public fixture: npx logseq-graph-living-atlas --demo");
|
|
38
|
+
console.error("[living-atlas] Run living-atlas --help for options.");
|
|
39
|
+
process.exitCode = 1;
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const root = path.resolve(rootInput);
|
|
44
|
+
const packagedStaticDir = path.resolve(__dirname, "..", "dist");
|
|
45
|
+
const staticDir = args["no-static"]
|
|
46
|
+
? null
|
|
47
|
+
: args.static
|
|
48
|
+
? path.resolve(__dirname, "..", args.static)
|
|
49
|
+
: fs.existsSync(path.join(packagedStaticDir, "index.html"))
|
|
50
|
+
? packagedStaticDir
|
|
51
|
+
: null;
|
|
52
|
+
const cachePath = path.resolve(args.cache || process.env.LIVING_ATLAS_CACHE || process.env.BRAIN_ATLAS_CACHE || path.join(defaultCacheDirectory(), "snapshot.json"));
|
|
53
|
+
const debugPaths = Boolean(args["debug-paths"] || process.env.LIVING_ATLAS_DEBUG_PATHS === "1" || process.env.BRAIN_ATLAS_DEBUG_PATHS === "1");
|
|
54
|
+
const allowUnauthenticatedRead = Boolean(args["allow-unauthenticated-read"] || process.env.LIVING_ATLAS_ALLOW_UNAUTHENTICATED_READ === "1");
|
|
55
|
+
const configuredToken = args.token || process.env.LIVING_ATLAS_TOKEN || process.env.BRAIN_ATLAS_TOKEN || "";
|
|
56
|
+
const requireToken = Boolean(
|
|
57
|
+
args["require-token"] ||
|
|
58
|
+
process.env.LIVING_ATLAS_REQUIRE_TOKEN === "1" ||
|
|
59
|
+
(!demoMode && !allowUnauthenticatedRead)
|
|
60
|
+
);
|
|
61
|
+
if (requireToken && configuredToken && configuredToken.length < 16) {
|
|
62
|
+
console.error("[living-atlas] LIVING_ATLAS_TOKEN / --token must be at least 16 characters when read-token mode is enabled.");
|
|
63
|
+
process.exitCode = 1;
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
const localToken = requireToken ? configuredToken || crypto.randomBytes(18).toString("base64url") : configuredToken;
|
|
67
|
+
|
|
68
|
+
let service;
|
|
69
|
+
try {
|
|
70
|
+
service = createBrainService({
|
|
71
|
+
root,
|
|
72
|
+
cachePath,
|
|
73
|
+
staticDir,
|
|
74
|
+
port,
|
|
75
|
+
watch: Boolean(args.watch),
|
|
76
|
+
debugPaths,
|
|
77
|
+
token: localToken,
|
|
78
|
+
requireToken,
|
|
79
|
+
allowUnauthenticatedRead: demoMode || allowUnauthenticatedRead,
|
|
80
|
+
allowUnauthenticatedReindex: Boolean(args["allow-unauthenticated-reindex"] || process.env.LIVING_ATLAS_ALLOW_UNAUTHENTICATED_REINDEX === "1"),
|
|
81
|
+
allowedOrigins: args["allowed-origin"] || process.env.LIVING_ATLAS_ALLOWED_ORIGINS || process.env.BRAIN_ATLAS_ALLOWED_ORIGINS || ""
|
|
82
|
+
});
|
|
83
|
+
const started = await service.listen();
|
|
84
|
+
console.log(`[living-atlas] root = ${debugPaths ? root : "configured Logseq graph"}`);
|
|
85
|
+
if (demoMode) console.log("[living-atlas] demo = public fixture graph");
|
|
86
|
+
console.log(`[living-atlas] snapshot = ${started.snapshot.totals.nodes} nodes / ${started.snapshot.totals.links} links`);
|
|
87
|
+
console.log(`[living-atlas] api = http://${started.bindHost}:${started.port}/api/snapshot`);
|
|
88
|
+
if (requireToken) {
|
|
89
|
+
const appPort = staticDir ? started.port : 5177;
|
|
90
|
+
console.log(`[living-atlas] token-protected reads = enabled`);
|
|
91
|
+
if (!configuredToken) console.log(`[living-atlas] session token = ${localToken}`);
|
|
92
|
+
console.log(`[living-atlas] app token URL = http://${started.bindHost}:${appPort}/#token=${encodeURIComponent(localToken)}`);
|
|
93
|
+
}
|
|
94
|
+
if (staticDir) console.log(`[living-atlas] app = http://${started.bindHost}:${started.port}/`);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
failStartup(error, debugPaths);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
for (const signal of ["SIGINT", "SIGTERM"]) {
|
|
101
|
+
process.once(signal, async () => {
|
|
102
|
+
await service.close();
|
|
103
|
+
process.exit(0);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function defaultCacheDirectory() {
|
|
109
|
+
if (process.env.XDG_CACHE_HOME) return path.join(process.env.XDG_CACHE_HOME, "logseq-graph-living-atlas");
|
|
110
|
+
if (process.platform === "darwin") return path.join(os.homedir(), "Library", "Caches", "logseq-graph-living-atlas");
|
|
111
|
+
if (process.platform === "win32") {
|
|
112
|
+
return path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local"), "logseq-graph-living-atlas");
|
|
113
|
+
}
|
|
114
|
+
return path.join(os.homedir(), ".cache", "logseq-graph-living-atlas");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function createDemoGraphRoot() {
|
|
118
|
+
const cacheDirectory = defaultCacheDirectory();
|
|
119
|
+
fs.mkdirSync(cacheDirectory, { recursive: true });
|
|
120
|
+
return createFixtureGraph({ out: fs.mkdtempSync(path.join(cacheDirectory, "demo-logseq-graph-")) });
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function failStartup(error, debugPaths) {
|
|
124
|
+
const message = String(error?.message || error || "Startup failed");
|
|
125
|
+
console.error(`[living-atlas] ${message}`);
|
|
126
|
+
console.error("[living-atlas] Expected --root to point at a Logseq graph folder containing pages/.");
|
|
127
|
+
console.error("[living-atlas] Try: living-atlas --root /path/to/logseq");
|
|
128
|
+
console.error("[living-atlas] Or run the public fixture: living-atlas --demo");
|
|
129
|
+
if (debugPaths) console.error(error?.stack || error);
|
|
130
|
+
process.exitCode = 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function parseArgs(argv) {
|
|
134
|
+
const parsed = {};
|
|
135
|
+
const valueFlags = new Set(["root", "cache", "port", "static", "token", "allowed-origin"]);
|
|
136
|
+
const booleanFlags = new Set([
|
|
137
|
+
"watch",
|
|
138
|
+
"help",
|
|
139
|
+
"version",
|
|
140
|
+
"debug-paths",
|
|
141
|
+
"no-static",
|
|
142
|
+
"demo",
|
|
143
|
+
"require-token",
|
|
144
|
+
"allow-unauthenticated-read",
|
|
145
|
+
"allow-unauthenticated-reindex"
|
|
146
|
+
]);
|
|
147
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
148
|
+
const arg = argv[index];
|
|
149
|
+
if (!arg.startsWith("--")) continue;
|
|
150
|
+
const inline = arg.match(/^--([^=]+)=(.*)$/);
|
|
151
|
+
if (inline) {
|
|
152
|
+
parsed[inline[1]] = inline[2];
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const key = arg.slice(2);
|
|
156
|
+
if (booleanFlags.has(key)) {
|
|
157
|
+
parsed[key] = true;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (valueFlags.has(key)) {
|
|
161
|
+
parsed[key] = argv[index + 1];
|
|
162
|
+
index += 1;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return parsed;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function printHelp() {
|
|
169
|
+
console.log(`Living Atlas ${packageJson.version}
|
|
170
|
+
|
|
171
|
+
Usage:
|
|
172
|
+
living-atlas --root /path/to/logseq [options]
|
|
173
|
+
npx logseq-graph-living-atlas --root /path/to/logseq
|
|
174
|
+
npx logseq-graph-living-atlas --demo
|
|
175
|
+
|
|
176
|
+
Options:
|
|
177
|
+
--root <path> Logseq graph folder containing pages/. journals/ is optional.
|
|
178
|
+
--demo Run a public fixture graph without needing Logseq data.
|
|
179
|
+
--port <number> Local port. Defaults to 8787.
|
|
180
|
+
--cache <path> Snapshot cache path outside the graph.
|
|
181
|
+
--static <path> Static UI directory. Defaults to packaged dist/ when present.
|
|
182
|
+
--no-static Serve API only.
|
|
183
|
+
--watch Watch pages/ and journals/ for markdown changes.
|
|
184
|
+
--token <value> Local API token. Required for reads when token mode is enabled.
|
|
185
|
+
--require-token Require the token for every /api/* read and write route.
|
|
186
|
+
--allow-unauthenticated-read
|
|
187
|
+
Allow local API reads without a token for trusted development.
|
|
188
|
+
--allow-unauthenticated-reindex
|
|
189
|
+
Allow POST /api/reindex without a token for local development.
|
|
190
|
+
--allowed-origin <origin> Add a local browser origin for split dev CORS.
|
|
191
|
+
--debug-paths Include absolute diagnostic paths and detailed errors.
|
|
192
|
+
--version Print version.
|
|
193
|
+
--help Print this help.
|
|
194
|
+
|
|
195
|
+
Examples:
|
|
196
|
+
npx logseq-graph-living-atlas --demo
|
|
197
|
+
npx logseq-graph-living-atlas --root ~/Documents/Logseq
|
|
198
|
+
living-atlas --root ~/Documents/Logseq --port 8787 --watch
|
|
199
|
+
LIVING_ATLAS_TOKEN=<random-local-token> LIVING_ATLAS_ALLOWED_ORIGINS=http://127.0.0.1:5177 npm run dev:api -- --root ~/Documents/Logseq
|
|
200
|
+
`);
|
|
201
|
+
}
|