@kizenapps/cli 0.1.0 → 0.3.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/index.js CHANGED
@@ -176,13 +176,21 @@ import { render as render2 } from "ink";
176
176
  // src/ui/DevUI.tsx
177
177
  import { useCallback, useEffect as useEffect2, useRef, useState as useState2 } from "react";
178
178
  import { Box as Box2, Text as Text2, useInput } from "ink";
179
- import * as ChromeLauncher from "chrome-launcher";
180
- import { createReadStream, mkdirSync, watch } from "fs";
179
+ import { spawn } from "child_process";
180
+ import {
181
+ createReadStream,
182
+ readFileSync,
183
+ statSync,
184
+ unlinkSync,
185
+ watch,
186
+ writeFileSync
187
+ } from "fs";
181
188
  import { access, readFile as readFile2 } from "fs/promises";
182
189
  import { createServer } from "http";
190
+ import { createRequire } from "module";
183
191
  import { dirname, extname, join as join3 } from "path";
184
192
  import { fileURLToPath } from "url";
185
- import { WebSocket, WebSocketServer } from "ws";
193
+ import { WebSocketServer } from "ws";
186
194
  import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
187
195
  var SKIP_WATCH_PREFIXES = [".kizenapp", ".git"];
188
196
  var LOG_LIMIT = 50;
@@ -219,141 +227,9 @@ function getViewerPath() {
219
227
  const filename = fileURLToPath(import.meta.url);
220
228
  return join3(dirname(filename), "viewer");
221
229
  }
