@kehto/paja 0.3.5 → 0.3.7

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.
@@ -369,7 +369,7 @@ function renderPajaHtml(config) {
369
369
  <head>
370
370
  <meta charset="utf-8">
371
371
  <meta name="viewport" content="width=device-width, initial-scale=1">
372
- <title>Kehto Paja</title>
372
+ <title>@kehto/paja</title>
373
373
  <style>
374
374
  :root {
375
375
  color-scheme: dark;
@@ -387,19 +387,46 @@ function renderPajaHtml(config) {
387
387
  .top { border-bottom: 1px solid var(--line); }
388
388
  .bottom { border-top: 1px solid var(--line); color: var(--muted); font-size: 12px; }
389
389
  .brand { font-weight: 700; letter-spacing: 0; color: var(--accent); white-space: nowrap; }
390
+ .brand-product { color: var(--text); }
390
391
  .target { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }
391
392
  .spacer { flex: 1; min-width: 0; }
392
393
  button { border: 1px solid var(--line); color: var(--text); background: #20241f; height: 26px; padding: 0 10px; border-radius: 4px; font: inherit; cursor: pointer; }
393
394
  button:hover { border-color: var(--accent); }
394
395
  label { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); white-space: nowrap; }
395
- select { border: 1px solid var(--line); color: var(--text); background: #20241f; height: 26px; border-radius: 4px; font: inherit; }
396
+ select, input { border: 1px solid var(--line); color: var(--text); background: #20241f; height: 26px; border-radius: 4px; font: inherit; }
397
+ main { min-height: 0; display: grid; grid-template-columns: minmax(320px, 380px) minmax(0, 1fr); }
398
+ .console { min-height: 0; overflow: auto; border-right: 1px solid var(--line); background: #121512; padding: 10px; display: flex; flex-direction: column; gap: 12px; }
399
+ .section { display: grid; gap: 8px; }
400
+ .section-title { color: var(--accent); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0; }
401
+ .switch-grid, .acl-grid { display: flex; flex-wrap: wrap; gap: 6px; }
402
+ .toggle { height: 24px; padding: 0 8px; color: var(--muted); }
403
+ .toggle[data-enabled="true"] { color: var(--text); border-color: #5f724f; background: #24301f; }
404
+ .toggle[data-enabled="false"] { color: #8d9187; border-color: #453536; background: #241d1d; }
405
+ .signer { color: var(--muted); word-break: break-all; font-size: 12px; }
406
+ .signer-controls { display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; gap: 6px; }
407
+ .signer-controls button[data-active="true"] { border-color: var(--accent); color: var(--text); background: #2a2a1d; }
408
+ .signer-controls input { min-width: 0; padding: 0 8px; }
409
+ .log-tools { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px; }
410
+ .log-list { min-height: 160px; max-height: 38vh; overflow: auto; border: 1px solid var(--line); border-radius: 4px; background: #0b0d0b; }
411
+ .log-row { display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: 6px; padding: 5px 7px; border-bottom: 1px solid #1b1f1a; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; }
412
+ .log-row[data-error="true"] { background: #1d1414; }
413
+ .log-row:last-child { border-bottom: 0; }
414
+ .log-dir { color: var(--muted); }
415
+ .log-body { min-width: 0; display: grid; gap: 2px; }
416
+ .log-type { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
417
+ .log-detail { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #e6a5a5; }
418
+ .stage { min-width: 0; min-height: 0; }
396
419
  iframe { width: 100%; height: 100%; border: 0; background: white; display: block; }
397
420
  code { color: var(--text); }
421
+ @media (max-width: 900px) {
422
+ main { grid-template-columns: 1fr; grid-template-rows: minmax(240px, 40vh) minmax(0, 1fr); }
423
+ .console { border-right: 0; border-bottom: 1px solid var(--line); }
424
+ }
398
425
  </style>
399
426
  </head>
400
427
  <body>
401
428
  <header class="bar top">
402
- <div class="brand">Kehto</div>
429
+ <div class="brand">@kehto/<span class="brand-product">paja</span></div>
403
430
  <div class="target" title="${targetUrl}">${targetUrl}</div>
404
431
  <div class="spacer"></div>
405
432
  <label>theme
@@ -411,7 +438,32 @@ function renderPajaHtml(config) {
411
438
  <button type="button" id="reload-target">Reload</button>
412
439
  </header>
413
440
  <main>
414
- <iframe id="napplet-frame" title="Napplet development target" sandbox="allow-scripts" data-target-url="${targetUrl}"></iframe>
441
+ <aside class="console" aria-label="Paja development controls">
442
+ <section class="section">
443
+ <div class="section-title">Interfaces</div>
444
+ <div class="switch-grid" id="interface-toggles"></div>
445
+ </section>
446
+ <section class="section">
447
+ <div class="section-title">ACL</div>
448
+ <div class="acl-grid" id="acl-controls"></div>
449
+ </section>
450
+ <section class="section">
451
+ <div class="section-title">Signer</div>
452
+ <div class="signer" id="signer-status">loading</div>
453
+ <div class="signer-controls" id="signer-controls"></div>
454
+ </section>
455
+ <section class="section">
456
+ <div class="section-title">Messages</div>
457
+ <div class="log-tools">
458
+ <input id="message-filter" type="search" autocomplete="off" placeholder="filter messages" aria-label="Filter message log">
459
+ <button type="button" id="clear-log">Clear</button>
460
+ </div>
461
+ <div class="log-list" id="message-log" aria-live="polite"></div>
462
+ </section>
463
+ </aside>
464
+ <section class="stage">
465
+ <iframe id="napplet-frame" title="Napplet development target" sandbox="allow-scripts" data-target-url="${targetUrl}"></iframe>
466
+ </section>
415
467
  </main>
416
468
  <footer class="bar bottom">
417
469
  <span>mode: <code>${config.target.command ? "managed-command" : "external-target"}</code></span>
@@ -560,9 +612,18 @@ import { readFileSync as readFileSync2 } from "fs";
560
612
  async function startPajaServer(input) {
561
613
  const rawOptions = resolvePajaRawOptions(input.options);
562
614
  const options = normalizePajaOptions(rawOptions);
563
- let hostConfig = createPajaHostConfig(options, input.now);
615
+ const createdAt = input.now ?? /* @__PURE__ */ new Date();
616
+ let hostConfig = createPajaHostConfig(options, createdAt);
564
617
  let html = renderPajaHtml(hostConfig);
565
618
  let configJson = JSON.stringify(hostConfig, null, 2);
619
+ let currentOptions = options;
620
+ const setHostConfig = (nextOptions) => {
621
+ currentOptions = nextOptions;
622
+ hostConfig = createPajaHostConfig(currentOptions, createdAt);
623
+ html = renderPajaHtml(hostConfig);
624
+ configJson = JSON.stringify(hostConfig, null, 2);
625
+ return hostConfig;
626
+ };
566
627
  const server = createServer((request, response) => {
567
628
  const requestUrl = request.url ?? "/";
568
629
  if (requestUrl === "/" || requestUrl.startsWith("/?")) {
@@ -586,12 +647,15 @@ async function startPajaServer(input) {
586
647
  });
587
648
  await listen(server, options.host, options.port);
588
649
  const servedOptions = withBoundPort(options, getBoundPort(server, options.port));
589
- hostConfig = createPajaHostConfig(servedOptions, input.now);
590
- html = renderPajaHtml(hostConfig);
591
- configJson = JSON.stringify(hostConfig, null, 2);
650
+ setHostConfig(servedOptions);
592
651
  return {
593
652
  url: formatPajaUrl(servedOptions),
594
- hostConfig,
653
+ get hostConfig() {
654
+ return hostConfig;
655
+ },
656
+ updateTargetUrl(targetUrl) {
657
+ return setHostConfig(withTargetUrl(currentOptions, targetUrl));
658
+ },
595
659
  close: () => close(server)
596
660
  };
597
661
  }
@@ -625,6 +689,23 @@ function getBoundPort(server, fallback) {
625
689
  function withBoundPort(options, port) {
626
690
  return port === options.port ? options : { ...options, port };
627
691
  }
692
+ function withTargetUrl(options, targetUrl) {
693
+ const url = normalizeServerTargetUrl(targetUrl);
694
+ return url === options.targetUrl ? options : { ...options, targetUrl: url };
695
+ }
696
+ function normalizeServerTargetUrl(value) {
697
+ const raw = value.trim();
698
+ let parsed;
699
+ try {
700
+ parsed = new URL(raw);
701
+ } catch {
702
+ throw new Error(`Invalid managed target URL "${raw}". Expected an absolute http(s) URL.`);
703
+ }
704
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
705
+ throw new Error(`Invalid managed target URL "${raw}". Only http: and https: URLs are supported.`);
706
+ }
707
+ return parsed.href;
708
+ }
628
709
 
629
710
  export {
630
711
  PajaSimulationError,
@@ -656,4 +737,4 @@ export {
656
737
  waitForTargetUrl,
657
738
  startPajaServer
658
739
  };
659
- //# sourceMappingURL=chunk-6QZXEPQJ.js.map
740
+ //# sourceMappingURL=chunk-WYIXZLDJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config-file.ts","../src/simulation.ts","../src/options.ts","../src/host-page.ts","../src/parity.ts","../src/readiness.ts","../src/server.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport type { PajaRawOptions } from './options.js';\nimport type { PajaSimulationRawOptions } from './simulation.js';\nimport { PajaSimulationError } from './simulation.js';\n\nexport function loadPajaConfigFile(configPath: string): PajaRawOptions {\n const resolved = resolve(configPath);\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(resolved, 'utf8'));\n } catch (error) {\n const detail = error instanceof Error ? error.message : String(error);\n throw new PajaSimulationError(`Unable to read --config \"${configPath}\": ${detail}`);\n }\n\n if (!isRecord(parsed)) {\n throw new PajaSimulationError(`Invalid --config \"${configPath}\": expected a JSON object.`);\n }\n\n return parsed as PajaRawOptions;\n}\n\nexport function resolvePajaRawOptions(raw: PajaRawOptions): PajaRawOptions {\n if (!raw.configPath?.trim()) return raw;\n return mergePajaRawOptions(loadPajaConfigFile(raw.configPath), raw);\n}\n\nexport function mergePajaRawOptions(\n base: PajaRawOptions,\n override: PajaRawOptions,\n): PajaRawOptions {\n return {\n targetUrl: override.targetUrl ?? base.targetUrl,\n command: override.command ?? base.command,\n host: override.host ?? base.host,\n port: override.port ?? base.port,\n readyTimeoutMs: override.readyTimeoutMs ?? base.readyTimeoutMs,\n configPath: override.configPath ?? base.configPath,\n simulation: mergeSimulationOptions(base.simulation, override.simulation),\n };\n}\n\nfunction mergeSimulationOptions(\n base: PajaSimulationRawOptions | undefined,\n override: PajaSimulationRawOptions | undefined,\n): PajaSimulationRawOptions | undefined {\n if (!base) return override;\n if (!override) return base;\n\n return {\n capabilities: {\n ...base.capabilities,\n ...override.capabilities,\n domains: {\n ...base.capabilities?.domains,\n ...override.capabilities?.domains,\n },\n },\n acl: { ...base.acl, ...override.acl },\n firewall: { ...base.firewall, ...override.firewall },\n identity: { ...base.identity, ...override.identity },\n relay: { ...base.relay, ...override.relay },\n storage: { ...base.storage, ...override.storage },\n cache: { ...base.cache, ...override.cache },\n upload: { ...base.upload, ...override.upload },\n media: { ...base.media, ...override.media },\n notifications: { ...base.notifications, ...override.notifications },\n config: {\n ...base.config,\n ...override.config,\n values: { ...base.config?.values, ...override.config?.values },\n },\n theme: {\n ...base.theme,\n ...override.theme,\n values: { ...base.theme?.values, ...override.theme?.values },\n },\n intent: { ...base.intent, ...override.intent },\n cvm: { ...base.cvm, ...override.cvm },\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","export type JsonPrimitive = string | number | boolean | null;\nexport type JsonValue = JsonPrimitive | JsonValue[] | { readonly [key: string]: JsonValue };\nexport type JsonRecord = Record<string, JsonValue>;\n\nexport type PajaCapabilityDomain =\n | 'relay'\n | 'outbox'\n | 'storage'\n | 'identity'\n | 'keys'\n | 'config'\n | 'resource'\n | 'theme'\n | 'notify'\n | 'media'\n | 'upload'\n | 'intent'\n | 'link'\n | 'common'\n | 'lists'\n | 'serial'\n | 'ble'\n | 'webrtc'\n | 'cvm'\n | 'inc';\n\nexport interface PajaSimulationRawOptions {\n readonly capabilities?: {\n readonly domains?: Partial<Record<PajaCapabilityDomain, boolean>>;\n };\n readonly acl?: {\n readonly mode?: 'allow' | 'deny';\n };\n readonly firewall?: {\n readonly mode?: 'allow' | 'deny' | 'observe';\n };\n readonly identity?: {\n readonly mode?: 'anonymous' | 'fixed';\n readonly pubkey?: string;\n };\n readonly relay?: {\n readonly mode?: 'memory' | 'disabled';\n readonly urls?: readonly string[];\n readonly fixtures?: readonly JsonRecord[];\n };\n readonly storage?: {\n readonly mode?: 'local' | 'memory' | 'disabled';\n };\n readonly cache?: {\n readonly mode?: 'memory' | 'disabled';\n };\n readonly upload?: {\n readonly mode?: 'memory' | 'disabled';\n readonly rail?: string;\n };\n readonly media?: {\n readonly enabled?: boolean;\n };\n readonly notifications?: {\n readonly enabled?: boolean;\n readonly grant?: boolean;\n };\n readonly config?: {\n readonly values?: JsonRecord;\n };\n readonly theme?: {\n readonly mode?: 'dark' | 'light';\n readonly values?: JsonRecord;\n };\n readonly intent?: {\n readonly enabled?: boolean;\n };\n readonly cvm?: {\n readonly enabled?: boolean;\n };\n}\n\nexport interface PajaSimulation {\n readonly capabilities: {\n readonly domains: Record<PajaCapabilityDomain, boolean>;\n readonly disabledDomains: readonly PajaCapabilityDomain[];\n };\n readonly acl: {\n readonly mode: 'allow' | 'deny';\n };\n readonly firewall: {\n readonly mode: 'allow' | 'deny' | 'observe';\n };\n readonly identity: {\n readonly mode: 'anonymous' | 'fixed';\n readonly pubkey: string;\n };\n readonly relay: {\n readonly mode: 'memory' | 'disabled';\n readonly urls: readonly string[];\n readonly fixtures: readonly JsonRecord[];\n };\n readonly storage: {\n readonly mode: 'local' | 'memory' | 'disabled';\n };\n readonly cache: {\n readonly mode: 'memory' | 'disabled';\n };\n readonly upload: {\n readonly mode: 'memory' | 'disabled';\n readonly rail: string;\n };\n readonly media: {\n readonly enabled: boolean;\n };\n readonly notifications: {\n readonly enabled: boolean;\n readonly grant: boolean;\n };\n readonly config: {\n readonly values: JsonRecord;\n };\n readonly theme: {\n readonly mode: 'dark' | 'light';\n readonly values: JsonRecord;\n };\n readonly intent: {\n readonly enabled: boolean;\n };\n readonly cvm: {\n readonly enabled: boolean;\n };\n}\n\nexport class PajaSimulationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PajaSimulationError';\n }\n}\n\nexport const PAJA_SIMULATION_DOMAINS: readonly PajaCapabilityDomain[] = [\n 'relay',\n 'outbox',\n 'storage',\n 'identity',\n 'keys',\n 'config',\n 'resource',\n 'theme',\n 'notify',\n 'media',\n 'upload',\n 'intent',\n 'link',\n 'common',\n 'lists',\n 'serial',\n 'ble',\n 'webrtc',\n 'cvm',\n 'inc',\n];\n\nconst DEFAULT_RELAY_URLS = ['wss://relay.kehto.dev'] as const;\nconst DEFAULT_CONFIG_VALUES: JsonRecord = {\n runtime: 'kehto paja',\n mode: 'development',\n target: 'single-window',\n};\n\nconst DEFAULT_THEME_VALUES: JsonRecord = {\n title: 'Kehto Paja',\n};\n\nexport function normalizePajaSimulation(\n raw: PajaSimulationRawOptions | undefined,\n): PajaSimulation {\n const domainOverrides = raw?.capabilities?.domains ?? {};\n const domains = Object.fromEntries(\n PAJA_SIMULATION_DOMAINS.map((domain) => [domain, domainOverrides[domain] ?? true]),\n ) as Record<PajaCapabilityDomain, boolean>;\n\n const relayMode = raw?.relay?.mode ?? (domains.relay ? 'memory' : 'disabled');\n if (!domains.relay && relayMode !== 'disabled') {\n throw new PajaSimulationError('Invalid simulation: relay.mode must be \"disabled\" when capabilities.domains.relay is false.');\n }\n if (!domains.outbox && relayMode !== 'disabled') {\n throw new PajaSimulationError('Invalid simulation: relay.mode must be \"disabled\" when capabilities.domains.outbox is false.');\n }\n if (relayMode === 'disabled') {\n domains.relay = false;\n domains.outbox = false;\n }\n\n const uploadMode = raw?.upload?.mode ?? (domains.upload ? 'memory' : 'disabled');\n if (!domains.upload && uploadMode !== 'disabled') {\n throw new PajaSimulationError('Invalid simulation: upload.mode must be \"disabled\" when capabilities.domains.upload is false.');\n }\n if (uploadMode === 'disabled') domains.upload = false;\n\n const intentEnabled = raw?.intent?.enabled ?? domains.intent;\n if (!domains.intent && intentEnabled) {\n throw new PajaSimulationError('Invalid simulation: intent.enabled must be false when capabilities.domains.intent is false.');\n }\n if (!intentEnabled) domains.intent = false;\n\n const mediaEnabled = raw?.media?.enabled ?? domains.media;\n if (!domains.media && mediaEnabled) {\n throw new PajaSimulationError('Invalid simulation: media.enabled must be false when capabilities.domains.media is false.');\n }\n if (!mediaEnabled) domains.media = false;\n\n const cvmEnabled = raw?.cvm?.enabled ?? domains.cvm;\n if (!domains.cvm && cvmEnabled) {\n throw new PajaSimulationError('Invalid simulation: cvm.enabled must be false when capabilities.domains.cvm is false.');\n }\n if (!cvmEnabled) domains.cvm = false;\n\n const notificationsEnabled = raw?.notifications?.enabled ?? domains.notify;\n if (!domains.notify && notificationsEnabled) {\n throw new PajaSimulationError('Invalid simulation: notifications.enabled must be false when capabilities.domains.notify is false.');\n }\n if (!notificationsEnabled) domains.notify = false;\n\n const storageMode = raw?.storage?.mode ?? (domains.storage ? 'local' : 'disabled');\n if (!domains.storage && storageMode !== 'disabled') {\n throw new PajaSimulationError('Invalid simulation: storage.mode must be \"disabled\" when capabilities.domains.storage is false.');\n }\n if (storageMode === 'disabled') domains.storage = false;\n\n const identityMode = raw?.identity?.mode ?? 'anonymous';\n const pubkey = raw?.identity?.pubkey?.trim() ?? '';\n if (identityMode === 'fixed' && !isHexPubkey(pubkey)) {\n throw new PajaSimulationError('Invalid simulation: identity.pubkey must be a 64-character hex string when identity.mode is \"fixed\".');\n }\n\n const relayUrls = raw?.relay?.urls ?? DEFAULT_RELAY_URLS;\n if (relayMode === 'memory' && relayUrls.length === 0) {\n throw new PajaSimulationError('Invalid simulation: relay.urls must contain at least one URL when relay.mode is \"memory\".');\n }\n for (const url of relayUrls) {\n if (typeof url !== 'string' || url.trim().length === 0) {\n throw new PajaSimulationError('Invalid simulation: relay.urls entries must be non-empty strings.');\n }\n }\n\n const uploadRail = raw?.upload?.rail?.trim() || 'dev-memory';\n if (uploadMode === 'memory' && uploadRail.length === 0) {\n throw new PajaSimulationError('Invalid simulation: upload.rail must be non-empty when upload.mode is \"memory\".');\n }\n\n return {\n capabilities: {\n domains,\n disabledDomains: PAJA_SIMULATION_DOMAINS.filter((domain) => !domains[domain]),\n },\n acl: {\n mode: raw?.acl?.mode ?? 'allow',\n },\n firewall: {\n mode: raw?.firewall?.mode ?? 'observe',\n },\n identity: {\n mode: identityMode,\n pubkey: identityMode === 'fixed' ? pubkey : '',\n },\n relay: {\n mode: relayMode,\n urls: relayUrls.map((url) => url.trim()),\n fixtures: raw?.relay?.fixtures ?? [],\n },\n storage: {\n mode: storageMode,\n },\n cache: {\n mode: raw?.cache?.mode ?? 'memory',\n },\n upload: {\n mode: uploadMode,\n rail: uploadRail,\n },\n media: {\n enabled: mediaEnabled,\n },\n notifications: {\n enabled: notificationsEnabled,\n grant: raw?.notifications?.grant ?? true,\n },\n config: {\n values: { ...DEFAULT_CONFIG_VALUES, ...raw?.config?.values },\n },\n theme: {\n mode: raw?.theme?.mode ?? 'dark',\n values: { ...DEFAULT_THEME_VALUES, ...raw?.theme?.values },\n },\n intent: {\n enabled: intentEnabled,\n },\n cvm: {\n enabled: cvmEnabled,\n },\n };\n}\n\nexport function summarizePajaSimulation(simulation: PajaSimulation): string {\n const relay = simulation.relay.mode === 'memory' ? `relay:${simulation.relay.urls.length}` : 'relay:off';\n const identity = simulation.identity.mode === 'fixed' ? 'identity:fixed' : 'identity:anon';\n const storage = `storage:${simulation.storage.mode}`;\n const theme = `theme:${simulation.theme.mode}`;\n const disabled = simulation.capabilities.disabledDomains.length > 0\n ? `off:${simulation.capabilities.disabledDomains.join(',')}`\n : 'off:none';\n return `${identity} ${relay} ${storage} ${theme} ${disabled}`;\n}\n\nfunction isHexPubkey(value: string): boolean {\n return /^[0-9a-fA-F]{64}$/.test(value);\n}\n","import {\n normalizePajaSimulation,\n type PajaSimulation,\n type PajaSimulationRawOptions,\n} from './simulation.js';\n\nexport type PajaCommand =\n | { readonly mode: 'argv'; readonly argv: readonly string[] }\n | { readonly mode: 'shell'; readonly command: string };\n\nexport interface PajaRawOptions {\n readonly targetUrl?: string;\n readonly command?: PajaCommand;\n readonly host?: string;\n readonly port?: number | string;\n readonly readyTimeoutMs?: number | string;\n readonly configPath?: string;\n readonly simulation?: PajaSimulationRawOptions;\n}\n\nexport interface PajaOptions {\n readonly targetUrl: string;\n readonly command?: PajaCommand;\n readonly host: string;\n readonly port: number;\n readonly readyTimeoutMs: number;\n readonly configPath?: string;\n readonly simulation: PajaSimulation;\n readonly mode: 'external-target' | 'managed-command';\n}\n\nexport interface PajaHostConfig {\n readonly version: 1;\n readonly window: {\n readonly id: string;\n readonly dTag: string;\n readonly aggregateHash: string;\n };\n readonly target: {\n readonly url: string;\n readonly hmrStrategy: 'iframe-target-url';\n readonly command?: PajaCommand;\n };\n readonly runtime: {\n readonly host: string;\n readonly port: number;\n readonly readyTimeoutMs: number;\n readonly configPath?: string;\n readonly reloadToken: string;\n readonly createdAt: string;\n };\n readonly chrome: {\n readonly topBar: true;\n readonly bottomBar: true;\n readonly sidePanels: false;\n };\n readonly simulation: PajaSimulation;\n}\n\nexport class PajaOptionsError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'PajaOptionsError';\n }\n}\n\nexport const DEFAULT_PAJA_HOST = '127.0.0.1';\nexport const DEFAULT_PAJA_PORT = 5197;\nexport const DEFAULT_READY_TIMEOUT_MS = 30_000;\nexport const DEFAULT_PAJA_WINDOW_ID = 'kehto-paja-window';\nexport const DEFAULT_PAJA_DTAG = 'dev-target';\nexport const DEFAULT_PAJA_AGGREGATE_HASH = 'paja';\n\nexport function normalizePajaOptions(raw: PajaRawOptions): PajaOptions {\n const targetUrl = normalizeTargetUrl(raw.targetUrl);\n const host = normalizeHost(raw.host);\n const port = normalizePort(raw.port, 'port');\n const readyTimeoutMs = normalizePositiveInteger(\n raw.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS,\n 'ready-timeout',\n );\n const command = normalizeCommand(raw.command);\n const configPath = raw.configPath?.trim();\n const simulation = normalizePajaSimulation(raw.simulation);\n\n return {\n targetUrl,\n command,\n host,\n port,\n readyTimeoutMs,\n configPath: configPath && configPath.length > 0 ? configPath : undefined,\n simulation,\n mode: command ? 'managed-command' : 'external-target',\n };\n}\n\nexport function createPajaHostConfig(\n options: PajaOptions,\n now: Date = new Date(),\n): PajaHostConfig {\n return {\n version: 1,\n window: {\n id: DEFAULT_PAJA_WINDOW_ID,\n dTag: DEFAULT_PAJA_DTAG,\n aggregateHash: DEFAULT_PAJA_AGGREGATE_HASH,\n },\n target: {\n url: options.targetUrl,\n hmrStrategy: 'iframe-target-url',\n command: options.command,\n },\n runtime: {\n host: options.host,\n port: options.port,\n readyTimeoutMs: options.readyTimeoutMs,\n configPath: options.configPath,\n reloadToken: createReloadToken(now),\n createdAt: now.toISOString(),\n },\n chrome: {\n topBar: true,\n bottomBar: true,\n sidePanels: false,\n },\n simulation: options.simulation,\n };\n}\n\nexport function formatPajaUrl(options: Pick<PajaOptions, 'host' | 'port'>): string {\n return `http://${options.host}:${options.port}/`;\n}\n\nfunction normalizeTargetUrl(value: string | undefined): string {\n const raw = value?.trim();\n if (!raw) {\n throw new PajaOptionsError('Missing --target-url. Provide the napplet app URL that the iframe should load.');\n }\n\n let parsed: URL;\n try {\n parsed = new URL(raw);\n } catch {\n throw new PajaOptionsError(`Invalid --target-url \"${raw}\". Expected an absolute http(s) URL.`);\n }\n\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new PajaOptionsError(`Invalid --target-url \"${raw}\". Only http: and https: URLs are supported.`);\n }\n\n return parsed.href;\n}\n\nfunction normalizeHost(value: string | undefined): string {\n const host = value?.trim() || DEFAULT_PAJA_HOST;\n if (host.length === 0 || host.includes('/')) {\n throw new PajaOptionsError(`Invalid --host \"${value ?? ''}\". Provide a hostname or IP address.`);\n }\n return host;\n}\n\nfunction normalizePort(value: number | string | undefined, label: string): number {\n return normalizeIntegerInRange(value ?? DEFAULT_PAJA_PORT, label, 0, 65_535);\n}\n\nfunction normalizePositiveInteger(value: number | string, label: string, max = Number.MAX_SAFE_INTEGER): number {\n return normalizeIntegerInRange(value, label, 1, max);\n}\n\nfunction normalizeIntegerInRange(value: number | string, label: string, min: number, max: number): number {\n const parsed = typeof value === 'number' ? value : Number(value);\n if (!Number.isInteger(parsed) || parsed < min || parsed > max) {\n throw new PajaOptionsError(`Invalid --${label} \"${String(value)}\". Expected an integer from ${min} to ${max}.`);\n }\n return parsed;\n}\n\nfunction normalizeCommand(command: PajaCommand | undefined): PajaCommand | undefined {\n if (!command) return undefined;\n\n if (command.mode === 'argv') {\n const argv = command.argv.map((part) => part.trim()).filter((part) => part.length > 0);\n if (argv.length === 0) {\n throw new PajaOptionsError('Command mode requires at least one command argument after --.');\n }\n return { mode: 'argv', argv };\n }\n\n const shellCommand = command.command.trim();\n if (shellCommand.length === 0) {\n throw new PajaOptionsError('--command requires a non-empty command string.');\n }\n return { mode: 'shell', command: shellCommand };\n}\n\nfunction createReloadToken(now: Date): string {\n const iso = now.toISOString();\n return `reload-${iso.replaceAll(/[^0-9A-Za-z]/g, '')}`;\n}\n","import type { PajaHostConfig } from './options.js';\nimport { summarizePajaSimulation } from './simulation.js';\n\nexport function renderPajaHtml(config: PajaHostConfig): string {\n const configJson = escapeJsonForHtml(JSON.stringify(config));\n const targetUrl = escapeAttribute(config.target.url);\n\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>@kehto/paja</title>\n <style>\n :root {\n color-scheme: dark;\n --bg: #101211;\n --bar: #181b19;\n --line: #30352f;\n --text: #f4f0df;\n --muted: #a9ad9f;\n --accent: #d8c36a;\n }\n * { box-sizing: border-box; }\n html, body { margin: 0; min-height: 100%; background: var(--bg); color: var(--text); font: 13px/1.4 ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif; }\n body { height: 100vh; display: grid; grid-template-rows: 38px minmax(0, 1fr) 30px; overflow: hidden; }\n .bar { display: flex; align-items: center; gap: 14px; min-width: 0; padding: 0 12px; background: var(--bar); border-color: var(--line); }\n .top { border-bottom: 1px solid var(--line); }\n .bottom { border-top: 1px solid var(--line); color: var(--muted); font-size: 12px; }\n .brand { font-weight: 700; letter-spacing: 0; color: var(--accent); white-space: nowrap; }\n .brand-product { color: var(--text); }\n .target { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }\n .spacer { flex: 1; min-width: 0; }\n button { border: 1px solid var(--line); color: var(--text); background: #20241f; height: 26px; padding: 0 10px; border-radius: 4px; font: inherit; cursor: pointer; }\n button:hover { border-color: var(--accent); }\n label { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); white-space: nowrap; }\n select, input { border: 1px solid var(--line); color: var(--text); background: #20241f; height: 26px; border-radius: 4px; font: inherit; }\n main { min-height: 0; display: grid; grid-template-columns: minmax(320px, 380px) minmax(0, 1fr); }\n .console { min-height: 0; overflow: auto; border-right: 1px solid var(--line); background: #121512; padding: 10px; display: flex; flex-direction: column; gap: 12px; }\n .section { display: grid; gap: 8px; }\n .section-title { color: var(--accent); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0; }\n .switch-grid, .acl-grid { display: flex; flex-wrap: wrap; gap: 6px; }\n .toggle { height: 24px; padding: 0 8px; color: var(--muted); }\n .toggle[data-enabled=\"true\"] { color: var(--text); border-color: #5f724f; background: #24301f; }\n .toggle[data-enabled=\"false\"] { color: #8d9187; border-color: #453536; background: #241d1d; }\n .signer { color: var(--muted); word-break: break-all; font-size: 12px; }\n .signer-controls { display: grid; grid-template-columns: auto auto minmax(0, 1fr) auto; gap: 6px; }\n .signer-controls button[data-active=\"true\"] { border-color: var(--accent); color: var(--text); background: #2a2a1d; }\n .signer-controls input { min-width: 0; padding: 0 8px; }\n .log-tools { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px; }\n .log-list { min-height: 160px; max-height: 38vh; overflow: auto; border: 1px solid var(--line); border-radius: 4px; background: #0b0d0b; }\n .log-row { display: grid; grid-template-columns: 88px minmax(0, 1fr); gap: 6px; padding: 5px 7px; border-bottom: 1px solid #1b1f1a; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; }\n .log-row[data-error=\"true\"] { background: #1d1414; }\n .log-row:last-child { border-bottom: 0; }\n .log-dir { color: var(--muted); }\n .log-body { min-width: 0; display: grid; gap: 2px; }\n .log-type { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .log-detail { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: #e6a5a5; }\n .stage { min-width: 0; min-height: 0; }\n iframe { width: 100%; height: 100%; border: 0; background: white; display: block; }\n code { color: var(--text); }\n @media (max-width: 900px) {\n main { grid-template-columns: 1fr; grid-template-rows: minmax(240px, 40vh) minmax(0, 1fr); }\n .console { border-right: 0; border-bottom: 1px solid var(--line); }\n }\n </style>\n </head>\n <body>\n <header class=\"bar top\">\n <div class=\"brand\">@kehto/<span class=\"brand-product\">paja</span></div>\n <div class=\"target\" title=\"${targetUrl}\">${targetUrl}</div>\n <div class=\"spacer\"></div>\n <label>theme\n <select id=\"simulation-theme\" aria-label=\"Simulation theme\">\n <option value=\"dark\"${config.simulation.theme.mode === 'dark' ? ' selected' : ''}>dark</option>\n <option value=\"light\"${config.simulation.theme.mode === 'light' ? ' selected' : ''}>light</option>\n </select>\n </label>\n <button type=\"button\" id=\"reload-target\">Reload</button>\n </header>\n <main>\n <aside class=\"console\" aria-label=\"Paja development controls\">\n <section class=\"section\">\n <div class=\"section-title\">Interfaces</div>\n <div class=\"switch-grid\" id=\"interface-toggles\"></div>\n </section>\n <section class=\"section\">\n <div class=\"section-title\">ACL</div>\n <div class=\"acl-grid\" id=\"acl-controls\"></div>\n </section>\n <section class=\"section\">\n <div class=\"section-title\">Signer</div>\n <div class=\"signer\" id=\"signer-status\">loading</div>\n <div class=\"signer-controls\" id=\"signer-controls\"></div>\n </section>\n <section class=\"section\">\n <div class=\"section-title\">Messages</div>\n <div class=\"log-tools\">\n <input id=\"message-filter\" type=\"search\" autocomplete=\"off\" placeholder=\"filter messages\" aria-label=\"Filter message log\">\n <button type=\"button\" id=\"clear-log\">Clear</button>\n </div>\n <div class=\"log-list\" id=\"message-log\" aria-live=\"polite\"></div>\n </section>\n </aside>\n <section class=\"stage\">\n <iframe id=\"napplet-frame\" title=\"Napplet development target\" sandbox=\"allow-scripts\" data-target-url=\"${targetUrl}\"></iframe>\n </section>\n </main>\n <footer class=\"bar bottom\">\n <span>mode: <code>${config.target.command ? 'managed-command' : 'external-target'}</code></span>\n <span>hmr: <code>${config.target.hmrStrategy}</code></span>\n <span>runtime: <code>${escapeHtml(config.runtime.host)}:${config.runtime.port}</code></span>\n <span>sim: <code id=\"simulation-status\">${escapeHtml(summarizePajaSimulation(config.simulation))}</code></span>\n <span>state: <code id=\"lifecycle-status\">booting</code></span>\n </footer>\n <script type=\"application/json\" id=\"kehto-paja-config\">${configJson}</script>\n <script type=\"module\" src=\"/__kehto/browser-host.js\"></script>\n </body>\n</html>`;\n}\n\nfunction escapeAttribute(value: string): string {\n return escapeHtml(value).replaceAll('\"', '&quot;');\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;');\n}\n\nfunction escapeJsonForHtml(value: string): string {\n return value.replaceAll('<', '\\\\u003c');\n}\n","import type { ShellCapabilities } from '@kehto/shell';\n\nconst PAJA_LEGACY_COMPATIBILITY_DOMAIN = `i${'fc'}`;\n\nexport const PAJA_UPSTREAM_WEB_DOMAINS = [\n 'ble',\n 'common',\n 'config',\n 'cvm',\n 'dm',\n 'identity',\n PAJA_LEGACY_COMPATIBILITY_DOMAIN,\n 'inc',\n 'intent',\n 'keys',\n 'link',\n 'lists',\n 'media',\n 'notify',\n 'outbox',\n 'relay',\n 'resource',\n 'serial',\n 'storage',\n 'theme',\n 'upload',\n 'webrtc',\n] as const;\n\nexport const PAJA_HANDSHAKE_DOMAINS = ['shell'] as const;\nexport const PAJA_DEFERRED_DOMAINS = ['dm'] as const;\n\nexport const PAJA_COMPATIBILITY_ALIASES = {\n [PAJA_LEGACY_COMPATIBILITY_DOMAIN]: 'inc',\n} as const;\n\nexport const PAJA_ADVERTISED_DOMAINS = [\n 'relay',\n 'outbox',\n 'identity',\n 'storage',\n 'inc',\n 'theme',\n 'keys',\n 'link',\n 'common',\n 'lists',\n 'serial',\n 'ble',\n 'webrtc',\n 'media',\n 'notify',\n 'config',\n 'resource',\n 'cvm',\n 'upload',\n 'intent',\n] as const;\n\nexport const PAJA_REQUIRED_SERVICES = [\n 'config',\n 'cvm',\n 'identity',\n 'intent',\n 'keys',\n 'link',\n 'common',\n 'lists',\n 'serial',\n 'ble',\n 'webrtc',\n 'media',\n 'notifications',\n 'notify',\n 'outbox',\n 'relay',\n 'resource',\n 'theme',\n 'upload',\n] as const;\n\nexport function getMissingAdvertisedDomains(capabilities: ShellCapabilities): string[] {\n const advertised = new Set(capabilities.domains);\n return PAJA_ADVERTISED_DOMAINS.filter((domain) => !advertised.has(domain));\n}\n\nexport function getMissingServices(services: readonly string[]): string[] {\n const wired = new Set(services);\n return PAJA_REQUIRED_SERVICES.filter((service) => !wired.has(service));\n}\n","export interface WaitForTargetUrlOptions {\n readonly timeoutMs: number;\n readonly intervalMs?: number;\n readonly fetch?: ReadinessFetch;\n readonly sleep?: (ms: number) => Promise<void>;\n readonly now?: () => number;\n}\n\nexport type ReadinessFetch = (url: string) => Promise<{ readonly status: number }>;\n\nexport class ReadinessError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ReadinessError';\n }\n}\n\nexport async function waitForTargetUrl(url: string, options: WaitForTargetUrlOptions): Promise<void> {\n const intervalMs = options.intervalMs ?? 250;\n const fetcher = options.fetch ?? defaultFetch;\n const sleep = options.sleep ?? defaultSleep;\n const now = options.now ?? Date.now;\n const deadline = now() + options.timeoutMs;\n let lastError = 'no response';\n\n while (now() <= deadline) {\n try {\n const response = await fetcher(url);\n if (response.status < 500) {\n return;\n }\n lastError = `status ${response.status}`;\n } catch (error) {\n lastError = error instanceof Error ? error.message : String(error);\n }\n\n await sleep(intervalMs);\n }\n\n throw new ReadinessError(`Timed out waiting ${options.timeoutMs}ms for target URL ${url}: ${lastError}`);\n}\n\nasync function defaultFetch(url: string): Promise<{ readonly status: number }> {\n return fetch(url, { method: 'GET', redirect: 'follow' });\n}\n\nfunction defaultSleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n","import { createServer } from 'node:http';\nimport { readFileSync } from 'node:fs';\nimport {\n createPajaHostConfig,\n formatPajaUrl,\n normalizePajaOptions,\n type PajaHostConfig,\n type PajaOptions,\n type PajaRawOptions,\n} from './options.js';\nimport { renderPajaHtml } from './host-page.js';\nimport { resolvePajaRawOptions } from './config-file.js';\n\nexport interface PajaServerOptions {\n readonly options: PajaRawOptions;\n readonly now?: Date;\n}\n\nexport interface PajaServer {\n readonly url: string;\n readonly hostConfig: PajaHostConfig;\n updateTargetUrl(targetUrl: string): PajaHostConfig;\n close(): Promise<void>;\n}\n\nexport async function startPajaServer(input: PajaServerOptions): Promise<PajaServer> {\n const rawOptions = resolvePajaRawOptions(input.options);\n const options = normalizePajaOptions(rawOptions);\n const createdAt = input.now ?? new Date();\n let hostConfig = createPajaHostConfig(options, createdAt);\n let html = renderPajaHtml(hostConfig);\n let configJson = JSON.stringify(hostConfig, null, 2);\n let currentOptions = options;\n\n const setHostConfig = (nextOptions: PajaOptions): PajaHostConfig => {\n currentOptions = nextOptions;\n hostConfig = createPajaHostConfig(currentOptions, createdAt);\n html = renderPajaHtml(hostConfig);\n configJson = JSON.stringify(hostConfig, null, 2);\n return hostConfig;\n };\n\n const server = createServer((request, response) => {\n const requestUrl = request.url ?? '/';\n\n if (requestUrl === '/' || requestUrl.startsWith('/?')) {\n response.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });\n response.end(html);\n return;\n }\n\n if (requestUrl === '/__kehto/config.json') {\n response.writeHead(200, { 'content-type': 'application/json; charset=utf-8' });\n response.end(configJson);\n return;\n }\n\n if (requestUrl === '/__kehto/browser-host.js') {\n const browserScript = readBrowserHostScript();\n response.writeHead(200, { 'content-type': 'text/javascript; charset=utf-8' });\n response.end(browserScript);\n return;\n }\n\n response.writeHead(404, { 'content-type': 'text/plain; charset=utf-8' });\n response.end('Not found');\n });\n\n await listen(server, options.host, options.port);\n const servedOptions = withBoundPort(options, getBoundPort(server, options.port));\n setHostConfig(servedOptions);\n\n return {\n url: formatPajaUrl(servedOptions),\n get hostConfig() {\n return hostConfig;\n },\n updateTargetUrl(targetUrl) {\n return setHostConfig(withTargetUrl(currentOptions, targetUrl));\n },\n close: () => close(server),\n };\n}\n\nfunction readBrowserHostScript(): string {\n return readFileSync(new URL('./browser-host.js', import.meta.url), 'utf8');\n}\n\nfunction listen(server: HttpServer, host: string, port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n server.once('error', reject);\n server.listen(port, host, () => {\n server.off('error', reject);\n resolve();\n });\n });\n}\n\nfunction close(server: HttpServer): Promise<void> {\n return new Promise((resolve, reject) => {\n server.close((error?: Error) => {\n if (error) {\n reject(error);\n return;\n }\n resolve();\n });\n });\n}\n\ninterface HttpServer {\n listen(port: number, host: string, callback: () => void): void;\n once(event: 'error', callback: (error: Error) => void): void;\n off(event: 'error', callback: (error: Error) => void): void;\n close(callback: (error?: Error) => void): void;\n address(): string | { port: number } | null;\n}\n\nfunction getBoundPort(server: HttpServer, fallback: number): number {\n const address = server.address();\n return typeof address === 'object' && address !== null ? address.port : fallback;\n}\n\nfunction withBoundPort(options: PajaOptions, port: number): PajaOptions {\n return port === options.port ? options : { ...options, port };\n}\n\nfunction withTargetUrl(options: PajaOptions, targetUrl: string): PajaOptions {\n const url = normalizeServerTargetUrl(targetUrl);\n return url === options.targetUrl ? options : { ...options, targetUrl: url };\n}\n\nfunction normalizeServerTargetUrl(value: string): string {\n const raw = value.trim();\n let parsed: URL;\n try {\n parsed = new URL(raw);\n } catch {\n throw new Error(`Invalid managed target URL \"${raw}\". Expected an absolute http(s) URL.`);\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {\n throw new Error(`Invalid managed target URL \"${raw}\". Only http: and https: URLs are supported.`);\n }\n return parsed.href;\n}\n"],"mappings":"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","names":["resolve","readFileSync","readFileSync","resolve"]}
package/dist/cli.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { P as PajaRawOptions } from './options-D4tneY-c.js';
2
+ import { P as PajaRawOptions, s as startPajaServer, a as PajaCommand, w as waitForTargetUrl } from './server-Ca1k_vlt.js';
3
3
 
4
4
  /**
5
5
  * Minimal output streams used by the CLI runner.
@@ -28,6 +28,10 @@ interface CliParseResult {
28
28
  */
29
29
  interface RunPajaCliOptions {
30
30
  readonly serve?: boolean;
31
+ readonly startServer?: typeof startPajaServer;
32
+ readonly startCommand?: (command: PajaCommand, io: CliIo) => ManagedChildProcess;
33
+ readonly waitForTargetUrl?: typeof waitForTargetUrl;
34
+ readonly targetDiscoveryGraceMs?: number;
31
35
  }
32
36
  /**
33
37
  * Parse raw `kehto paja` arguments into raw runtime options.
@@ -38,5 +42,9 @@ interface RunPajaCliOptions {
38
42
  declare function parsePajaArgs(args: readonly string[]): CliParseResult;
39
43
  declare function runPajaCli(args?: readonly string[], io?: CliIo, runOptions?: RunPajaCliOptions): Promise<number>;
40
44
  declare function isDirectPajaCli(entryPath?: string): boolean;
45
+ interface ManagedChildProcess {
46
+ kill(): void;
47
+ readonly detectedTargetUrl: Promise<string>;
48
+ }
41
49
 
42
- export { type CliIo, type CliParseResult, type RunPajaCliOptions, isDirectPajaCli, parsePajaArgs, runPajaCli };
50
+ export { type CliIo, type CliParseResult, type ManagedChildProcess, type RunPajaCliOptions, isDirectPajaCli, parsePajaArgs, runPajaCli };
package/dist/cli.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  startPajaServer,
10
10
  summarizePajaSimulation,
11
11
  waitForTargetUrl
12
- } from "./chunk-6QZXEPQJ.js";
12
+ } from "./chunk-WYIXZLDJ.js";
13
13
 
14
14
  // src/cli.ts
15
15
  import { spawn } from "child_process";
@@ -45,15 +45,27 @@ async function runPajaCli(args = process.argv.slice(2), io = defaultIo, runOptio
45
45
  const options = normalizePajaOptions(rawOptions);
46
46
  const hostConfig = createPajaHostConfig(options);
47
47
  const shouldServe = runOptions.serve ?? true;
48
+ const startServer = runOptions.startServer ?? startPajaServer;
49
+ const startCommand = runOptions.startCommand ?? startManagedCommand;
50
+ const waitForTarget = runOptions.waitForTargetUrl ?? waitForTargetUrl;
48
51
  let child;
49
52
  let server;
50
53
  if (shouldServe) {
51
54
  try {
52
- server = await startPajaServer({ options: rawOptions });
55
+ server = await startServer({ options: rawOptions });
53
56
  writeRuntimeSummary(io, server.url, hostConfig, options);
54
57
  if (options.command) {
55
- child = startManagedCommand(options.command);
56
- await waitForTargetUrl(options.targetUrl, { timeoutMs: options.readyTimeoutMs });
58
+ child = startCommand(options.command, io);
59
+ const targetUrl = await resolveManagedTargetUrl(options.targetUrl, child, {
60
+ timeoutMs: options.readyTimeoutMs,
61
+ discoveryGraceMs: runOptions.targetDiscoveryGraceMs,
62
+ waitForTargetUrl: waitForTarget
63
+ });
64
+ if (targetUrl !== options.targetUrl) {
65
+ server.updateTargetUrl(targetUrl);
66
+ io.stdout.write(`Target URL updated: ${targetUrl}
67
+ `);
68
+ }
57
69
  }
58
70
  } catch (error) {
59
71
  child?.kill();
@@ -293,15 +305,112 @@ function ensureSimulation(raw) {
293
305
  raw.simulation ??= {};
294
306
  return raw.simulation;
295
307
  }
296
- function startManagedCommand(command) {
308
+ async function resolveManagedTargetUrl(configuredUrl, child, options) {
309
+ let configuredError;
310
+ const configuredReady = options.waitForTargetUrl(configuredUrl, { timeoutMs: options.timeoutMs }).then(() => configuredUrl).catch((error) => {
311
+ configuredError = error;
312
+ return void 0;
313
+ });
314
+ const first = await Promise.race([
315
+ configuredReady.then((url) => url ? { kind: "configured", url } : void 0),
316
+ child.detectedTargetUrl.then((url) => ({ kind: "detected", url }))
317
+ ]);
318
+ if (first?.kind === "detected") {
319
+ await options.waitForTargetUrl(first.url, { timeoutMs: options.timeoutMs });
320
+ return first.url;
321
+ }
322
+ const graceMs = options.discoveryGraceMs ?? Math.min(1e3, options.timeoutMs);
323
+ const detected = await resolveWithin(child.detectedTargetUrl, graceMs);
324
+ if (!detected) {
325
+ if (first?.url) {
326
+ return first.url;
327
+ }
328
+ throw configuredError instanceof Error ? configuredError : new Error(String(configuredError ?? "Target URL was not ready."));
329
+ }
330
+ await options.waitForTargetUrl(detected, { timeoutMs: options.timeoutMs });
331
+ return detected;
332
+ }
333
+ function resolveWithin(promise, timeoutMs) {
334
+ return new Promise((resolve) => {
335
+ let settled = false;
336
+ const timeout = setTimeout(() => {
337
+ if (settled) return;
338
+ settled = true;
339
+ resolve(void 0);
340
+ }, Math.max(0, timeoutMs));
341
+ promise.then((value) => {
342
+ if (settled) return;
343
+ settled = true;
344
+ clearTimeout(timeout);
345
+ resolve(value);
346
+ }, () => {
347
+ if (settled) return;
348
+ settled = true;
349
+ clearTimeout(timeout);
350
+ resolve(void 0);
351
+ });
352
+ });
353
+ }
354
+ function startManagedCommand(command, io) {
355
+ const detector = createManagedTargetUrlDetector();
356
+ const child = spawnManagedCommand(command);
357
+ forwardManagedOutput(child, detector, io);
358
+ return {
359
+ kill: () => child.kill(),
360
+ detectedTargetUrl: detector.detectedTargetUrl
361
+ };
362
+ }
363
+ function spawnManagedCommand(command) {
297
364
  if (command.mode === "shell") {
298
- return spawn(command.command, { shell: true, stdio: "inherit" });
365
+ return spawn(command.command, { shell: true, stdio: ["inherit", "pipe", "pipe"] });
299
366
  }
300
367
  const [executable, ...args] = command.argv;
301
368
  if (!executable) {
302
369
  throw new PajaOptionsError("Argv command mode requires an executable.");
303
370
  }
304
- return spawn(executable, args, { stdio: "inherit" });
371
+ return spawn(executable, args, { stdio: ["inherit", "pipe", "pipe"] });
372
+ }
373
+ function forwardManagedOutput(child, detector, io) {
374
+ child.stdout?.on("data", (chunk) => {
375
+ const text = String(chunk);
376
+ detector.observe(text);
377
+ io.stdout.write(text);
378
+ });
379
+ child.stderr?.on("data", (chunk) => {
380
+ const text = String(chunk);
381
+ detector.observe(text);
382
+ io.stderr.write(text);
383
+ });
384
+ }
385
+ function createManagedTargetUrlDetector() {
386
+ let resolveDetected = () => {
387
+ };
388
+ let detected;
389
+ const detectedTargetUrl = new Promise((resolve) => {
390
+ resolveDetected = resolve;
391
+ });
392
+ return {
393
+ detectedTargetUrl,
394
+ observe(chunk) {
395
+ if (detected) return;
396
+ const text = stripAnsi(chunk);
397
+ for (const match of text.matchAll(LOCAL_HTTP_URL_PATTERN)) {
398
+ const rawUrl = match[0];
399
+ let url;
400
+ try {
401
+ url = new URL(rawUrl);
402
+ } catch {
403
+ continue;
404
+ }
405
+ detected = url.href;
406
+ resolveDetected(detected);
407
+ return;
408
+ }
409
+ }
410
+ };
411
+ }
412
+ function stripAnsi(value) {
413
+ return value.replace(ANSI_PATTERN, "");
305
414
  }
306
415
  var defaultIo = {
307
416
  stdout: { write: (chunk) => process.stdout.write(chunk) },
@@ -316,6 +425,8 @@ function isDirectPajaCli(entryPath = process.argv[1]) {
316
425
  if (!entryPath) return false;
317
426
  return entryPath.endsWith("/cli.js") || entryPath.endsWith("/paja");
318
427
  }
428
+ var LOCAL_HTTP_URL_PATTERN = /https?:\/\/(?:localhost|127(?:\.\d{1,3}){3}|\[::1\])(?::\d+)?(?:\/[^\s'"<>)\]]*)?/g;
429
+ var ANSI_PATTERN = /\u001b\[[0-?]*[ -/]*[@-~]/g;
319
430
  export {
320
431
  isDirectPajaCli,
321
432
  parsePajaArgs,
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { spawn } from 'node:child_process';\nimport {\n createPajaHostConfig,\n formatPajaUrl,\n normalizePajaOptions,\n waitForTargetUrl,\n type PajaCommand,\n type PajaRawOptions,\n PajaOptionsError,\n} from './index.js';\nimport { resolvePajaRawOptions } from './config-file.js';\nimport { startPajaServer } from './server.js';\nimport {\n PAJA_SIMULATION_DOMAINS,\n summarizePajaSimulation,\n type PajaCapabilityDomain,\n type PajaSimulationRawOptions,\n type JsonValue,\n} from './simulation.js';\n\n/**\n * Minimal output streams used by the CLI runner.\n *\n * @remarks\n * Tests and embedders can pass custom streams to capture output without\n * patching global `process.stdout` or `process.stderr`.\n */\nexport interface CliIo {\n readonly stdout: { write(chunk: string): void };\n readonly stderr: { write(chunk: string): void };\n}\n\n/**\n * Parsed CLI arguments before full option normalization.\n */\nexport interface CliParseResult {\n readonly options?: PajaRawOptions;\n readonly help: boolean;\n}\n\n/**\n * Execution controls for embedding the CLI runner in tests or wrappers.\n */\nexport interface RunPajaCliOptions {\n readonly serve?: boolean;\n}\n\n/**\n * Parse raw `kehto paja` arguments into raw runtime options.\n *\n * @param args - Argument vector without the node executable or script path.\n * @returns Parsed raw options, or a help flag when `--help` is present.\n */\nexport function parsePajaArgs(args: readonly string[]): CliParseResult {\n const raw: MutablePajaRawOptions = {};\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n\n if (arg === '--') {\n const argv = args.slice(index + 1);\n raw.command = { mode: 'argv', argv };\n break;\n }\n\n if (arg === '--help' || arg === '-h') {\n return { help: true };\n }\n\n if (applyCoreOption(arg, args, index, raw) || applySimulationOption(arg, args, index, raw)) {\n index += 1;\n continue;\n }\n\n throw new PajaOptionsError(`Unknown option \"${arg}\". Run kehto paja --help for usage.`);\n }\n\n return { help: false, options: raw };\n}\n\nexport async function runPajaCli(\n args: readonly string[] = process.argv.slice(2),\n io: CliIo = defaultIo,\n runOptions: RunPajaCliOptions = {},\n): Promise<number> {\n try {\n const parsed = parsePajaArgs(args);\n if (parsed.help) {\n io.stdout.write(`${HELP_TEXT}\\n`);\n return 0;\n }\n\n const rawOptions = resolvePajaRawOptions(parsed.options ?? {});\n const options = normalizePajaOptions(rawOptions);\n const hostConfig = createPajaHostConfig(options);\n const shouldServe = runOptions.serve ?? true;\n let child: ManagedChildProcess | undefined;\n let server: Awaited<ReturnType<typeof startPajaServer>> | undefined;\n if (shouldServe) {\n try {\n server = await startPajaServer({ options: rawOptions });\n writeRuntimeSummary(io, server.url, hostConfig, options);\n\n if (options.command) {\n child = startManagedCommand(options.command);\n await waitForTargetUrl(options.targetUrl, { timeoutMs: options.readyTimeoutMs });\n }\n } catch (error) {\n child?.kill();\n await server?.close().catch(() => undefined);\n throw error;\n }\n }\n const runtimeUrl = server?.url ?? formatPajaUrl(options);\n\n if (!shouldServe) {\n writeRuntimeSummary(io, runtimeUrl, hostConfig, options);\n }\n\n return 0;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n io.stderr.write(`kehto paja: ${message}\\n`);\n return 1;\n }\n}\n\nfunction writeRuntimeSummary(\n io: CliIo,\n runtimeUrl: string,\n hostConfig: ReturnType<typeof createPajaHostConfig>,\n options: ReturnType<typeof normalizePajaOptions>,\n): void {\n io.stdout.write(`Kehto Paja\\n`);\n io.stdout.write(`Runtime URL: ${runtimeUrl}\\n`);\n io.stdout.write(`Target URL: ${hostConfig.target.url}\\n`);\n io.stdout.write(`Mode: ${options.mode}\\n`);\n io.stdout.write(`HMR: ${hostConfig.target.hmrStrategy}\\n`);\n io.stdout.write(`Simulation: ${summarizePajaSimulation(options.simulation)}\\n`);\n\n if (options.command) {\n io.stdout.write(`Command: ${formatCommand(options.command)}\\n`);\n }\n}\n\nconst HELP_TEXT = `Usage:\n kehto paja --target-url <url> [options]\n kehto paja --target-url <url> [options] -- <command...>\n\nOptions:\n --target-url, -u <url> App dev-server URL to load in the runtime iframe.\n --command, -c <command> Shell command to start before waiting for target URL.\n -- <command...> Argv command form; preserves arbitrary framework commands.\n --host <host> Runtime host. Default: 127.0.0.1.\n --port <port> Runtime port. Default: 5197.\n --ready-timeout <ms> Target readiness timeout. Default: 30000.\n --config <path> JSON config file using the same option schema.\n --identity-mode <mode> anonymous or fixed.\n --identity-pubkey <hex> Required when identity mode is fixed.\n --relay-mode <mode> memory or disabled.\n --relay-url <url> Add a relay URL for memory relay simulation.\n --storage-mode <mode> local, memory, or disabled.\n --cache-mode <mode> memory or disabled.\n --upload-mode <mode> memory or disabled.\n --upload-rail <name> Upload rail name for memory uploads.\n --media <state> enabled or disabled.\n --notifications <state> enabled or disabled.\n --notify-grant <bool> true or false default notification grant.\n --theme <mode> dark or light.\n --config-value <key=json> Add a JSON config value.\n --capability <domain:on|off> Toggle an advertised capability domain.\n --acl-mode <mode> allow or deny.\n --firewall-mode <mode> allow, deny, or observe.\n --help, -h Show this help.`;\n\nfunction readValue(args: readonly string[], index: number, option: string): string {\n const value = args[index + 1];\n if (!value || value.startsWith('--')) {\n throw new PajaOptionsError(`${option} requires a value.`);\n }\n return value;\n}\n\nfunction applyCoreOption(\n arg: string,\n args: readonly string[],\n index: number,\n raw: MutablePajaRawOptions,\n): boolean {\n switch (arg) {\n case '--target-url':\n case '-u':\n raw.targetUrl = readValue(args, index, arg);\n return true;\n case '--command':\n case '-c':\n raw.command = { mode: 'shell', command: readValue(args, index, arg) };\n return true;\n case '--host':\n raw.host = readValue(args, index, arg);\n return true;\n case '--port':\n raw.port = readValue(args, index, arg);\n return true;\n case '--ready-timeout':\n raw.readyTimeoutMs = readValue(args, index, arg);\n return true;\n case '--config':\n raw.configPath = readValue(args, index, arg);\n return true;\n default:\n return false;\n }\n}\n\nfunction applySimulationOption(\n arg: string,\n args: readonly string[],\n index: number,\n raw: MutablePajaRawOptions,\n): boolean {\n switch (arg) {\n case '--identity-mode':\n setIdentity(raw, { mode: readEnum(args, index, arg, ['anonymous', 'fixed']) });\n return true;\n case '--identity-pubkey':\n setIdentity(raw, { pubkey: readValue(args, index, arg) });\n return true;\n case '--relay-mode':\n setRelay(raw, { mode: readEnum(args, index, arg, ['memory', 'disabled']) });\n return true;\n case '--relay-url':\n setRelay(raw, { urls: [...(raw.simulation?.relay?.urls ?? []), readValue(args, index, arg)] });\n return true;\n case '--storage-mode':\n ensureSimulation(raw).storage = { ...raw.simulation?.storage, mode: readEnum(args, index, arg, ['local', 'memory', 'disabled']) };\n return true;\n case '--cache-mode':\n ensureSimulation(raw).cache = { ...raw.simulation?.cache, mode: readEnum(args, index, arg, ['memory', 'disabled']) };\n return true;\n case '--upload-mode':\n setUpload(raw, { mode: readEnum(args, index, arg, ['memory', 'disabled']) });\n return true;\n case '--upload-rail':\n setUpload(raw, { rail: readValue(args, index, arg) });\n return true;\n case '--media':\n ensureSimulation(raw).media = { ...raw.simulation?.media, enabled: readEnabled(args, index, arg) };\n return true;\n case '--notifications':\n setNotifications(raw, { enabled: readEnabled(args, index, arg) });\n return true;\n case '--notify-grant':\n setNotifications(raw, { grant: readBoolean(args, index, arg) });\n return true;\n case '--theme':\n ensureSimulation(raw).theme = { ...raw.simulation?.theme, mode: readEnum(args, index, arg, ['dark', 'light']) };\n return true;\n case '--config-value':\n setConfigValue(raw, readConfigValue(args, index, arg));\n return true;\n case '--capability':\n setCapability(raw, readCapability(args, index, arg));\n return true;\n case '--acl-mode':\n ensureSimulation(raw).acl = { ...raw.simulation?.acl, mode: readEnum(args, index, arg, ['allow', 'deny']) };\n return true;\n case '--firewall-mode':\n ensureSimulation(raw).firewall = { ...raw.simulation?.firewall, mode: readEnum(args, index, arg, ['allow', 'deny', 'observe']) };\n return true;\n default:\n return false;\n }\n}\n\nfunction formatCommand(command: PajaCommand): string {\n return command.mode === 'argv' ? command.argv.join(' ') : command.command;\n}\n\nfunction readEnum<const T extends readonly string[]>(\n args: readonly string[],\n index: number,\n option: string,\n allowed: T,\n): T[number] {\n const value = readValue(args, index, option);\n if (!allowed.includes(value)) {\n throw new PajaOptionsError(`${option} must be one of: ${allowed.join(', ')}.`);\n }\n return value;\n}\n\nfunction readEnabled(args: readonly string[], index: number, option: string): boolean {\n const value = readValue(args, index, option);\n if (value === 'enabled') return true;\n if (value === 'disabled') return false;\n throw new PajaOptionsError(`${option} must be \"enabled\" or \"disabled\".`);\n}\n\nfunction readBoolean(args: readonly string[], index: number, option: string): boolean {\n const value = readValue(args, index, option);\n if (value === 'true') return true;\n if (value === 'false') return false;\n throw new PajaOptionsError(`${option} must be \"true\" or \"false\".`);\n}\n\nfunction readConfigValue(\n args: readonly string[],\n index: number,\n option: string,\n): { key: string; value: JsonValue } {\n const raw = readValue(args, index, option);\n const separator = raw.indexOf('=');\n if (separator <= 0) {\n throw new PajaOptionsError(`${option} expects key=json.`);\n }\n const key = raw.slice(0, separator).trim();\n if (!key) {\n throw new PajaOptionsError(`${option} expects a non-empty key.`);\n }\n try {\n return { key, value: JSON.parse(raw.slice(separator + 1)) as JsonValue };\n } catch {\n throw new PajaOptionsError(`${option} value for \"${key}\" must be valid JSON.`);\n }\n}\n\nfunction readCapability(\n args: readonly string[],\n index: number,\n option: string,\n): { domain: PajaCapabilityDomain; enabled: boolean } {\n const raw = readValue(args, index, option);\n const [domainRaw, stateRaw] = raw.split(':') as [string | undefined, string | undefined];\n if (!domainRaw || (stateRaw !== 'on' && stateRaw !== 'off')) {\n throw new PajaOptionsError(`${option} expects domain:on or domain:off.`);\n }\n if (!PAJA_SIMULATION_DOMAINS.includes(domainRaw as PajaCapabilityDomain)) {\n throw new PajaOptionsError(`${option} unknown domain \"${domainRaw}\".`);\n }\n return {\n domain: domainRaw as PajaCapabilityDomain,\n enabled: stateRaw === 'on',\n };\n}\n\nfunction setIdentity(raw: MutablePajaRawOptions, identity: NonNullable<PajaSimulationRawOptions['identity']>): void {\n ensureSimulation(raw).identity = { ...raw.simulation?.identity, ...identity };\n}\n\nfunction setRelay(raw: MutablePajaRawOptions, relay: NonNullable<PajaSimulationRawOptions['relay']>): void {\n ensureSimulation(raw).relay = { ...raw.simulation?.relay, ...relay };\n}\n\nfunction setUpload(raw: MutablePajaRawOptions, upload: NonNullable<PajaSimulationRawOptions['upload']>): void {\n ensureSimulation(raw).upload = { ...raw.simulation?.upload, ...upload };\n}\n\nfunction setNotifications(\n raw: MutablePajaRawOptions,\n notifications: NonNullable<PajaSimulationRawOptions['notifications']>,\n): void {\n ensureSimulation(raw).notifications = { ...raw.simulation?.notifications, ...notifications };\n}\n\nfunction setConfigValue(\n raw: MutablePajaRawOptions,\n entry: { key: string; value: JsonValue },\n): void {\n ensureSimulation(raw).config = {\n ...raw.simulation?.config,\n values: {\n ...raw.simulation?.config?.values,\n [entry.key]: entry.value,\n },\n };\n}\n\nfunction setCapability(\n raw: MutablePajaRawOptions,\n entry: { domain: PajaCapabilityDomain; enabled: boolean },\n): void {\n ensureSimulation(raw).capabilities = {\n ...raw.simulation?.capabilities,\n domains: {\n ...raw.simulation?.capabilities?.domains,\n [entry.domain]: entry.enabled,\n },\n };\n}\n\nfunction ensureSimulation(raw: MutablePajaRawOptions): MutablePajaSimulationRawOptions {\n raw.simulation ??= {};\n return raw.simulation as MutablePajaSimulationRawOptions;\n}\n\nfunction startManagedCommand(command: PajaCommand): ManagedChildProcess {\n if (command.mode === 'shell') {\n return spawn(command.command, { shell: true, stdio: 'inherit' });\n }\n\n const [executable, ...args] = command.argv;\n if (!executable) {\n throw new PajaOptionsError('Argv command mode requires an executable.');\n }\n return spawn(executable, args, { stdio: 'inherit' });\n}\n\ntype MutablePajaRawOptions = {\n -readonly [K in keyof PajaRawOptions]: PajaRawOptions[K];\n};\n\ntype MutablePajaSimulationRawOptions = {\n -readonly [K in keyof PajaSimulationRawOptions]: PajaSimulationRawOptions[K];\n};\n\nconst defaultIo: CliIo = {\n stdout: { write: (chunk) => process.stdout.write(chunk) },\n stderr: { write: (chunk) => process.stderr.write(chunk) },\n};\n\nif (isDirectPajaCli()) {\n void runPajaCli().then((code) => {\n process.exitCode = code;\n });\n}\n\nexport function isDirectPajaCli(entryPath = process.argv[1]): boolean {\n if (!entryPath) return false;\n return entryPath.endsWith('/cli.js') || entryPath.endsWith('/paja');\n}\n\ndeclare const process: {\n argv: string[];\n exitCode?: number;\n stdout: { write(chunk: string): void };\n stderr: { write(chunk: string): void };\n};\n\ninterface ManagedChildProcess {\n kill(): void;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { spawn, type ChildProcess } from 'node:child_process';\nimport {\n createPajaHostConfig,\n formatPajaUrl,\n normalizePajaOptions,\n waitForTargetUrl,\n type PajaCommand,\n type PajaRawOptions,\n PajaOptionsError,\n} from './index.js';\nimport { resolvePajaRawOptions } from './config-file.js';\nimport { startPajaServer } from './server.js';\nimport {\n PAJA_SIMULATION_DOMAINS,\n summarizePajaSimulation,\n type PajaCapabilityDomain,\n type PajaSimulationRawOptions,\n type JsonValue,\n} from './simulation.js';\n\n/**\n * Minimal output streams used by the CLI runner.\n *\n * @remarks\n * Tests and embedders can pass custom streams to capture output without\n * patching global `process.stdout` or `process.stderr`.\n */\nexport interface CliIo {\n readonly stdout: { write(chunk: string): void };\n readonly stderr: { write(chunk: string): void };\n}\n\n/**\n * Parsed CLI arguments before full option normalization.\n */\nexport interface CliParseResult {\n readonly options?: PajaRawOptions;\n readonly help: boolean;\n}\n\n/**\n * Execution controls for embedding the CLI runner in tests or wrappers.\n */\nexport interface RunPajaCliOptions {\n readonly serve?: boolean;\n readonly startServer?: typeof startPajaServer;\n readonly startCommand?: (command: PajaCommand, io: CliIo) => ManagedChildProcess;\n readonly waitForTargetUrl?: typeof waitForTargetUrl;\n readonly targetDiscoveryGraceMs?: number;\n}\n\n/**\n * Parse raw `kehto paja` arguments into raw runtime options.\n *\n * @param args - Argument vector without the node executable or script path.\n * @returns Parsed raw options, or a help flag when `--help` is present.\n */\nexport function parsePajaArgs(args: readonly string[]): CliParseResult {\n const raw: MutablePajaRawOptions = {};\n\n for (let index = 0; index < args.length; index += 1) {\n const arg = args[index];\n\n if (arg === '--') {\n const argv = args.slice(index + 1);\n raw.command = { mode: 'argv', argv };\n break;\n }\n\n if (arg === '--help' || arg === '-h') {\n return { help: true };\n }\n\n if (applyCoreOption(arg, args, index, raw) || applySimulationOption(arg, args, index, raw)) {\n index += 1;\n continue;\n }\n\n throw new PajaOptionsError(`Unknown option \"${arg}\". Run kehto paja --help for usage.`);\n }\n\n return { help: false, options: raw };\n}\n\nexport async function runPajaCli(\n args: readonly string[] = process.argv.slice(2),\n io: CliIo = defaultIo,\n runOptions: RunPajaCliOptions = {},\n): Promise<number> {\n try {\n const parsed = parsePajaArgs(args);\n if (parsed.help) {\n io.stdout.write(`${HELP_TEXT}\\n`);\n return 0;\n }\n\n const rawOptions = resolvePajaRawOptions(parsed.options ?? {});\n const options = normalizePajaOptions(rawOptions);\n const hostConfig = createPajaHostConfig(options);\n const shouldServe = runOptions.serve ?? true;\n const startServer = runOptions.startServer ?? startPajaServer;\n const startCommand = runOptions.startCommand ?? startManagedCommand;\n const waitForTarget = runOptions.waitForTargetUrl ?? waitForTargetUrl;\n let child: ManagedChildProcess | undefined;\n let server: Awaited<ReturnType<typeof startPajaServer>> | undefined;\n if (shouldServe) {\n try {\n server = await startServer({ options: rawOptions });\n writeRuntimeSummary(io, server.url, hostConfig, options);\n\n if (options.command) {\n child = startCommand(options.command, io);\n const targetUrl = await resolveManagedTargetUrl(options.targetUrl, child, {\n timeoutMs: options.readyTimeoutMs,\n discoveryGraceMs: runOptions.targetDiscoveryGraceMs,\n waitForTargetUrl: waitForTarget,\n });\n if (targetUrl !== options.targetUrl) {\n server.updateTargetUrl(targetUrl);\n io.stdout.write(`Target URL updated: ${targetUrl}\\n`);\n }\n }\n } catch (error) {\n child?.kill();\n await server?.close().catch(() => undefined);\n throw error;\n }\n }\n const runtimeUrl = server?.url ?? formatPajaUrl(options);\n\n if (!shouldServe) {\n writeRuntimeSummary(io, runtimeUrl, hostConfig, options);\n }\n\n return 0;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n io.stderr.write(`kehto paja: ${message}\\n`);\n return 1;\n }\n}\n\nfunction writeRuntimeSummary(\n io: CliIo,\n runtimeUrl: string,\n hostConfig: ReturnType<typeof createPajaHostConfig>,\n options: ReturnType<typeof normalizePajaOptions>,\n): void {\n io.stdout.write(`Kehto Paja\\n`);\n io.stdout.write(`Runtime URL: ${runtimeUrl}\\n`);\n io.stdout.write(`Target URL: ${hostConfig.target.url}\\n`);\n io.stdout.write(`Mode: ${options.mode}\\n`);\n io.stdout.write(`HMR: ${hostConfig.target.hmrStrategy}\\n`);\n io.stdout.write(`Simulation: ${summarizePajaSimulation(options.simulation)}\\n`);\n\n if (options.command) {\n io.stdout.write(`Command: ${formatCommand(options.command)}\\n`);\n }\n}\n\nconst HELP_TEXT = `Usage:\n kehto paja --target-url <url> [options]\n kehto paja --target-url <url> [options] -- <command...>\n\nOptions:\n --target-url, -u <url> App dev-server URL to load in the runtime iframe.\n --command, -c <command> Shell command to start before waiting for target URL.\n -- <command...> Argv command form; preserves arbitrary framework commands.\n --host <host> Runtime host. Default: 127.0.0.1.\n --port <port> Runtime port. Default: 5197.\n --ready-timeout <ms> Target readiness timeout. Default: 30000.\n --config <path> JSON config file using the same option schema.\n --identity-mode <mode> anonymous or fixed.\n --identity-pubkey <hex> Required when identity mode is fixed.\n --relay-mode <mode> memory or disabled.\n --relay-url <url> Add a relay URL for memory relay simulation.\n --storage-mode <mode> local, memory, or disabled.\n --cache-mode <mode> memory or disabled.\n --upload-mode <mode> memory or disabled.\n --upload-rail <name> Upload rail name for memory uploads.\n --media <state> enabled or disabled.\n --notifications <state> enabled or disabled.\n --notify-grant <bool> true or false default notification grant.\n --theme <mode> dark or light.\n --config-value <key=json> Add a JSON config value.\n --capability <domain:on|off> Toggle an advertised capability domain.\n --acl-mode <mode> allow or deny.\n --firewall-mode <mode> allow, deny, or observe.\n --help, -h Show this help.`;\n\nfunction readValue(args: readonly string[], index: number, option: string): string {\n const value = args[index + 1];\n if (!value || value.startsWith('--')) {\n throw new PajaOptionsError(`${option} requires a value.`);\n }\n return value;\n}\n\nfunction applyCoreOption(\n arg: string,\n args: readonly string[],\n index: number,\n raw: MutablePajaRawOptions,\n): boolean {\n switch (arg) {\n case '--target-url':\n case '-u':\n raw.targetUrl = readValue(args, index, arg);\n return true;\n case '--command':\n case '-c':\n raw.command = { mode: 'shell', command: readValue(args, index, arg) };\n return true;\n case '--host':\n raw.host = readValue(args, index, arg);\n return true;\n case '--port':\n raw.port = readValue(args, index, arg);\n return true;\n case '--ready-timeout':\n raw.readyTimeoutMs = readValue(args, index, arg);\n return true;\n case '--config':\n raw.configPath = readValue(args, index, arg);\n return true;\n default:\n return false;\n }\n}\n\nfunction applySimulationOption(\n arg: string,\n args: readonly string[],\n index: number,\n raw: MutablePajaRawOptions,\n): boolean {\n switch (arg) {\n case '--identity-mode':\n setIdentity(raw, { mode: readEnum(args, index, arg, ['anonymous', 'fixed']) });\n return true;\n case '--identity-pubkey':\n setIdentity(raw, { pubkey: readValue(args, index, arg) });\n return true;\n case '--relay-mode':\n setRelay(raw, { mode: readEnum(args, index, arg, ['memory', 'disabled']) });\n return true;\n case '--relay-url':\n setRelay(raw, { urls: [...(raw.simulation?.relay?.urls ?? []), readValue(args, index, arg)] });\n return true;\n case '--storage-mode':\n ensureSimulation(raw).storage = { ...raw.simulation?.storage, mode: readEnum(args, index, arg, ['local', 'memory', 'disabled']) };\n return true;\n case '--cache-mode':\n ensureSimulation(raw).cache = { ...raw.simulation?.cache, mode: readEnum(args, index, arg, ['memory', 'disabled']) };\n return true;\n case '--upload-mode':\n setUpload(raw, { mode: readEnum(args, index, arg, ['memory', 'disabled']) });\n return true;\n case '--upload-rail':\n setUpload(raw, { rail: readValue(args, index, arg) });\n return true;\n case '--media':\n ensureSimulation(raw).media = { ...raw.simulation?.media, enabled: readEnabled(args, index, arg) };\n return true;\n case '--notifications':\n setNotifications(raw, { enabled: readEnabled(args, index, arg) });\n return true;\n case '--notify-grant':\n setNotifications(raw, { grant: readBoolean(args, index, arg) });\n return true;\n case '--theme':\n ensureSimulation(raw).theme = { ...raw.simulation?.theme, mode: readEnum(args, index, arg, ['dark', 'light']) };\n return true;\n case '--config-value':\n setConfigValue(raw, readConfigValue(args, index, arg));\n return true;\n case '--capability':\n setCapability(raw, readCapability(args, index, arg));\n return true;\n case '--acl-mode':\n ensureSimulation(raw).acl = { ...raw.simulation?.acl, mode: readEnum(args, index, arg, ['allow', 'deny']) };\n return true;\n case '--firewall-mode':\n ensureSimulation(raw).firewall = { ...raw.simulation?.firewall, mode: readEnum(args, index, arg, ['allow', 'deny', 'observe']) };\n return true;\n default:\n return false;\n }\n}\n\nfunction formatCommand(command: PajaCommand): string {\n return command.mode === 'argv' ? command.argv.join(' ') : command.command;\n}\n\nfunction readEnum<const T extends readonly string[]>(\n args: readonly string[],\n index: number,\n option: string,\n allowed: T,\n): T[number] {\n const value = readValue(args, index, option);\n if (!allowed.includes(value)) {\n throw new PajaOptionsError(`${option} must be one of: ${allowed.join(', ')}.`);\n }\n return value;\n}\n\nfunction readEnabled(args: readonly string[], index: number, option: string): boolean {\n const value = readValue(args, index, option);\n if (value === 'enabled') return true;\n if (value === 'disabled') return false;\n throw new PajaOptionsError(`${option} must be \"enabled\" or \"disabled\".`);\n}\n\nfunction readBoolean(args: readonly string[], index: number, option: string): boolean {\n const value = readValue(args, index, option);\n if (value === 'true') return true;\n if (value === 'false') return false;\n throw new PajaOptionsError(`${option} must be \"true\" or \"false\".`);\n}\n\nfunction readConfigValue(\n args: readonly string[],\n index: number,\n option: string,\n): { key: string; value: JsonValue } {\n const raw = readValue(args, index, option);\n const separator = raw.indexOf('=');\n if (separator <= 0) {\n throw new PajaOptionsError(`${option} expects key=json.`);\n }\n const key = raw.slice(0, separator).trim();\n if (!key) {\n throw new PajaOptionsError(`${option} expects a non-empty key.`);\n }\n try {\n return { key, value: JSON.parse(raw.slice(separator + 1)) as JsonValue };\n } catch {\n throw new PajaOptionsError(`${option} value for \"${key}\" must be valid JSON.`);\n }\n}\n\nfunction readCapability(\n args: readonly string[],\n index: number,\n option: string,\n): { domain: PajaCapabilityDomain; enabled: boolean } {\n const raw = readValue(args, index, option);\n const [domainRaw, stateRaw] = raw.split(':') as [string | undefined, string | undefined];\n if (!domainRaw || (stateRaw !== 'on' && stateRaw !== 'off')) {\n throw new PajaOptionsError(`${option} expects domain:on or domain:off.`);\n }\n if (!PAJA_SIMULATION_DOMAINS.includes(domainRaw as PajaCapabilityDomain)) {\n throw new PajaOptionsError(`${option} unknown domain \"${domainRaw}\".`);\n }\n return {\n domain: domainRaw as PajaCapabilityDomain,\n enabled: stateRaw === 'on',\n };\n}\n\nfunction setIdentity(raw: MutablePajaRawOptions, identity: NonNullable<PajaSimulationRawOptions['identity']>): void {\n ensureSimulation(raw).identity = { ...raw.simulation?.identity, ...identity };\n}\n\nfunction setRelay(raw: MutablePajaRawOptions, relay: NonNullable<PajaSimulationRawOptions['relay']>): void {\n ensureSimulation(raw).relay = { ...raw.simulation?.relay, ...relay };\n}\n\nfunction setUpload(raw: MutablePajaRawOptions, upload: NonNullable<PajaSimulationRawOptions['upload']>): void {\n ensureSimulation(raw).upload = { ...raw.simulation?.upload, ...upload };\n}\n\nfunction setNotifications(\n raw: MutablePajaRawOptions,\n notifications: NonNullable<PajaSimulationRawOptions['notifications']>,\n): void {\n ensureSimulation(raw).notifications = { ...raw.simulation?.notifications, ...notifications };\n}\n\nfunction setConfigValue(\n raw: MutablePajaRawOptions,\n entry: { key: string; value: JsonValue },\n): void {\n ensureSimulation(raw).config = {\n ...raw.simulation?.config,\n values: {\n ...raw.simulation?.config?.values,\n [entry.key]: entry.value,\n },\n };\n}\n\nfunction setCapability(\n raw: MutablePajaRawOptions,\n entry: { domain: PajaCapabilityDomain; enabled: boolean },\n): void {\n ensureSimulation(raw).capabilities = {\n ...raw.simulation?.capabilities,\n domains: {\n ...raw.simulation?.capabilities?.domains,\n [entry.domain]: entry.enabled,\n },\n };\n}\n\nfunction ensureSimulation(raw: MutablePajaRawOptions): MutablePajaSimulationRawOptions {\n raw.simulation ??= {};\n return raw.simulation as MutablePajaSimulationRawOptions;\n}\n\nasync function resolveManagedTargetUrl(\n configuredUrl: string,\n child: ManagedChildProcess,\n options: {\n readonly timeoutMs: number;\n readonly discoveryGraceMs?: number;\n readonly waitForTargetUrl: typeof waitForTargetUrl;\n },\n): Promise<string> {\n let configuredError: unknown;\n const configuredReady = options.waitForTargetUrl(configuredUrl, { timeoutMs: options.timeoutMs })\n .then(() => configuredUrl)\n .catch((error) => {\n configuredError = error;\n return undefined;\n });\n const first = await Promise.race([\n configuredReady.then((url) => url ? { kind: 'configured' as const, url } : undefined),\n child.detectedTargetUrl.then((url) => ({ kind: 'detected' as const, url })),\n ]);\n\n if (first?.kind === 'detected') {\n await options.waitForTargetUrl(first.url, { timeoutMs: options.timeoutMs });\n return first.url;\n }\n\n const graceMs = options.discoveryGraceMs ?? Math.min(1000, options.timeoutMs);\n const detected = await resolveWithin(child.detectedTargetUrl, graceMs);\n if (!detected) {\n if (first?.url) {\n return first.url;\n }\n throw configuredError instanceof Error ? configuredError : new Error(String(configuredError ?? 'Target URL was not ready.'));\n }\n\n await options.waitForTargetUrl(detected, { timeoutMs: options.timeoutMs });\n return detected;\n}\n\nfunction resolveWithin<T>(promise: Promise<T>, timeoutMs: number): Promise<T | undefined> {\n return new Promise((resolve) => {\n let settled = false;\n const timeout = setTimeout(() => {\n if (settled) return;\n settled = true;\n resolve(undefined);\n }, Math.max(0, timeoutMs));\n\n promise.then((value) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeout);\n resolve(value);\n }, () => {\n if (settled) return;\n settled = true;\n clearTimeout(timeout);\n resolve(undefined);\n });\n });\n}\n\nfunction startManagedCommand(command: PajaCommand, io: CliIo): ManagedChildProcess {\n const detector = createManagedTargetUrlDetector();\n const child = spawnManagedCommand(command);\n forwardManagedOutput(child, detector, io);\n return {\n kill: () => child.kill(),\n detectedTargetUrl: detector.detectedTargetUrl,\n };\n}\n\nfunction spawnManagedCommand(command: PajaCommand): ChildProcess {\n if (command.mode === 'shell') {\n return spawn(command.command, { shell: true, stdio: ['inherit', 'pipe', 'pipe'] as const });\n }\n\n const [executable, ...args] = command.argv;\n if (!executable) {\n throw new PajaOptionsError('Argv command mode requires an executable.');\n }\n return spawn(executable, args, { stdio: ['inherit', 'pipe', 'pipe'] as const });\n}\n\nfunction forwardManagedOutput(\n child: ChildProcess,\n detector: ManagedTargetUrlDetector,\n io: CliIo,\n): void {\n child.stdout?.on('data', (chunk: string | Uint8Array) => {\n const text = String(chunk);\n detector.observe(text);\n io.stdout.write(text);\n });\n child.stderr?.on('data', (chunk: string | Uint8Array) => {\n const text = String(chunk);\n detector.observe(text);\n io.stderr.write(text);\n });\n}\n\nfunction createManagedTargetUrlDetector(): ManagedTargetUrlDetector {\n let resolveDetected: (url: string) => void = () => {\n // Promise executor replaces this before any child-process output can arrive.\n };\n let detected: string | undefined;\n const detectedTargetUrl = new Promise<string>((resolve) => {\n resolveDetected = resolve;\n });\n\n return {\n detectedTargetUrl,\n observe(chunk) {\n if (detected) return;\n const text = stripAnsi(chunk);\n for (const match of text.matchAll(LOCAL_HTTP_URL_PATTERN)) {\n const rawUrl = match[0];\n let url: URL;\n try {\n url = new URL(rawUrl);\n } catch {\n continue;\n }\n detected = url.href;\n resolveDetected(detected);\n return;\n }\n },\n };\n}\n\nfunction stripAnsi(value: string): string {\n return value.replace(ANSI_PATTERN, '');\n}\n\ntype MutablePajaRawOptions = {\n -readonly [K in keyof PajaRawOptions]: PajaRawOptions[K];\n};\n\ntype MutablePajaSimulationRawOptions = {\n -readonly [K in keyof PajaSimulationRawOptions]: PajaSimulationRawOptions[K];\n};\n\nconst defaultIo: CliIo = {\n stdout: { write: (chunk) => process.stdout.write(chunk) },\n stderr: { write: (chunk) => process.stderr.write(chunk) },\n};\n\nif (isDirectPajaCli()) {\n void runPajaCli().then((code) => {\n process.exitCode = code;\n });\n}\n\nexport function isDirectPajaCli(entryPath = process.argv[1]): boolean {\n if (!entryPath) return false;\n return entryPath.endsWith('/cli.js') || entryPath.endsWith('/paja');\n}\n\ndeclare const process: {\n argv: string[];\n exitCode?: number;\n stdout: { write(chunk: string): void };\n stderr: { write(chunk: string): void };\n};\n\nexport interface ManagedChildProcess {\n kill(): void;\n readonly detectedTargetUrl: Promise<string>;\n}\n\ninterface ManagedTargetUrlDetector {\n readonly detectedTargetUrl: Promise<string>;\n observe(chunk: string): void;\n}\n\nconst LOCAL_HTTP_URL_PATTERN = /https?:\\/\\/(?:localhost|127(?:\\.\\d{1,3}){3}|\\[::1\\])(?::\\d+)?(?:\\/[^\\s'\"<>)\\]]*)?/g;\nconst ANSI_PATTERN = /\\u001b\\[[0-?]*[ -/]*[@-~]/g;\n"],"mappings":"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","names":[]}