@metapages/metapage 1.10.0 → 1.10.2

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.
Files changed (39) hide show
  1. package/README.md +187 -15
  2. package/dist/index.js +2425 -2222
  3. package/dist/index.js.map +1 -1
  4. package/dist/metapage/Metapage.d.ts +43 -3
  5. package/dist/metapage/Metapage.d.ts.map +1 -1
  6. package/dist/metapage/MetapageTools.d.ts +3 -3
  7. package/dist/metapage/MetapageTools.d.ts.map +1 -1
  8. package/dist/metapage/Shared.d.ts +2 -2
  9. package/dist/metapage/Shared.d.ts.map +1 -1
  10. package/dist/metapage/conversions-metaframe.d.ts +1 -1
  11. package/dist/metapage/conversions-metaframe.d.ts.map +1 -1
  12. package/dist/metapage/conversions-metapage.d.ts +1 -1
  13. package/dist/metapage/conversions-metapage.d.ts.map +1 -1
  14. package/dist/metapage/data.d.ts.map +1 -1
  15. package/dist/metapage/events.d.ts +17 -2
  16. package/dist/metapage/events.d.ts.map +1 -1
  17. package/dist/metapage/metapageRenderer.d.ts +4 -4
  18. package/dist/metapage/metapageRenderer.d.ts.map +1 -1
  19. package/dist/metapage/util.d.ts +4 -4
  20. package/dist/metapage/util.d.ts.map +1 -1
  21. package/dist/metapage/v1/metapage.d.ts +1 -0
  22. package/dist/metapage/v1/metapage.d.ts.map +1 -1
  23. package/dist/metapage/v2/metaframe.d.ts +2 -2
  24. package/dist/metapage/v2/metaframe.d.ts.map +1 -1
  25. package/dist/metapage/v2/metapage.d.ts +2 -2
  26. package/dist/metapage/v2/metapage.d.ts.map +1 -1
  27. package/package.json +5 -5
  28. package/src/metapage/Metapage.ts +519 -25
  29. package/src/metapage/MetapageTools.ts +13 -12
  30. package/src/metapage/Shared.ts +2 -2
  31. package/src/metapage/conversions-metaframe.ts +4 -1
  32. package/src/metapage/conversions-metapage.ts +4 -1
  33. package/src/metapage/data.ts +13 -5
  34. package/src/metapage/events.ts +13 -2
  35. package/src/metapage/metapageRenderer.ts +7 -9
  36. package/src/metapage/util.ts +5 -7
  37. package/src/metapage/v1/metapage.ts +1 -0
  38. package/src/metapage/v2/metaframe.ts +2 -2
  39. package/src/metapage/v2/metapage.ts +2 -2
package/README.md CHANGED
@@ -36,7 +36,7 @@ import {
36
36
  renderMetapage,
37
37
  Metapage,
38
38
  Metaframe,
39
- } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
39
+ } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.10.2";
40
40
  ```
41
41
 
42
42
  ## Quick Start
@@ -82,7 +82,7 @@ The `renderMetapage` function the `react-grid-layout` layout in `metapage.json`:
82
82
  If you're building a component to use in a metapage:
83
83
 
84
84
  ```javascript
85
- import { Metaframe } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
85
+ import { Metaframe } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.10.2";
86
86
 
87
87
  const metaframe = new Metaframe();
88
88
 
@@ -107,7 +107,6 @@ A metapage is defined using JSON that specifies which metaframes to load and how
107
107
 
108
108
  ```javascript
109
109
  {
110
- "version": "2",
111
110
  "metaframes": {
112
111
  "input": {
113
112
  "url": "https://editor.mtfm.io/#?hm=disabled"
@@ -149,8 +148,7 @@ This is provided either by:
149
148
  The definition describes inputs, outputs, security, and the types of hash parameters (so AI tools can correctly modify)
150
149
 
151
150
  ```typescript
