@kehto/paja 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -16
- package/dist/browser-host.js +13762 -10815
- package/dist/browser-host.js.map +1 -1
- package/dist/{chunk-5QKVKI4K.js → chunk-NFJCS5PG.js} +177 -32
- package/dist/chunk-NFJCS5PG.js.map +1 -0
- package/dist/cli.d.ts +18 -1
- package/dist/cli.js +10 -6
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +89 -5
- package/dist/index.js +3 -1
- package/dist/{server-qAXYczds.d.ts → server-efRTBcMR.d.ts} +132 -7
- package/package.json +13 -13
- package/dist/chunk-5QKVKI4K.js.map +0 -1
|
@@ -1,13 +1,20 @@
|
|
|
1
|
+
/** JSON primitive accepted in Paja simulation config values. */
|
|
1
2
|
type JsonPrimitive = string | number | boolean | null;
|
|
3
|
+
/** JSON value accepted in Paja simulation config values. */
|
|
2
4
|
type JsonValue = JsonPrimitive | JsonValue[] | {
|
|
3
5
|
readonly [key: string]: JsonValue;
|
|
4
6
|
};
|
|
7
|
+
/** JSON object used for Paja simulation fixtures and config/theme values. */
|
|
5
8
|
type JsonRecord = Record<string, JsonValue>;
|
|
9
|
+
/** Capability domain names Paja can advertise or disable. */
|
|
6
10
|
type PajaCapabilityDomain = 'relay' | 'outbox' | 'storage' | 'identity' | 'keys' | 'config' | 'resource' | 'theme' | 'notify' | 'media' | 'upload' | 'intent' | 'count' | 'link' | 'common' | 'lists' | 'serial' | 'ble' | 'webrtc' | 'cvm' | 'inc';
|
|
11
|
+
/** Raw simulation controls accepted from CLI args or JSON config. */
|
|
7
12
|
interface PajaSimulationRawOptions {
|
|
13
|
+
/** Per-domain capability overrides. */
|
|
8
14
|
readonly capabilities?: {
|
|
9
15
|
readonly domains?: Partial<Record<PajaCapabilityDomain, boolean>>;
|
|
10
16
|
};
|
|
17
|
+
/** ACL behavior mode for simulated services. */
|
|
11
18
|
readonly acl?: {
|
|
12
19
|
readonly mode?: 'allow' | 'deny';
|
|
13
20
|
};
|
|
@@ -19,7 +26,7 @@ interface PajaSimulationRawOptions {
|
|
|
19
26
|
readonly pubkey?: string;
|
|
20
27
|
};
|
|
21
28
|
readonly relay?: {
|
|
22
|
-
readonly mode?: 'memory' | 'disabled';
|
|
29
|
+
readonly mode?: 'live' | 'memory' | 'disabled';
|
|
23
30
|
readonly urls?: readonly string[];
|
|
24
31
|
readonly fixtures?: readonly JsonRecord[];
|
|
25
32
|
};
|
|
@@ -30,8 +37,12 @@ interface PajaSimulationRawOptions {
|
|
|
30
37
|
readonly mode?: 'memory' | 'disabled';
|
|
31
38
|
};
|
|
32
39
|
readonly upload?: {
|
|
33
|
-
readonly mode?: 'memory' | 'disabled';
|
|
40
|
+
readonly mode?: 'memory' | 'blossom' | 'disabled';
|
|
34
41
|
readonly rail?: string;
|
|
42
|
+
readonly servers?: readonly string[];
|
|
43
|
+
readonly discoverServers?: boolean;
|
|
44
|
+
readonly maxBytes?: number;
|
|
45
|
+
readonly mimeTypes?: readonly string[];
|
|
35
46
|
};
|
|
36
47
|
readonly media?: {
|
|
37
48
|
readonly enabled?: boolean;
|
|
@@ -54,7 +65,9 @@ interface PajaSimulationRawOptions {
|
|
|
54
65
|
readonly enabled?: boolean;
|
|
55
66
|
};
|
|
56
67
|
}
|
|
68
|
+
/** Fully normalized Paja simulation model served to the browser host. */
|
|
57
69
|
interface PajaSimulation {
|
|
70
|
+
/** Capability domains and disabled-domain summary. */
|
|
58
71
|
readonly capabilities: {
|
|
59
72
|
readonly domains: Record<PajaCapabilityDomain, boolean>;
|
|
60
73
|
readonly disabledDomains: readonly PajaCapabilityDomain[];
|
|
@@ -70,7 +83,7 @@ interface PajaSimulation {
|
|
|
70
83
|
readonly pubkey: string;
|
|
71
84
|
};
|
|
72
85
|
readonly relay: {
|
|
73
|
-
readonly mode: 'memory' | 'disabled';
|
|
86
|
+
readonly mode: 'live' | 'memory' | 'disabled';
|
|
74
87
|
readonly urls: readonly string[];
|
|
75
88
|
readonly fixtures: readonly JsonRecord[];
|
|
76
89
|
};
|
|
@@ -81,8 +94,12 @@ interface PajaSimulation {
|
|
|
81
94
|
readonly mode: 'memory' | 'disabled';
|
|
82
95
|
};
|
|
83
96
|
readonly upload: {
|
|
84
|
-
readonly mode: 'memory' | 'disabled';
|
|
85
|
-
readonly rail
|
|
97
|
+
readonly mode: 'memory' | 'blossom' | 'disabled';
|
|
98
|
+
readonly rail?: string;
|
|
99
|
+
readonly servers: readonly string[];
|
|
100
|
+
readonly discoverServers: boolean;
|
|
101
|
+
readonly maxBytes?: number;
|
|
102
|
+
readonly mimeTypes?: readonly string[];
|
|
86
103
|
};
|
|
87
104
|
readonly media: {
|
|
88
105
|
readonly enabled: boolean;
|
|
@@ -105,49 +122,95 @@ interface PajaSimulation {
|
|
|
105
122
|
readonly enabled: boolean;
|
|
106
123
|
};
|
|
107
124
|
}
|
|
125
|
+
/** Thrown when Paja simulation options are internally inconsistent. */
|
|
108
126
|
declare class PajaSimulationError extends Error {
|
|
109
127
|
constructor(message: string);
|
|
110
128
|
}
|
|
129
|
+
/** Capability domains exposed by Paja simulation controls. */
|
|
111
130
|
declare const PAJA_SIMULATION_DOMAINS: readonly PajaCapabilityDomain[];
|
|
131
|
+
/**
|
|
132
|
+
* Normalize raw simulation options into a complete deterministic model.
|
|
133
|
+
*
|
|
134
|
+
* @param raw - Partial simulation options from CLI args or config.
|
|
135
|
+
* @returns Complete simulation model.
|
|
136
|
+
*/
|
|
112
137
|
declare function normalizePajaSimulation(raw: PajaSimulationRawOptions | undefined): PajaSimulation;
|
|
138
|
+
/**
|
|
139
|
+
* Format a compact, human-readable simulation summary.
|
|
140
|
+
*
|
|
141
|
+
* @param simulation - Normalized simulation model.
|
|
142
|
+
* @returns One-line summary used by CLI and host-page chrome.
|
|
143
|
+
*/
|
|
113
144
|
declare function summarizePajaSimulation(simulation: PajaSimulation): string;
|
|
114
145
|
|
|
115
|
-
|
|
146
|
+
/** Command configuration for a managed Paja target process. */
|
|
147
|
+
type PajaCommand =
|
|
148
|
+
/** Spawn an executable with argv preserved exactly after `--`. */
|
|
149
|
+
{
|
|
116
150
|
readonly mode: 'argv';
|
|
117
151
|
readonly argv: readonly string[];
|
|
118
|
-
}
|
|
152
|
+
}
|
|
153
|
+
/** Run a shell command string. */
|
|
154
|
+
| {
|
|
119
155
|
readonly mode: 'shell';
|
|
120
156
|
readonly command: string;
|
|
121
157
|
};
|
|
158
|
+
/** Raw, unnormalized options accepted from CLI arguments or config files. */
|
|
122
159
|
interface PajaRawOptions {
|
|
160
|
+
/** App dev-server URL that Paja should load. */
|
|
123
161
|
readonly targetUrl?: string;
|
|
162
|
+
/** Optional managed command to start before serving Paja. */
|
|
124
163
|
readonly command?: PajaCommand;
|
|
164
|
+
/** Hostname or IP address for the Paja HTTP server. */
|
|
125
165
|
readonly host?: string;
|
|
166
|
+
/** Runtime HTTP port. */
|
|
126
167
|
readonly port?: number | string;
|
|
168
|
+
/** Target readiness timeout in milliseconds. */
|
|
127
169
|
readonly readyTimeoutMs?: number | string;
|
|
170
|
+
/** Optional JSON config file path. */
|
|
128
171
|
readonly configPath?: string;
|
|
172
|
+
/** Simulation controls for injected shell domains. */
|
|
129
173
|
readonly simulation?: PajaSimulationRawOptions;
|
|
130
174
|
}
|
|
175
|
+
/** Paja target loading mode. */
|
|
131
176
|
type PajaTargetMode = 'iframe-url' | 'runtime-pointer';
|
|
177
|
+
/** Hot-module-reload strategy for the hosted target. */
|
|
132
178
|
type PajaHmrStrategy = 'iframe-target-url' | 'none';
|
|
179
|
+
/** Runtime-pointer resolution config embedded into the Paja host page. */
|
|
133
180
|
interface PajaPointerRuntimeConfig {
|
|
181
|
+
/** Optional naddr/nevent pointer to resolve at boot. */
|
|
134
182
|
readonly value?: string;
|
|
183
|
+
/** Relay hints used to resolve the pointer. */
|
|
135
184
|
readonly relays: readonly string[];
|
|
185
|
+
/** Blossom server hints used for artifact blob fetches. */
|
|
136
186
|
readonly blossomServers: readonly string[];
|
|
187
|
+
/** Maximum pointer-resolution wait in milliseconds. */
|
|
137
188
|
readonly maxWaitMs: number;
|
|
138
189
|
}
|
|
190
|
+
/** Normalized Paja runtime options. */
|
|
139
191
|
interface PajaOptions {
|
|
192
|
+
/** Absolute target URL for iframe-url mode. */
|
|
140
193
|
readonly targetUrl: string;
|
|
194
|
+
/** Optional managed target command. */
|
|
141
195
|
readonly command?: PajaCommand;
|
|
196
|
+
/** Paja server host. */
|
|
142
197
|
readonly host: string;
|
|
198
|
+
/** Paja server port. */
|
|
143
199
|
readonly port: number;
|
|
200
|
+
/** Target readiness timeout in milliseconds. */
|
|
144
201
|
readonly readyTimeoutMs: number;
|
|
202
|
+
/** Optional config path retained for host diagnostics. */
|
|
145
203
|
readonly configPath?: string;
|
|
204
|
+
/** Normalized simulation model. */
|
|
146
205
|
readonly simulation: PajaSimulation;
|
|
206
|
+
/** Whether Paja owns a managed command or attaches to an external target. */
|
|
147
207
|
readonly mode: 'external-target' | 'managed-command';
|
|
148
208
|
}
|
|
209
|
+
/** Serialized host-page config served to the browser runtime. */
|
|
149
210
|
interface PajaHostConfig {
|
|
211
|
+
/** Config schema version. */
|
|
150
212
|
readonly version: 1;
|
|
213
|
+
/** Window identity used for the development target. */
|
|
151
214
|
readonly window: {
|
|
152
215
|
readonly id: string;
|
|
153
216
|
readonly dTag: string;
|
|
@@ -175,51 +238,113 @@ interface PajaHostConfig {
|
|
|
175
238
|
};
|
|
176
239
|
readonly simulation: PajaSimulation;
|
|
177
240
|
}
|
|
241
|
+
/** Thrown when raw Paja options cannot be normalized. */
|
|
178
242
|
declare class PajaOptionsError extends Error {
|
|
179
243
|
constructor(message: string);
|
|
180
244
|
}
|
|
245
|
+
/** Default loopback host for the Paja HTTP server. */
|
|
181
246
|
declare const DEFAULT_PAJA_HOST = "127.0.0.1";
|
|
247
|
+
/** Default Paja HTTP port. */
|
|
182
248
|
declare const DEFAULT_PAJA_PORT = 5197;
|
|
249
|
+
/** Default readiness timeout for the target URL. */
|
|
183
250
|
declare const DEFAULT_READY_TIMEOUT_MS = 30000;
|
|
251
|
+
/** Default development window id used in host config. */
|
|
184
252
|
declare const DEFAULT_PAJA_WINDOW_ID = "kehto-paja-window";
|
|
253
|
+
/** Default development `d` tag used for target identity. */
|
|
185
254
|
declare const DEFAULT_PAJA_DTAG = "dev-target";
|
|
255
|
+
/** Default development aggregate hash used for target identity. */
|
|
186
256
|
declare const DEFAULT_PAJA_AGGREGATE_HASH = "paja";
|
|
257
|
+
/** Default pointer resolution wait in runtime-pointer mode. */
|
|
187
258
|
declare const DEFAULT_PAJA_RUNTIME_WAIT_MS = 5000;
|
|
259
|
+
/**
|
|
260
|
+
* Normalize raw CLI/config options into a validated Paja runtime config.
|
|
261
|
+
*
|
|
262
|
+
* @param raw - Raw options from CLI parsing or a config file.
|
|
263
|
+
* @returns Fully normalized runtime options.
|
|
264
|
+
*/
|
|
188
265
|
declare function normalizePajaOptions(raw: PajaRawOptions): PajaOptions;
|
|
266
|
+
/**
|
|
267
|
+
* Create browser host-page config for iframe-url mode.
|
|
268
|
+
*
|
|
269
|
+
* @param options - Normalized Paja options.
|
|
270
|
+
* @param now - Clock value used for reload token and timestamps.
|
|
271
|
+
* @returns Serializable host-page config.
|
|
272
|
+
*/
|
|
189
273
|
declare function createPajaHostConfig(options: PajaOptions, now?: Date): PajaHostConfig;
|
|
274
|
+
/**
|
|
275
|
+
* Create browser host-page config for runtime-pointer mode.
|
|
276
|
+
*
|
|
277
|
+
* @param options - Pointer, relay, and Blossom hints.
|
|
278
|
+
* @param now - Clock value used for reload token and timestamps.
|
|
279
|
+
* @returns Serializable host-page config.
|
|
280
|
+
*/
|
|
190
281
|
declare function createPajaRuntimeHostConfig(options?: {
|
|
191
282
|
readonly pointer?: string;
|
|
192
283
|
readonly relays?: readonly string[];
|
|
193
284
|
readonly blossomServers?: readonly string[];
|
|
194
285
|
readonly maxWaitMs?: number;
|
|
195
286
|
}, now?: Date): PajaHostConfig;
|
|
287
|
+
/**
|
|
288
|
+
* Format the local Paja runtime URL for display and CLI output.
|
|
289
|
+
*
|
|
290
|
+
* @param options - Host and port pair.
|
|
291
|
+
* @returns HTTP URL for the Paja runtime.
|
|
292
|
+
*/
|
|
196
293
|
declare function formatPajaUrl(options: Pick<PajaOptions, 'host' | 'port'>): string;
|
|
197
294
|
|
|
295
|
+
/** Options for polling a target URL until it is ready. */
|
|
198
296
|
interface WaitForTargetUrlOptions {
|
|
297
|
+
/** Total wait budget in milliseconds. */
|
|
199
298
|
readonly timeoutMs: number;
|
|
299
|
+
/** Poll interval in milliseconds. Defaults to 250. */
|
|
200
300
|
readonly intervalMs?: number;
|
|
301
|
+
/** Fetch implementation override for tests. */
|
|
201
302
|
readonly fetch?: ReadinessFetch;
|
|
303
|
+
/** Sleep implementation override for tests. */
|
|
202
304
|
readonly sleep?: (ms: number) => Promise<void>;
|
|
305
|
+
/** Clock override for tests. */
|
|
203
306
|
readonly now?: () => number;
|
|
204
307
|
}
|
|
308
|
+
/** Fetch-like target readiness probe. */
|
|
205
309
|
type ReadinessFetch = (url: string) => Promise<{
|
|
206
310
|
readonly status: number;
|
|
207
311
|
}>;
|
|
312
|
+
/** Thrown when a target URL does not become ready before the timeout. */
|
|
208
313
|
declare class ReadinessError extends Error {
|
|
209
314
|
constructor(message: string);
|
|
210
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* Poll a target URL until it returns a non-5xx response or times out.
|
|
318
|
+
*
|
|
319
|
+
* @param url - Target URL to poll.
|
|
320
|
+
* @param options - Timeout and polling controls.
|
|
321
|
+
*/
|
|
211
322
|
declare function waitForTargetUrl(url: string, options: WaitForTargetUrlOptions): Promise<void>;
|
|
212
323
|
|
|
324
|
+
/** Options for starting the Paja local HTTP server. */
|
|
213
325
|
interface PajaServerOptions {
|
|
326
|
+
/** Raw options accepted by Paja; config-file references are resolved before serving. */
|
|
214
327
|
readonly options: PajaRawOptions;
|
|
328
|
+
/** Clock override used for deterministic host config in tests. */
|
|
215
329
|
readonly now?: Date;
|
|
216
330
|
}
|
|
331
|
+
/** Running Paja server handle. */
|
|
217
332
|
interface PajaServer {
|
|
333
|
+
/** Runtime URL where the Paja host page is served. */
|
|
218
334
|
readonly url: string;
|
|
335
|
+
/** Current host-page config. */
|
|
219
336
|
readonly hostConfig: PajaHostConfig;
|
|
337
|
+
/** Update the target iframe URL without restarting the server. */
|
|
220
338
|
updateTargetUrl(targetUrl: string): PajaHostConfig;
|
|
339
|
+
/** Stop the HTTP server. */
|
|
221
340
|
close(): Promise<void>;
|
|
222
341
|
}
|
|
342
|
+
/**
|
|
343
|
+
* Start the local Paja development HTTP server.
|
|
344
|
+
*
|
|
345
|
+
* @param input - Raw options and optional clock override.
|
|
346
|
+
* @returns Running server handle.
|
|
347
|
+
*/
|
|
223
348
|
declare function startPajaServer(input: PajaServerOptions): Promise<PajaServer>;
|
|
224
349
|
|
|
225
350
|
export { createPajaRuntimeHostConfig as A, formatPajaUrl as B, normalizePajaOptions as C, DEFAULT_PAJA_AGGREGATE_HASH as D, normalizePajaSimulation as E, summarizePajaSimulation as F, type JsonPrimitive as J, type PajaRawOptions as P, ReadinessError as R, type WaitForTargetUrlOptions as W, type PajaCommand as a, type PajaHostConfig as b, DEFAULT_PAJA_DTAG as c, DEFAULT_PAJA_HOST as d, DEFAULT_PAJA_PORT as e, DEFAULT_PAJA_RUNTIME_WAIT_MS as f, DEFAULT_PAJA_WINDOW_ID as g, DEFAULT_READY_TIMEOUT_MS as h, type JsonRecord as i, type JsonValue as j, PAJA_SIMULATION_DOMAINS as k, type PajaCapabilityDomain as l, type PajaHmrStrategy as m, type PajaOptions as n, PajaOptionsError as o, type PajaPointerRuntimeConfig as p, type PajaServer as q, type PajaServerOptions as r, startPajaServer as s, type PajaSimulation as t, PajaSimulationError as u, type PajaSimulationRawOptions as v, waitForTargetUrl as w, type PajaTargetMode as x, type ReadinessFetch as y, createPajaHostConfig as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kehto/paja",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Paja local authoring workshop for hosting napplets in a real Kehto iframe during development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -25,22 +25,22 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@kehto/acl": "^0.15.
|
|
29
|
-
"@kehto/firewall": "^0.3.
|
|
30
|
-
"@kehto/nip": "^0.4.
|
|
31
|
-
"@kehto/runtime": "^0.18.
|
|
32
|
-
"@kehto/services": "^0.
|
|
33
|
-
"@kehto/shell": "^0.
|
|
34
|
-
"@kehto/wm": "^0.0.
|
|
28
|
+
"@kehto/acl": "^0.15.6",
|
|
29
|
+
"@kehto/firewall": "^0.3.9",
|
|
30
|
+
"@kehto/nip": "^0.4.2",
|
|
31
|
+
"@kehto/runtime": "^0.18.5",
|
|
32
|
+
"@kehto/services": "^0.16.5",
|
|
33
|
+
"@kehto/shell": "^0.17.2",
|
|
34
|
+
"@kehto/wm": "^0.0.2"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
|
-
"@napplet/core": ">=0.23.0
|
|
38
|
-
"@napplet/nap": ">=0.23.0
|
|
39
|
-
"nostr-tools": ">=2.23.3
|
|
37
|
+
"@napplet/core": ">=0.23.0 <=0.28.x",
|
|
38
|
+
"@napplet/nap": ">=0.23.0 <=0.28.x",
|
|
39
|
+
"nostr-tools": ">=2.23.3 <=2.x"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@napplet/core": ">=0.23.0
|
|
43
|
-
"@napplet/nap": ">=0.23.0
|
|
42
|
+
"@napplet/core": ">=0.23.0 <=0.28.x",
|
|
43
|
+
"@napplet/nap": ">=0.23.0 <=0.28.x",
|
|
44
44
|
"nostr-tools": "^2.23.3",
|
|
45
45
|
"tsup": "^8.5.0",
|
|
46
46
|
"typescript": "^5.9.3",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config-file.ts","../src/simulation.ts","../src/options.ts","../src/host-page.ts","../src/runtime-resolver.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 | 'count'\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 'count',\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 if (!domains.relay) domains.count = 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 type PajaTargetMode = 'iframe-url' | 'runtime-pointer';\nexport type PajaHmrStrategy = 'iframe-target-url' | 'none';\n\nexport interface PajaPointerRuntimeConfig {\n readonly value?: string;\n readonly relays: readonly string[];\n readonly blossomServers: readonly string[];\n readonly maxWaitMs: number;\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 mode: PajaTargetMode;\n readonly url: string;\n readonly hmrStrategy: PajaHmrStrategy;\n readonly command?: PajaCommand;\n readonly pointer?: PajaPointerRuntimeConfig;\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';\nexport const DEFAULT_PAJA_RUNTIME_WAIT_MS = 5_000;\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 const base = createPajaHostConfigBase(options.simulation);\n return {\n ...base,\n target: {\n mode: 'iframe-url',\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 };\n}\n\nexport function createPajaRuntimeHostConfig(\n options: {\n readonly pointer?: string;\n readonly relays?: readonly string[];\n readonly blossomServers?: readonly string[];\n readonly maxWaitMs?: number;\n } = {},\n now: Date = new Date(),\n): PajaHostConfig {\n const base = createPajaHostConfigBase(normalizePajaSimulation({}));\n return {\n ...base,\n target: {\n mode: 'runtime-pointer',\n url: 'about:blank',\n hmrStrategy: 'none',\n pointer: {\n ...(options.pointer ? { value: options.pointer } : {}),\n relays: [...(options.relays ?? [])],\n blossomServers: [...(options.blossomServers ?? [])],\n maxWaitMs: normalizePositiveInteger(\n options.maxWaitMs ?? DEFAULT_PAJA_RUNTIME_WAIT_MS,\n 'runtime-wait',\n ),\n },\n },\n runtime: {\n host: 'static',\n port: 0,\n readyTimeoutMs: 1,\n reloadToken: createReloadToken(now),\n createdAt: now.toISOString(),\n },\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 createPajaHostConfigBase(simulation: PajaSimulation): Pick<PajaHostConfig, 'version' | 'window' | 'chrome' | 'simulation'> {\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 chrome: {\n topBar: true,\n bottomBar: true,\n sidePanels: false,\n },\n simulation,\n };\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 targetLabel = escapeAttribute(getTargetLabel(config));\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 .pointer-controls { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px; }\n .pointer-status { min-width: 0; color: var(--muted); font-size: 12px; overflow-wrap: anywhere; }\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=\"${targetLabel}\">${targetLabel}</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 ${renderPointerControls(config)}\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 ${config.target.mode === 'runtime-pointer' ? 'runtime' : 'development'} target\" sandbox=\"allow-scripts\" data-target-url=\"${targetLabel}\"></iframe>\n </section>\n </main>\n <footer class=\"bar bottom\">\n <span>mode: <code>${escapeHtml(getModeLabel(config))}</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 renderPointerControls(config: PajaHostConfig): string {\n if (config.target.mode !== 'runtime-pointer') return '';\n const value = escapeAttribute(config.target.pointer?.value ?? '');\n return `<section class=\"section\" id=\"runtime-pointer-section\">\n <div class=\"section-title\">Pointer</div>\n <form class=\"pointer-controls\" id=\"runtime-pointer-form\">\n <input id=\"runtime-pointer-input\" type=\"text\" inputmode=\"url\" autocomplete=\"off\" spellcheck=\"false\" placeholder=\"naddr or nevent\" aria-label=\"Runtime napplet pointer\" value=\"${value}\">\n <button type=\"submit\" id=\"runtime-pointer-load\">Load</button>\n </form>\n <div class=\"pointer-status\" id=\"runtime-pointer-status\" aria-live=\"polite\">idle</div>\n </section>`;\n}\n\nfunction getModeLabel(config: PajaHostConfig): string {\n if (config.target.mode === 'runtime-pointer') return 'runtime-pointer';\n return config.target.command ? 'managed-command' : 'external-target';\n}\n\nfunction getTargetLabel(config: PajaHostConfig): string {\n if (config.target.mode === 'runtime-pointer') {\n return config.target.pointer?.value ?? 'runtime pointer';\n }\n return config.target.url;\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 { NostrEvent } from 'nostr-tools';\nimport type { Filter } from 'nostr-tools/filter';\nimport { SimplePool } from 'nostr-tools/pool';\nimport { decode } from 'nostr-tools/nip19';\nimport {\n fetchBlob,\n openNappletArtifactCache,\n resolveNapplet,\n type ResolvedNapplet,\n} from '@kehto/nip/5d';\n\nexport const PAJA_NAPPLET_MANIFEST_KIND = 35129;\n\nexport type PajaDecodedPointer =\n | {\n readonly type: 'naddr';\n readonly value: string;\n readonly identifier: string;\n readonly pubkey: string;\n readonly kind: number;\n readonly relays: readonly string[];\n }\n | {\n readonly type: 'nevent';\n readonly value: string;\n readonly id: string;\n readonly author?: string;\n readonly kind?: number;\n readonly relays: readonly string[];\n };\n\nexport interface PajaResolvedPointer {\n readonly pointer: PajaDecodedPointer;\n readonly event: NostrEvent;\n readonly relays: readonly string[];\n readonly blossomServers: readonly string[];\n readonly dTag: string;\n readonly aggregateHash: string;\n readonly indexHtml: string;\n readonly manifest: ResolvedNapplet['manifest'];\n}\n\nexport interface PajaPointerRelayPool {\n querySync(\n relays: string[],\n filter: Filter,\n params?: { readonly maxWait?: number; readonly label?: string; readonly id?: string },\n ): Promise<NostrEvent[]>;\n close?(relays: string[]): void;\n destroy?(): void;\n}\n\nexport interface ResolvePajaPointerOptions {\n readonly pool?: PajaPointerRelayPool;\n readonly fetcher?: (url: string) => Promise<Response>;\n readonly relays?: readonly string[];\n readonly blossomServers?: readonly string[];\n readonly maxWaitMs?: number;\n}\n\nexport function decodePajaPointer(value: string): PajaDecodedPointer {\n const trimmed = value.trim();\n const decoded = decode(trimmed);\n if (decoded.type === 'naddr') {\n return {\n type: 'naddr',\n value: trimmed,\n identifier: decoded.data.identifier,\n pubkey: decoded.data.pubkey,\n kind: decoded.data.kind,\n relays: [...(decoded.data.relays ?? [])],\n };\n }\n if (decoded.type === 'nevent') {\n return {\n type: 'nevent',\n value: trimmed,\n id: decoded.data.id,\n ...(decoded.data.author ? { author: decoded.data.author } : {}),\n ...(decoded.data.kind ? { kind: decoded.data.kind } : {}),\n relays: [...(decoded.data.relays ?? [])],\n };\n }\n throw new Error(`Expected naddr or nevent pointer, got ${decoded.type}.`);\n}\n\nexport async function resolvePajaPointer(\n value: string,\n options: ResolvePajaPointerOptions = {},\n): Promise<PajaResolvedPointer> {\n const pointer = decodePajaPointer(value);\n const relays = uniqueRelayUrls([...pointer.relays, ...(options.relays ?? [])]);\n if (relays.length === 0) {\n throw new Error('Pointer does not include relay hints; add a relay-bearing naddr or nevent.');\n }\n\n const pool = options.pool ?? new SimplePool();\n const ownsPool = options.pool === undefined;\n try {\n const event = await resolvePointerEvent(pointer, pool, relays, options.maxWaitMs ?? 5_000);\n const blossomServers = [...(options.blossomServers ?? [])];\n const resolved = await resolveNapplet({\n event,\n cache: await openNappletArtifactCache({ requireStorageEstimate: false }),\n fetchBlob: (sha256Hex, servers) =>\n fetchBlob([...servers, ...blossomServers], sha256Hex, async (url) => {\n const response = await (options.fetcher ?? fetch)(url);\n if (!response.ok) throw new Error(`[paja-runtime] blob ${url}: ${response.status}`);\n return new Uint8Array(await response.arrayBuffer());\n }),\n });\n return {\n pointer,\n event,\n relays,\n blossomServers,\n dTag: resolved.dTag,\n aggregateHash: resolved.aggregateHash,\n indexHtml: resolved.indexHtml,\n manifest: resolved.manifest,\n };\n } finally {\n if (ownsPool) {\n pool.close?.(relays);\n pool.destroy?.();\n }\n }\n}\n\nexport function injectPajaRuntimeCsp(html: string, origins: readonly string[]): string {\n const value = origins.length > 0\n ? `connect-src ${[...new Set(origins)].sort().join(' ')}`\n : \"connect-src 'none'\";\n const meta = `<meta http-equiv=\"Content-Security-Policy\" content=\"${escapeAttribute(value)}\">`;\n if (/<head[^>]*>/i.test(html)) {\n return html.replace(/<head[^>]*>/i, (open) => `${open}${meta}`);\n }\n if (/<html[^>]*>/i.test(html)) {\n return html.replace(/<html[^>]*>/i, (open) => `${open}<head>${meta}</head>`);\n }\n return `${meta}${html}`;\n}\n\nasync function resolvePointerEvent(\n pointer: PajaDecodedPointer,\n pool: PajaPointerRelayPool,\n relays: readonly string[],\n maxWaitMs: number,\n): Promise<NostrEvent> {\n const filter = pointer.type === 'naddr'\n ? addressableFilter(pointer)\n : eventFilter(pointer);\n const events = await pool.querySync([...relays], filter, {\n maxWait: maxWaitMs,\n label: 'kehto-paja-runtime',\n });\n const event = events\n .filter((candidate) => matchesPointer(pointer, candidate))\n .sort((a, b) => b.created_at - a.created_at)[0];\n if (!event) {\n throw new Error(`No napplet manifest event found for ${pointer.type} pointer.`);\n }\n if (event.kind !== PAJA_NAPPLET_MANIFEST_KIND) {\n throw new Error(`Pointer resolved kind ${event.kind}; expected ${PAJA_NAPPLET_MANIFEST_KIND}.`);\n }\n return event;\n}\n\nfunction addressableFilter(pointer: Extract<PajaDecodedPointer, { type: 'naddr' }>): Filter {\n if (pointer.kind !== PAJA_NAPPLET_MANIFEST_KIND) {\n throw new Error(`naddr kind ${pointer.kind} is not a napplet manifest kind.`);\n }\n return {\n kinds: [PAJA_NAPPLET_MANIFEST_KIND],\n authors: [pointer.pubkey],\n '#d': [pointer.identifier],\n limit: 1,\n };\n}\n\nfunction eventFilter(pointer: Extract<PajaDecodedPointer, { type: 'nevent' }>): Filter {\n return {\n ids: [pointer.id],\n ...(pointer.kind ? { kinds: [pointer.kind] } : {}),\n ...(pointer.author ? { authors: [pointer.author] } : {}),\n limit: 1,\n };\n}\n\nfunction matchesPointer(pointer: PajaDecodedPointer, event: NostrEvent): boolean {\n if (pointer.type === 'nevent') {\n if (event.id !== pointer.id) return false;\n if (pointer.author && event.pubkey !== pointer.author) return false;\n if (pointer.kind && event.kind !== pointer.kind) return false;\n return true;\n }\n return event.kind === pointer.kind\n && event.pubkey === pointer.pubkey\n && event.tags.some((tag) => tag[0] === 'd' && tag[1] === pointer.identifier);\n}\n\nfunction uniqueRelayUrls(values: readonly string[]): string[] {\n const out: string[] = [];\n const seen = new Set<string>();\n for (const value of values) {\n const url = normalizeRelayUrl(value);\n if (!url || seen.has(url)) continue;\n seen.add(url);\n out.push(url);\n }\n return out;\n}\n\nfunction normalizeRelayUrl(value: string): string | undefined {\n const raw = value.trim();\n if (!raw) return undefined;\n try {\n const url = new URL(raw);\n if (url.protocol !== 'wss:' && url.protocol !== 'ws:') return undefined;\n url.hash = '';\n url.search = '';\n return url.href.replace(/\\/$/, '');\n } catch {\n return undefined;\n }\n}\n\nfunction escapeAttribute(value: string): string {\n return value\n .replaceAll('&', '&')\n .replaceAll('\"', '"')\n .replaceAll('<', '<')\n .replaceAll('>', '>');\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 'count',\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 'count',\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 'count',\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":["escapeAttribute","resolve","readFileSync","readFileSync","resolve"]}
|