@lumencast/dev-server 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/dist/server.js ADDED
@@ -0,0 +1,422 @@
1
+ // Mock LSDP/1 server for Lumencast SDK tests.
2
+ //
3
+ // Behaviour parity with a real LSDP/1 server (LSDP/1 spec):
4
+ // - WebSocket subprotocol negotiation: `lsdp.v1`
5
+ // - subscribe → snapshot(seq=1) → delta(seq=2,3,...)
6
+ // - scene_changed(seq=N) → snapshot(seq=1) (sequence reset)
7
+ // - error frame on malformed input (taxonomy-aligned codes)
8
+ //
9
+ // What it skips: auth (any token accepted), rate limiting, persistence.
10
+ import { existsSync, readFileSync } from "node:fs";
11
+ import { createServer } from "node:http";
12
+ import { dirname, resolve as resolvePath } from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+ import { WebSocketServer } from "ws";
15
+ import { delta as deltaFrame, decodeClientFrame, encodeFrame, errorFrame, pong, sceneChanged as sceneChangedFrame, snapshot as snapshotFrame, WS_SUBPROTOCOL, WS_SUBPROTOCOL_V1_1, } from "@lumencast/protocol";
16
+ export async function startDevServer(config) {
17
+ let activeSceneId = config.initialSceneId;
18
+ let activeSceneVersion = config.initialSceneVersion;
19
+ let activeState = { ...config.initialState };
20
+ const bundles = new Map();
21
+ bundles.set(config.initialSceneVersion, config.initialBundle);
22
+ const subscribers = new Set();
23
+ const httpServer = createServer((req, res) => handleHttp(req, res));
24
+ await new Promise((resolve, reject) => {
25
+ httpServer.once("error", reject);
26
+ httpServer.listen(config.port ?? 0, config.host ?? "127.0.0.1", () => {
27
+ httpServer.off("error", reject);
28
+ resolve();
29
+ });
30
+ });
31
+ const address = httpServer.address();
32
+ if (!address || typeof address === "string") {
33
+ throw new Error("dev-server: failed to bind HTTP server");
34
+ }
35
+ const host = config.host ?? "127.0.0.1";
36
+ const port = address.port;
37
+ const wss = new WebSocketServer({
38
+ server: httpServer,
39
+ handleProtocols: (offered) => {
40
+ // LSDP/1.1 preferred, 1.0 fallback.
41
+ if (offered.has(WS_SUBPROTOCOL_V1_1))
42
+ return WS_SUBPROTOCOL_V1_1;
43
+ if (offered.has(WS_SUBPROTOCOL))
44
+ return WS_SUBPROTOCOL;
45
+ return false;
46
+ },
47
+ });
48
+ wss.on("connection", (socket) => {
49
+ const sub = { ws: socket, seq: 0 };
50
+ subscribers.add(sub);
51
+ socket.on("message", (data) => handleMessage(sub, String(data)));
52
+ socket.on("close", () => {
53
+ subscribers.delete(sub);
54
+ });
55
+ });
56
+ function handleMessage(sub, raw) {
57
+ let frame;
58
+ try {
59
+ frame = decodeClientFrame(raw);
60
+ }
61
+ catch {
62
+ sendError(sub, "INVALID_VALUE", "malformed client frame", false);
63
+ sub.ws.close(1002, "INVALID_VALUE");
64
+ return;
65
+ }
66
+ if (frame === null)
67
+ return; // unknown frame type — forward-compat ignore
68
+ switch (frame.type) {
69
+ case "subscribe": {
70
+ sub.seq = 1;
71
+ send(sub, snapshotFrame({
72
+ seq: 1,
73
+ scene_id: activeSceneId,
74
+ scene_version: activeSceneVersion,
75
+ state: { ...activeState },
76
+ ts: new Date().toISOString(),
77
+ }));
78
+ return;
79
+ }
80
+ case "input": {
81
+ // Mock-mode echoes inputs as deltas to all subscribers.
82
+ broadcastDelta(frame.patches);
83
+ return;
84
+ }
85
+ case "ping": {
86
+ send(sub, pong());
87
+ return;
88
+ }
89
+ }
90
+ }
91
+ function broadcastDelta(patches) {
92
+ for (const p of patches)
93
+ activeState[p.path] = p.value;
94
+ for (const sub of subscribers) {
95
+ sub.seq += 1;
96
+ send(sub, deltaFrame({ seq: sub.seq, patches }));
97
+ }
98
+ }
99
+ function pushDelta(patches) {
100
+ broadcastDelta(patches);
101
+ }
102
+ function switchScene(args) {
103
+ activeSceneId = args.sceneId;
104
+ activeSceneVersion = args.sceneVersion;
105
+ activeState = { ...args.state };
106
+ bundles.set(args.sceneVersion, args.bundle);
107
+ for (const sub of subscribers) {
108
+ sub.seq += 1;
109
+ send(sub, sceneChangedFrame({
110
+ seq: sub.seq,
111
+ scene_id: args.sceneId,
112
+ scene_version: args.sceneVersion,
113
+ }));
114
+ // LSDP/1 §3.3: the next server frame after scene_changed is a snapshot
115
+ // for the new scene with seq = 1.
116
+ sub.seq = 1;
117
+ send(sub, snapshotFrame({
118
+ seq: 1,
119
+ scene_id: args.sceneId,
120
+ scene_version: args.sceneVersion,
121
+ state: { ...activeState },
122
+ ts: new Date().toISOString(),
123
+ }));
124
+ }
125
+ }
126
+ function registerBundle(version, bundle) {
127
+ bundles.set(version, bundle);
128
+ }
129
+ function send(sub, frame) {
130
+ if (sub.ws.readyState !== sub.ws.OPEN)
131
+ return;
132
+ sub.ws.send(encodeFrame(frame));
133
+ }
134
+ function sendError(sub, code, message, recoverable) {
135
+ sub.seq += 1;
136
+ send(sub, errorFrame({ seq: sub.seq, code, message, recoverable }));
137
+ }
138
+ function handleHttp(req, res) {
139
+ res.setHeader("access-control-allow-origin", "*");
140
+ res.setHeader("access-control-allow-methods", "GET, POST, OPTIONS");
141
+ res.setHeader("access-control-allow-headers", "*");
142
+ if (req.method === "OPTIONS") {
143
+ res.statusCode = 204;
144
+ res.end();
145
+ return;
146
+ }
147
+ const url = req.url ?? "/";
148
+ if (req.method === "GET" && url === "/lsdp/v1/health") {
149
+ writeJson(res, 200, { status: "ok" });
150
+ return;
151
+ }
152
+ // GET /lsdp/v1/scenes/{id}/bundle?v=sha256:...
153
+ const bundleMatch = url.match(/^\/lsdp\/v1\/scenes\/([^/?]+)\/bundle(?:\?v=([^&]+))?$/);
154
+ if (req.method === "GET" && bundleMatch) {
155
+ const versionParam = bundleMatch[2] ? decodeURIComponent(bundleMatch[2]) : undefined;
156
+ const bundle = versionParam ? bundles.get(versionParam) : bundles.get(activeSceneVersion);
157
+ if (!bundle) {
158
+ writeJson(res, 404, { error: "bundle_not_found" });
159
+ return;
160
+ }
161
+ res.statusCode = 200;
162
+ res.setHeader("content-type", "application/json");
163
+ res.setHeader("cache-control", "public, max-age=31536000, immutable");
164
+ res.end(JSON.stringify(bundle));
165
+ return;
166
+ }
167
+ if (req.method === "POST" && url === "/__mock/delta") {
168
+ readJson(req)
169
+ .then((body) => {
170
+ const patches = body.patches;
171
+ pushDelta(patches);
172
+ res.statusCode = 204;
173
+ res.end();
174
+ })
175
+ .catch((err) => writeJson(res, 400, { error: String(err) }));
176
+ return;
177
+ }
178
+ if (req.method === "POST" && url === "/__mock/scene-changed") {
179
+ readJson(req)
180
+ .then((body) => {
181
+ switchScene(body);
182
+ res.statusCode = 204;
183
+ res.end();
184
+ })
185
+ .catch((err) => writeJson(res, 400, { error: String(err) }));
186
+ return;
187
+ }
188
+ if (req.method === "POST" && url === "/__mock/register-bundle") {
189
+ readJson(req)
190
+ .then((body) => {
191
+ const { sceneVersion, bundle } = body;
192
+ registerBundle(sceneVersion, bundle);
193
+ res.statusCode = 204;
194
+ res.end();
195
+ })
196
+ .catch((err) => writeJson(res, 400, { error: String(err) }));
197
+ return;
198
+ }
199
+ // Demo host (optional) — serves a static HTML at `/` and the
200
+ // runtime bundle at `/lumencast.js` so a developer can open the
201
+ // server URL in a browser and see the scene render live without
202
+ // any external Vite/build step.
203
+ if (config.demoHost && req.method === "GET" && (url === "/" || url === "/index.html")) {
204
+ const wsUrl = `ws://${host}:${port}/lsdp/v1`;
205
+ const title = config.demoHost.title ?? "Lumencast demo";
206
+ const html = renderDemoHostHtml({ wsUrl, title });
207
+ res.statusCode = 200;
208
+ res.setHeader("content-type", "text/html; charset=utf-8");
209
+ res.end(html);
210
+ return;
211
+ }
212
+ if (config.demoHost && req.method === "GET" && isStaticAssetPath(url)) {
213
+ const bundlePath = resolveRuntimeBundlePath(config.demoHost.runtimeBundlePath);
214
+ if (!bundlePath) {
215
+ writeJson(res, 500, {
216
+ error: "runtime_bundle_not_found",
217
+ hint: "pnpm --filter @lumencast/runtime build (or pass demoHost.runtimeBundlePath)",
218
+ });
219
+ return;
220
+ }
221
+ // The runtime bundle is split into chunks. Serve any file under
222
+ // its dist/ tree by name, sandboxed to that directory.
223
+ const distDir = dirname(bundlePath);
224
+ const requested = url.split("?")[0].replace(/^\//, "");
225
+ const filePath = resolvePath(distDir, requested);
226
+ // Sandbox check : file must live under distDir.
227
+ if (!filePath.startsWith(distDir)) {
228
+ writeJson(res, 400, { error: "path_traversal" });
229
+ return;
230
+ }
231
+ if (!existsSync(filePath)) {
232
+ writeJson(res, 404, { error: "static_not_found", path: requested });
233
+ return;
234
+ }
235
+ try {
236
+ const body = readFileSync(filePath);
237
+ res.statusCode = 200;
238
+ res.setHeader("content-type", contentTypeFor(requested));
239
+ res.setHeader("cache-control", "no-store");
240
+ res.end(body);
241
+ }
242
+ catch (e) {
243
+ writeJson(res, 500, { error: "static_read_failed", detail: String(e) });
244
+ }
245
+ return;
246
+ }
247
+ if (req.method === "POST" && url === "/__mock/reset") {
248
+ activeSceneId = config.initialSceneId;
249
+ activeSceneVersion = config.initialSceneVersion;
250
+ activeState = { ...config.initialState };
251
+ bundles.clear();
252
+ bundles.set(config.initialSceneVersion, config.initialBundle);
253
+ res.statusCode = 204;
254
+ res.end();
255
+ return;
256
+ }
257
+ writeJson(res, 404, { error: "not_found" });
258
+ }
259
+ async function close() {
260
+ for (const sub of subscribers) {
261
+ try {
262
+ sub.ws.close(1000, "shutdown");
263
+ }
264
+ catch {
265
+ // ignore
266
+ }
267
+ }
268
+ subscribers.clear();
269
+ await new Promise((resolve) => wss.close(() => resolve()));
270
+ await new Promise((resolve) => httpServer.close(() => resolve()));
271
+ }
272
+ return {
273
+ wsUrl: `ws://${host}:${port}/lsdp/v1`,
274
+ httpUrl: `http://${host}:${port}`,
275
+ registerBundle,
276
+ pushDelta,
277
+ switchScene,
278
+ close,
279
+ };
280
+ }
281
+ function writeJson(res, status, body) {
282
+ res.statusCode = status;
283
+ res.setHeader("content-type", "application/json");
284
+ res.end(JSON.stringify(body));
285
+ }
286
+ async function readJson(req) {
287
+ const chunks = [];
288
+ for await (const chunk of req) {
289
+ chunks.push(chunk);
290
+ }
291
+ const body = Buffer.concat(chunks).toString("utf8");
292
+ return body.length === 0 ? {} : JSON.parse(body);
293
+ }
294
+ /**
295
+ * Resolve the on-disk path of `@lumencast/runtime`'s built bundle.
296
+ * Walks up from this file's directory looking for the workspace's
297
+ * `packages/runtime/dist/lumencast.js`. Returns the override when
298
+ * provided.
299
+ */
300
+ /** Heuristic : a static asset request looks like `/something.ext`
301
+ * (single segment, with extension), and isn't an LSDP API path or a
302
+ * mock control plane path. The dev-server's other GET routes are
303
+ * matched before this one, so this only fires when nothing else
304
+ * caught the URL. */
305
+ function isStaticAssetPath(url) {
306
+ const path = url.split("?")[0] ?? "/";
307
+ if (path === "/" || path === "/index.html")
308
+ return false; // handled above
309
+ if (path.startsWith("/lsdp/") || path.startsWith("/__mock/"))
310
+ return false;
311
+ return /\.[a-zA-Z0-9]{1,8}$/.test(path);
312
+ }
313
+ function contentTypeFor(filename) {
314
+ const lower = filename.toLowerCase();
315
+ if (lower.endsWith(".js") || lower.endsWith(".mjs"))
316
+ return "application/javascript; charset=utf-8";
317
+ if (lower.endsWith(".css"))
318
+ return "text/css; charset=utf-8";
319
+ if (lower.endsWith(".html"))
320
+ return "text/html; charset=utf-8";
321
+ if (lower.endsWith(".json") || lower.endsWith(".map"))
322
+ return "application/json; charset=utf-8";
323
+ if (lower.endsWith(".svg"))
324
+ return "image/svg+xml";
325
+ if (lower.endsWith(".png"))
326
+ return "image/png";
327
+ if (lower.endsWith(".woff2"))
328
+ return "font/woff2";
329
+ return "application/octet-stream";
330
+ }
331
+ function resolveRuntimeBundlePath(override) {
332
+ if (override) {
333
+ return existsSync(override) ? override : null;
334
+ }
335
+ // Best-effort workspace lookup. dev-server lives at
336
+ // packages/dev-server/src/server.ts ; the runtime bundle lives at
337
+ // packages/runtime/dist/lumencast.js relative to the same workspace
338
+ // root.
339
+ const here = dirname(fileURLToPath(import.meta.url));
340
+ const candidates = [
341
+ resolvePath(here, "../../runtime/dist/lumencast.js"),
342
+ resolvePath(here, "../../../runtime/dist/lumencast.js"),
343
+ resolvePath(process.cwd(), "node_modules/@lumencast/runtime/dist/lumencast.js"),
344
+ resolvePath(process.cwd(), "packages/runtime/dist/lumencast.js"),
345
+ ];
346
+ for (const c of candidates) {
347
+ if (existsSync(c))
348
+ return c;
349
+ }
350
+ return null;
351
+ }
352
+ /** Render the static demo HTML host. The page mounts the runtime
353
+ * against the same dev-server's WS endpoint and watches the scene
354
+ * update live.
355
+ *
356
+ * The runtime is built as ES modules with externalised peer deps
357
+ * (react, framer-motion, @preact/signals-react, etc). The demo HTML
358
+ * uses an importmap to resolve those bare specifiers to esm.sh CDN
359
+ * URLs so the browser can load everything without a bundler.
360
+ *
361
+ * @lumencast/protocol is also externalised — we map it back to the
362
+ * runtime's own dist relative path because it travels with the bundle.
363
+ */
364
+ function renderDemoHostHtml(opts) {
365
+ const importMap = {
366
+ imports: {
367
+ react: "https://esm.sh/react@19?dev",
368
+ "react/jsx-runtime": "https://esm.sh/react@19/jsx-runtime?dev",
369
+ "react/jsx-dev-runtime": "https://esm.sh/react@19/jsx-dev-runtime?dev",
370
+ "react-dom": "https://esm.sh/react-dom@19?dev",
371
+ "react-dom/client": "https://esm.sh/react-dom@19/client?dev",
372
+ "framer-motion": "https://esm.sh/framer-motion@12?dev&deps=react@19,react-dom@19",
373
+ "@preact/signals-react": "https://esm.sh/@preact/signals-react@3?dev&deps=react@19,react-dom@19",
374
+ "@preact/signals-react/runtime": "https://esm.sh/@preact/signals-react@3/runtime?dev&deps=react@19,react-dom@19",
375
+ "@lumencast/protocol": "https://esm.sh/@lumencast/protocol",
376
+ },
377
+ };
378
+ return `<!doctype html>
379
+ <html lang="en">
380
+ <head>
381
+ <meta charset="utf-8" />
382
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
383
+ <title>${escapeHtml(opts.title)}</title>
384
+ <style>
385
+ html, body { margin: 0; padding: 0; height: 100%; background: #000; color: #fff; font-family: system-ui, sans-serif; }
386
+ #scene { position: relative; width: 100vw; height: 100vh; overflow: hidden; }
387
+ #lumencast-error { position: fixed; bottom: 0; left: 0; right: 0; padding: 12px; background: #b00020; font-family: monospace; font-size: 12px; display: none; white-space: pre-wrap; }
388
+ #lumencast-status { position: fixed; top: 8px; right: 8px; padding: 4px 8px; font-family: monospace; font-size: 11px; background: rgba(0,0,0,0.5); border-radius: 4px; opacity: 0.7; }
389
+ </style>
390
+ <script type="importmap">${JSON.stringify(importMap)}</script>
391
+ </head>
392
+ <body>
393
+ <div id="scene" data-testid="lumencast-scene-root"></div>
394
+ <div id="lumencast-status">connecting…</div>
395
+ <div id="lumencast-error"></div>
396
+ <script type="module">
397
+ import { mount } from "/lumencast.js";
398
+
399
+ const target = document.getElementById("scene");
400
+ const status = document.getElementById("lumencast-status");
401
+ const errBox = document.getElementById("lumencast-error");
402
+
403
+ mount({
404
+ target,
405
+ serverUrl: ${JSON.stringify(opts.wsUrl)},
406
+ token: "demo",
407
+ mode: "broadcast",
408
+ onStatus: (s) => { status.textContent = s; },
409
+ onError: (err) => {
410
+ errBox.style.display = "block";
411
+ errBox.textContent = "[lumencast] " + (err && err.message ? err.message : String(err));
412
+ console.error("[lumencast]", err);
413
+ },
414
+ });
415
+ </script>
416
+ </body>
417
+ </html>`;
418
+ }
419
+ function escapeHtml(s) {
420
+ return s.replace(/[&<>"']/g, (c) => c === "&" ? "&amp;" : c === "<" ? "&lt;" : c === ">" ? "&gt;" : c === '"' ? "&quot;" : "&#39;");
421
+ }
422
+ //# 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,46 @@
1
+ {
2
+ "name": "@lumencast/dev-server",
3
+ "version": "0.1.0",
4
+ "description": "Mock LSDP/1 server for tests — WS protocol + HTTP bundle serving + /__mock/* control plane.",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "src"
19
+ ],
20
+ "homepage": "https://github.com/Lumencast/lumencast-js/tree/main/packages/dev-server",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/Lumencast/lumencast-js.git",
24
+ "directory": "packages/dev-server"
25
+ },
26
+ "engines": {
27
+ "node": ">=22"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "registry": "https://registry.npmjs.org/"
32
+ },
33
+ "dependencies": {
34
+ "ws": "^8.18.0",
35
+ "@lumencast/protocol": "0.1.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/ws": "^8.5.13",
39
+ "vitest": "^4.1.5"
40
+ },
41
+ "scripts": {
42
+ "build": "tsc -b",
43
+ "typecheck": "tsc -b --pretty",
44
+ "test": "vitest run"
45
+ }
46
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ // Public surface of @lumencast/dev-server.
2
+
3
+ export { startDevServer, type DevServer, type DevServerConfig } from "./server.js";