chisel-studio 0.1.0 → 0.1.2
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/README.md +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -0
- package/dist/index.mjs.map +1 -1
- package/dist/ui/assets/index-DI8TefNH.js +2699 -0
- package/dist/ui/index.html +1 -1
- package/package.json +4 -4
- package/dist/ui/assets/index-B2dja40T.js +0 -2607
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -176,6 +176,10 @@ function resolveUiDir() {
|
|
|
176
176
|
}
|
|
177
177
|
function createStudioApp(engine) {
|
|
178
178
|
const app = new hono.Hono();
|
|
179
|
+
app.onError((err, c) => {
|
|
180
|
+
console.error(`[studio] ${c.req.method} ${c.req.path} error:`, err);
|
|
181
|
+
return c.json({ error: err.message }, 500);
|
|
182
|
+
});
|
|
179
183
|
app.use("*", cors.cors());
|
|
180
184
|
app.route("/api", createApiRoutes(engine));
|
|
181
185
|
app.route("/api", createSseRoute(engine));
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/api.ts","../src/routes/sse.ts","../src/static.ts","../src/server.ts","../src/index.ts"],"names":["Hono","streamSSE","join","existsSync","readFileSync","extname","cors","serve"],"mappings":"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","file":"index.js","sourcesContent":["import { Hono } from \"hono\";\nimport type { Engine } from \"chisel-engine\";\nimport type { RunStatus } from \"chisel-engine\";\n\nexport function createApiRoutes(engine: Engine): Hono {\n const app = new Hono();\n\n // Health check\n app.get(\"/health\", async (c) => {\n const health = await engine.health();\n return c.json(health, health.connected ? 200 : 503);\n });\n\n // List registered workflows\n app.get(\"/workflows\", (c) => {\n return c.json(engine.listWorkflows());\n });\n\n // List runs for a workflow\n app.get(\"/workflows/:id/runs\", async (c) => {\n const id = c.req.param(\"id\");\n const query = c.req.query();\n\n const result = await engine.listRuns(id, {\n limit: query.limit ? Number(query.limit) : undefined,\n cursor: query.cursor ? Number(query.cursor) : undefined,\n order: query.order as \"asc\" | \"desc\" | undefined,\n status: query.status as RunStatus | undefined,\n });\n\n return c.json(result);\n });\n\n // Get run detail\n app.get(\"/runs/:runId\", async (c) => {\n const runId = c.req.param(\"runId\");\n const run = await engine.getRun(runId);\n\n if (!run) {\n return c.json({ error: \"Run not found\" }, 404);\n }\n\n return c.json(run);\n });\n\n // Cancel a run\n app.post(\"/runs/:runId/cancel\", async (c) => {\n const runId = c.req.param(\"runId\");\n\n try {\n await engine.cancelRun(runId);\n return c.json({ success: true });\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n // Retry a failed run\n app.post(\"/runs/:runId/retry\", async (c) => {\n const runId = c.req.param(\"runId\");\n\n try {\n await engine.retryRun(runId);\n return c.json({ success: true });\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n // Trigger a workflow\n app.post(\"/workflows/:id/trigger\", async (c) => {\n const id = c.req.param(\"id\");\n\n try {\n const body = await c.req.json();\n const { runId } = await engine.trigger(id, body);\n return c.json({ runId }, 202);\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport type { Engine, EngineEventName } from \"chisel-engine\";\n\nconst ENGINE_EVENTS: EngineEventName[] = [\n \"workflow:start\",\n \"workflow:complete\",\n \"workflow:fail\",\n \"step:start\",\n \"step:complete\",\n \"step:fail\",\n \"step:retry\",\n];\n\nexport function createSseRoute(engine: Engine): Hono {\n const app = new Hono();\n\n app.get(\"/events\", (c) => {\n return streamSSE(c, async (stream) => {\n const handlers = new Map<string, (payload: unknown) => void>();\n\n for (const event of ENGINE_EVENTS) {\n const handler = (payload: unknown) => {\n stream\n .writeSSE({\n event,\n data: JSON.stringify(payload, (_key, value) =>\n value instanceof Error\n ? { message: value.message, name: value.name }\n : value\n ),\n })\n .catch(() => {});\n };\n handlers.set(event, handler);\n engine.on(event, handler as any);\n }\n\n // Heartbeat every 15 seconds\n const heartbeat = setInterval(() => {\n stream\n .writeSSE({\n event: \"heartbeat\",\n data: JSON.stringify({ time: Date.now() }),\n })\n .catch(() => {});\n }, 15_000);\n\n // Keep the stream alive until client disconnects\n try {\n while (true) {\n await stream.sleep(1000);\n }\n } finally {\n clearInterval(heartbeat);\n for (const [event, handler] of handlers) {\n engine.off(event as EngineEventName, handler as any);\n }\n }\n });\n });\n\n return app;\n}\n","import { readFileSync, existsSync } from \"fs\";\nimport { join, extname } from \"path\";\nimport type { Context } from \"hono\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".js\": \"application/javascript; charset=utf-8\",\n \".mjs\": \"application/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n};\n\nexport function createStaticHandler(uiDir: string) {\n // Pre-load index.html into memory (small file, hot path)\n const indexPath = join(uiDir, \"index.html\");\n let indexHtml = \"\";\n if (existsSync(indexPath)) {\n indexHtml = readFileSync(indexPath, \"utf-8\");\n }\n\n return async (c: Context) => {\n const reqPath = new URL(c.req.url).pathname;\n\n // Try serving static asset\n const filePath = join(uiDir, reqPath);\n if (existsSync(filePath) && reqPath !== \"/\") {\n try {\n const content = readFileSync(filePath);\n const ext = extname(filePath);\n const contentType = MIME_TYPES[ext] || \"application/octet-stream\";\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Cache-Control\": \"public, max-age=31536000, immutable\",\n },\n });\n } catch {\n // Fall through to index.html\n }\n }\n\n // SPA fallback: serve index.html for all non-file routes\n if (!indexHtml) {\n return c.text(\"Studio UI not built. Run: bun run build:ui\", 500);\n }\n return c.html(indexHtml);\n };\n}\n","import { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { join } from \"path\";\nimport { existsSync } from \"fs\";\nimport type { Engine } from \"chisel-engine\";\nimport { createApiRoutes } from \"./routes/api\";\nimport { createSseRoute } from \"./routes/sse\";\nimport { createStaticHandler } from \"./static\";\n\nfunction resolveUiDir(): string {\n // When running from built output: __dirname is dist/, ui is dist/ui/\n const fromDist = join(__dirname, \"ui\");\n if (existsSync(join(fromDist, \"index.html\"))) return fromDist;\n\n // When running from source via bun/tsx: __dirname is src/, ui is ../dist/ui/\n const fromSrc = join(__dirname, \"..\", \"dist\", \"ui\");\n if (existsSync(join(fromSrc, \"index.html\"))) return fromSrc;\n\n // Fallback\n return fromDist;\n}\n\nexport function createStudioApp(engine: Engine): Hono {\n const app = new Hono();\n\n // Enable CORS for development\n app.use(\"*\", cors());\n\n // API routes\n app.route(\"/api\", createApiRoutes(engine));\n\n // SSE events\n app.route(\"/api\", createSseRoute(engine));\n\n // Static SPA assets\n app.get(\"*\", createStaticHandler(resolveUiDir()));\n\n return app;\n}\n","import { serve } from \"@hono/node-server\";\nimport type { Engine } from \"chisel-engine\";\nimport { createStudioApp } from \"./server\";\nimport type { StudioOptions, StudioServer } from \"./types\";\n\nexport type { StudioOptions, StudioServer } from \"./types\";\n\nexport function createStudio(\n engine: Engine,\n options: StudioOptions = {}\n): StudioServer {\n const port = options.port ?? 4040;\n const host = options.host ?? \"localhost\";\n const url = `http://${host}:${port}`;\n\n const app = createStudioApp(engine);\n let server: ReturnType<typeof serve> | null = null;\n\n return {\n get url() {\n return url;\n },\n\n async start() {\n server = serve({ fetch: app.fetch, port, hostname: host });\n\n console.log(`Chisel Studio running at ${url}`);\n\n if (options.open) {\n const { exec } = await import(\"child_process\");\n const cmd =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n exec(`${cmd} ${url}`);\n }\n },\n\n async stop() {\n if (server) {\n server.close();\n server = null;\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/routes/api.ts","../src/routes/sse.ts","../src/static.ts","../src/server.ts","../src/index.ts"],"names":["Hono","streamSSE","join","existsSync","readFileSync","extname","cors","serve"],"mappings":"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","file":"index.js","sourcesContent":["import { Hono } from \"hono\";\nimport type { Engine } from \"chisel-engine\";\nimport type { RunStatus } from \"chisel-engine\";\n\nexport function createApiRoutes(engine: Engine): Hono {\n const app = new Hono();\n\n // Health check\n app.get(\"/health\", async (c) => {\n const health = await engine.health();\n return c.json(health, health.connected ? 200 : 503);\n });\n\n // List registered workflows\n app.get(\"/workflows\", (c) => {\n return c.json(engine.listWorkflows());\n });\n\n // List runs for a workflow\n app.get(\"/workflows/:id/runs\", async (c) => {\n const id = c.req.param(\"id\");\n const query = c.req.query();\n\n const result = await engine.listRuns(id, {\n limit: query.limit ? Number(query.limit) : undefined,\n cursor: query.cursor ? Number(query.cursor) : undefined,\n order: query.order as \"asc\" | \"desc\" | undefined,\n status: query.status as RunStatus | undefined,\n });\n\n return c.json(result);\n });\n\n // Get run detail\n app.get(\"/runs/:runId\", async (c) => {\n const runId = c.req.param(\"runId\");\n const run = await engine.getRun(runId);\n\n if (!run) {\n return c.json({ error: \"Run not found\" }, 404);\n }\n\n return c.json(run);\n });\n\n // Cancel a run\n app.post(\"/runs/:runId/cancel\", async (c) => {\n const runId = c.req.param(\"runId\");\n\n try {\n await engine.cancelRun(runId);\n return c.json({ success: true });\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n // Retry a failed run\n app.post(\"/runs/:runId/retry\", async (c) => {\n const runId = c.req.param(\"runId\");\n\n try {\n await engine.retryRun(runId);\n return c.json({ success: true });\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n // Trigger a workflow\n app.post(\"/workflows/:id/trigger\", async (c) => {\n const id = c.req.param(\"id\");\n\n try {\n const body = await c.req.json();\n const { runId } = await engine.trigger(id, body);\n return c.json({ runId }, 202);\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport type { Engine, EngineEventName } from \"chisel-engine\";\n\nconst ENGINE_EVENTS: EngineEventName[] = [\n \"workflow:start\",\n \"workflow:complete\",\n \"workflow:fail\",\n \"step:start\",\n \"step:complete\",\n \"step:fail\",\n \"step:retry\",\n];\n\nexport function createSseRoute(engine: Engine): Hono {\n const app = new Hono();\n\n app.get(\"/events\", (c) => {\n return streamSSE(c, async (stream) => {\n const handlers = new Map<string, (payload: unknown) => void>();\n\n for (const event of ENGINE_EVENTS) {\n const handler = (payload: unknown) => {\n stream\n .writeSSE({\n event,\n data: JSON.stringify(payload, (_key, value) =>\n value instanceof Error\n ? { message: value.message, name: value.name }\n : value\n ),\n })\n .catch(() => {});\n };\n handlers.set(event, handler);\n engine.on(event, handler as any);\n }\n\n // Heartbeat every 15 seconds\n const heartbeat = setInterval(() => {\n stream\n .writeSSE({\n event: \"heartbeat\",\n data: JSON.stringify({ time: Date.now() }),\n })\n .catch(() => {});\n }, 15_000);\n\n // Keep the stream alive until client disconnects\n try {\n while (true) {\n await stream.sleep(1000);\n }\n } finally {\n clearInterval(heartbeat);\n for (const [event, handler] of handlers) {\n engine.off(event as EngineEventName, handler as any);\n }\n }\n });\n });\n\n return app;\n}\n","import { readFileSync, existsSync } from \"fs\";\nimport { join, extname } from \"path\";\nimport type { Context } from \"hono\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".js\": \"application/javascript; charset=utf-8\",\n \".mjs\": \"application/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n};\n\nexport function createStaticHandler(uiDir: string) {\n // Pre-load index.html into memory (small file, hot path)\n const indexPath = join(uiDir, \"index.html\");\n let indexHtml = \"\";\n if (existsSync(indexPath)) {\n indexHtml = readFileSync(indexPath, \"utf-8\");\n }\n\n return async (c: Context) => {\n const reqPath = new URL(c.req.url).pathname;\n\n // Try serving static asset\n const filePath = join(uiDir, reqPath);\n if (existsSync(filePath) && reqPath !== \"/\") {\n try {\n const content = readFileSync(filePath);\n const ext = extname(filePath);\n const contentType = MIME_TYPES[ext] || \"application/octet-stream\";\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Cache-Control\": \"public, max-age=31536000, immutable\",\n },\n });\n } catch {\n // Fall through to index.html\n }\n }\n\n // SPA fallback: serve index.html for all non-file routes\n if (!indexHtml) {\n return c.text(\"Studio UI not built. Run: bun run build:ui\", 500);\n }\n return c.html(indexHtml);\n };\n}\n","import { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { join } from \"path\";\nimport { existsSync } from \"fs\";\nimport type { Engine } from \"chisel-engine\";\nimport { createApiRoutes } from \"./routes/api\";\nimport { createSseRoute } from \"./routes/sse\";\nimport { createStaticHandler } from \"./static\";\n\nfunction resolveUiDir(): string {\n // When running from built output: __dirname is dist/, ui is dist/ui/\n const fromDist = join(__dirname, \"ui\");\n if (existsSync(join(fromDist, \"index.html\"))) return fromDist;\n\n // When running from source via bun/tsx: __dirname is src/, ui is ../dist/ui/\n const fromSrc = join(__dirname, \"..\", \"dist\", \"ui\");\n if (existsSync(join(fromSrc, \"index.html\"))) return fromSrc;\n\n // Fallback\n return fromDist;\n}\n\nexport function createStudioApp(engine: Engine): Hono {\n const app = new Hono();\n\n app.onError((err, c) => {\n console.error(`[studio] ${c.req.method} ${c.req.path} error:`, err);\n return c.json({ error: err.message }, 500);\n });\n\n // Enable CORS for development\n app.use(\"*\", cors());\n\n // API routes\n app.route(\"/api\", createApiRoutes(engine));\n\n // SSE events\n app.route(\"/api\", createSseRoute(engine));\n\n // Static SPA assets\n app.get(\"*\", createStaticHandler(resolveUiDir()));\n\n return app;\n}\n","import { serve } from \"@hono/node-server\";\nimport type { Engine } from \"chisel-engine\";\nimport { createStudioApp } from \"./server\";\nimport type { StudioOptions, StudioServer } from \"./types\";\n\nexport type { StudioOptions, StudioServer } from \"./types\";\n\nexport function createStudio(\n engine: Engine,\n options: StudioOptions = {}\n): StudioServer {\n const port = options.port ?? 4040;\n const host = options.host ?? \"localhost\";\n const url = `http://${host}:${port}`;\n\n const app = createStudioApp(engine);\n let server: ReturnType<typeof serve> | null = null;\n\n return {\n get url() {\n return url;\n },\n\n async start() {\n server = serve({ fetch: app.fetch, port, hostname: host });\n\n console.log(`Chisel Studio running at ${url}`);\n\n if (options.open) {\n const { exec } = await import(\"child_process\");\n const cmd =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n exec(`${cmd} ${url}`);\n }\n },\n\n async stop() {\n if (server) {\n server.close();\n server = null;\n }\n },\n };\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -174,6 +174,10 @@ function resolveUiDir() {
|
|
|
174
174
|
}
|
|
175
175
|
function createStudioApp(engine) {
|
|
176
176
|
const app = new Hono();
|
|
177
|
+
app.onError((err, c) => {
|
|
178
|
+
console.error(`[studio] ${c.req.method} ${c.req.path} error:`, err);
|
|
179
|
+
return c.json({ error: err.message }, 500);
|
|
180
|
+
});
|
|
177
181
|
app.use("*", cors());
|
|
178
182
|
app.route("/api", createApiRoutes(engine));
|
|
179
183
|
app.route("/api", createSseRoute(engine));
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/routes/api.ts","../src/routes/sse.ts","../src/static.ts","../src/server.ts","../src/index.ts"],"names":["Hono","join","existsSync"],"mappings":"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","file":"index.mjs","sourcesContent":["import { Hono } from \"hono\";\nimport type { Engine } from \"chisel-engine\";\nimport type { RunStatus } from \"chisel-engine\";\n\nexport function createApiRoutes(engine: Engine): Hono {\n const app = new Hono();\n\n // Health check\n app.get(\"/health\", async (c) => {\n const health = await engine.health();\n return c.json(health, health.connected ? 200 : 503);\n });\n\n // List registered workflows\n app.get(\"/workflows\", (c) => {\n return c.json(engine.listWorkflows());\n });\n\n // List runs for a workflow\n app.get(\"/workflows/:id/runs\", async (c) => {\n const id = c.req.param(\"id\");\n const query = c.req.query();\n\n const result = await engine.listRuns(id, {\n limit: query.limit ? Number(query.limit) : undefined,\n cursor: query.cursor ? Number(query.cursor) : undefined,\n order: query.order as \"asc\" | \"desc\" | undefined,\n status: query.status as RunStatus | undefined,\n });\n\n return c.json(result);\n });\n\n // Get run detail\n app.get(\"/runs/:runId\", async (c) => {\n const runId = c.req.param(\"runId\");\n const run = await engine.getRun(runId);\n\n if (!run) {\n return c.json({ error: \"Run not found\" }, 404);\n }\n\n return c.json(run);\n });\n\n // Cancel a run\n app.post(\"/runs/:runId/cancel\", async (c) => {\n const runId = c.req.param(\"runId\");\n\n try {\n await engine.cancelRun(runId);\n return c.json({ success: true });\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n // Retry a failed run\n app.post(\"/runs/:runId/retry\", async (c) => {\n const runId = c.req.param(\"runId\");\n\n try {\n await engine.retryRun(runId);\n return c.json({ success: true });\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n // Trigger a workflow\n app.post(\"/workflows/:id/trigger\", async (c) => {\n const id = c.req.param(\"id\");\n\n try {\n const body = await c.req.json();\n const { runId } = await engine.trigger(id, body);\n return c.json({ runId }, 202);\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport type { Engine, EngineEventName } from \"chisel-engine\";\n\nconst ENGINE_EVENTS: EngineEventName[] = [\n \"workflow:start\",\n \"workflow:complete\",\n \"workflow:fail\",\n \"step:start\",\n \"step:complete\",\n \"step:fail\",\n \"step:retry\",\n];\n\nexport function createSseRoute(engine: Engine): Hono {\n const app = new Hono();\n\n app.get(\"/events\", (c) => {\n return streamSSE(c, async (stream) => {\n const handlers = new Map<string, (payload: unknown) => void>();\n\n for (const event of ENGINE_EVENTS) {\n const handler = (payload: unknown) => {\n stream\n .writeSSE({\n event,\n data: JSON.stringify(payload, (_key, value) =>\n value instanceof Error\n ? { message: value.message, name: value.name }\n : value\n ),\n })\n .catch(() => {});\n };\n handlers.set(event, handler);\n engine.on(event, handler as any);\n }\n\n // Heartbeat every 15 seconds\n const heartbeat = setInterval(() => {\n stream\n .writeSSE({\n event: \"heartbeat\",\n data: JSON.stringify({ time: Date.now() }),\n })\n .catch(() => {});\n }, 15_000);\n\n // Keep the stream alive until client disconnects\n try {\n while (true) {\n await stream.sleep(1000);\n }\n } finally {\n clearInterval(heartbeat);\n for (const [event, handler] of handlers) {\n engine.off(event as EngineEventName, handler as any);\n }\n }\n });\n });\n\n return app;\n}\n","import { readFileSync, existsSync } from \"fs\";\nimport { join, extname } from \"path\";\nimport type { Context } from \"hono\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".js\": \"application/javascript; charset=utf-8\",\n \".mjs\": \"application/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n};\n\nexport function createStaticHandler(uiDir: string) {\n // Pre-load index.html into memory (small file, hot path)\n const indexPath = join(uiDir, \"index.html\");\n let indexHtml = \"\";\n if (existsSync(indexPath)) {\n indexHtml = readFileSync(indexPath, \"utf-8\");\n }\n\n return async (c: Context) => {\n const reqPath = new URL(c.req.url).pathname;\n\n // Try serving static asset\n const filePath = join(uiDir, reqPath);\n if (existsSync(filePath) && reqPath !== \"/\") {\n try {\n const content = readFileSync(filePath);\n const ext = extname(filePath);\n const contentType = MIME_TYPES[ext] || \"application/octet-stream\";\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Cache-Control\": \"public, max-age=31536000, immutable\",\n },\n });\n } catch {\n // Fall through to index.html\n }\n }\n\n // SPA fallback: serve index.html for all non-file routes\n if (!indexHtml) {\n return c.text(\"Studio UI not built. Run: bun run build:ui\", 500);\n }\n return c.html(indexHtml);\n };\n}\n","import { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { join } from \"path\";\nimport { existsSync } from \"fs\";\nimport type { Engine } from \"chisel-engine\";\nimport { createApiRoutes } from \"./routes/api\";\nimport { createSseRoute } from \"./routes/sse\";\nimport { createStaticHandler } from \"./static\";\n\nfunction resolveUiDir(): string {\n // When running from built output: __dirname is dist/, ui is dist/ui/\n const fromDist = join(__dirname, \"ui\");\n if (existsSync(join(fromDist, \"index.html\"))) return fromDist;\n\n // When running from source via bun/tsx: __dirname is src/, ui is ../dist/ui/\n const fromSrc = join(__dirname, \"..\", \"dist\", \"ui\");\n if (existsSync(join(fromSrc, \"index.html\"))) return fromSrc;\n\n // Fallback\n return fromDist;\n}\n\nexport function createStudioApp(engine: Engine): Hono {\n const app = new Hono();\n\n // Enable CORS for development\n app.use(\"*\", cors());\n\n // API routes\n app.route(\"/api\", createApiRoutes(engine));\n\n // SSE events\n app.route(\"/api\", createSseRoute(engine));\n\n // Static SPA assets\n app.get(\"*\", createStaticHandler(resolveUiDir()));\n\n return app;\n}\n","import { serve } from \"@hono/node-server\";\nimport type { Engine } from \"chisel-engine\";\nimport { createStudioApp } from \"./server\";\nimport type { StudioOptions, StudioServer } from \"./types\";\n\nexport type { StudioOptions, StudioServer } from \"./types\";\n\nexport function createStudio(\n engine: Engine,\n options: StudioOptions = {}\n): StudioServer {\n const port = options.port ?? 4040;\n const host = options.host ?? \"localhost\";\n const url = `http://${host}:${port}`;\n\n const app = createStudioApp(engine);\n let server: ReturnType<typeof serve> | null = null;\n\n return {\n get url() {\n return url;\n },\n\n async start() {\n server = serve({ fetch: app.fetch, port, hostname: host });\n\n console.log(`Chisel Studio running at ${url}`);\n\n if (options.open) {\n const { exec } = await import(\"child_process\");\n const cmd =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n exec(`${cmd} ${url}`);\n }\n },\n\n async stop() {\n if (server) {\n server.close();\n server = null;\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/routes/api.ts","../src/routes/sse.ts","../src/static.ts","../src/server.ts","../src/index.ts"],"names":["Hono","join","existsSync"],"mappings":";;;;;;;;AAIO,SAAS,gBAAgB,MAAA,EAAsB;AACpD,EAAA,MAAM,GAAA,GAAM,IAAI,IAAA,EAAK;AAGrB,EAAA,GAAA,CAAI,GAAA,CAAI,SAAA,EAAW,OAAO,CAAA,KAAM;AAC9B,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,MAAA,EAAO;AACnC,IAAA,OAAO,EAAE,IAAA,CAAK,MAAA,EAAQ,MAAA,CAAO,SAAA,GAAY,MAAM,GAAG,CAAA;AAAA,EACpD,CAAC,CAAA;AAGD,EAAA,GAAA,CAAI,GAAA,CAAI,YAAA,EAAc,CAAC,CAAA,KAAM;AAC3B,IAAA,OAAO,CAAA,CAAE,IAAA,CAAK,MAAA,CAAO,aAAA,EAAe,CAAA;AAAA,EACtC,CAAC,CAAA;AAGD,EAAA,GAAA,CAAI,GAAA,CAAI,qBAAA,EAAuB,OAAO,CAAA,KAAM;AAC1C,IAAA,MAAM,EAAA,GAAK,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,GAAA,CAAI,KAAA,EAAM;AAE1B,IAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,QAAA,CAAS,EAAA,EAAI;AAAA,MACvC,OAAO,KAAA,CAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA,GAAI,MAAA;AAAA,MAC3C,QAAQ,KAAA,CAAM,MAAA,GAAS,MAAA,CAAO,KAAA,CAAM,MAAM,CAAA,GAAI,MAAA;AAAA,MAC9C,OAAO,KAAA,CAAM,KAAA;AAAA,MACb,QAAQ,KAAA,CAAM;AAAA,KACf,CAAA;AAED,IAAA,OAAO,CAAA,CAAE,KAAK,MAAM,CAAA;AAAA,EACtB,CAAC,CAAA;AAGD,EAAA,GAAA,CAAI,GAAA,CAAI,cAAA,EAAgB,OAAO,CAAA,KAAM;AACnC,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA;AACjC,IAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA;AAErC,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,OAAO,EAAE,IAAA,CAAK,EAAE,KAAA,EAAO,eAAA,IAAmB,GAAG,CAAA;AAAA,IAC/C;AAEA,IAAA,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AAAA,EACnB,CAAC,CAAA;AAGD,EAAA,GAAA,CAAI,IAAA,CAAK,qBAAA,EAAuB,OAAO,CAAA,KAAM;AAC3C,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA;AAEjC,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,UAAU,KAAK,CAAA;AAC5B,MAAA,OAAO,CAAA,CAAE,IAAA,CAAK,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,IACjC,SAAS,KAAA,EAAO;AACd,MAAA,OAAO,CAAA,CAAE,IAAA;AAAA,QACP,EAAE,OAAO,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA,EAAE;AAAA,QAChE;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAGD,EAAA,GAAA,CAAI,IAAA,CAAK,oBAAA,EAAsB,OAAO,CAAA,KAAM;AAC1C,IAAA,MAAM,KAAA,GAAQ,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,OAAO,CAAA;AAEjC,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,CAAO,SAAS,KAAK,CAAA;AAC3B,MAAA,OAAO,CAAA,CAAE,IAAA,CAAK,EAAE,OAAA,EAAS,MAAM,CAAA;AAAA,IACjC,SAAS,KAAA,EAAO;AACd,MAAA,OAAO,CAAA,CAAE,IAAA;AAAA,QACP,EAAE,OAAO,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA,EAAE;AAAA,QAChE;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAGD,EAAA,GAAA,CAAI,IAAA,CAAK,wBAAA,EAA0B,OAAO,CAAA,KAAM;AAC9C,IAAA,MAAM,EAAA,GAAK,CAAA,CAAE,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAE3B,IAAA,IAAI;AACF,MAAA,MAAM,IAAA,GAAO,MAAM,CAAA,CAAE,GAAA,CAAI,IAAA,EAAK;AAC9B,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,MAAA,CAAO,OAAA,CAAQ,IAAI,IAAI,CAAA;AAC/C,MAAA,OAAO,CAAA,CAAE,IAAA,CAAK,EAAE,KAAA,IAAS,GAAG,CAAA;AAAA,IAC9B,SAAS,KAAA,EAAO;AACd,MAAA,OAAO,CAAA,CAAE,IAAA;AAAA,QACP,EAAE,OAAO,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CAAA,EAAE;AAAA,QAChE;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,OAAO,GAAA;AACT;ACxFA,IAAM,aAAA,GAAmC;AAAA,EACvC,gBAAA;AAAA,EACA,mBAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,eAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAAA;AAEO,SAAS,eAAe,MAAA,EAAsB;AACnD,EAAA,MAAM,GAAA,GAAM,IAAIA,IAAAA,EAAK;AAErB,EAAA,GAAA,CAAI,GAAA,CAAI,SAAA,EAAW,CAAC,CAAA,KAAM;AACxB,IAAA,OAAO,SAAA,CAAU,CAAA,EAAG,OAAO,MAAA,KAAW;AACpC,MAAA,MAAM,QAAA,uBAAe,GAAA,EAAwC;AAE7D,MAAA,KAAA,MAAW,SAAS,aAAA,EAAe;AACjC,QAAA,MAAM,OAAA,GAAU,CAAC,OAAA,KAAqB;AACpC,UAAA,MAAA,CACG,QAAA,CAAS;AAAA,YACR,KAAA;AAAA,YACA,MAAM,IAAA,CAAK,SAAA;AAAA,cAAU,OAAA;AAAA,cAAS,CAAC,IAAA,EAAM,KAAA,KACnC,KAAA,YAAiB,KAAA,GACb,EAAE,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,IAAA,EAAM,KAAA,CAAM,IAAA,EAAK,GAC3C;AAAA;AACN,WACD,CAAA,CACA,KAAA,CAAM,MAAM;AAAA,UAAC,CAAC,CAAA;AAAA,QACnB,CAAA;AACA,QAAA,QAAA,CAAS,GAAA,CAAI,OAAO,OAAO,CAAA;AAC3B,QAAA,MAAA,CAAO,EAAA,CAAG,OAAO,OAAc,CAAA;AAAA,MACjC;AAGA,MAAA,MAAM,SAAA,GAAY,YAAY,MAAM;AAClC,QAAA,MAAA,CACG,QAAA,CAAS;AAAA,UACR,KAAA,EAAO,WAAA;AAAA,UACP,IAAA,EAAM,KAAK,SAAA,CAAU,EAAE,MAAM,IAAA,CAAK,GAAA,IAAO;AAAA,SAC1C,CAAA,CACA,KAAA,CAAM,MAAM;AAAA,QAAC,CAAC,CAAA;AAAA,MACnB,GAAG,IAAM,CAAA;AAGT,MAAA,IAAI;AACF,QAAA,OAAO,IAAA,EAAM;AACX,UAAA,MAAM,MAAA,CAAO,MAAM,GAAI,CAAA;AAAA,QACzB;AAAA,MACF,CAAA,SAAE;AACA,QAAA,aAAA,CAAc,SAAS,CAAA;AACvB,QAAA,KAAA,MAAW,CAAC,KAAA,EAAO,OAAO,CAAA,IAAK,QAAA,EAAU;AACvC,UAAA,MAAA,CAAO,GAAA,CAAI,OAA0B,OAAc,CAAA;AAAA,QACrD;AAAA,MACF;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AAED,EAAA,OAAO,GAAA;AACT;AC3DA,IAAM,UAAA,GAAqC;AAAA,EACzC,OAAA,EAAS,0BAAA;AAAA,EACT,MAAA,EAAQ,yBAAA;AAAA,EACR,KAAA,EAAO,uCAAA;AAAA,EACP,MAAA,EAAQ,uCAAA;AAAA,EACR,OAAA,EAAS,iCAAA;AAAA,EACT,MAAA,EAAQ,eAAA;AAAA,EACR,MAAA,EAAQ,WAAA;AAAA,EACR,MAAA,EAAQ,cAAA;AAAA,EACR,OAAA,EAAS,WAAA;AAAA,EACT,QAAA,EAAU;AACZ,CAAA;AAEO,SAAS,oBAAoB,KAAA,EAAe;AAEjD,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,KAAA,EAAO,YAAY,CAAA;AAC1C,EAAA,IAAI,SAAA,GAAY,EAAA;AAChB,EAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,IAAA,SAAA,GAAY,YAAA,CAAa,WAAW,OAAO,CAAA;AAAA,EAC7C;AAEA,EAAA,OAAO,OAAO,CAAA,KAAe;AAC3B,IAAA,MAAM,UAAU,IAAI,GAAA,CAAI,CAAA,CAAE,GAAA,CAAI,GAAG,CAAA,CAAE,QAAA;AAGnC,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,KAAA,EAAO,OAAO,CAAA;AACpC,IAAA,IAAI,UAAA,CAAW,QAAQ,CAAA,IAAK,OAAA,KAAY,GAAA,EAAK;AAC3C,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,aAAa,QAAQ,CAAA;AACrC,QAAA,MAAM,GAAA,GAAM,QAAQ,QAAQ,CAAA;AAC5B,QAAA,MAAM,WAAA,GAAc,UAAA,CAAW,GAAG,CAAA,IAAK,0BAAA;AACvC,QAAA,OAAO,IAAI,SAAS,OAAA,EAAS;AAAA,UAC3B,OAAA,EAAS;AAAA,YACP,cAAA,EAAgB,WAAA;AAAA,YAChB,eAAA,EAAiB;AAAA;AACnB,SACD,CAAA;AAAA,MACH,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAGA,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,OAAO,CAAA,CAAE,IAAA,CAAK,4CAAA,EAA8C,GAAG,CAAA;AAAA,IACjE;AACA,IAAA,OAAO,CAAA,CAAE,KAAK,SAAS,CAAA;AAAA,EACzB,CAAA;AACF;;;AC3CA,SAAS,YAAA,GAAuB;AAE9B,EAAA,MAAM,QAAA,GAAWC,IAAAA,CAAK,SAAA,EAAW,IAAI,CAAA;AACrC,EAAA,IAAIC,WAAWD,IAAAA,CAAK,QAAA,EAAU,YAAY,CAAC,GAAG,OAAO,QAAA;AAGrD,EAAA,MAAM,OAAA,GAAUA,IAAAA,CAAK,SAAA,EAAW,IAAA,EAAM,QAAQ,IAAI,CAAA;AAClD,EAAA,IAAIC,WAAWD,IAAAA,CAAK,OAAA,EAAS,YAAY,CAAC,GAAG,OAAO,OAAA;AAGpD,EAAA,OAAO,QAAA;AACT;AAEO,SAAS,gBAAgB,MAAA,EAAsB;AACpD,EAAA,MAAM,GAAA,GAAM,IAAID,IAAAA,EAAK;AAErB,EAAA,GAAA,CAAI,OAAA,CAAQ,CAAC,GAAA,EAAK,CAAA,KAAM;AACtB,IAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,SAAA,EAAY,CAAA,CAAE,GAAA,CAAI,MAAM,IAAI,CAAA,CAAE,GAAA,CAAI,IAAI,CAAA,OAAA,CAAA,EAAW,GAAG,CAAA;AAClE,IAAA,OAAO,EAAE,IAAA,CAAK,EAAE,OAAO,GAAA,CAAI,OAAA,IAAW,GAAG,CAAA;AAAA,EAC3C,CAAC,CAAA;AAGD,EAAA,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,IAAA,EAAM,CAAA;AAGnB,EAAA,GAAA,CAAI,KAAA,CAAM,MAAA,EAAQ,eAAA,CAAgB,MAAM,CAAC,CAAA;AAGzC,EAAA,GAAA,CAAI,KAAA,CAAM,MAAA,EAAQ,cAAA,CAAe,MAAM,CAAC,CAAA;AAGxC,EAAA,GAAA,CAAI,GAAA,CAAI,GAAA,EAAK,mBAAA,CAAoB,YAAA,EAAc,CAAC,CAAA;AAEhD,EAAA,OAAO,GAAA;AACT;;;ACpCO,SAAS,YAAA,CACd,MAAA,EACA,OAAA,GAAyB,EAAC,EACZ;AACd,EAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,IAAQ,IAAA;AAC7B,EAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,IAAQ,WAAA;AAC7B,EAAA,MAAM,GAAA,GAAM,CAAA,OAAA,EAAU,IAAI,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA;AAElC,EAAA,MAAM,GAAA,GAAM,gBAAgB,MAAM,CAAA;AAClC,EAAA,IAAI,MAAA,GAA0C,IAAA;AAE9C,EAAA,OAAO;AAAA,IACL,IAAI,GAAA,GAAM;AACR,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,IAEA,MAAM,KAAA,GAAQ;AACZ,MAAA,MAAA,GAAS,KAAA,CAAM,EAAE,KAAA,EAAO,GAAA,CAAI,OAAO,IAAA,EAAM,QAAA,EAAU,MAAM,CAAA;AAEzD,MAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,yBAAA,EAA4B,GAAG,CAAA,CAAE,CAAA;AAE7C,MAAA,IAAI,QAAQ,IAAA,EAAM;AAChB,QAAA,MAAM,EAAE,IAAA,EAAK,GAAI,MAAM,OAAO,eAAe,CAAA;AAC7C,QAAA,MAAM,GAAA,GACJ,QAAQ,QAAA,KAAa,QAAA,GACjB,SACA,OAAA,CAAQ,QAAA,KAAa,UACnB,OAAA,GACA,UAAA;AACR,QAAA,IAAA,CAAK,CAAA,EAAG,GAAG,CAAA,CAAA,EAAI,GAAG,CAAA,CAAE,CAAA;AAAA,MACtB;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,IAAA,GAAO;AACX,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,MAAA,CAAO,KAAA,EAAM;AACb,QAAA,MAAA,GAAS,IAAA;AAAA,MACX;AAAA,IACF;AAAA,GACF;AACF","file":"index.mjs","sourcesContent":["import { Hono } from \"hono\";\nimport type { Engine } from \"chisel-engine\";\nimport type { RunStatus } from \"chisel-engine\";\n\nexport function createApiRoutes(engine: Engine): Hono {\n const app = new Hono();\n\n // Health check\n app.get(\"/health\", async (c) => {\n const health = await engine.health();\n return c.json(health, health.connected ? 200 : 503);\n });\n\n // List registered workflows\n app.get(\"/workflows\", (c) => {\n return c.json(engine.listWorkflows());\n });\n\n // List runs for a workflow\n app.get(\"/workflows/:id/runs\", async (c) => {\n const id = c.req.param(\"id\");\n const query = c.req.query();\n\n const result = await engine.listRuns(id, {\n limit: query.limit ? Number(query.limit) : undefined,\n cursor: query.cursor ? Number(query.cursor) : undefined,\n order: query.order as \"asc\" | \"desc\" | undefined,\n status: query.status as RunStatus | undefined,\n });\n\n return c.json(result);\n });\n\n // Get run detail\n app.get(\"/runs/:runId\", async (c) => {\n const runId = c.req.param(\"runId\");\n const run = await engine.getRun(runId);\n\n if (!run) {\n return c.json({ error: \"Run not found\" }, 404);\n }\n\n return c.json(run);\n });\n\n // Cancel a run\n app.post(\"/runs/:runId/cancel\", async (c) => {\n const runId = c.req.param(\"runId\");\n\n try {\n await engine.cancelRun(runId);\n return c.json({ success: true });\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n // Retry a failed run\n app.post(\"/runs/:runId/retry\", async (c) => {\n const runId = c.req.param(\"runId\");\n\n try {\n await engine.retryRun(runId);\n return c.json({ success: true });\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n // Trigger a workflow\n app.post(\"/workflows/:id/trigger\", async (c) => {\n const id = c.req.param(\"id\");\n\n try {\n const body = await c.req.json();\n const { runId } = await engine.trigger(id, body);\n return c.json({ runId }, 202);\n } catch (error) {\n return c.json(\n { error: error instanceof Error ? error.message : String(error) },\n 400\n );\n }\n });\n\n return app;\n}\n","import { Hono } from \"hono\";\nimport { streamSSE } from \"hono/streaming\";\nimport type { Engine, EngineEventName } from \"chisel-engine\";\n\nconst ENGINE_EVENTS: EngineEventName[] = [\n \"workflow:start\",\n \"workflow:complete\",\n \"workflow:fail\",\n \"step:start\",\n \"step:complete\",\n \"step:fail\",\n \"step:retry\",\n];\n\nexport function createSseRoute(engine: Engine): Hono {\n const app = new Hono();\n\n app.get(\"/events\", (c) => {\n return streamSSE(c, async (stream) => {\n const handlers = new Map<string, (payload: unknown) => void>();\n\n for (const event of ENGINE_EVENTS) {\n const handler = (payload: unknown) => {\n stream\n .writeSSE({\n event,\n data: JSON.stringify(payload, (_key, value) =>\n value instanceof Error\n ? { message: value.message, name: value.name }\n : value\n ),\n })\n .catch(() => {});\n };\n handlers.set(event, handler);\n engine.on(event, handler as any);\n }\n\n // Heartbeat every 15 seconds\n const heartbeat = setInterval(() => {\n stream\n .writeSSE({\n event: \"heartbeat\",\n data: JSON.stringify({ time: Date.now() }),\n })\n .catch(() => {});\n }, 15_000);\n\n // Keep the stream alive until client disconnects\n try {\n while (true) {\n await stream.sleep(1000);\n }\n } finally {\n clearInterval(heartbeat);\n for (const [event, handler] of handlers) {\n engine.off(event as EngineEventName, handler as any);\n }\n }\n });\n });\n\n return app;\n}\n","import { readFileSync, existsSync } from \"fs\";\nimport { join, extname } from \"path\";\nimport type { Context } from \"hono\";\n\nconst MIME_TYPES: Record<string, string> = {\n \".html\": \"text/html; charset=utf-8\",\n \".css\": \"text/css; charset=utf-8\",\n \".js\": \"application/javascript; charset=utf-8\",\n \".mjs\": \"application/javascript; charset=utf-8\",\n \".json\": \"application/json; charset=utf-8\",\n \".svg\": \"image/svg+xml\",\n \".png\": \"image/png\",\n \".ico\": \"image/x-icon\",\n \".woff\": \"font/woff\",\n \".woff2\": \"font/woff2\",\n};\n\nexport function createStaticHandler(uiDir: string) {\n // Pre-load index.html into memory (small file, hot path)\n const indexPath = join(uiDir, \"index.html\");\n let indexHtml = \"\";\n if (existsSync(indexPath)) {\n indexHtml = readFileSync(indexPath, \"utf-8\");\n }\n\n return async (c: Context) => {\n const reqPath = new URL(c.req.url).pathname;\n\n // Try serving static asset\n const filePath = join(uiDir, reqPath);\n if (existsSync(filePath) && reqPath !== \"/\") {\n try {\n const content = readFileSync(filePath);\n const ext = extname(filePath);\n const contentType = MIME_TYPES[ext] || \"application/octet-stream\";\n return new Response(content, {\n headers: {\n \"Content-Type\": contentType,\n \"Cache-Control\": \"public, max-age=31536000, immutable\",\n },\n });\n } catch {\n // Fall through to index.html\n }\n }\n\n // SPA fallback: serve index.html for all non-file routes\n if (!indexHtml) {\n return c.text(\"Studio UI not built. Run: bun run build:ui\", 500);\n }\n return c.html(indexHtml);\n };\n}\n","import { Hono } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { join } from \"path\";\nimport { existsSync } from \"fs\";\nimport type { Engine } from \"chisel-engine\";\nimport { createApiRoutes } from \"./routes/api\";\nimport { createSseRoute } from \"./routes/sse\";\nimport { createStaticHandler } from \"./static\";\n\nfunction resolveUiDir(): string {\n // When running from built output: __dirname is dist/, ui is dist/ui/\n const fromDist = join(__dirname, \"ui\");\n if (existsSync(join(fromDist, \"index.html\"))) return fromDist;\n\n // When running from source via bun/tsx: __dirname is src/, ui is ../dist/ui/\n const fromSrc = join(__dirname, \"..\", \"dist\", \"ui\");\n if (existsSync(join(fromSrc, \"index.html\"))) return fromSrc;\n\n // Fallback\n return fromDist;\n}\n\nexport function createStudioApp(engine: Engine): Hono {\n const app = new Hono();\n\n app.onError((err, c) => {\n console.error(`[studio] ${c.req.method} ${c.req.path} error:`, err);\n return c.json({ error: err.message }, 500);\n });\n\n // Enable CORS for development\n app.use(\"*\", cors());\n\n // API routes\n app.route(\"/api\", createApiRoutes(engine));\n\n // SSE events\n app.route(\"/api\", createSseRoute(engine));\n\n // Static SPA assets\n app.get(\"*\", createStaticHandler(resolveUiDir()));\n\n return app;\n}\n","import { serve } from \"@hono/node-server\";\nimport type { Engine } from \"chisel-engine\";\nimport { createStudioApp } from \"./server\";\nimport type { StudioOptions, StudioServer } from \"./types\";\n\nexport type { StudioOptions, StudioServer } from \"./types\";\n\nexport function createStudio(\n engine: Engine,\n options: StudioOptions = {}\n): StudioServer {\n const port = options.port ?? 4040;\n const host = options.host ?? \"localhost\";\n const url = `http://${host}:${port}`;\n\n const app = createStudioApp(engine);\n let server: ReturnType<typeof serve> | null = null;\n\n return {\n get url() {\n return url;\n },\n\n async start() {\n server = serve({ fetch: app.fetch, port, hostname: host });\n\n console.log(`Chisel Studio running at ${url}`);\n\n if (options.open) {\n const { exec } = await import(\"child_process\");\n const cmd =\n process.platform === \"darwin\"\n ? \"open\"\n : process.platform === \"win32\"\n ? \"start\"\n : \"xdg-open\";\n exec(`${cmd} ${url}`);\n }\n },\n\n async stop() {\n if (server) {\n server.close();\n server = null;\n }\n },\n };\n}\n"]}
|