152
- export interface MetaframeDefinitionV2 {
153
- version: VersionsMetaframe;
151
+ export interface MetaframeDefinition {
154
152
  inputs?: {
155
153
  [key: string]: MetaframePipeDefinition;
156
154
  }; // <MetaframePipeId, MetaframePipeDefinition>
@@ -225,7 +223,7 @@ metaframe.onInput("file", (file) => {
225
223
  <div id="metapage-container"></div>
226
224
 
227
225
  <script type="module">
228
- import { renderMetapage } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
226
+ import { renderMetapage } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.10.2";
229
227
 
230
228
  const definition = await fetch(
231
229
  "https://metapage.io/m/87ae11673508447e883b598bf7da9c5d/metapage.json",
@@ -260,7 +258,7 @@ metaframe.onInput("file", (file) => {
260
258
  ### Building a Metaframe Component
261
259
 
262
260
  ```javascript
263
- import { Metaframe } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
261
+ import { Metaframe } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.10.2";
264
262
 
265
263
  const metaframe = new Metaframe();
266
264
 
@@ -300,7 +298,6 @@ import { Metapage } from "@metapages/metapage";
300
298
 
301
299
  const metapage = new Metapage({
302
300
  definition: {
303
- version: "2",
304
301
  metaframes: {
305
302
  viewer: {
306
303
  url: "https://markdown.mtfm.io/",
@@ -338,7 +335,7 @@ Metaframes can read and write to their URL hash parameters:
338
335
  import {
339
336
  getHashParamValueJsonFromWindow,
340
337
  setHashParamValueJsonInWindow,
341
- } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
338
+ } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.10.2";
342
339
 
343
340
  // Read from URL hash
344
341
  const config = getHashParamValueJsonFromWindow("config");
@@ -378,6 +375,177 @@ metaframe.onInput("image", async (data) => {
378
375
  });
379
376
  ```
380
377
 
378
+ ## Secrets
379
+
380
+ Inject sensitive credentials (API keys, tokens, etc.) into metaframe URLs at runtime while ensuring they are never exposed when retrieving the metapage definition.
381
+
382
+ ### API
383
+
384
+ ```typescript
385
+ import { Metapage, InjectSecretsPayload } from "@metapages/metapage";
386
+
387
+ const metapage = new Metapage();
388
+ await metapage.setDefinition(definition);
389
+
390
+ const secrets: InjectSecretsPayload = {
391
+ frameSecrets: {
392
+ myMetaframe: {
393
+ hashParams: {
394
+ apiKey: "sk-abc123",
395
+ token: "secret-token",
396
+ },
397
+ queryParams: {
398
+ auth: "bearer-token",
399
+ },
400
+ },
401
+ },
402
+ };
403
+
404
+ metapage.injectSecrets(secrets);
405
+ ```
406
+
407
+ ### Type Definition
408
+
409
+ ```typescript
410
+ type InjectSecretsPayload = {
411
+ frameSecrets: {
412
+ [metaframeName: string]: {
413
+ hashParams?: { [name: string]: string };
414
+ queryParams?: { [name: string]: string };
415
+ };
416
+ };
417
+ };
418
+ ```
419
+
420
+ ### Behavior
421
+
422
+ - **Injection**: Secrets are base64-encoded into metaframe URL hash/query parameters using `setHashParamValueBase64EncodedInUrl` from `@metapages/hash-query`
423
+ - **Accumulation**: Multiple calls to `injectSecrets()` accumulate secrets rather than replacing previous ones
424
+ - **Safe removal**: `getDefinition()` and definition change events automatically strip secrets, restoring original parameter values
425
+ - **Persistence across updates**: Secrets survive `setDefinition()` calls — if a metaframe still exists in the new definition, its secrets are re-injected
426
+ - **Cleanup**: Secrets are removed when metaframes are removed via `removeMetaframe()` or `removeAll()`
427
+
428
+ ### Example
429
+
430
+ ```typescript
431
+ const metapage = new Metapage();
432
+ await metapage.setDefinition(definition);
433
+
434
+ // Inject a secret
435
+ metapage.injectSecrets({
436
+ frameSecrets: {
437
+ secret1test: {
438
+ hashParams: {
439
+ secret1: "injected secret",
440
+ },
441
+ },
442
+ },
443
+ });
444
+
445
+ // The metaframe iframe URL now contains the secret (base64-encoded in hash)
446
+ // But getDefinition() returns the original URL without secrets:
447
+ const def = metapage.getDefinition();
448
+ // def.metaframes.secret1test.url has NO secret params
449
+
450
+ // Definition events also exclude secrets:
451
+ metapage.on(Metapage.DEFINITION, (cleanDef) => {
452
+ // cleanDef has no secrets
453
+ });
454
+ ```
455
+
456
+ ### Security Notes
457
+
458
+ - Secrets are base64-encoded (not encrypted) in URLs
459
+ - Metaframe iframes receive secrets via their URL hash/query params at runtime
460
+ - Secrets are stripped from all definition retrieval methods and events
461
+ - Secret storage is cleared on `dispose()`
462
+
463
+ ## updateDefinition
464
+
465
+ `updateDefinition` is the preferred way to change the metapage definition at runtime when you need to react to what changed. Unlike `setDefinition`, it:
466
+
467
+ - Always emits a `DefinitionUpdate` event — even on the very first call
468
+ - Includes a structured diff of which metaframes were added and removed
469
+ - Automatically emits a `State` event when metaframes are added or removed
470
+
471
+ ### API
472
+
473
+ ```typescript
474
+ await metapage.updateDefinition(definition, state?);
475
+ ```
476
+
477
+ | Parameter | Type | Description |
478
+ | ------------ | -------------------------- | ------------------------------------------------------ |
479
+ | `definition` | `MetapageDefinition` | The new metapage definition |
480
+ | `state` | `MetapageState` (optional) | Initial state to apply alongside the definition update |
481
+
482
+ ### Event Payload
483
+
484
+ Listen with `Metapage.DEFINITION_UPDATE`. The event payload has this shape:
485
+
486
+ ```typescript
487
+ interface MetapageEventDefinitionUpdate {
488
+ definition: MetapageDefinition; // current definition (secrets stripped)
489
+ metaframes: {
490
+ current: { [id: string]: MetapageIFrameRpcClient }; // all metaframes after update
491
+ added: { [id: string]: MetapageIFrameRpcClient }; // metaframes that were added
492
+ removed: { [id: string]: MetapageIFrameRpcClient }; // metaframes that were removed (disposed)
493
+ };
494
+ }
495
+ ```
496
+
497
+ ### Example
498
+
499
+ ```typescript
500
+ import { Metapage, MetapageEventDefinitionUpdate } from "@metapages/metapage";
501
+
502
+ const metapage = new Metapage();
503
+
504
+ metapage.on(
505
+ Metapage.DEFINITION_UPDATE,
506
+ (event: MetapageEventDefinitionUpdate) => {
507
+ const { added, removed, current } = event.metaframes;
508
+
509
+ console.log("Current metaframes:", Object.keys(current));
510
+ console.log("Added:", Object.keys(added));
511
+ console.log("Removed:", Object.keys(removed));
512
+ },
513
+ );
514
+
515
+ // First call — fires immediately (unlike setDefinition)
516
+ await metapage.updateDefinition({
517
+ metaframes: {
518
+ viewer: { url: "https://markdown.mtfm.io/" },
519
+ },
520
+ });
521
+
522
+ // Second call — event reports frame2 in `added`
523
+ await metapage.updateDefinition({
524
+ metaframes: {
525
+ viewer: { url: "https://markdown.mtfm.io/" },
526
+ editor: { url: "https://editor.mtfm.io/" },
527
+ },
528
+ });
529
+ ```
530
+
531
+ ### Comparison with setDefinition
532
+
533
+ | Behaviour | `setDefinition` | `updateDefinition` |
534
+ | ----------------------------- | --------------- | ------------------ |
535
+ | Emits event on first call | No | Yes |
536
+ | Event type | `Definition` | `DefinitionUpdate` |
537
+ | Diff of added/removed frames | No | Yes |
538
+ | Emits `State` on frame change | No | Yes |
539
+
540
+ ### State event
541
+
542
+ `State` is automatically emitted (to any listeners) when:
543
+
544
+ - Metaframes are added or removed, OR
545
+ - An explicit `state` argument is passed and is non-empty
546
+
547
+ ---
548
+
381
549
  ## API Overview
382
550
 
383
551
  ### renderMetapage(options)
@@ -401,8 +569,11 @@ Render a metapage into a DOM element.
401
569
 
402
570
  **Methods:**
403
571
 
572
+ - `setDefinition(def, state?)`: Set the metapage definition; emits `Definition` on subsequent calls only
573
+ - `updateDefinition(def, state?)`: Set the definition and always emit `DefinitionUpdate` with added/removed diff (see [updateDefinition](#updatedefinition))
404
574
  - `setInputs(inputs)`: Set inputs for metaframes
405
575
  - `getState()`: Get current state (inputs/outputs)
576
+ - `injectSecrets(secrets)`: Inject secrets into metaframe URLs (see [Secrets](#secrets))
406
577
  - `dispose()`: Clean up and remove all listeners
407
578
  - `on(event, handler)`: Listen to events
408
579
 
@@ -410,7 +581,9 @@ Render a metapage into a DOM element.
410
581
 
411
582
  - `Metapage.OUTPUTS`: When metaframe outputs change
412
583
  - `Metapage.INPUTS`: When metapage inputs change
413
- - `Metapage.DEFINITION`: When definition changes
584
+ - `Metapage.DEFINITION`: When definition changes (not emitted on first `setDefinition` call)
585
+ - `Metapage.DEFINITION_UPDATE`: When `updateDefinition` is called; payload includes added/removed metaframe diff (see [updateDefinition](#updatedefinition))
586
+ - `Metapage.STATE`: When metapage state changes
414
587
 
415
588
  ### Metaframe Class
416
589
 
@@ -448,7 +621,7 @@ Example minimal metaframe:
448
621
  </head>
449
622
  <body>
450
623
  <script type="module">
451
- import { Metaframe } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
624
+ import { Metaframe } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.10.2";
452
625
 
453
626
  const metaframe = new Metaframe();
454
627
 
@@ -469,13 +642,12 @@ Full TypeScript definitions are included:
469
642
  import {
470
643
  Metapage,
471
644
  Metaframe,
472
- MetapageDefinitionV2,
645
+ MetapageDefinition,
473
646
  MetaframeInputMap,
474
647
  MetapageInstanceInputs,
475
- } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.8.35";
648
+ } from "https://cdn.jsdelivr.net/npm/@metapages/metapage@1.10.2";
476
649
 
477
- const definition: MetapageDefinitionV2 = {
478
- version: "2",
650
+ const definition: MetapageDefinition = {
479
651
  metaframes: {
480
652
  example: {
481
653
  url: "https://example.com",