222
- function setupCspBypass(debugPort) {
223
- void (async () => {
224
- let wsUrl;
225
- try {
226
- const res = await fetch(`http://localhost:${String(debugPort)}/json/version`);
227
- const data = await res.json();
228
- wsUrl = data.webSocketDebuggerUrl;
229
- } catch {
230
- return;
231
- }
232
- const ws = new WebSocket(wsUrl);
233
- let msgId = 0;
234
- const pending = /* @__PURE__ */ new Map();
235
- const send = (method, params, sessionId) => {
236
- ws.send(
237
- JSON.stringify({
238
- id: ++msgId,
239
- method,
240
- ...params !== void 0 && { params },
241
- ...sessionId !== void 0 && { sessionId }
242
- })
243
- );
244
- };
245
- const sendAndAwait = (method, params, sessionId) => {
246
- const id = ++msgId;
247
- return new Promise((resolve) => {
248
- pending.set(id, resolve);
249
- ws.send(
250
- JSON.stringify({
251
- id,
252
- method,
253
- ...params !== void 0 && { params },
254
- ...sessionId !== void 0 && { sessionId }
255
- })
256
- );
257
- });
258
- };
259
- const CSP_HEADERS = /* @__PURE__ */ new Set([
260
- "content-security-policy",
261
- "content-security-policy-report-only",
262
- "x-frame-options"
263
- ]);
264
- const KIZEN_DOMAINS = ["kizen.dev", "kizen.com"];
265
- let primarySession;
266
- ws.on("open", () => {
267
- send("Target.setAutoAttach", {
268
- autoAttach: true,
269
- waitForDebuggerOnStart: false,
270
- flatten: true
271
- });
272
- });
273
- ws.on("message", (data) => {
274
- const msg = JSON.parse(data.toString());
275
- if (msg.id !== void 0 && pending.has(msg.id)) {
276
- pending.get(msg.id)?.(msg.result);
277
- pending.delete(msg.id);
278
- return;
279
- }
280
- if (msg.method === "Target.attachedToTarget" && msg.params?.sessionId) {
281
- send(
282
- "Fetch.enable",
283
- { patterns: [{ requestStage: "Response", resourceType: "Document" }] },
284
- msg.params.sessionId
285
- );
286
- send("Network.enable", {}, msg.params.sessionId);
287
- primarySession ??= msg.params.sessionId;
288
- }
289
- if (msg.method === "Fetch.requestPaused" && msg.params?.requestId) {
290
- const { requestId, responseHeaders, responseStatusCode = 200 } = msg.params;
291
- const sessionId = msg.sessionId;
292
- const hasCsp = responseHeaders?.some((h) => CSP_HEADERS.has(h.name.toLowerCase()));
293
- if (!hasCsp) {
294
- send("Fetch.continueResponse", { requestId }, sessionId);
295
- return;
296
- }
297
- void (async () => {
298
- try {
299
- const { body, base64Encoded } = await sendAndAwait(
300
- "Fetch.getResponseBody",
301
- { requestId },
302
- sessionId
303
- );
304
- const filteredHeaders = (responseHeaders ?? []).filter(
305
- (h) => !CSP_HEADERS.has(h.name.toLowerCase())
306
- );
307
- const bodyBase64 = base64Encoded ? body : Buffer.from(body).toString("base64");
308
- send(
309
- "Fetch.fulfillRequest",
310
- {
311
- requestId,
312
- responseCode: responseStatusCode,
313
- responseHeaders: filteredHeaders,
314
- body: bodyBase64
315
- },
316
- sessionId
317
- );
318
- } catch {
319
- send("Fetch.continueResponse", { requestId }, sessionId);
320
- }
321
- })();
322
- }
323
- });
324
- ws.on("error", () => {
325
- });
326
- setInterval(() => {
327
- const session = primarySession;
328
- if (!session) {
329
- return;
330
- }
331
- void (async () => {
332
- try {
333
- const { cookies } = await sendAndAwait("Network.getAllCookies", void 0, session);
334
- const toFix = cookies.filter(
335
- (c) => KIZEN_DOMAINS.some((d) => c.domain === d || c.domain.endsWith("." + d)) && c.sameSite !== "None"
336
- );
337
- if (toFix.length === 0) {
338
- return;
339
- }
340
- await sendAndAwait(
341
- "Network.setCookies",
342
- {
343
- cookies: toFix.map(({ expires, ...rest }) => ({
344
- ...rest,
345
- sameSite: "None",
346
- secure: true,
347
- ...expires !== -1 && { expires }
348
- }))
349
- },
350
- session
351
- );
352
- } catch {
353
- }
354
- })();
355
- }, 2e3);
356
- })();
230
+ function getElectronMainPath() {
231
+ const filename = fileURLToPath(import.meta.url);
232
+ return join3(dirname(filename), "electron", "main.js");
357
233
  }
358
234
  async function fileExists(filePath) {
359
235
  try {
@@ -430,7 +306,7 @@ var DevUI = ({ port, pluginDir, outputDir }) => {
430
306
  const [lastBuilt, setLastBuilt] = useState2(null);
431
307
  const [wsClientCount, setWsClientCount] = useState2(0);
432
308
  const buildingRef = useRef(false);
433
- const chromiumLaunchedRef = useRef(false);
309
+ const electronLaunchedRef = useRef(false);
434
310
  const debounceTimerRef = useRef(null);
435
311
  const wsClientsRef = useRef(/* @__PURE__ */ new Set());
436
312
  const pendingMessagesRef = useRef([]);
@@ -440,24 +316,44 @@ var DevUI = ({ port, pluginDir, outputDir }) => {
440
316
  }
441
317
  });
442
318
  useEffect2(() => {
443
- if (status !== "running" || chromiumLaunchedRef.current) {
319
+ if (status !== "running" || electronLaunchedRef.current) {
444
320
  return;
445
321
  }
446
- chromiumLaunchedRef.current = true;
447
- const chromeDataDir = join3(outputDir, ".chrome");
448
- mkdirSync(chromeDataDir, { recursive: true });
449
- void ChromeLauncher.launch({
450
- startingUrl: "",
451
- chromeFlags: [`--app=http://localhost:${String(port)}`],
452
- userDataDir: chromeDataDir,
453
- logLevel: "silent"
454
- }).then((chrome) => {
455
- chrome.process.unref();
456
- setupCspBypass(chrome.port);
457
- process.on("exit", () => {
458
- chrome.process.kill();
459
- });
460
- }).catch(() => {
322
+ electronLaunchedRef.current = true;
323
+ const _require = createRequire(import.meta.url);
324
+ const electronBin = _require("electron");
325
+ const electronMain = getElectronMainPath();
326
+ const userDataDir = join3(outputDir, ".electron");
327
+ if (process.platform === "darwin") {
328
+ try {
329
+ const plistPath = join3(dirname(dirname(electronBin)), "Info.plist");
330
+ const plist = readFileSync(plistPath, "utf-8");
331
+ if (!plist.includes(">Kizen Dev<")) {
332
+ if (statSync(plistPath).nlink > 1) {
333
+ unlinkSync(plistPath);
334
+ writeFileSync(plistPath, plist);
335
+ }
336
+ writeFileSync(
337
+ plistPath,
338
+ plist.replace(/(<key>CFBundleName<\/key>\s*<string>)[^<]*(<\/string>)/, "$1Kizen Dev$2").replace(
339
+ /(<key>CFBundleDisplayName<\/key>\s*<string>)[^<]*(<\/string>)/,
340
+ "$1Kizen Dev$2"
341
+ )
342
+ );
343
+ }
344
+ } catch {
345
+ }
346
+ }
347
+ const proc = spawn(
348
+ electronBin,
349
+ [electronMain, `--port=${String(port)}`, `--user-data-dir=${userDataDir}`],
350
+ {
351
+ stdio: "ignore"
352
+ }
353
+ );
354
+ proc.unref();
355
+ process.on("exit", () => {
356
+ proc.kill();
461
357
  });
462
358
  }, [status, port, outputDir]);
463
359
  const createServerLog = useCallback((message) => {
@@ -622,10 +518,6 @@ var DevUI = ({ port, pluginDir, outputDir }) => {
622
518
  status === "starting" && /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Starting server..." }),
623
519
  status === "running" && /* @__PURE__ */ jsxs2(Fragment2, { children: [
624
520
  /* @__PURE__ */ jsx2(Text2, { color: "green", children: "\u2713 Dev Server running" }),
625
- /* @__PURE__ */ jsxs2(Text2, { color: "cyan", bold: true, children: [
626
- "http://localhost:",
627
- port
628
- ] }),
629
521
  /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
630
522
  "\u25CF ",
631
523
  wsClientCount,
@@ -670,11 +562,13 @@ var DevUI = ({ port, pluginDir, outputDir }) => {
670
562
 
671
563
  // src/commands/dev.ts
672
564
  function devCommand(program2) {
673
- program2.command("dev").description("Start the plugin viewer dev server").option("-p, --port <port>", "port to listen on", "3000").action(async (options) => {
565
+ program2.command("dev").description("Start the plugin viewer dev server").option("-p, --port <port>", "port to listen on", "3121").action(async (options) => {
674
566
  const port = parseInt(options.port, 10);
675
567
  const pluginDir = process.cwd();
676
568
  const outputDir = `${pluginDir}/.kizenapp`;
677
- const { waitUntilExit } = render2(createElement2(DevUI, { port, pluginDir, outputDir }), { exitOnCtrlC: false });
569
+ const { waitUntilExit } = render2(createElement2(DevUI, { port, pluginDir, outputDir }), {
570
+ exitOnCtrlC: false
571
+ });
678
572
  await waitUntilExit();
679
573
  });
680
574
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/build.ts","../src/ui/BuildUI.tsx","../src/lib/runBuild.ts","../src/lib/readFiles.ts","../src/commands/dev.ts","../src/ui/DevUI.tsx"],"sourcesContent":["import { program } from 'commander';\nimport { buildCommand } from './commands/build.js';\nimport { devCommand } from './commands/dev.js';\n\nprogram.name('appbuilder').description('Kizen plugin app builder').version('0.1.0');\n\nbuildCommand(program);\ndevCommand(program);\n\nprogram.parse();\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { BuildUI } from '../ui/BuildUI.js';\n\nexport function buildCommand(program: Command): void {\n program\n .command('build')\n .description('Bundle the plugin app into .kizenapp directory')\n .action(async () => {\n const outputDir = `${process.cwd()}/.kizenapp`;\n const pluginDir = process.cwd();\n const { waitUntilExit } = render(createElement(BuildUI, { outputDir, pluginDir }));\n await waitUntilExit();\n });\n}\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { Box, Text, useApp } from 'ink';\nimport { runBuild } from '../lib/runBuild.js';\nimport type { BuildStepName } from '../lib/runBuild.js';\n\ntype BuildStep = BuildStepName | 'done' | 'error';\n\ninterface BuildUIProps {\n outputDir: string;\n pluginDir: string;\n}\n\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nconst Spinner: FC = () => {\n const [frame, setFrame] = useState(0);\n\n useEffect(() => {\n const id = setInterval(() => {\n setFrame((prev) => (prev + 1) % SPINNER_FRAMES.length);\n }, 80);\n\n return () => {\n clearInterval(id);\n };\n }, []);\n\n return <Text color=\"cyan\">{SPINNER_FRAMES[frame] ?? '⠋'}</Text>;\n};\n\nconst STEPS: BuildStepName[] = [\n 'creating-dir',\n 'reading-files',\n 'minifying',\n 'packaging',\n 'writing-bundle',\n];\n\nconst STEP_LABELS: Record<BuildStepName, string> = {\n 'creating-dir': 'Creating .kizenapp directory',\n 'reading-files': 'Reading plugin files',\n minifying: 'Minifying scripts',\n packaging: 'Packaging plugin',\n 'writing-bundle': 'Writing bundle.json',\n};\n\nexport const BuildUI: FC<BuildUIProps> = ({ outputDir, pluginDir }) => {\n const { exit } = useApp();\n const [step, setStep] = useState<BuildStep>('creating-dir');\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n useEffect(() => {\n void runBuild(pluginDir, outputDir, setStep)\n .then(() => {\n setStep('done');\n exit();\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n setErrorMessage(message);\n setStep('error');\n exit(err instanceof Error ? err : new Error(message));\n });\n }, [outputDir, pluginDir, exit]);\n\n const currentIndex = STEPS.indexOf(step as BuildStepName);\n const isError = step === 'error';\n const isDone = step === 'done';\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={1}>\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color=\"cyan\">\n Kizen App Builder\n </Text>\n <Text dimColor>{'─'.repeat(22)}</Text>\n </Box>\n\n <Box flexDirection=\"column\" gap={1}>\n {STEPS.map((s, i) => {\n const isActive = step === s;\n const isStepDone = isDone || currentIndex > i;\n const isFailed = isError && i === currentIndex;\n\n return (\n <Box key={s} gap={1}>\n {isFailed ? (\n <Text color=\"red\">✗ {STEP_LABELS[s]}</Text>\n ) : isStepDone ? (\n <Text color=\"green\">✓ {STEP_LABELS[s]}</Text>\n ) : isActive ? (\n <>\n <Spinner />\n <Text>{STEP_LABELS[s]}</Text>\n </>\n ) : (\n <Text dimColor>· {STEP_LABELS[s]}</Text>\n )}\n </Box>\n );\n })}\n\n {errorMessage !== null && (\n <Box marginTop={1}>\n <Text color=\"red\">{errorMessage}</Text>\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { minifyFiles, packagePlugin, transformDeployablePlugin } from '@kizenapps/packager';\nimport type { DeployablePlugin } from '@kizenapps/packager';\nimport { readLocalFiles } from './readFiles.js';\n\nexport type BuildStepName =\n | 'creating-dir'\n | 'reading-files'\n | 'minifying'\n | 'packaging'\n | 'writing-bundle';\n\ntype SerializableDeployablePlugin = Omit<DeployablePlugin, 'thumbnail' | 'kznFile'> & {\n thumbnail: string | null;\n kznFile: string | null;\n};\n\nconst serializePlugin = (plugin: DeployablePlugin): SerializableDeployablePlugin => ({\n ...plugin,\n thumbnail: plugin.thumbnail ? Buffer.from(plugin.thumbnail).toString('base64') : null,\n kznFile: plugin.kznFile ? Buffer.from(plugin.kznFile).toString('base64') : null,\n});\n\nexport async function runBuild(\n pluginDir: string,\n outputDir: string,\n onStep?: (step: BuildStepName) => void,\n): Promise<void> {\n await mkdir(outputDir, { recursive: true });\n\n onStep?.('reading-files');\n const files = await readLocalFiles(pluginDir);\n\n onStep?.('minifying');\n const minified = await minifyFiles(files);\n\n onStep?.('packaging');\n const manifestFile = minified.find((f) => f.path === 'kizen.json');\n if (!manifestFile) {\n throw new Error('kizen.json not found in plugin directory.');\n }\n const manifests = JSON.parse(manifestFile.content) as Parameters<typeof packagePlugin>[1];\n const packaged = packagePlugin(minified, manifests);\n const deployable = Object.values(packaged).map(transformDeployablePlugin);\n\n onStep?.('writing-bundle');\n const bundle = deployable.map(serializePlugin);\n await writeFile(join(outputDir, 'bundle.json'), JSON.stringify(bundle, null, 2), 'utf-8');\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { FileContent } from '@kizenapps/packager';\n\nconst IMAGE_EXTENSIONS = new Set(['.png', '.svg']);\nconst BINARY_EXTENSIONS = new Set(['.kzn']);\n\nconst SKIP_DIRS = new Set(['node_modules', '.git', '.kizenapp', '.github']);\n\nasync function walk(dir: string, rootDir: string): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const paths: string[] = [];\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) {\n continue;\n }\n\n paths.push(...(await walk(join(dir, entry.name), rootDir)));\n } else if (entry.isFile()) {\n paths.push(join(dir, entry.name));\n }\n }\n\n return paths;\n}\n\nexport async function readLocalFiles(rootDir: string): Promise<FileContent[]> {\n const absolutePaths = await walk(rootDir, rootDir);\n\n return Promise.all(\n absolutePaths.map(async (absPath): Promise<FileContent> => {\n const relPath = relative(rootDir, absPath).split('\\\\').join('/');\n const dotIndex = relPath.lastIndexOf('.');\n const ext = dotIndex >= 0 ? relPath.slice(dotIndex).toLowerCase() : '';\n\n if (IMAGE_EXTENSIONS.has(ext)) {\n const buf = await readFile(absPath);\n return { path: relPath, content: '', base64Image: buf.toString('base64') };\n }\n\n if (BINARY_EXTENSIONS.has(ext)) {\n const buf = await readFile(absPath);\n return { path: relPath, content: '', binaryData: buf };\n }\n\n const content = await readFile(absPath, 'utf-8');\n return { path: relPath, content };\n }),\n );\n}\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { DevUI } from '../ui/DevUI.js';\n\nexport function devCommand(program: Command): void {\n program\n .command('dev')\n .description('Start the plugin viewer dev server')\n .option('-p, --port <port>', 'port to listen on', '3000')\n .action(async (options: { port: string }) => {\n const port = parseInt(options.port, 10);\n const pluginDir = process.cwd();\n const outputDir = `${pluginDir}/.kizenapp`;\n const { waitUntilExit } = render(createElement(DevUI, { port, pluginDir, outputDir }), { exitOnCtrlC: false });\n await waitUntilExit();\n });\n}\n","import type { FC } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport * as ChromeLauncher from 'chrome-launcher';\nimport { createReadStream, mkdirSync, watch } from 'node:fs';\nimport type { FSWatcher } from 'node:fs';\nimport { access, readFile } from 'node:fs/promises';\nimport { createServer } from 'node:http';\nimport type { IncomingMessage, Server, ServerResponse } from 'node:http';\nimport { dirname, extname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { WebSocket, WebSocketServer } from 'ws';\nimport { runBuild } from '../lib/runBuild.js';\n\ntype ServerStatus = 'starting' | 'running' | 'error';\ntype BuildStatus = 'pending' | 'building' | 'done' | 'error';\n\nconst SKIP_WATCH_PREFIXES = ['.kizenapp', '.git'];\nconst LOG_LIMIT = 50;\nconst LOG_DISPLAY = 8;\n\ninterface DevUIProps {\n port: number;\n pluginDir: string;\n outputDir: string;\n}\n\nconst MIME_TYPES: Readonly<Record<string, string>> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.json': 'application/json; charset=utf-8',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.map': 'application/json',\n};\n\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nconst Spinner: FC = () => {\n const [frame, setFrame] = useState(0);\n\n useEffect(() => {\n const id = setInterval(() => {\n setFrame((prev) => (prev + 1) % SPINNER_FRAMES.length);\n }, 80);\n\n return () => {\n clearInterval(id);\n };\n }, []);\n\n return <Text color=\"cyan\">{SPINNER_FRAMES[frame] ?? '⠋'}</Text>;\n};\n\nfunction getViewerPath(): string {\n const filename = fileURLToPath(import.meta.url);\n return join(dirname(filename), 'viewer');\n}\n\nfunction setupCspBypass(debugPort: number): void {\n void (async () => {\n let wsUrl: string;\n try {\n const res = await fetch(`http://localhost:${String(debugPort)}/json/version`);\n const data = (await res.json()) as { webSocketDebuggerUrl: string };\n wsUrl = data.webSocketDebuggerUrl;\n } catch {\n return;\n }\n\n const ws = new WebSocket(wsUrl);\n let msgId = 0;\n const pending = new Map<number, (result: unknown) => void>();\n\n const send = (method: string, params?: object, sessionId?: string): void => {\n ws.send(\n JSON.stringify({\n id: ++msgId,\n method,\n ...(params !== undefined && { params }),\n ...(sessionId !== undefined && { sessionId }),\n }),\n );\n };\n\n const sendAndAwait = (\n method: string,\n params?: object,\n sessionId?: string,\n ): Promise<unknown> => {\n const id = ++msgId;\n return new Promise((resolve) => {\n pending.set(id, resolve);\n ws.send(\n JSON.stringify({\n id,\n method,\n ...(params !== undefined && { params }),\n ...(sessionId !== undefined && { sessionId }),\n }),\n );\n });\n };\n\n const CSP_HEADERS = new Set([\n 'content-security-policy',\n 'content-security-policy-report-only',\n 'x-frame-options',\n ]);\n\n const KIZEN_DOMAINS = ['kizen.dev', 'kizen.com'];\n let primarySession: string | undefined;\n\n ws.on('open', () => {\n send('Target.setAutoAttach', {\n autoAttach: true,\n waitForDebuggerOnStart: false,\n flatten: true,\n });\n });\n\n ws.on('message', (data) => {\n const msg = JSON.parse((data as Buffer).toString()) as {\n id?: number;\n result?: unknown;\n method?: string;\n sessionId?: string;\n params?: {\n sessionId?: string;\n requestId?: string;\n responseStatusCode?: number;\n responseHeaders?: { name: string; value: string }[];\n };\n };\n\n if (msg.id !== undefined && pending.has(msg.id)) {\n pending.get(msg.id)?.(msg.result);\n pending.delete(msg.id);\n return;\n }\n\n if (msg.method === 'Target.attachedToTarget' && msg.params?.sessionId) {\n send(\n 'Fetch.enable',\n { patterns: [{ requestStage: 'Response', resourceType: 'Document' }] },\n msg.params.sessionId,\n );\n send('Network.enable', {}, msg.params.sessionId);\n primarySession ??= msg.params.sessionId;\n }\n\n if (msg.method === 'Fetch.requestPaused' && msg.params?.requestId) {\n const { requestId, responseHeaders, responseStatusCode = 200 } = msg.params;\n const sessionId = msg.sessionId;\n\n const hasCsp = responseHeaders?.some((h) => CSP_HEADERS.has(h.name.toLowerCase()));\n\n if (!hasCsp) {\n // Nothing to strip — pass through without touching headers.\n send('Fetch.continueResponse', { requestId }, sessionId);\n return;\n }\n\n // Has CSP headers: fetch the body and re-serve with stripped headers.\n // Fetch.continueResponse with modified headers hangs on streaming responses;\n // Fetch.fulfillRequest with the full body is reliable.\n void (async () => {\n try {\n const { body, base64Encoded } = (await sendAndAwait(\n 'Fetch.getResponseBody',\n { requestId },\n sessionId,\n )) as {\n body: string;\n base64Encoded: boolean;\n };\n const filteredHeaders = (responseHeaders ?? []).filter(\n (h) => !CSP_HEADERS.has(h.name.toLowerCase()),\n );\n const bodyBase64 = base64Encoded ? body : Buffer.from(body).toString('base64');\n send(\n 'Fetch.fulfillRequest',\n {\n requestId,\n responseCode: responseStatusCode,\n responseHeaders: filteredHeaders,\n body: bodyBase64,\n },\n sessionId,\n );\n } catch {\n send('Fetch.continueResponse', { requestId }, sessionId);\n }\n })();\n }\n });\n\n ws.on('error', () => {\n /* ignore CDP connection errors */\n });\n\n // Periodically re-set Kizen cookies with SameSite=None so they are sent\n // when a Kizen page is embedded inside localhost (cross-site iframe).\n // Browsers default to SameSite=Lax which blocks cookies in that context.\n setInterval(() => {\n const session = primarySession;\n if (!session) {\n return;\n }\n\n void (async () => {\n try {\n const { cookies } = (await sendAndAwait('Network.getAllCookies', undefined, session)) as {\n cookies: {\n name: string;\n value: string;\n domain: string;\n path: string;\n expires: number;\n httpOnly: boolean;\n secure: boolean;\n sameSite?: string;\n priority?: string;\n sameParty?: boolean;\n sourceScheme?: string;\n sourcePort?: number;\n }[];\n };\n\n const toFix = cookies.filter(\n (c) =>\n KIZEN_DOMAINS.some((d) => c.domain === d || c.domain.endsWith('.' + d)) &&\n c.sameSite !== 'None',\n );\n\n if (toFix.length === 0) {\n return;\n }\n\n await sendAndAwait(\n 'Network.setCookies',\n {\n cookies: toFix.map(({ expires, ...rest }) => ({\n ...rest,\n sameSite: 'None',\n secure: true,\n ...(expires !== -1 && { expires }),\n })),\n },\n session,\n );\n } catch {\n /* ignore CDP errors */\n }\n })();\n }, 2000);\n })();\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction createRequestHandler(\n viewerPath: string,\n createServerLog: (message: string) => void,\n createProxyLog: (message: string) => void,\n): (req: IncomingMessage, res: ServerResponse) => void {\n return (req, res) => {\n void (async () => {\n const url = req.url ?? '/';\n\n createServerLog(`Received request: ${url}`);\n\n if (url === '/api/bundle') {\n const bundlePath = join(process.cwd(), '.kizenapp', 'bundle.json');\n try {\n const content = await readFile(bundlePath, 'utf-8');\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(content);\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{}');\n }\n return;\n }\n\n if (url.startsWith('/api/proxy')) {\n const proxyTarget = req.headers['x-proxy-target'];\n if (typeof proxyTarget !== 'string') {\n res.writeHead(400);\n res.end('Missing x-proxy-target header');\n return;\n }\n\n const upstreamPath = url.slice('/api/proxy'.length) || '/';\n const upstreamUrl = `${proxyTarget}${upstreamPath}`;\n\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { host, 'x-proxy-target': _drop, ...forwardHeaders } = req.headers;\n\n const resolvedBody = body && body.length > 0 ? body : undefined;\n const upstream = await fetch(upstreamUrl, {\n ...(req.method !== undefined && { method: req.method }),\n headers: forwardHeaders as Record<string, string>,\n ...(resolvedBody !== undefined && { body: resolvedBody }),\n });\n\n createProxyLog(`${req.method ?? 'GET'} ${upstreamPath} → ${String(upstream.status)}`);\n\n // Node fetch auto-decompresses the body, so strip encoding/length headers\n // that describe the compressed wire format — they no longer apply.\n const responseHeaders = Object.fromEntries(upstream.headers);\n delete responseHeaders['content-encoding'];\n delete responseHeaders['content-length'];\n\n res.writeHead(upstream.status, responseHeaders);\n res.end(Buffer.from(await upstream.arrayBuffer()));\n return;\n }\n\n const rawPath = url === '/' ? '/index.html' : url;\n const filePath = join(viewerPath, rawPath);\n const resolvedPath = (await fileExists(filePath)) ? filePath : join(viewerPath, 'index.html');\n const ext = extname(resolvedPath);\n const mimeType = MIME_TYPES[ext] ?? 'application/octet-stream';\n res.writeHead(200, { 'Content-Type': mimeType });\n createReadStream(resolvedPath).pipe(res);\n })();\n };\n}\n\nexport const DevUI: FC<DevUIProps> = ({ port, pluginDir, outputDir }) => {\n const [status, setStatus] = useState<ServerStatus>('starting');\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [serverLogHistory, setServerLogHistory] = useState<string[]>([]);\n const [buildLogHistory, setBuildLogHistory] = useState<string[]>([]);\n const [proxyLogHistory, setProxyLogHistory] = useState<string[]>([]);\n const [buildStatus, setBuildStatus] = useState<BuildStatus>('pending');\n const [buildError, setBuildError] = useState<string | null>(null);\n const [lastBuilt, setLastBuilt] = useState<Date | null>(null);\n const [wsClientCount, setWsClientCount] = useState(0);\n\n const buildingRef = useRef(false);\n const chromiumLaunchedRef = useRef(false);\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wsClientsRef = useRef<Set<WebSocket>>(new Set());\n const pendingMessagesRef = useRef<string[]>([]);\n\n useInput((input, key) => {\n if (input === 'q' || (key.ctrl && input === 'c')) {\n process.exit(0);\n }\n });\n\n useEffect(() => {\n if (status !== 'running' || chromiumLaunchedRef.current) {\n return;\n }\n chromiumLaunchedRef.current = true;\n\n const chromeDataDir = join(outputDir, '.chrome');\n mkdirSync(chromeDataDir, { recursive: true });\n\n void ChromeLauncher.launch({\n startingUrl: '',\n chromeFlags: [`--app=http://localhost:${String(port)}`],\n userDataDir: chromeDataDir,\n logLevel: 'silent',\n })\n .then((chrome) => {\n chrome.process.unref();\n setupCspBypass(chrome.port);\n process.on('exit', () => {\n chrome.process.kill();\n });\n })\n .catch(() => {\n // Chrome not found or failed to launch\n });\n }, [status, port, outputDir]);\n\n const createServerLog = useCallback((message: string): void => {\n setServerLogHistory((h) =>\n [...h, `${new Date().toLocaleTimeString()}: ${message}`].slice(-LOG_LIMIT),\n );\n }, []);\n\n const broadcast = useCallback((msg: object): void => {\n const json = JSON.stringify(msg);\n if (wsClientsRef.current.size === 0) {\n pendingMessagesRef.current = [...pendingMessagesRef.current, json].slice(-LOG_LIMIT);\n return;\n }\n for (const client of wsClientsRef.current) {\n if (client.readyState === 1) {\n client.send(json);\n }\n }\n }, []);\n\n const createProxyLog = useCallback(\n (message: string): void => {\n setProxyLogHistory((h) =>\n [...h, `${new Date().toLocaleTimeString()}: ${message}`].slice(-LOG_LIMIT),\n );\n broadcast({ type: 'proxy-log', message });\n },\n [broadcast],\n );\n\n const createBuildLog = useCallback(\n (message: string): void => {\n setBuildLogHistory((h) =>\n [...h, `${new Date().toLocaleTimeString()}: ${message}`].slice(-LOG_LIMIT),\n );\n broadcast({ type: 'log', message });\n },\n [broadcast],\n );\n\n const triggerBuild = useCallback(() => {\n if (buildingRef.current) {\n return;\n }\n\n buildingRef.current = true;\n\n setBuildStatus('building');\n setBuildError(null);\n createBuildLog('Build started');\n\n void runBuild(pluginDir, outputDir)\n .then(() => {\n createBuildLog('Build finished');\n setBuildStatus('done');\n setLastBuilt(new Date());\n\n createBuildLog('Notifying viewers to reload');\n for (const client of wsClientsRef.current) {\n if (client.readyState === 1) {\n client.send(JSON.stringify({ type: 'rebuild' }));\n }\n }\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n setBuildError(message);\n setBuildStatus('error');\n })\n .finally(() => {\n buildingRef.current = false;\n });\n }, [pluginDir, outputDir, createBuildLog]);\n\n useEffect(() => {\n triggerBuild();\n\n const watcher: FSWatcher = watch(pluginDir, { recursive: true }, (_, filename) => {\n if (!filename) {\n return;\n }\n\n const normalized = filename.replace(/\\\\/g, '/');\n\n if (SKIP_WATCH_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {\n return;\n }\n\n createBuildLog(`File change detected: ${filename}`);\n\n if (debounceTimerRef.current !== null) {\n clearTimeout(debounceTimerRef.current);\n }\n debounceTimerRef.current = setTimeout(triggerBuild, 150);\n });\n\n return () => {\n watcher.close();\n\n if (debounceTimerRef.current !== null) {\n clearTimeout(debounceTimerRef.current);\n }\n };\n }, [pluginDir, triggerBuild, createBuildLog]);\n\n useEffect(() => {\n const viewerPath = getViewerPath();\n\n void fileExists(join(viewerPath, 'index.html')).then((viewerBuilt) => {\n if (!viewerBuilt) {\n setErrorMessage(\"Viewer not built. Run 'pnpm build:viewer' first.\");\n setStatus('error');\n return;\n }\n\n const handler = createRequestHandler(viewerPath, createServerLog, createProxyLog);\n const server: Server = createServer(handler);\n const wss = new WebSocketServer({ server });\n\n wss.on('connection', (ws: WebSocket) => {\n for (const json of pendingMessagesRef.current) {\n if (ws.readyState === 1) {\n ws.send(json);\n }\n }\n pendingMessagesRef.current = [];\n\n createServerLog('Viewer connected for live reload');\n wsClientsRef.current.add(ws);\n setWsClientCount(wsClientsRef.current.size);\n\n ws.on('close', () => {\n wsClientsRef.current.delete(ws);\n setWsClientCount(wsClientsRef.current.size);\n });\n });\n\n server.listen(port, () => {\n setStatus('running');\n createServerLog(`Server started on port ${String(port)}`);\n });\n\n server.on('error', (err: Error) => {\n setErrorMessage(err.message);\n setStatus('error');\n });\n\n return () => {\n wss.close();\n server.close();\n };\n });\n }, [port, createServerLog, createProxyLog]);\n\n const elapsedSeconds =\n lastBuilt !== null ? Math.round((Date.now() - lastBuilt.getTime()) / 1000) : null;\n const elapsedLabel =\n elapsedSeconds === null\n ? ''\n : elapsedSeconds < 5\n ? ' (just now)'\n : ` (${String(elapsedSeconds)}s ago)`;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={1}>\n {/* Header */}\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box gap={1}>\n <Text bold color=\"cyan\">\n Kizen App Builder\n </Text>\n </Box>\n </Box>\n\n {/* Build log */}\n <Box flexDirection=\"column\">\n <Box gap={1} marginBottom={0}>\n {buildStatus === 'pending' && <Text dimColor>Build waiting...</Text>}\n {buildStatus === 'building' && (\n <>\n <Spinner />\n <Text>Building Plugin Package...</Text>\n </>\n )}\n {buildStatus === 'done' && (\n <Text color=\"green\">\n ✓ Built Plugin Package\n {lastBuilt !== null ? ` at ${lastBuilt.toLocaleTimeString()}` : ''}\n <Text dimColor>{elapsedLabel}</Text>\n </Text>\n )}\n {buildStatus === 'error' && (\n <Text color=\"red\">✗ Build error: {buildError ?? 'unknown error'}</Text>\n )}\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY}\n borderStyle=\"round\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {buildLogHistory.slice(-LOG_DISPLAY).map((log, index) => (\n <Text key={index} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))}\n </Box>\n </Box>\n\n {/* Web server log */}\n <Box marginTop={1} flexDirection=\"column\">\n <Box gap={2}>\n {status === 'starting' && <Text dimColor>Starting server...</Text>}\n {status === 'running' && (\n <>\n <Text color=\"green\">✓ Dev Server running</Text>\n <Text color=\"cyan\" bold>\n http://localhost:{port}\n </Text>\n <Text dimColor>\n ● {wsClientCount} viewer{wsClientCount !== 1 ? 's' : ''}\n </Text>\n </>\n )}\n {status === 'error' && <Text color=\"red\">✗ {errorMessage ?? 'Server error'}</Text>}\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY}\n borderStyle=\"round\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {serverLogHistory.slice(-LOG_DISPLAY).map((log, index) => (\n <Text key={index} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))}\n </Box>\n </Box>\n\n {/* Proxy log */}\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>Proxy</Text>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY}\n borderStyle=\"round\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {proxyLogHistory.length === 0 ? (\n <Text dimColor> No proxy requests yet.</Text>\n ) : (\n proxyLogHistory.slice(-LOG_DISPLAY).map((log, i) => (\n <Text key={i} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))\n )}\n </Box>\n </Box>\n\n {/* Footer */}\n <Box marginTop={1}>\n <Text dimColor>q to quit</Text>\n </Box>\n </Box>\n );\n};\n"],"mappings":"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","names":["join","join","program","createElement","render","useEffect","useState","Box","Text","readFile","join","Fragment","jsx","jsxs","SPINNER_FRAMES","Spinner","useState","useEffect","Text","join","readFile","Box","program","render","createElement"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/build.ts","../src/ui/BuildUI.tsx","../src/lib/runBuild.ts","../src/lib/readFiles.ts","../src/commands/dev.ts","../src/ui/DevUI.tsx"],"sourcesContent":["import { program } from 'commander';\nimport { buildCommand } from './commands/build.js';\nimport { devCommand } from './commands/dev.js';\n\nprogram.name('appbuilder').description('Kizen plugin app builder').version('0.1.0');\n\nbuildCommand(program);\ndevCommand(program);\n\nprogram.parse();\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { BuildUI } from '../ui/BuildUI.js';\n\nexport function buildCommand(program: Command): void {\n program\n .command('build')\n .description('Bundle the plugin app into .kizenapp directory')\n .action(async () => {\n const outputDir = `${process.cwd()}/.kizenapp`;\n const pluginDir = process.cwd();\n const { waitUntilExit } = render(createElement(BuildUI, { outputDir, pluginDir }));\n await waitUntilExit();\n });\n}\n","import type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { Box, Text, useApp } from 'ink';\nimport { runBuild } from '../lib/runBuild.js';\nimport type { BuildStepName } from '../lib/runBuild.js';\n\ntype BuildStep = BuildStepName | 'done' | 'error';\n\ninterface BuildUIProps {\n outputDir: string;\n pluginDir: string;\n}\n\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nconst Spinner: FC = () => {\n const [frame, setFrame] = useState(0);\n\n useEffect(() => {\n const id = setInterval(() => {\n setFrame((prev) => (prev + 1) % SPINNER_FRAMES.length);\n }, 80);\n\n return () => {\n clearInterval(id);\n };\n }, []);\n\n return <Text color=\"cyan\">{SPINNER_FRAMES[frame] ?? '⠋'}</Text>;\n};\n\nconst STEPS: BuildStepName[] = [\n 'creating-dir',\n 'reading-files',\n 'minifying',\n 'packaging',\n 'writing-bundle',\n];\n\nconst STEP_LABELS: Record<BuildStepName, string> = {\n 'creating-dir': 'Creating .kizenapp directory',\n 'reading-files': 'Reading plugin files',\n minifying: 'Minifying scripts',\n packaging: 'Packaging plugin',\n 'writing-bundle': 'Writing bundle.json',\n};\n\nexport const BuildUI: FC<BuildUIProps> = ({ outputDir, pluginDir }) => {\n const { exit } = useApp();\n const [step, setStep] = useState<BuildStep>('creating-dir');\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n\n useEffect(() => {\n void runBuild(pluginDir, outputDir, setStep)\n .then(() => {\n setStep('done');\n exit();\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n setErrorMessage(message);\n setStep('error');\n exit(err instanceof Error ? err : new Error(message));\n });\n }, [outputDir, pluginDir, exit]);\n\n const currentIndex = STEPS.indexOf(step as BuildStepName);\n const isError = step === 'error';\n const isDone = step === 'done';\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={1}>\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color=\"cyan\">\n Kizen App Builder\n </Text>\n <Text dimColor>{'─'.repeat(22)}</Text>\n </Box>\n\n <Box flexDirection=\"column\" gap={1}>\n {STEPS.map((s, i) => {\n const isActive = step === s;\n const isStepDone = isDone || currentIndex > i;\n const isFailed = isError && i === currentIndex;\n\n return (\n <Box key={s} gap={1}>\n {isFailed ? (\n <Text color=\"red\">✗ {STEP_LABELS[s]}</Text>\n ) : isStepDone ? (\n <Text color=\"green\">✓ {STEP_LABELS[s]}</Text>\n ) : isActive ? (\n <>\n <Spinner />\n <Text>{STEP_LABELS[s]}</Text>\n </>\n ) : (\n <Text dimColor>· {STEP_LABELS[s]}</Text>\n )}\n </Box>\n );\n })}\n\n {errorMessage !== null && (\n <Box marginTop={1}>\n <Text color=\"red\">{errorMessage}</Text>\n </Box>\n )}\n </Box>\n </Box>\n );\n};\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { minifyFiles, packagePlugin, transformDeployablePlugin } from '@kizenapps/packager';\nimport type { DeployablePlugin } from '@kizenapps/packager';\nimport { readLocalFiles } from './readFiles.js';\n\nexport type BuildStepName =\n | 'creating-dir'\n | 'reading-files'\n | 'minifying'\n | 'packaging'\n | 'writing-bundle';\n\ntype SerializableDeployablePlugin = Omit<DeployablePlugin, 'thumbnail' | 'kznFile'> & {\n thumbnail: string | null;\n kznFile: string | null;\n};\n\nconst serializePlugin = (plugin: DeployablePlugin): SerializableDeployablePlugin => ({\n ...plugin,\n thumbnail: plugin.thumbnail ? Buffer.from(plugin.thumbnail).toString('base64') : null,\n kznFile: plugin.kznFile ? Buffer.from(plugin.kznFile).toString('base64') : null,\n});\n\nexport async function runBuild(\n pluginDir: string,\n outputDir: string,\n onStep?: (step: BuildStepName) => void,\n): Promise<void> {\n await mkdir(outputDir, { recursive: true });\n\n onStep?.('reading-files');\n const files = await readLocalFiles(pluginDir);\n\n onStep?.('minifying');\n const minified = await minifyFiles(files);\n\n onStep?.('packaging');\n const manifestFile = minified.find((f) => f.path === 'kizen.json');\n if (!manifestFile) {\n throw new Error('kizen.json not found in plugin directory.');\n }\n const manifests = JSON.parse(manifestFile.content) as Parameters<typeof packagePlugin>[1];\n const packaged = packagePlugin(minified, manifests);\n const deployable = Object.values(packaged).map(transformDeployablePlugin);\n\n onStep?.('writing-bundle');\n const bundle = deployable.map(serializePlugin);\n await writeFile(join(outputDir, 'bundle.json'), JSON.stringify(bundle, null, 2), 'utf-8');\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path';\nimport type { FileContent } from '@kizenapps/packager';\n\nconst IMAGE_EXTENSIONS = new Set(['.png', '.svg']);\nconst BINARY_EXTENSIONS = new Set(['.kzn']);\n\nconst SKIP_DIRS = new Set(['node_modules', '.git', '.kizenapp', '.github']);\n\nasync function walk(dir: string, rootDir: string): Promise<string[]> {\n const entries = await readdir(dir, { withFileTypes: true });\n const paths: string[] = [];\n\n for (const entry of entries) {\n if (entry.isDirectory()) {\n if (SKIP_DIRS.has(entry.name)) {\n continue;\n }\n\n paths.push(...(await walk(join(dir, entry.name), rootDir)));\n } else if (entry.isFile()) {\n paths.push(join(dir, entry.name));\n }\n }\n\n return paths;\n}\n\nexport async function readLocalFiles(rootDir: string): Promise<FileContent[]> {\n const absolutePaths = await walk(rootDir, rootDir);\n\n return Promise.all(\n absolutePaths.map(async (absPath): Promise<FileContent> => {\n const relPath = relative(rootDir, absPath).split('\\\\').join('/');\n const dotIndex = relPath.lastIndexOf('.');\n const ext = dotIndex >= 0 ? relPath.slice(dotIndex).toLowerCase() : '';\n\n if (IMAGE_EXTENSIONS.has(ext)) {\n const buf = await readFile(absPath);\n return { path: relPath, content: '', base64Image: buf.toString('base64') };\n }\n\n if (BINARY_EXTENSIONS.has(ext)) {\n const buf = await readFile(absPath);\n return { path: relPath, content: '', binaryData: buf };\n }\n\n const content = await readFile(absPath, 'utf-8');\n return { path: relPath, content };\n }),\n );\n}\n","import { createElement } from 'react';\nimport { render } from 'ink';\nimport type { Command } from 'commander';\nimport { DevUI } from '../ui/DevUI.js';\n\nexport function devCommand(program: Command): void {\n program\n .command('dev')\n .description('Start the plugin viewer dev server')\n .option('-p, --port <port>', 'port to listen on', '3121')\n .action(async (options: { port: string }) => {\n const port = parseInt(options.port, 10);\n const pluginDir = process.cwd();\n const outputDir = `${pluginDir}/.kizenapp`;\n const { waitUntilExit } = render(createElement(DevUI, { port, pluginDir, outputDir }), {\n exitOnCtrlC: false,\n });\n await waitUntilExit();\n });\n}\n","import type { FC } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { spawn } from 'node:child_process';\nimport {\n createReadStream,\n readFileSync,\n statSync,\n unlinkSync,\n watch,\n writeFileSync,\n} from 'node:fs';\nimport type { FSWatcher } from 'node:fs';\nimport { access, readFile } from 'node:fs/promises';\nimport { createServer } from 'node:http';\nimport type { IncomingMessage, Server, ServerResponse } from 'node:http';\nimport { createRequire } from 'node:module';\nimport { dirname, extname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { type WebSocket, WebSocketServer } from 'ws';\nimport { runBuild } from '../lib/runBuild.js';\n\ntype ServerStatus = 'starting' | 'running' | 'error';\ntype BuildStatus = 'pending' | 'building' | 'done' | 'error';\n\nconst SKIP_WATCH_PREFIXES = ['.kizenapp', '.git'];\nconst LOG_LIMIT = 50;\nconst LOG_DISPLAY = 8;\n\ninterface DevUIProps {\n port: number;\n pluginDir: string;\n outputDir: string;\n}\n\nconst MIME_TYPES: Readonly<Record<string, string>> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.json': 'application/json; charset=utf-8',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.map': 'application/json',\n};\n\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\nconst Spinner: FC = () => {\n const [frame, setFrame] = useState(0);\n\n useEffect(() => {\n const id = setInterval(() => {\n setFrame((prev) => (prev + 1) % SPINNER_FRAMES.length);\n }, 80);\n\n return () => {\n clearInterval(id);\n };\n }, []);\n\n return <Text color=\"cyan\">{SPINNER_FRAMES[frame] ?? '⠋'}</Text>;\n};\n\nfunction getViewerPath(): string {\n const filename = fileURLToPath(import.meta.url);\n return join(dirname(filename), 'viewer');\n}\n\nfunction getElectronMainPath(): string {\n const filename = fileURLToPath(import.meta.url);\n return join(dirname(filename), 'electron', 'main.js');\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n try {\n await access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction createRequestHandler(\n viewerPath: string,\n createServerLog: (message: string) => void,\n createProxyLog: (message: string) => void,\n): (req: IncomingMessage, res: ServerResponse) => void {\n return (req, res) => {\n void (async () => {\n const url = req.url ?? '/';\n\n createServerLog(`Received request: ${url}`);\n\n if (url === '/api/bundle') {\n const bundlePath = join(process.cwd(), '.kizenapp', 'bundle.json');\n try {\n const content = await readFile(bundlePath, 'utf-8');\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end(content);\n } catch {\n res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });\n res.end('{}');\n }\n return;\n }\n\n if (url.startsWith('/api/proxy')) {\n const proxyTarget = req.headers['x-proxy-target'];\n if (typeof proxyTarget !== 'string') {\n res.writeHead(400);\n res.end('Missing x-proxy-target header');\n return;\n }\n\n const upstreamPath = url.slice('/api/proxy'.length) || '/';\n const upstreamUrl = `${proxyTarget}${upstreamPath}`;\n\n const chunks: Buffer[] = [];\n for await (const chunk of req) {\n chunks.push(chunk as Buffer);\n }\n\n const body = chunks.length > 0 ? Buffer.concat(chunks) : undefined;\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { host, 'x-proxy-target': _drop, ...forwardHeaders } = req.headers;\n\n const resolvedBody = body && body.length > 0 ? body : undefined;\n const upstream = await fetch(upstreamUrl, {\n ...(req.method !== undefined && { method: req.method }),\n headers: forwardHeaders as Record<string, string>,\n ...(resolvedBody !== undefined && { body: resolvedBody }),\n });\n\n createProxyLog(`${req.method ?? 'GET'} ${upstreamPath} → ${String(upstream.status)}`);\n\n // Node fetch auto-decompresses the body, so strip encoding/length headers\n // that describe the compressed wire format — they no longer apply.\n const responseHeaders = Object.fromEntries(upstream.headers);\n delete responseHeaders['content-encoding'];\n delete responseHeaders['content-length'];\n\n res.writeHead(upstream.status, responseHeaders);\n res.end(Buffer.from(await upstream.arrayBuffer()));\n return;\n }\n\n const rawPath = url === '/' ? '/index.html' : url;\n const filePath = join(viewerPath, rawPath);\n const resolvedPath = (await fileExists(filePath)) ? filePath : join(viewerPath, 'index.html');\n const ext = extname(resolvedPath);\n const mimeType = MIME_TYPES[ext] ?? 'application/octet-stream';\n res.writeHead(200, { 'Content-Type': mimeType });\n createReadStream(resolvedPath).pipe(res);\n })();\n };\n}\n\nexport const DevUI: FC<DevUIProps> = ({ port, pluginDir, outputDir }) => {\n const [status, setStatus] = useState<ServerStatus>('starting');\n const [errorMessage, setErrorMessage] = useState<string | null>(null);\n const [serverLogHistory, setServerLogHistory] = useState<string[]>([]);\n const [buildLogHistory, setBuildLogHistory] = useState<string[]>([]);\n const [proxyLogHistory, setProxyLogHistory] = useState<string[]>([]);\n const [buildStatus, setBuildStatus] = useState<BuildStatus>('pending');\n const [buildError, setBuildError] = useState<string | null>(null);\n const [lastBuilt, setLastBuilt] = useState<Date | null>(null);\n const [wsClientCount, setWsClientCount] = useState(0);\n\n const buildingRef = useRef(false);\n const electronLaunchedRef = useRef(false);\n const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const wsClientsRef = useRef<Set<WebSocket>>(new Set());\n const pendingMessagesRef = useRef<string[]>([]);\n\n useInput((input, key) => {\n if (input === 'q' || (key.ctrl && input === 'c')) {\n process.exit(0);\n }\n });\n\n useEffect(() => {\n if (status !== 'running' || electronLaunchedRef.current) {\n return;\n }\n\n electronLaunchedRef.current = true;\n\n const _require = createRequire(import.meta.url);\n const electronBin = _require('electron') as string;\n const electronMain = getElectronMainPath();\n const userDataDir = join(outputDir, '.electron');\n\n // Patch Electron's CFBundleName so macOS shows \"Kizen Dev\" in the Dock.\n // Breaks the pnpm hard link first so the global content-addressable store is unaffected.\n if (process.platform === 'darwin') {\n try {\n const plistPath = join(dirname(dirname(electronBin)), 'Info.plist');\n const plist = readFileSync(plistPath, 'utf-8');\n if (!plist.includes('>Kizen Dev<')) {\n if (statSync(plistPath).nlink > 1) {\n unlinkSync(plistPath);\n writeFileSync(plistPath, plist);\n }\n writeFileSync(\n plistPath,\n plist\n .replace(/(<key>CFBundleName<\\/key>\\s*<string>)[^<]*(<\\/string>)/, '$1Kizen Dev$2')\n .replace(\n /(<key>CFBundleDisplayName<\\/key>\\s*<string>)[^<]*(<\\/string>)/,\n '$1Kizen Dev$2',\n ),\n );\n }\n } catch {\n // Non-fatal — Dock will show \"Electron\" if patching fails\n }\n }\n\n const proc = spawn(\n electronBin,\n [electronMain, `--port=${String(port)}`, `--user-data-dir=${userDataDir}`],\n {\n stdio: 'ignore',\n },\n );\n proc.unref();\n process.on('exit', () => {\n proc.kill();\n });\n }, [status, port, outputDir]);\n\n const createServerLog = useCallback((message: string): void => {\n setServerLogHistory((h) =>\n [...h, `${new Date().toLocaleTimeString()}: ${message}`].slice(-LOG_LIMIT),\n );\n }, []);\n\n const broadcast = useCallback((msg: object): void => {\n const json = JSON.stringify(msg);\n if (wsClientsRef.current.size === 0) {\n pendingMessagesRef.current = [...pendingMessagesRef.current, json].slice(-LOG_LIMIT);\n return;\n }\n for (const client of wsClientsRef.current) {\n if (client.readyState === 1) {\n client.send(json);\n }\n }\n }, []);\n\n const createProxyLog = useCallback(\n (message: string): void => {\n setProxyLogHistory((h) =>\n [...h, `${new Date().toLocaleTimeString()}: ${message}`].slice(-LOG_LIMIT),\n );\n broadcast({ type: 'proxy-log', message });\n },\n [broadcast],\n );\n\n const createBuildLog = useCallback(\n (message: string): void => {\n setBuildLogHistory((h) =>\n [...h, `${new Date().toLocaleTimeString()}: ${message}`].slice(-LOG_LIMIT),\n );\n broadcast({ type: 'log', message });\n },\n [broadcast],\n );\n\n const triggerBuild = useCallback(() => {\n if (buildingRef.current) {\n return;\n }\n\n buildingRef.current = true;\n\n setBuildStatus('building');\n setBuildError(null);\n createBuildLog('Build started');\n\n void runBuild(pluginDir, outputDir)\n .then(() => {\n createBuildLog('Build finished');\n setBuildStatus('done');\n setLastBuilt(new Date());\n\n createBuildLog('Notifying viewers to reload');\n for (const client of wsClientsRef.current) {\n if (client.readyState === 1) {\n client.send(JSON.stringify({ type: 'rebuild' }));\n }\n }\n })\n .catch((err: unknown) => {\n const message = err instanceof Error ? err.message : String(err);\n setBuildError(message);\n setBuildStatus('error');\n })\n .finally(() => {\n buildingRef.current = false;\n });\n }, [pluginDir, outputDir, createBuildLog]);\n\n useEffect(() => {\n triggerBuild();\n\n const watcher: FSWatcher = watch(pluginDir, { recursive: true }, (_, filename) => {\n if (!filename) {\n return;\n }\n\n const normalized = filename.replace(/\\\\/g, '/');\n\n if (SKIP_WATCH_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {\n return;\n }\n\n createBuildLog(`File change detected: ${filename}`);\n\n if (debounceTimerRef.current !== null) {\n clearTimeout(debounceTimerRef.current);\n }\n debounceTimerRef.current = setTimeout(triggerBuild, 150);\n });\n\n return () => {\n watcher.close();\n\n if (debounceTimerRef.current !== null) {\n clearTimeout(debounceTimerRef.current);\n }\n };\n }, [pluginDir, triggerBuild, createBuildLog]);\n\n useEffect(() => {\n const viewerPath = getViewerPath();\n\n void fileExists(join(viewerPath, 'index.html')).then((viewerBuilt) => {\n if (!viewerBuilt) {\n setErrorMessage(\"Viewer not built. Run 'pnpm build:viewer' first.\");\n setStatus('error');\n return;\n }\n\n const handler = createRequestHandler(viewerPath, createServerLog, createProxyLog);\n const server: Server = createServer(handler);\n const wss = new WebSocketServer({ server });\n\n wss.on('connection', (ws: WebSocket) => {\n for (const json of pendingMessagesRef.current) {\n if (ws.readyState === 1) {\n ws.send(json);\n }\n }\n pendingMessagesRef.current = [];\n\n createServerLog('Viewer connected for live reload');\n wsClientsRef.current.add(ws);\n setWsClientCount(wsClientsRef.current.size);\n\n ws.on('close', () => {\n wsClientsRef.current.delete(ws);\n setWsClientCount(wsClientsRef.current.size);\n });\n });\n\n server.listen(port, () => {\n setStatus('running');\n createServerLog(`Server started on port ${String(port)}`);\n });\n\n server.on('error', (err: Error) => {\n setErrorMessage(err.message);\n setStatus('error');\n });\n\n return () => {\n wss.close();\n server.close();\n };\n });\n }, [port, createServerLog, createProxyLog]);\n\n const elapsedSeconds =\n lastBuilt !== null ? Math.round((Date.now() - lastBuilt.getTime()) / 1000) : null;\n const elapsedLabel =\n elapsedSeconds === null\n ? ''\n : elapsedSeconds < 5\n ? ' (just now)'\n : ` (${String(elapsedSeconds)}s ago)`;\n\n return (\n <Box flexDirection=\"column\" paddingY={1} paddingX={1}>\n {/* Header */}\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box gap={1}>\n <Text bold color=\"cyan\">\n Kizen App Builder\n </Text>\n </Box>\n </Box>\n\n {/* Build log */}\n <Box flexDirection=\"column\">\n <Box gap={1} marginBottom={0}>\n {buildStatus === 'pending' && <Text dimColor>Build waiting...</Text>}\n {buildStatus === 'building' && (\n <>\n <Spinner />\n <Text>Building Plugin Package...</Text>\n </>\n )}\n {buildStatus === 'done' && (\n <Text color=\"green\">\n ✓ Built Plugin Package\n {lastBuilt !== null ? ` at ${lastBuilt.toLocaleTimeString()}` : ''}\n <Text dimColor>{elapsedLabel}</Text>\n </Text>\n )}\n {buildStatus === 'error' && (\n <Text color=\"red\">✗ Build error: {buildError ?? 'unknown error'}</Text>\n )}\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY}\n borderStyle=\"round\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {buildLogHistory.slice(-LOG_DISPLAY).map((log, index) => (\n <Text key={index} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))}\n </Box>\n </Box>\n\n {/* Web server log */}\n <Box marginTop={1} flexDirection=\"column\">\n <Box gap={2}>\n {status === 'starting' && <Text dimColor>Starting server...</Text>}\n {status === 'running' && (\n <>\n <Text color=\"green\">✓ Dev Server running</Text>\n <Text dimColor>\n ● {wsClientCount} viewer{wsClientCount !== 1 ? 's' : ''}\n </Text>\n </>\n )}\n {status === 'error' && <Text color=\"red\">✗ {errorMessage ?? 'Server error'}</Text>}\n </Box>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY}\n borderStyle=\"round\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {serverLogHistory.slice(-LOG_DISPLAY).map((log, index) => (\n <Text key={index} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))}\n </Box>\n </Box>\n\n {/* Proxy log */}\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>Proxy</Text>\n <Box\n flexDirection=\"column\"\n height={LOG_DISPLAY}\n borderStyle=\"round\"\n borderColor=\"gray\"\n overflow=\"hidden\"\n >\n {proxyLogHistory.length === 0 ? (\n <Text dimColor> No proxy requests yet.</Text>\n ) : (\n proxyLogHistory.slice(-LOG_DISPLAY).map((log, i) => (\n <Text key={i} dimColor wrap=\"truncate\">\n {log}\n </Text>\n ))\n )}\n </Box>\n </Box>\n\n {/* Footer */}\n <Box marginTop={1}>\n <Text dimColor>q to quit</Text>\n </Box>\n </Box>\n );\n};\n"],"mappings":"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","names":["join","join","program","createElement","render","useEffect","useState","Box","Text","readFile","join","Fragment","jsx","jsxs","SPINNER_FRAMES","Spinner","useState","useEffect","Text","join","readFile","Box","program","render","createElement"]}
Binary file