@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.
@@ -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: string;
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
- type PajaCommand = {
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.6.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.1",
29
- "@kehto/firewall": "^0.3.6",
30
- "@kehto/nip": "^0.4.0",
31
- "@kehto/runtime": "^0.18.0",
32
- "@kehto/services": "^0.15.0",
33
- "@kehto/shell": "^0.16.2",
34
- "@kehto/wm": "^0.0.1"
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 <0.26.0",
38
- "@napplet/nap": ">=0.23.0 <0.26.0",
39
- "nostr-tools": ">=2.23.3 <3.0.0"
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 <0.26.0",
43
- "@napplet/nap": ">=0.23.0 <0.26.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('\"', '&quot;');\n}\n\nfunction escapeHtml(value: string): string {\n return value\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;');\n}\n\nfunction escapeJsonForHtml(value: string): string {\n return value.replaceAll('<', '\\\\u003c');\n}\n","import type { 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('&', '&amp;')\n .replaceAll('\"', '&quot;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;');\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"]}