@kehto/paja 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/dist/browser-host.js +2127 -114
- package/dist/browser-host.js.map +1 -1
- package/dist/{chunk-6QZXEPQJ.js → chunk-WIMZGAOX.js} +81 -8
- package/dist/chunk-WIMZGAOX.js.map +1 -0
- package/dist/cli.d.ts +10 -2
- package/dist/cli.js +118 -7
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +3 -29
- package/dist/index.js +1 -1
- package/dist/{options-D4tneY-c.d.ts → server-Ca1k_vlt.d.ts} +28 -1
- package/package.json +2 -2
- package/dist/chunk-6QZXEPQJ.js.map +0 -1
|
@@ -392,9 +392,29 @@ function renderPajaHtml(config) {
|
|
|
392
392
|
button { border: 1px solid var(--line); color: var(--text); background: #20241f; height: 26px; padding: 0 10px; border-radius: 4px; font: inherit; cursor: pointer; }
|
|
393
393
|
button:hover { border-color: var(--accent); }
|
|
394
394
|
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; }
|
|
395
|
+
select, input { border: 1px solid var(--line); color: var(--text); background: #20241f; height: 26px; border-radius: 4px; font: inherit; }
|
|
396
|
+
main { min-height: 0; display: grid; grid-template-columns: minmax(320px, 380px) minmax(0, 1fr); }
|
|
397
|
+
.console { min-height: 0; overflow: auto; border-right: 1px solid var(--line); background: #121512; padding: 10px; display: flex; flex-direction: column; gap: 12px; }
|
|
398
|
+
.section { display: grid; gap: 8px; }
|
|
399
|
+
.section-title { color: var(--accent); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0; }
|
|
400
|
+
.switch-grid, .acl-grid { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
401
|
+
.toggle { height: 24px; padding: 0 8px; color: var(--muted); }
|
|
402
|
+
.toggle[data-enabled="true"] { color: var(--text); border-color: #5f724f; background: #24301f; }
|
|
403
|
+
.toggle[data-enabled="false"] { color: #8d9187; border-color: #453536; background: #241d1d; }
|
|
404
|
+
.signer { color: var(--muted); word-break: break-all; font-size: 12px; }
|
|
405
|
+
.log-tools { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px; }
|
|
406
|
+
.log-list { min-height: 160px; max-height: 38vh; overflow: auto; border: 1px solid var(--line); border-radius: 4px; background: #0b0d0b; }
|
|
407
|
+
.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; }
|
|
408
|
+
.log-row:last-child { border-bottom: 0; }
|
|
409
|
+
.log-dir { color: var(--muted); }
|
|
410
|
+
.log-type { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
411
|
+
.stage { min-width: 0; min-height: 0; }
|
|
396
412
|
iframe { width: 100%; height: 100%; border: 0; background: white; display: block; }
|
|
397
413
|
code { color: var(--text); }
|
|
414
|
+
@media (max-width: 900px) {
|
|
415
|
+
main { grid-template-columns: 1fr; grid-template-rows: minmax(240px, 40vh) minmax(0, 1fr); }
|
|
416
|
+
.console { border-right: 0; border-bottom: 1px solid var(--line); }
|
|
417
|
+
}
|
|
398
418
|
</style>
|
|
399
419
|
</head>
|
|
400
420
|
<body>
|
|
@@ -411,7 +431,31 @@ function renderPajaHtml(config) {
|
|
|
411
431
|
<button type="button" id="reload-target">Reload</button>
|
|
412
432
|
</header>
|
|
413
433
|
<main>
|
|
414
|
-
<
|
|
434
|
+
<aside class="console" aria-label="Paja development controls">
|
|
435
|
+
<section class="section">
|
|
436
|
+
<div class="section-title">Interfaces</div>
|
|
437
|
+
<div class="switch-grid" id="interface-toggles"></div>
|
|
438
|
+
</section>
|
|
439
|
+
<section class="section">
|
|
440
|
+
<div class="section-title">ACL</div>
|
|
441
|
+
<div class="acl-grid" id="acl-controls"></div>
|
|
442
|
+
</section>
|
|
443
|
+
<section class="section">
|
|
444
|
+
<div class="section-title">Signer</div>
|
|
445
|
+
<div class="signer" id="signer-status">loading</div>
|
|
446
|
+
</section>
|
|
447
|
+
<section class="section">
|
|
448
|
+
<div class="section-title">Messages</div>
|
|
449
|
+
<div class="log-tools">
|
|
450
|
+
<input id="message-filter" type="search" autocomplete="off" placeholder="filter messages" aria-label="Filter message log">
|
|
451
|
+
<button type="button" id="clear-log">Clear</button>
|
|
452
|
+
</div>
|
|
453
|
+
<div class="log-list" id="message-log" aria-live="polite"></div>
|
|
454
|
+
</section>
|
|
455
|
+
</aside>
|
|
456
|
+
<section class="stage">
|
|
457
|
+
<iframe id="napplet-frame" title="Napplet development target" sandbox="allow-scripts" data-target-url="${targetUrl}"></iframe>
|
|
458
|
+
</section>
|
|
415
459
|
</main>
|
|
416
460
|
<footer class="bar bottom">
|
|
417
461
|
<span>mode: <code>${config.target.command ? "managed-command" : "external-target"}</code></span>
|
|
@@ -560,9 +604,18 @@ import { readFileSync as readFileSync2 } from "fs";
|
|
|
560
604
|
async function startPajaServer(input) {
|
|
561
605
|
const rawOptions = resolvePajaRawOptions(input.options);
|
|
562
606
|
const options = normalizePajaOptions(rawOptions);
|
|
563
|
-
|
|
607
|
+
const createdAt = input.now ?? /* @__PURE__ */ new Date();
|
|
608
|
+
let hostConfig = createPajaHostConfig(options, createdAt);
|
|
564
609
|
let html = renderPajaHtml(hostConfig);
|
|
565
610
|
let configJson = JSON.stringify(hostConfig, null, 2);
|
|
611
|
+
let currentOptions = options;
|
|
612
|
+
const setHostConfig = (nextOptions) => {
|
|
613
|
+
currentOptions = nextOptions;
|
|
614
|
+
hostConfig = createPajaHostConfig(currentOptions, createdAt);
|
|
615
|
+
html = renderPajaHtml(hostConfig);
|
|
616
|
+
configJson = JSON.stringify(hostConfig, null, 2);
|
|
617
|
+
return hostConfig;
|
|
618
|
+
};
|
|
566
619
|
const server = createServer((request, response) => {
|
|
567
620
|
const requestUrl = request.url ?? "/";
|
|
568
621
|
if (requestUrl === "/" || requestUrl.startsWith("/?")) {
|
|
@@ -586,12 +639,15 @@ async function startPajaServer(input) {
|
|
|
586
639
|
});
|
|
587
640
|
await listen(server, options.host, options.port);
|
|
588
641
|
const servedOptions = withBoundPort(options, getBoundPort(server, options.port));
|
|
589
|
-
|
|
590
|
-
html = renderPajaHtml(hostConfig);
|
|
591
|
-
configJson = JSON.stringify(hostConfig, null, 2);
|
|
642
|
+
setHostConfig(servedOptions);
|
|
592
643
|
return {
|
|
593
644
|
url: formatPajaUrl(servedOptions),
|
|
594
|
-
hostConfig
|
|
645
|
+
get hostConfig() {
|
|
646
|
+
return hostConfig;
|
|
647
|
+
},
|
|
648
|
+
updateTargetUrl(targetUrl) {
|
|
649
|
+
return setHostConfig(withTargetUrl(currentOptions, targetUrl));
|
|
650
|
+
},
|
|
595
651
|
close: () => close(server)
|
|
596
652
|
};
|
|
597
653
|
}
|
|
@@ -625,6 +681,23 @@ function getBoundPort(server, fallback) {
|
|
|
625
681
|
function withBoundPort(options, port) {
|
|
626
682
|
return port === options.port ? options : { ...options, port };
|
|
627
683
|
}
|
|
684
|
+
function withTargetUrl(options, targetUrl) {
|
|
685
|
+
const url = normalizeServerTargetUrl(targetUrl);
|
|
686
|
+
return url === options.targetUrl ? options : { ...options, targetUrl: url };
|
|
687
|
+
}
|
|
688
|
+
function normalizeServerTargetUrl(value) {
|
|
689
|
+
const raw = value.trim();
|
|
690
|
+
let parsed;
|
|
691
|
+
try {
|
|
692
|
+
parsed = new URL(raw);
|
|
693
|
+
} catch {
|
|
694
|
+
throw new Error(`Invalid managed target URL "${raw}". Expected an absolute http(s) URL.`);
|
|
695
|
+
}
|
|
696
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
697
|
+
throw new Error(`Invalid managed target URL "${raw}". Only http: and https: URLs are supported.`);
|
|
698
|
+
}
|
|
699
|
+
return parsed.href;
|
|
700
|
+
}
|
|
628
701
|
|
|
629
702
|
export {
|
|
630
703
|
PajaSimulationError,
|
|
@@ -656,4 +729,4 @@ export {
|
|
|
656
729
|
waitForTargetUrl,
|
|
657
730
|
startPajaServer
|
|
658
731
|
};
|
|
659
|
-
//# sourceMappingURL=chunk-
|
|
732
|
+
//# sourceMappingURL=chunk-WIMZGAOX.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 .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 .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:last-child { border-bottom: 0; }\n .log-dir { color: var(--muted); }\n .log-type { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\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</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 </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('\"', '"');\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>');\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 './
|
|
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-
|
|
12
|
+
} from "./chunk-WIMZGAOX.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
|
|
55
|
+
server = await startServer({ options: rawOptions });
|
|
53
56
|
writeRuntimeSummary(io, server.url, hostConfig, options);
|
|
54
57
|
if (options.command) {
|
|
55
|
-
child =
|
|
56
|
-
await
|
|
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
|
|
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":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PajaRawOptions,
|
|
2
|
-
export { D as DEFAULT_PAJA_AGGREGATE_HASH,
|
|
1
|
+
import { P as PajaRawOptions, b as PajaHostConfig } from './server-Ca1k_vlt.js';
|
|
2
|
+
export { D as DEFAULT_PAJA_AGGREGATE_HASH, c as DEFAULT_PAJA_DTAG, d as DEFAULT_PAJA_HOST, e as DEFAULT_PAJA_PORT, f as DEFAULT_PAJA_WINDOW_ID, g as DEFAULT_READY_TIMEOUT_MS, J as JsonPrimitive, h as JsonRecord, i as JsonValue, j as PAJA_SIMULATION_DOMAINS, k as PajaCapabilityDomain, a as PajaCommand, l as PajaOptions, m as PajaOptionsError, n as PajaServer, o as PajaServerOptions, p as PajaSimulation, q as PajaSimulationError, r as PajaSimulationRawOptions, R as ReadinessError, t as ReadinessFetch, W as WaitForTargetUrlOptions, u as createPajaHostConfig, v as formatPajaUrl, x as normalizePajaOptions, y as normalizePajaSimulation, s as startPajaServer, z as summarizePajaSimulation, w as waitForTargetUrl } from './server-Ca1k_vlt.js';
|
|
3
3
|
import { ShellCapabilities } from '@kehto/shell';
|
|
4
4
|
|
|
5
5
|
declare function loadPajaConfigFile(configPath: string): PajaRawOptions;
|
|
@@ -18,30 +18,4 @@ declare const PAJA_REQUIRED_SERVICES: readonly ["config", "cvm", "identity", "in
|
|
|
18
18
|
declare function getMissingAdvertisedDomains(capabilities: ShellCapabilities): string[];
|
|
19
19
|
declare function getMissingServices(services: readonly string[]): string[];
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
readonly timeoutMs: number;
|
|
23
|
-
readonly intervalMs?: number;
|
|
24
|
-
readonly fetch?: ReadinessFetch;
|
|
25
|
-
readonly sleep?: (ms: number) => Promise<void>;
|
|
26
|
-
readonly now?: () => number;
|
|
27
|
-
}
|
|
28
|
-
type ReadinessFetch = (url: string) => Promise<{
|
|
29
|
-
readonly status: number;
|
|
30
|
-
}>;
|
|
31
|
-
declare class ReadinessError extends Error {
|
|
32
|
-
constructor(message: string);
|
|
33
|
-
}
|
|
34
|
-
declare function waitForTargetUrl(url: string, options: WaitForTargetUrlOptions): Promise<void>;
|
|
35
|
-
|
|
36
|
-
interface PajaServerOptions {
|
|
37
|
-
readonly options: PajaRawOptions;
|
|
38
|
-
readonly now?: Date;
|
|
39
|
-
}
|
|
40
|
-
interface PajaServer {
|
|
41
|
-
readonly url: string;
|
|
42
|
-
readonly hostConfig: PajaHostConfig;
|
|
43
|
-
close(): Promise<void>;
|
|
44
|
-
}
|
|
45
|
-
declare function startPajaServer(input: PajaServerOptions): Promise<PajaServer>;
|
|
46
|
-
|
|
47
|
-
export { PAJA_ADVERTISED_DOMAINS, PAJA_COMPATIBILITY_ALIASES, PAJA_HANDSHAKE_DOMAINS, PAJA_REQUIRED_SERVICES, PAJA_UPSTREAM_WEB_DOMAINS, PajaHostConfig, PajaRawOptions, type PajaServer, type PajaServerOptions, ReadinessError, type ReadinessFetch, type WaitForTargetUrlOptions, getMissingAdvertisedDomains, getMissingServices, loadPajaConfigFile, mergePajaRawOptions, renderPajaHtml, resolvePajaRawOptions, startPajaServer, waitForTargetUrl };
|
|
21
|
+
export { PAJA_ADVERTISED_DOMAINS, PAJA_COMPATIBILITY_ALIASES, PAJA_HANDSHAKE_DOMAINS, PAJA_REQUIRED_SERVICES, PAJA_UPSTREAM_WEB_DOMAINS, PajaHostConfig, PajaRawOptions, getMissingAdvertisedDomains, getMissingServices, loadPajaConfigFile, mergePajaRawOptions, renderPajaHtml, resolvePajaRawOptions };
|