@kehto/paja 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -3,9 +3,9 @@ export { D as DEFAULT_PAJA_AGGREGATE_HASH, c as DEFAULT_PAJA_DTAG, d as DEFAULT_
3
3
  import { NostrEvent } from 'nostr-tools';
4
4
  import { Filter } from 'nostr-tools/filter';
5
5
  import { ResolvedNapplet } from '@kehto/nip/5d';
6
- import { ShellCapabilities } from '@kehto/shell';
6
+ import { ShellCapabilities, NormalizedIntentUri } from '@kehto/shell';
7
7
  export { NappletCspDirective, NappletCspDirectives, NappletCspOptions } from '@kehto/shell';
8
- import { IntentCatalogEntry, IntentTargetController, IntentDispatchParams, IntentTargetDispatch } from '@kehto/services';
8
+ import { IntentCatalogEntry, IntentTargetController, IntentDispatchParams, IntentTargetAcceptance } from '@kehto/services';
9
9
 
10
10
  /**
11
11
  * Load a JSON Paja config file from disk.
@@ -297,7 +297,9 @@ declare function findRelativeAssetReferences(html: string): string[];
297
297
 
298
298
  /** Serializable verified pointer and manifest facts for one installed napplet. */
299
299
  interface InstalledNappletRecord {
300
- /** Verified manifest d-tag used as the handler identity. */
300
+ /** Publisher/kind-safe verified catalog identity used as the handler identity. */
301
+ readonly id: string;
302
+ /** Literal manifest d-tag retained only as artifact metadata. */
301
303
  readonly dTag: string;
302
304
  /** Verified NIP-5A aggregate hash for the installed artifact. */
303
305
  readonly aggregateHash: string;
@@ -313,10 +315,11 @@ interface InstalledNappletRecord {
313
315
  readonly archetypes: readonly {
314
316
  readonly slug: string;
315
317
  readonly convention: string;
318
+ readonly params: readonly string[];
316
319
  }[];
317
320
  }
318
321
  /** Listener notified when an installed artifact is inserted or removed. */
319
- type InstalledNappletCatalogListener = (dTag: string) => void;
322
+ type InstalledNappletCatalogListener = (id: string) => void;
320
323
  /**
321
324
  * Stores verified Paja installations separately from the browser runtime.
322
325
  *
@@ -333,19 +336,19 @@ declare class InstalledNappletCatalog {
333
336
  /** Insert or replace a record from an already resolver-verified pointer. */
334
337
  install(resolved: PajaResolvedPointer): InstalledNappletRecord;
335
338
  /** Remove an artifact explicitly; frame teardown never calls this method. */
336
- remove(dTag: string): boolean;
337
- /** Return whether a verified installation exists for a d-tag. */
338
- has(dTag: string): boolean;
339
+ remove(id: string): boolean;
340
+ /** Return whether a verified installation exists for a catalog ID. */
341
+ has(id: string): boolean;
339
342
  /** Return immutable serializable installed-artifact facts. */
340
343
  installed(): readonly InstalledNappletRecord[];
341
- /** Return a verified record by d-tag. */
342
- get(dTag: string): InstalledNappletRecord | undefined;
344
+ /** Return a verified record by catalog ID. */
345
+ get(id: string): InstalledNappletRecord | undefined;
343
346
  /**
344
347
  * Atomically confirm that a resolved target still belongs to the exact record
345
348
  * selected before an async operation. The record object is the catalog version
346
349
  * token, so even a same-identity replacement cannot pass this check.
347
350
  */
348
- validateCurrent(selected: InstalledNappletRecord, target: Pick<InstalledNappletRecord, 'dTag' | 'aggregateHash'>): InstalledNappletRecord | null;
351
+ validateCurrent(selected: InstalledNappletRecord, target: Pick<InstalledNappletRecord, 'id' | 'aggregateHash'>): InstalledNappletRecord | null;
349
352
  /**
350
353
  * Return declared handlers whose host environment can receive intent delivery.
351
354
  * @param canReceiveIntent - Resolve intent availability for each verified identity;
@@ -384,14 +387,18 @@ interface BrowserIntentControllerOptions {
384
387
  waitForReady(generation: BrowserIntentGeneration): void | Promise<void>;
385
388
  /** Return true only while the generation remains the selected current target. */
386
389
  isCurrent(generation: BrowserIntentGeneration): boolean | Promise<boolean>;
387
- /** Return the runtime-assigned window identifier once the target is ready. */
388
- getWindowId(generation: BrowserIntentGeneration): string | null;
390
+ /** Deprecated target identity probe retained for adapter test compatibility. */
391
+ getWindowId?(generation: BrowserIntentGeneration): string | null;
389
392
  /** Send the convention through the ordinary carrier to the ready generation. */
390
393
  send(generation: BrowserIntentGeneration, params: IntentDispatchParams): void | Promise<void>;
391
394
  /** Maximum open/replacement attempts. Finite values clamp to 1–10; defaults to two. */
392
395
  maxAttempts?: number;
393
396
  /** Observe terminal target policy. */
394
397
  onTerminal?(params: IntentDispatchParams, reason: BrowserIntentTerminalReason): void;
398
+ /** Observe successful terminal delivery without adding a second source result. */
399
+ onDelivered?(params: IntentDispatchParams): void;
400
+ /** Observe retained target work before its asynchronous completion can race. */
401
+ onAccepted?(params: IntentDispatchParams, acceptance: IntentTargetAcceptance): void;
395
402
  }
396
403
  /**
397
404
  * Creates/focuses a target and enqueues one convention delivery.
@@ -400,8 +407,75 @@ declare class BrowserIntentController implements IntentTargetController {
400
407
  private readonly options;
401
408
  private readonly maxAttempts;
402
409
  constructor(options: BrowserIntentControllerOptions);
403
- dispatch(params: IntentDispatchParams): Promise<IntentTargetDispatch>;
410
+ /** Retain delivery work immediately; completion remains host-observable only. */
411
+ accept(params: IntentDispatchParams): IntentTargetAcceptance;
412
+ /** Complete an already accepted delivery. Kept public for host diagnostics and tests. */
413
+ dispatch(params: IntentDispatchParams): Promise<void>;
414
+ }
415
+
416
+ /** Input used to create a Paja intent deep link. */
417
+ interface PajaIntentLinkDescriptor {
418
+ /** Complete convention URI, including its own query or recommendation fragment. */
419
+ readonly uri: string;
420
+ /** Optional Paja target pointer. */
421
+ readonly pointer?: string;
422
+ /** Explicit JSON payload kept outside the convention URI. */
423
+ readonly payload?: unknown;
424
+ }
425
+ /** A validated Paja intent deep link. */
426
+ interface ParsedPajaIntentLink extends PajaIntentLinkDescriptor {
427
+ /** Canonical request produced from the URI and optional explicit payload. */
428
+ readonly request: NormalizedIntentUri;
429
+ }
430
+ /**
431
+ * Parse a Paja intent deep link without invoking it.
432
+ *
433
+ * Pointer-only links intentionally return `null` so existing runtime-pointer
434
+ * startup remains unchanged.
435
+ *
436
+ * @param href - Browser location to inspect.
437
+ * @returns A validated descriptor, or `null` when no intent parameter exists.
438
+ * @example
439
+ * ```ts
440
+ * parsePajaIntentLink('https://paja.example/?intent=napplet%3Anote%2Fopen');
441
+ * ```
442
+ */
443
+ declare function parsePajaIntentLink(href: string): ParsedPajaIntentLink | null;
444
+ /**
445
+ * Create a canonical Paja intent deep link without invoking it.
446
+ *
447
+ * @param descriptor - Convention URI, optional pointer, and optional JSON payload.
448
+ * @param href - Absolute Paja URL to use as the link base.
449
+ * @returns A canonical intent URL.
450
+ * @example
451
+ * ```ts
452
+ * createPajaIntentLink({ uri: 'napplet:note/open' }, 'https://paja.example/');
453
+ * ```
454
+ */
455
+ declare function createPajaIntentLink(descriptor: PajaIntentLinkDescriptor, href: string): string;
456
+
457
+ /**
458
+ * Verified, ephemeral source for Paja deep-link intent invocation.
459
+ *
460
+ * The launcher event and artifact are static publish-time data. The signing key
461
+ * used to create the event is deliberately not present in this repository; a
462
+ * link's URI and payload travel only over the parent-bound launcher channel.
463
+ */
464
+
465
+ /** One parent-to-launcher message; it is deliberately outside signed artifact bytes. */
466
+ interface PajaIntentLauncherMessage {
467
+ readonly type: 'paja.intent.launch';
468
+ readonly correlation: string;
469
+ readonly uri: string;
470
+ readonly options?: {
471
+ readonly payload?: unknown;
472
+ readonly handler?: string;
473
+ };
404
474
  }
