@ryanstark24/sfgraph-web 1.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.
@@ -0,0 +1,17 @@
1
+ export interface ServeOpts {
2
+ port?: number;
3
+ host?: string;
4
+ log?: (s: string) => void;
5
+ }
6
+ export interface ServeHandle {
7
+ port: number;
8
+ url: string;
9
+ stop(): Promise<void>;
10
+ }
11
+ /**
12
+ * Boot the local web visualiser. Returns a handle the caller can use to
13
+ * stop the server cleanly. The server binds to localhost by default to
14
+ * avoid accidentally exposing the ingested graph on the network.
15
+ */
16
+ export declare function startWebServer(opts?: ServeOpts): Promise<ServeHandle>;
17
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAwJA,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,GAAE,SAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAmC/E"}
package/dist/server.js ADDED
@@ -0,0 +1,179 @@
1
+ import { readFile, stat } from "node:fs/promises";
2
+ import { createServer } from "node:http";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { ALL_REL_TYPES, closeAllStores, fullGraph, listOrgs, neighborhood, overview, schema, search, validOrgId, } from "./api.js";
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+ const PUBLIC_DIR = path.resolve(__dirname, "public");
9
+ const MIME = {
10
+ ".html": "text/html; charset=utf-8",
11
+ ".js": "application/javascript; charset=utf-8",
12
+ ".mjs": "application/javascript; charset=utf-8",
13
+ ".css": "text/css; charset=utf-8",
14
+ ".json": "application/json; charset=utf-8",
15
+ ".svg": "image/svg+xml",
16
+ ".ico": "image/x-icon",
17
+ };
18
+ function sendJson(res, status, body) {
19
+ res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" });
20
+ res.end(JSON.stringify(body));
21
+ }
22
+ function sendText(res, status, body) {
23
+ res.writeHead(status, { "Content-Type": "text/plain; charset=utf-8" });
24
+ res.end(body);
25
+ }
26
+ async function serveStatic(res, urlPath) {
27
+ // Resolve to PUBLIC_DIR and reject anything that escapes it (path traversal).
28
+ // Using `path.relative` instead of `startsWith` avoids the classic prefix
29
+ // trap on Windows: `C:\app\public` is a prefix of `C:\app\public_evil\...`
30
+ // but `path.relative(PUBLIC_DIR, abs)` would yield `..\public_evil\...`
31
+ // and be rejected.
32
+ const rel = urlPath === "/" ? "/index.html" : urlPath;
33
+ const abs = path.resolve(PUBLIC_DIR, `.${rel}`);
34
+ const insideRel = path.relative(PUBLIC_DIR, abs);
35
+ if (insideRel.startsWith("..") || path.isAbsolute(insideRel)) {
36
+ sendText(res, 403, "forbidden");
37
+ return;
38
+ }
39
+ try {
40
+ const s = await stat(abs);
41
+ if (!s.isFile()) {
42
+ sendText(res, 404, "not found");
43
+ return;
44
+ }
45
+ const ext = path.extname(abs).toLowerCase();
46
+ const mime = MIME[ext] ?? "application/octet-stream";
47
+ const body = await readFile(abs);
48
+ res.writeHead(200, { "Content-Type": mime, "Cache-Control": "no-cache" });
49
+ res.end(body);
50
+ }
51
+ catch {
52
+ sendText(res, 404, "not found");
53
+ }
54
+ }
55
+ function parseQuery(url) {
56
+ const idx = url.indexOf("?");
57
+ return new URLSearchParams(idx >= 0 ? url.slice(idx + 1) : "");
58
+ }
59
+ function requireOrgId(qs, res) {
60
+ const org = qs.get("org");
61
+ if (!org || !validOrgId(org)) {
62
+ sendJson(res, 400, { error: "missing or invalid 'org' query param (expected 15/18-char id)" });
63
+ return null;
64
+ }
65
+ return org;
66
+ }
67
+ async function handleApi(req, res, url) {
68
+ const qs = parseQuery(url);
69
+ const pathOnly = url.split("?")[0];
70
+ try {
71
+ if (pathOnly === "/api/orgs") {
72
+ // Returns { orgs, errors }. Errors are logged to stderr too; surface
73
+ // them in the response so the UI can show "why no orgs?" without the
74
+ // user having to check terminal logs. Empty errors[] = success.
75
+ sendJson(res, 200, await listOrgs());
76
+ return;
77
+ }
78
+ if (pathOnly === "/api/rel-types") {
79
+ sendJson(res, 200, ALL_REL_TYPES);
80
+ return;
81
+ }
82
+ if (pathOnly === "/api/search") {
83
+ const org = requireOrgId(qs, res);
84
+ if (!org)
85
+ return;
86
+ const q = qs.get("q") ?? "";
87
+ const limit = Math.min(100, Number.parseInt(qs.get("limit") ?? "25", 10) || 25);
88
+ sendJson(res, 200, await search(org, q, limit));
89
+ return;
90
+ }
91
+ if (pathOnly === "/api/neighborhood") {
92
+ const org = requireOrgId(qs, res);
93
+ if (!org)
94
+ return;
95
+ const qname = qs.get("qname") ?? "";
96
+ if (!qname) {
97
+ sendJson(res, 400, { error: "missing 'qname'" });
98
+ return;
99
+ }
100
+ const depth = Math.min(4, Math.max(1, Number.parseInt(qs.get("depth") ?? "2", 10) || 2));
101
+ const rels = qs.get("rels");
102
+ const relTypes = rels ? rels.split(",").filter(Boolean) : undefined;
103
+ sendJson(res, 200, await neighborhood(org, qname, depth, relTypes));
104
+ return;
105
+ }
106
+ if (pathOnly === "/api/overview") {
107
+ const org = requireOrgId(qs, res);
108
+ if (!org)
109
+ return;
110
+ const labels = (qs.get("labels") ?? "").split(",").filter(Boolean);
111
+ if (labels.length === 0) {
112
+ sendJson(res, 400, { error: "missing 'labels' (comma-separated)" });
113
+ return;
114
+ }
115
+ const limit = Math.min(5000, Number.parseInt(qs.get("limit") ?? "1500", 10) || 1500);
116
+ sendJson(res, 200, await overview(org, labels, limit));
117
+ return;
118
+ }
119
+ if (pathOnly === "/api/full") {
120
+ const org = requireOrgId(qs, res);
121
+ if (!org)
122
+ return;
123
+ const limit = Math.min(15_000, Number.parseInt(qs.get("limit") ?? "5000", 10) || 5000);
124
+ sendJson(res, 200, await fullGraph(org, limit));
125
+ return;
126
+ }
127
+ if (pathOnly === "/api/schema") {
128
+ const org = requireOrgId(qs, res);
129
+ if (!org)
130
+ return;
131
+ const limit = Math.min(5000, Number.parseInt(qs.get("limit") ?? "1500", 10) || 1500);
132
+ sendJson(res, 200, await schema(org, limit));
133
+ return;
134
+ }
135
+ sendJson(res, 404, { error: `unknown api path ${pathOnly}` });
136
+ }
137
+ catch (e) {
138
+ sendJson(res, 500, { error: e.message ?? String(e) });
139
+ }
140
+ }
141
+ /**
142
+ * Boot the local web visualiser. Returns a handle the caller can use to
143
+ * stop the server cleanly. The server binds to localhost by default to
144
+ * avoid accidentally exposing the ingested graph on the network.
145
+ */
146
+ export async function startWebServer(opts = {}) {
147
+ const host = opts.host ?? "127.0.0.1";
148
+ const port = opts.port ?? 7777;
149
+ const log = opts.log ?? ((s) => console.log(s));
150
+ const server = createServer((req, res) => {
151
+ const url = req.url ?? "/";
152
+ if (url.startsWith("/api/")) {
153
+ void handleApi(req, res, url);
154
+ }
155
+ else {
156
+ void serveStatic(res, url.split("?")[0] ?? "/");
157
+ }
158
+ });
159
+ await new Promise((resolve, reject) => {
160
+ server.once("error", reject);
161
+ server.listen(port, host, () => {
162
+ server.off("error", reject);
163
+ resolve();
164
+ });
165
+ });
166
+ const addr = server.address();
167
+ const actualPort = typeof addr === "object" && addr ? addr.port : port;
168
+ const url = `http://${host}:${actualPort}`;
169
+ log(`sfgraph-web listening at ${url}`);
170
+ return {
171
+ port: actualPort,
172
+ url,
173
+ async stop() {
174
+ await new Promise((resolve) => server.close(() => resolve()));
175
+ await closeAllStores();
176
+ },
177
+ };
178
+ }
179
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@ryanstark24/sfgraph-web",
3
+ "version": "1.1.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "dependencies": {
14
+ "@ryanstark24/sfgraph-core": "1.1.0",
15
+ "@ryanstark24/sfgraph-shared": "1.1.0"
16
+ },
17
+ "devDependencies": {
18
+ "@biomejs/biome": "^1.9.0",
19
+ "@types/node": "^22.0.0",
20
+ "typescript": "^5.6.0",
21
+ "vitest": "^3.2.4"
22
+ },
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/ryanStark24/sfgraph"
27
+ },
28
+ "engines": {
29
+ "node": ">=20"
30
+ },
31
+ "publishConfig": {
32
+ "access": "public"
33
+ },
34
+ "description": "sfgraph local web visualiser — graph explorer for ingested orgs",
35
+ "files": [
36
+ "dist",
37
+ "README.md"
38
+ ],
39
+ "scripts": {
40
+ "build": "tsc -p tsconfig.json && node --input-type=module -e \"import {cpSync,mkdirSync} from 'node:fs'; mkdirSync('dist/public',{recursive:true}); cpSync('public','dist/public',{recursive:true});\"",
41
+ "test": "vitest run --passWithNoTests",
42
+ "lint": "biome check src",
43
+ "lint:fix": "biome check --write src",
44
+ "typecheck": "tsc -p tsconfig.json --noEmit",
45
+ "clean": "rm -rf dist"
46
+ }
47
+ }