475
+ /** Verify the bundled signed manifest and content-addressed launcher bytes. */
476
+ declare function resolvePajaIntentLauncher(): Promise<PajaResolvedPointer>;
477
+ /** Send a reviewed URI only to the frame registered for this launcher generation. */
478
+ declare function postPajaIntentLauncherMessage(frame: Pick<HTMLIFrameElement, 'contentWindow'>, message: PajaIntentLauncherMessage): void;
405
479
 
406
480
  /**
407
481
  * Target dev-server CORS diagnostics.
@@ -471,4 +545,4 @@ type PajaTargetCorsFetch = (input: string, init: {
471
545
  */
472
546
  declare function probeTargetCors(targetUrl: string, fetchImpl?: PajaTargetCorsFetch): Promise<PajaTargetCorsDiagnostic>;
473
547
 
474
- export { BrowserIntentController, type BrowserIntentControllerOptions, type BrowserIntentGeneration, type BrowserIntentTerminalReason, InstalledNappletCatalog, type InstalledNappletCatalogListener, type InstalledNappletRecord, PAJA_ADVERTISED_DOMAINS, PAJA_COMPATIBILITY_ALIASES, PAJA_HANDSHAKE_DOMAINS, PAJA_LOCAL_SINGLE_FILE_HINT, PAJA_NAPPLET_MANIFEST_KIND, PAJA_NAPPLET_MANIFEST_KINDS, PAJA_REQUIRED_SERVICES, PAJA_TARGET_CORS_HINT, PAJA_UPSTREAM_WEB_DOMAINS, type PajaDecodedPointer, PajaHostConfig, type PajaLocalFileInput, type PajaLocalTarget, type PajaPointerRelayPool, PajaRawOptions, type PajaResolvedPointer, type PajaRuntimeTarget, type PajaTargetCorsDiagnostic, type PajaTargetCorsFetch, type PajaTargetCorsStatus, type ResolvePajaPointerOptions, classifyTargetCors, createPajaLocalTarget, decodePajaPointer, findRelativeAssetReferences, getMissingAdvertisedDomains, getMissingServices, injectPajaRuntimeCsp, isPajaLocalHtmlFile, isPajaLocalTarget, loadPajaConfigFile, mergePajaRawOptions, probeTargetCors, readNappletIdMeta, renderPajaHtml, resolvePajaPointer, resolvePajaRawOptions };
548
+ export { BrowserIntentController, type BrowserIntentControllerOptions, type BrowserIntentGeneration, type BrowserIntentTerminalReason, InstalledNappletCatalog, type InstalledNappletCatalogListener, type InstalledNappletRecord, PAJA_ADVERTISED_DOMAINS, PAJA_COMPATIBILITY_ALIASES, PAJA_HANDSHAKE_DOMAINS, PAJA_LOCAL_SINGLE_FILE_HINT, PAJA_NAPPLET_MANIFEST_KIND, PAJA_NAPPLET_MANIFEST_KINDS, PAJA_REQUIRED_SERVICES, PAJA_TARGET_CORS_HINT, PAJA_UPSTREAM_WEB_DOMAINS, type PajaDecodedPointer, PajaHostConfig, type PajaIntentLauncherMessage, type PajaIntentLinkDescriptor, type PajaLocalFileInput, type PajaLocalTarget, type PajaPointerRelayPool, PajaRawOptions, type PajaResolvedPointer, type PajaRuntimeTarget, type PajaTargetCorsDiagnostic, type PajaTargetCorsFetch, type PajaTargetCorsStatus, type ParsedPajaIntentLink, type ResolvePajaPointerOptions, classifyTargetCors, createPajaIntentLink, createPajaLocalTarget, decodePajaPointer, findRelativeAssetReferences, getMissingAdvertisedDomains, getMissingServices, injectPajaRuntimeCsp, isPajaLocalHtmlFile, isPajaLocalTarget, loadPajaConfigFile, mergePajaRawOptions, parsePajaIntentLink, postPajaIntentLauncherMessage, probeTargetCors, readNappletIdMeta, renderPajaHtml, resolvePajaIntentLauncher, resolvePajaPointer, resolvePajaRawOptions };
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  ReadinessError,
24
24
  classifyTargetCors,
25
25
  createPajaHostConfig,
26
+ createPajaIntentLink,
26
27
  createPajaLocalTarget,
27
28
  createPajaRuntimeHostConfig,
28
29
  decodePajaPointer,
@@ -37,15 +38,18 @@ import {
37
38
  mergePajaRawOptions,
38
39
  normalizePajaOptions,
39
40
  normalizePajaSimulation,
41
+ parsePajaIntentLink,
42
+ postPajaIntentLauncherMessage,
40
43
  probeTargetCors,
41
44
  readNappletIdMeta,
42
45
  renderPajaHtml,
46
+ resolvePajaIntentLauncher,
43
47
  resolvePajaPointer,
44
48
  resolvePajaRawOptions,
45
49
  startPajaServer,
46
50
  summarizePajaSimulation,
47
51
  waitForTargetUrl
48
- } from "./chunk-GY5ET3PC.js";
52
+ } from "./chunk-6WEO5D3Z.js";
49
53
  export {
50
54
  BrowserIntentController,
51
55
  DEFAULT_PAJA_AGGREGATE_HASH,
@@ -71,6 +75,7 @@ export {
71
75
  ReadinessError,
72
76
  classifyTargetCors,
73
77
  createPajaHostConfig,
78
+ createPajaIntentLink,
74
79
  createPajaLocalTarget,
75
80
  createPajaRuntimeHostConfig,
76
81
  decodePajaPointer,
@@ -85,9 +90,12 @@ export {
85
90
  mergePajaRawOptions,
86
91
  normalizePajaOptions,
87
92
  normalizePajaSimulation,
93
+ parsePajaIntentLink,
94
+ postPajaIntentLauncherMessage,
88
95
  probeTargetCors,
89
96
  readNappletIdMeta,
90
97
  renderPajaHtml,
98
+ resolvePajaIntentLauncher,
91
99
  resolvePajaPointer,
92
100
  resolvePajaRawOptions,
93
101
  startPajaServer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kehto/paja",
3
- "version": "0.19.0",
3
+ "version": "0.20.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,13 +25,13 @@
25
25
  "access": "public"
26
26
  },
27
27
  "dependencies": {
28
- "@kehto/acl": "^0.19.0",
29
- "@kehto/nip": "^0.6.0",
30
28
  "@kehto/firewall": "^0.6.0",
29
+ "@kehto/acl": "^0.19.0",
30
+ "@kehto/nip": "^0.7.0",
31
31
  "@kehto/runtime": "^0.24.0",
32
- "@kehto/services": "^0.22.1",
33
- "@kehto/wm": "^0.0.2",
34
- "@kehto/shell": "^0.22.0"
32
+ "@kehto/services": "^0.23.0",
33
+ "@kehto/shell": "^0.23.0",
34
+ "@kehto/wm": "^0.0.2"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@napplet/core": ">=0.32.0 <0.33.0",