vitral 0.2.0 → 0.3.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.
Files changed (53) hide show
  1. package/README.md +1 -1
  2. package/dist/angular.d.ts +3 -2
  3. package/dist/angular.js +7 -6
  4. package/dist/auto.js +7 -6
  5. package/dist/capture-JYFERAPL.js +42 -0
  6. package/dist/{chunk-6Y3VMWHH.js → chunk-3YXI3G34.js} +3 -3
  7. package/dist/{chunk-S5MZT5IT.js → chunk-AH7KNMBW.js} +1 -1
  8. package/dist/chunk-AKNNHQ2H.js +45 -0
  9. package/dist/{chunk-PX7PBCCT.js → chunk-GNHCZRQP.js} +7 -17
  10. package/dist/{chunk-NCONW6WS.js → chunk-I3VSKSAZ.js} +58 -30
  11. package/dist/{chunk-UTYAX6MU.js → chunk-IHTUM6LT.js} +2 -2
  12. package/dist/{chunk-HP6QWU6K.js → chunk-SDB5AZEI.js} +2 -2
  13. package/dist/{chunk-2XF5BKV3.js → chunk-TD4S3IHA.js} +23 -12
  14. package/dist/chunk-ZAC6QQI6.js +64 -0
  15. package/dist/cli.js +59 -9
  16. package/dist/contract-46EZFQPQ.js +17 -0
  17. package/dist/{dedupe-IWFIXRWG.js → dedupe-S7BHQMOZ.js} +4 -3
  18. package/dist/element.d.ts +3 -3
  19. package/dist/element.js +7 -6
  20. package/dist/{errors-KKB8FGCz.d.ts → errors-kjBv6IH_.d.ts} +7 -1
  21. package/dist/{events-DUdjhfps.d.ts → events-D5gs7rff.d.ts} +1 -1
  22. package/dist/expose-JUOUN5N5.js +15 -0
  23. package/dist/iframe.d.ts +1 -1
  24. package/dist/iframe.js +13 -10
  25. package/dist/index.d.ts +23 -21
  26. package/dist/index.js +5 -4
  27. package/dist/otel.d.ts +44 -0
  28. package/dist/otel.js +27 -0
  29. package/dist/preact.d.ts +5 -5
  30. package/dist/preact.js +6 -5
  31. package/dist/react.d.ts +12 -4
  32. package/dist/react.js +11 -6
  33. package/dist/routes.d.ts +3 -3
  34. package/dist/routes.js +5 -4
  35. package/dist/sentry.d.ts +25 -0
  36. package/dist/sentry.js +11 -0
  37. package/dist/{shadow-MYRJQLLY.js → shadow-6HELCHCJ.js} +37 -11
  38. package/dist/{slot-pB276oPt.d.ts → slot-DqXTwGbs.d.ts} +2 -2
  39. package/dist/solid.d.ts +4 -4
  40. package/dist/solid.js +6 -5
  41. package/dist/{sri-BVKZNX5Q.js → sri-JMX6JLQP.js} +6 -4
  42. package/dist/svelte.d.ts +5 -5
  43. package/dist/svelte.js +6 -5
  44. package/dist/testing.d.ts +2 -1
  45. package/dist/testing.js +5 -4
  46. package/dist/{types-BV-hUrms.d.ts → types-Czvm-siZ.d.ts} +63 -1
  47. package/dist/vite.d.ts +8 -0
  48. package/dist/vite.js +364 -35
  49. package/dist/vue.d.ts +10 -3
  50. package/dist/vue.js +10 -5
  51. package/package.json +54 -20
  52. package/dist/chunk-SFL6LTP3.js +0 -56
  53. package/dist/expose-53BEJB34.js +0 -14
package/dist/cli.js CHANGED
@@ -7,10 +7,13 @@ var PROPS = /export type Props =\s*([\s\S]*?)\s*$/;
7
7
  function parseProps(dts) {
8
8
  return PROPS.exec(dts.replace(/^\s*\/\/.*$/gm, "").trim())?.[1]?.replace(/;$/, "") || null;
9
9
  }
10
- function envFile(props) {
10
+ var HASH = /^\/\/ vitral:hash ("(?:[^"\\]|\\.)*") (\S+)$/gm;
11
+ function envFile(props, hashes = {}) {
11
12
  const lines = Object.entries(props).map(([name, type]) => ` ${JSON.stringify(name)}: ${type}`);
13
+ const marks = Object.entries(hashes).map(([name, hash]) => `// vitral:hash ${JSON.stringify(name)} ${hash}
14
+ `);
12
15
  return `// Gerado por \`npx vitral types\`. N\xE3o edite.
13
- import 'vitral'
16
+ ${marks.join("")}import 'vitral'
14
17
 
15
18
  declare module 'vitral' {
16
19
  interface Remotes {
@@ -19,6 +22,43 @@ ${lines.join("\n")}
19
22
  }
20
23
  `;
21
24
  }
25
+ function readHashes(env) {
26
+ return Object.fromEntries([...env.matchAll(HASH)].map((m) => [JSON.parse(m[1]), m[2]]));
27
+ }
28
+ async function manifestHash(get, url) {
29
+ try {
30
+ const res = await get(url);
31
+ if (!res.ok) return void 0;
32
+ const { integrity } = await res.json();
33
+ return typeof integrity === "string" ? integrity : void 0;
34
+ } catch {
35
+ return void 0;
36
+ }
37
+ }
38
+ async function check(remotes, out, get, log) {
39
+ if (!existsSync(out)) {
40
+ log(`[vitral] ${out} n\xE3o existe. Rode \`npx vitral types\`.`);
41
+ return 1;
42
+ }
43
+ const recorded = readHashes(readFileSync(out, "utf8"));
44
+ let stale = 0;
45
+ for (const [name, url] of Object.entries(remotes)) {
46
+ const hash = await manifestHash(get, url);
47
+ if (!hash) log(`[vitral] ${name}: manifesto sem hash, n\xE3o deu para conferir.`);
48
+ else if (recorded[name] !== hash) {
49
+ log(`[vitral] ${name}: tipos desatualizados (${recorded[name] ? "o manifesto mudou" : "sem hash registrado"}).`);
50
+ stale++;
51
+ }
52
+ }
53
+ for (const name of Object.keys(recorded)) {
54
+ if (!(name in remotes)) {
55
+ log(`[vitral] ${name}: n\xE3o est\xE1 mais no remotes.json.`);
56
+ stale++;
57
+ }
58
+ }
59
+ log(stale ? `[vitral] ${stale} remote(s) com tipos desatualizados. Rode \`npx vitral types\`.` : `[vitral] tipos em dia com os manifestos.`);
60
+ return stale;
61
+ }
22
62
  function readRemotes(cwd, args2, base) {
23
63
  const pairs = args2.filter((a) => a.includes("="));
24
64
  if (pairs.length) return Object.fromEntries(pairs.map((p) => [p.slice(0, p.indexOf("=")), p.slice(p.indexOf("=") + 1)]));
@@ -37,7 +77,10 @@ async function types(options = {}) {
37
77
  const get = options.fetch ?? fetch;
38
78
  const log = options.log ?? console.log;
39
79
  const remotes = readRemotes(cwd, options.args ?? [], options.base);
80
+ const out = resolve(cwd, options.out ?? "vitral-env.d.ts");
81
+ if (options.check) return check(remotes, out, get, log);
40
82
  const props = {};
83
+ const hashes = {};
41
84
  let falhas = 0;
42
85
  for (const [name, url] of Object.entries(remotes)) {
43
86
  let dts;
@@ -51,19 +94,25 @@ async function types(options = {}) {
51
94
  continue;
52
95
  }
53
96
  const type = parseProps(dts);
54
- if (type) props[name] = type;
55
- else log(`[vitral] ${name}: vitral.d.ts sem "export type Props".`);
97
+ if (!type) {
98
+ log(`[vitral] ${name}: vitral.d.ts sem "export type Props".`);
99
+ continue;
100
+ }
101
+ props[name] = type;
102
+ const hash = await manifestHash(get, url);
103
+ if (hash) hashes[name] = hash;
56
104
  }
57
- const out = resolve(cwd, options.out ?? "vitral-env.d.ts");
58
- writeFileSync(out, envFile(props));
105
+ writeFileSync(out, envFile(props, hashes));
59
106
  log(`[vitral] ${Object.keys(props).length} remote(s) em ${out}`);
60
107
  return falhas;
61
108
  }
62
109
 
63
110
  // src/cli.ts
64
- var AJUDA = `Uso: vitral types [remotes.json | nome=url ...] [--base url] [--out arquivo]
111
+ var AJUDA = `Uso: vitral types [remotes.json | nome=url ...] [--base url] [--out arquivo] [--check]
65
112
 
66
- Baixa o vitral.d.ts de cada remote e gera vitral-env.d.ts.`;
113
+ Baixa o vitral.d.ts de cada remote e gera vitral-env.d.ts.
114
+ --check s\xF3 confere se o hash de cada manifesto ainda \xE9 o registrado;
115
+ sai com erro se algum mudou (\xFAtil no CI).`;
67
116
  function flag(args2, name) {
68
117
  const i = args2.indexOf(name);
69
118
  if (i < 0) return void 0;
@@ -75,7 +124,8 @@ var [command, ...args] = process.argv.slice(2);
75
124
  if (command === "types") {
76
125
  const base = flag(args, "--base");
77
126
  const out = flag(args, "--out");
78
- types({ args, base, out }).then(
127
+ const check2 = args.includes("--check");
128
+ types({ args: args.filter((a) => a !== "--check"), base, out, check: check2 }).then(
79
129
  (falhas) => process.exitCode = falhas ? 1 : 0,
80
130
  (err) => {
81
131
  console.error(err.message);
@@ -0,0 +1,17 @@
1
+ import {
2
+ protocol
3
+ } from "./chunk-GNPFWISJ.js";
4
+
5
+ // src/core/contract.ts
6
+ async function checkContract(c, range = protocol().settings().contract) {
7
+ const { satisfies } = await import("./dedupe-S7BHQMOZ.js");
8
+ if (c.version && !satisfies(c.version, range)) return `o host aceita contrato ${range}, o remote publica ${c.version}`;
9
+ const offered = protocol().settings().offered ?? {};
10
+ for (const dep in c.peers) {
11
+ const have = offered[dep];
12
+ if (have && !satisfies(have, c.peers[dep])) return `o remote espera ${dep} ${c.peers[dep]}, o host oferece ${have}`;
13
+ }
14
+ }
15
+ export {
16
+ checkContract
17
+ };
@@ -3,14 +3,13 @@ function satisfies(version, range) {
3
3
  if (range === "*") return true;
4
4
  const [, op = "", want = ""] = /^(\^|~|>=|=)?(.*)$/.exec(range.trim());
5
5
  if (!op || op === "=" || version.includes("-")) return version === want;
6
- const v = version.split(".").map(Number);
7
- const w = want.split(".").map(Number);
6
+ const [v, w] = [version, want].map((s) => (s + ".0.0").split(".", 3).map(Number));
8
7
  for (let i = 0; i < 3; i++) if (v[i] !== w[i]) {
9
8
  if (!(v[i] > w[i])) return false;
10
9
  break;
11
10
  }
12
11
  if (op === ">=") return true;
13
- const fixed = op === "~" ? 2 : w[0] ? 1 : w[1] ? 2 : 3;
12
+ const fixed = Math.min(want.split(".").length, op === "~" ? 2 : w[0] ? 1 : w[1] ? 2 : 3);
14
13
  return v.slice(0, fixed).join(".") === w.slice(0, fixed).join(".");
15
14
  }
16
15
 
@@ -73,9 +72,11 @@ function offer(p, groups) {
73
72
  for (const name in groups) {
74
73
  const { version, modules } = groups[name];
75
74
  shared(p)(name, version, { version, load: async () => modules });
75
+ p.configure({ offered: { ...p.settings().offered, [name]: version } });
76
76
  }
77
77
  }
78
78
  export {
79
79
  offer,
80
+ satisfies,
80
81
  shared
81
82
  };
package/dist/element.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { P as Props, S as Shared, a as RemoteModule } from './types-BV-hUrms.js';
2
- import { S as SlotStatus } from './slot-pB276oPt.js';
3
- import './errors-KKB8FGCz.js';
1
+ import { P as Props, S as Shared, a as RemoteModule } from './types-Czvm-siZ.js';
2
+ import { S as SlotStatus } from './slot-DqXTwGbs.js';
3
+ import './errors-kjBv6IH_.js';
4
4
 
5
5
  /**
6
6
  * Host universal: `<vitral-remote>` funciona em qualquer lugar que renderize
package/dist/element.js CHANGED
@@ -3,12 +3,13 @@ import {
3
3
  VitralRemoteElement,
4
4
  defineVitralElement,
5
5
  elementRemote
6
- } from "./chunk-6Y3VMWHH.js";
7
- import "./chunk-UTYAX6MU.js";
8
- import "./chunk-NCONW6WS.js";
9
- import "./chunk-2XF5BKV3.js";
10
- import "./chunk-SFL6LTP3.js";
11
- import "./chunk-PX7PBCCT.js";
6
+ } from "./chunk-3YXI3G34.js";
7
+ import "./chunk-IHTUM6LT.js";
8
+ import "./chunk-I3VSKSAZ.js";
9
+ import "./chunk-TD4S3IHA.js";
10
+ import "./chunk-ZAC6QQI6.js";
11
+ import "./chunk-GNHCZRQP.js";
12
+ import "./chunk-AKNNHQ2H.js";
12
13
  import "./chunk-GNPFWISJ.js";
13
14
  export {
14
15
  SharedController,
@@ -1,10 +1,16 @@
1
- type RemoteErrorCode = 'NOT_REGISTERED' | 'NOT_EXPOSED' | 'ORIGIN_BLOCKED' | 'TIMEOUT' | 'INTEGRITY' | 'INVALID_MODULE' | 'LOAD_FAILED' | 'MOUNT_FAILED' | 'RENDER_FAILED' | 'SHARED_READONLY';
1
+ type RemoteErrorCode = 'NOT_REGISTERED' | 'NOT_EXPOSED' | 'ORIGIN_BLOCKED' | 'TIMEOUT' | 'INTEGRITY' | 'INVALID_MODULE' | 'LOAD_FAILED' | 'MOUNT_FAILED' | 'RENDER_FAILED' | 'SHARED_READONLY' | 'CONTRACT_MISMATCH';
2
2
  declare class RemoteError extends Error {
3
3
  code: RemoteErrorCode;
4
4
  remote: string;
5
5
  cause?: unknown | undefined;
6
6
  /** Link da página deste erro na documentação. */
7
7
  docs: string;
8
+ /** URL do JS do remote (ou a registrada, se o erro veio antes do manifesto). */
9
+ entry?: string;
10
+ /** Versão do remote, do campo `version` do `vitral.json`. */
11
+ version?: string;
12
+ /** `location.pathname` no momento do erro. */
13
+ route?: string;
8
14
  constructor(code: RemoteErrorCode, remote: string, message: string, cause?: unknown | undefined);
9
15
  }
10
16
 
@@ -1,4 +1,4 @@
1
- import { E as EventBus } from './types-BV-hUrms.js';
1
+ import { E as EventBus } from './types-Czvm-siZ.js';
2
2
 
3
3
  /** Barramento global. É o mesmo objeto que os remotes recebem em `ctx.events`. */
4
4
  declare const events: EventBus;
@@ -0,0 +1,15 @@
1
+ import {
2
+ resolveModule,
3
+ resolveTarget,
4
+ splitName
5
+ } from "./chunk-SDB5AZEI.js";
6
+ import "./chunk-TD4S3IHA.js";
7
+ import "./chunk-ZAC6QQI6.js";
8
+ import "./chunk-GNHCZRQP.js";
9
+ import "./chunk-AKNNHQ2H.js";
10
+ import "./chunk-GNPFWISJ.js";
11
+ export {
12
+ resolveModule,
13
+ resolveTarget,
14
+ splitName
15
+ };
package/dist/iframe.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /** Script inline do iframe. Libere o hash dele no CSP (`script-src 'sha256-…'`). */
2
- declare const FRAME_SCRIPT = "(function (w, load) {\n var parent = w.parent, doc = w.document, handlers = {}, last = {}, channel = {}, mounted = null, stage = 'LOAD_FAILED'\n function post(type, data) { parent.postMessage({ vitral: 1, type: type, data: data }, '*') }\n function call(fn, arg) { try { fn(arg) } catch (e) { w.console.error(e) } }\n var events = {\n emit: function (type, payload) { post('emit', { type: type, payload: payload }) },\n on: function (type, fn) {\n if (!handlers[type]) { handlers[type] = []; post('on', { type: type }) }\n handlers[type].push(fn)\n return function () { handlers[type] = handlers[type].filter(function (h) { return h !== fn }) }\n },\n last: function (type) { return last[type] }\n }\n function start(d) {\n var root = doc.createElement('div')\n root.setAttribute('data-vitral-root', d.name)\n if (d.scope) root.setAttribute('data-vitral-scope', d.scope)\n doc.body.appendChild(root)\n // Ponto de extens\u00E3o: uma ponte nova registra handlers em channel[tipo] e\n // acrescenta campos aqui (a Fase 2 acrescenta ctx.shared).\n var ctx = {\n name: d.name, baseUrl: d.baseUrl, events: events, shadowRoot: null, protocol: 1,\n reportError: function (e) { post('report', { message: String((e && e.message) || e) }) },\n navigate: function (url, o) { post('navigate', { url: String(url), replace: !!(o && o.replace) }) }\n }\n Promise.all(d.css.map(function (href) {\n return new Promise(function (done) {\n var link = doc.createElement('link')\n link.rel = 'stylesheet'; link.href = href; link.crossOrigin = 'anonymous'\n link.onload = link.onerror = done\n doc.head.appendChild(link)\n })\n })).then(function () {\n return load(d.code ? w.URL.createObjectURL(new w.Blob([d.code], { type: 'text/javascript' })) : d.url)\n }).then(function (ns) {\n if (!d.key) return ns\n var table = ns.exposes, part = table && table[d.key]\n if (!part) { stage = 'NOT_EXPOSED'; throw new Error(d.name + ' n\u00E3o exp\u00F5e ' + d.key) }\n return typeof part === 'function' ? part() : part\n }).then(function (ns) {\n var mod = (ns && ns.default) || ns\n if (!mod || typeof mod.mount !== 'function') { stage = 'INVALID_MODULE'; throw new Error('o m\u00F3dulo n\u00E3o exporta mount()') }\n stage = 'MOUNT_FAILED'\n return mod.mount(root, d.props, ctx)\n }).then(function (handle) {\n mounted = handle\n post('mounted')\n var size = function () { post('size', { height: Math.ceil(doc.body.getBoundingClientRect().height) }) }\n size()\n if (w.ResizeObserver) new w.ResizeObserver(size).observe(doc.body)\n }, function (e) {\n post('error', { code: stage, message: String((e && e.message) || e) })\n })\n }\n w.addEventListener('message', function (e) {\n var m = e.data\n if (e.source !== parent || !m || m.vitral !== 1) return\n var d = m.data\n if (m.type === 'mount') start(d)\n else if (m.type === 'update') { if (mounted && mounted.update) mounted.update(d) }\n else if (m.type === 'unmount') { if (mounted) mounted.unmount(); mounted = null }\n else if (m.type === 'last') last[d.type] = d.payload\n else if (m.type === 'event') {\n last[d.type] = d.payload\n ;(handlers[d.type] || []).slice().forEach(function (h) { call(h, d.payload) })\n } else (channel[m.type] || []).forEach(function (h) { call(h, d) })\n })\n post('ready')\n})(window, function (u) { return import(u) })";
2
+ declare const FRAME_SCRIPT = "(function (w, load) {\n var parent = w.parent, doc = w.document, handlers = {}, last = {}, channel = {}, mounted = null, stage = 'LOAD_FAILED'\n function post(type, data) { parent.postMessage({ vitral: 1, type: type, data: data }, '*') }\n function call(fn, arg) { try { fn(arg) } catch (e) { w.console.error(e) } }\n var events = {\n emit: function (type, payload) { post('emit', { type: type, payload: payload }) },\n on: function (type, fn) {\n if (!handlers[type]) { handlers[type] = []; post('on', { type: type }) }\n handlers[type].push(fn)\n return function () { handlers[type] = handlers[type].filter(function (h) { return h !== fn }) }\n },\n last: function (type) { return last[type] }\n }\n function start(d) {\n var root = doc.createElement('div')\n root.setAttribute('data-vitral-root', d.name)\n if (d.scope) root.setAttribute('data-vitral-scope', d.scope)\n doc.body.appendChild(root)\n // Ponto de extens\u00E3o: uma ponte nova registra handlers em channel[tipo] e\n // acrescenta campos aqui (a Fase 2 acrescenta ctx.shared).\n var ctx = {\n name: d.name, baseUrl: d.baseUrl, events: events, shadowRoot: null, portalContainer: doc.body, protocol: 1,\n reportError: function (e) { post('report', { message: String((e && e.message) || e) }) },\n navigate: function (url, o) { post('navigate', { url: String(url), replace: !!(o && o.replace) }) }\n }\n Promise.all(d.css.map(function (href) {\n return new Promise(function (done) {\n var link = doc.createElement('link')\n link.rel = 'stylesheet'; link.href = href; link.crossOrigin = 'anonymous'\n link.onload = link.onerror = done\n doc.head.appendChild(link)\n })\n })).then(function () {\n return load(d.code ? w.URL.createObjectURL(new w.Blob([d.code], { type: 'text/javascript' })) : d.url)\n }).then(function (ns) {\n if (!d.key) return ns\n var table = ns.exposes, part = table && table[d.key]\n if (!part) { stage = 'NOT_EXPOSED'; throw new Error(d.name + ' n\u00E3o exp\u00F5e ' + d.key) }\n return typeof part === 'function' ? part() : part\n }).then(function (ns) {\n var mod = (ns && ns.default) || ns\n if (!mod || typeof mod.mount !== 'function') { stage = 'INVALID_MODULE'; throw new Error('o m\u00F3dulo n\u00E3o exporta mount()') }\n stage = 'MOUNT_FAILED'\n return mod.mount(root, d.props, ctx)\n }).then(function (handle) {\n mounted = handle\n post('mounted')\n var size = function () { post('size', { height: Math.ceil(doc.body.getBoundingClientRect().height) }) }\n size()\n if (w.ResizeObserver) new w.ResizeObserver(size).observe(doc.body)\n }, function (e) {\n post('error', { code: stage, message: String((e && e.message) || e) })\n })\n }\n w.addEventListener('message', function (e) {\n var m = e.data\n if (e.source !== parent || !m || m.vitral !== 1) return\n var d = m.data\n if (m.type === 'mount') start(d)\n else if (m.type === 'update') { if (mounted && mounted.update) mounted.update(d) }\n else if (m.type === 'unmount') { if (mounted) mounted.unmount(); mounted = null }\n else if (m.type === 'last') last[d.type] = d.payload\n else if (m.type === 'event') {\n last[d.type] = d.payload\n ;(handlers[d.type] || []).slice().forEach(function (h) { call(h, d.payload) })\n } else (channel[m.type] || []).forEach(function (h) { call(h, d) })\n })\n post('ready')\n})(window, function (u) { return import(u) })";
3
3
 
4
4
  /** Canal com um iframe montado, para pontes novas (ex.: estado compartilhado). */
5
5
  interface FramePort {
package/dist/iframe.js CHANGED
@@ -1,25 +1,28 @@
1
1
  import {
2
2
  splitName
3
- } from "./chunk-HP6QWU6K.js";
3
+ } from "./chunk-SDB5AZEI.js";
4
4
  import {
5
5
  verifyIntegrity
6
- } from "./chunk-S5MZT5IT.js";
6
+ } from "./chunk-AH7KNMBW.js";
7
7
  import {
8
8
  events,
9
9
  navigate,
10
10
  setFrameMounter,
11
11
  track
12
- } from "./chunk-NCONW6WS.js";
12
+ } from "./chunk-I3VSKSAZ.js";
13
13
  import {
14
14
  resolveEntry
15
- } from "./chunk-2XF5BKV3.js";
16
- import "./chunk-SFL6LTP3.js";
15
+ } from "./chunk-TD4S3IHA.js";
16
+ import "./chunk-ZAC6QQI6.js";
17
17
  import {
18
- RemoteError,
19
18
  fetchBytes,
20
19
  withRetry,
21
20
  withTimeout
22
- } from "./chunk-PX7PBCCT.js";
21
+ } from "./chunk-GNHCZRQP.js";
22
+ import {
23
+ RemoteError,
24
+ report
25
+ } from "./chunk-AKNNHQ2H.js";
23
26
  import {
24
27
  protocol
25
28
  } from "./chunk-GNPFWISJ.js";
@@ -46,7 +49,7 @@ var FRAME_RUNTIME = `function (w, load) {
46
49
  // Ponto de extens\xE3o: uma ponte nova registra handlers em channel[tipo] e
47
50
  // acrescenta campos aqui (a Fase 2 acrescenta ctx.shared).
48
51
  var ctx = {
49
- name: d.name, baseUrl: d.baseUrl, events: events, shadowRoot: null, protocol: 1,
52
+ name: d.name, baseUrl: d.baseUrl, events: events, shadowRoot: null, portalContainer: doc.body, protocol: 1,
50
53
  reportError: function (e) { post('report', { message: String((e && e.message) || e) }) },
51
54
  navigate: function (url, o) { post('navigate', { url: String(url), replace: !!(o && o.replace) }) }
52
55
  }
@@ -119,7 +122,6 @@ async function mountFrame(target, name, props, options, sandbox, bridges) {
119
122
  await verifyIntegrity(name, bytes, integrity);
120
123
  return bytes;
121
124
  }) : void 0;
122
- track(name, resolved.entry);
123
125
  const baseUrl = /^https?:/.test(resolved.entry) ? new URL(".", resolved.entry).href : resolved.entry;
124
126
  const frame = document.createElement("iframe");
125
127
  frame.setAttribute("sandbox", sandbox);
@@ -188,7 +190,7 @@ async function mountFrame(target, name, props, options, sandbox, bridges) {
188
190
  break;
189
191
  }
190
192
  case "report": {
191
- const err = new RemoteError("RENDER_FAILED", name, String(d?.message));
193
+ const err = report(new RemoteError("RENDER_FAILED", name, String(d?.message)), resolved);
192
194
  if (options.onError) options.onError(err);
193
195
  else console.error(err);
194
196
  break;
@@ -217,6 +219,7 @@ async function mountFrame(target, name, props, options, sandbox, bridges) {
217
219
  cleanup();
218
220
  throw e;
219
221
  }
222
+ disposers.push(track(name, resolved));
220
223
  let alive = true;
221
224
  return {
222
225
  update(next) {
package/dist/index.d.ts CHANGED
@@ -1,24 +1,12 @@
1
- import { V as VitralConfig, c as RemoteEntry, P as Props, a as RemoteModule, I as Isolation, b as StyleOptions, M as MountedRemote, E as EventBus, R as RemoteContext, d as SharedValue } from './types-BV-hUrms.js';
2
- export { C as CheckedProps, H as Handler, e as PropsOf, f as ProvideOptions, g as ProvidedValue, h as RemoteManifest, i as RemoteMetric, j as Remotes, S as Shared, k as SharedApi, l as SharedModules, m as SharedType, n as batch, p as provide, s as shared } from './types-BV-hUrms.js';
3
- import { R as RemoteError } from './errors-KKB8FGCz.js';
4
- export { a as RemoteErrorCode } from './errors-KKB8FGCz.js';
5
- export { R as RemoteSlot, a as SlotOptions, S as SlotStatus, c as createSlot } from './slot-pB276oPt.js';
6
- export { e as events } from './events-DUdjhfps.js';
1
+ import { V as VitralConfig, c as RemoteEntry, P as Props, a as RemoteModule, I as Isolation, b as StyleOptions, M as MountedRemote, E as EventBus, R as RemoteContext, d as SharedValue } from './types-Czvm-siZ.js';
2
+ export { C as CheckedProps, H as Handler, e as PropsOf, f as ProvideOptions, g as ProvidedValue, h as RemoteContract, i as RemoteManifest, j as RemoteMetric, k as Remotes, S as Shared, l as SharedApi, m as SharedModules, n as SharedType, o as batch, p as provide, s as shared } from './types-Czvm-siZ.js';
3
+ import { R as RemoteError } from './errors-kjBv6IH_.js';
4
+ export { a as RemoteErrorCode } from './errors-kjBv6IH_.js';
5
+ export { R as RemoteSlot, a as SlotOptions, S as SlotStatus, c as createSlot } from './slot-DqXTwGbs.js';
6
+ export { e as events } from './events-D5gs7rff.js';
7
7
  export { n as navigate } from './navigate-BRG1WJUM.js';
8
8
  export { r as __reset } from './state-BDdCwc21.js';
9
9
 
10
- /** Configura a lib. Pode ser chamada mais de uma vez; as opções são mescladas. */
11
- declare function configure(config: VitralConfig): void;
12
- /** Registra (ou substitui) um remote. */
13
- declare function register(name: string, entry: string | RemoteEntry): void;
14
- /**
15
- * Registra a URL de um `src` e devolve o nome para montar. Sem `name`, o nome
16
- * é a própria URL (e o nome do manifesto vira um apelido). Com `trusted`, a
17
- * origem entra na allowlist mesmo com `allowedOrigins`: vale para URL escrita
18
- * no código do host, nunca para URL vinda de dados.
19
- */
20
- declare function registerSrc(src: string, name?: string, trusted?: boolean): string;
21
-
22
10
  /** Uma chave do store vista de fora (devtools, SSR, ponte do iframe). */
23
11
  interface SharedEntry {
24
12
  key: string;
@@ -60,6 +48,18 @@ interface SharedStore {
60
48
  list(): SharedEntry[];
61
49
  }
62
50
 
51
+ /** Configura a lib. Pode ser chamada mais de uma vez; as opções são mescladas. */
52
+ declare function configure(config: VitralConfig): void;
53
+ /** Registra (ou substitui) um remote. */
54
+ declare function register(name: string, entry: string | RemoteEntry): void;
55
+ /**
56
+ * Registra a URL de um `src` e devolve o nome para montar. Sem `name`, o nome
57
+ * é a própria URL (e o nome do manifesto vira um apelido). Com `trusted`, a
58
+ * origem entra na allowlist mesmo com `allowedOrigins`: vale para URL escrita
59
+ * no código do host, nunca para URL vinda de dados.
60
+ */
61
+ declare function registerSrc(src: string, name?: string, trusted?: boolean): string;
62
+
63
63
  /** Baixa (uma vez só) e devolve o módulo de um remote. */
64
64
  declare function loadRemote<P extends Props = Props>(name: string): Promise<RemoteModule<P>>;
65
65
  /**
@@ -97,12 +97,14 @@ declare function createEventBus(): EventBus;
97
97
 
98
98
  /**
99
99
  * Troca as montagens de `name` (e das partes, `name/…`) pela versão que o
100
- * manifesto aponta agora, sem recarregar a página. Rejeita se a versão nova
101
- * não carregar; nesse caso nada muda na tela.
100
+ * manifesto aponta agora, sem recarregar a página. Resolve quando todas as
101
+ * montagens já mostram a versão nova. Rejeita se a versão nova não carregar
102
+ * ou se o `mount` dela falhar; nesse caso a montagem antiga fica na tela.
102
103
  */
103
104
  declare function refresh(name: string): Promise<void>;
104
105
  /**
105
- * Revalida os manifestos dos remotes montados e emite
106
+ * Revalida os manifestos dos remotes montados agora (os desmontados ficam de
107
+ * fora) e emite
106
108
  * `vitral:update-available` com `{ name, entry }` para cada deploy novo.
107
109
  * Devolve os nomes com versão nova. Falhas de rede são ignoradas.
108
110
  */
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  syncTabs,
18
18
  unsafeHTML,
19
19
  watchUpdates
20
- } from "./chunk-NCONW6WS.js";
20
+ } from "./chunk-I3VSKSAZ.js";
21
21
  import {
22
22
  configure,
23
23
  loadModule,
@@ -25,11 +25,12 @@ import {
25
25
  preload,
26
26
  register,
27
27
  registerSrc
28
- } from "./chunk-2XF5BKV3.js";
29
- import "./chunk-SFL6LTP3.js";
28
+ } from "./chunk-TD4S3IHA.js";
29
+ import "./chunk-ZAC6QQI6.js";
30
+ import "./chunk-GNHCZRQP.js";
30
31
  import {
31
32
  RemoteError
32
- } from "./chunk-PX7PBCCT.js";
33
+ } from "./chunk-AKNNHQ2H.js";
33
34
  import {
34
35
  createEventBus,
35
36
  resetProtocol
package/dist/otel.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ import { R as RemoteError } from './errors-kjBv6IH_.js';
2
+
3
+ /**
4
+ * Erros dos remotes no OpenTelemetry, sem depender do `@opentelemetry/api`:
5
+ *
6
+ * import { trace } from '@opentelemetry/api'
7
+ * import { otelOnError } from 'vitral/otel'
8
+ *
9
+ * configure({ onError: otelOnError({ trace, tracer: trace.getTracer('host') }) })
10
+ *
11
+ * Com um span ativo, o erro vira um evento `exception` nele. Sem span ativo
12
+ * (ou sem `trace`), o `tracer` abre e fecha um span `vitral.error` com o erro.
13
+ * Os atributos são os de exceção do OpenTelemetry mais `vitral.remote`,
14
+ * `vitral.version`, `vitral.code`, `vitral.entry` e `vitral.route`.
15
+ */
16
+
17
+ /** Atributos de span e de evento. */
18
+ type Attributes = Record<string, string>;
19
+ /** A parte de um `Span` que o adaptador usa. */
20
+ interface SpanLike {
21
+ addEvent(name: string, attributes?: Attributes): unknown;
22
+ recordException(exception: Error): void;
23
+ setStatus(status: {
24
+ code: number;
25
+ message?: string;
26
+ }): unknown;
27
+ end(): void;
28
+ }
29
+ interface OtelOptions {
30
+ /** O `trace` de `@opentelemetry/api`, para achar o span ativo. */
31
+ trace?: {
32
+ getActiveSpan(): SpanLike | undefined;
33
+ };
34
+ /** Tracer que abre um span quando não há span ativo. */
35
+ tracer?: {
36
+ startSpan(name: string, options?: {
37
+ attributes?: Attributes;
38
+ }): SpanLike;
39
+ };
40
+ }
41
+ /** `onError` para o `configure` que registra cada `RemoteError` no OpenTelemetry. */
42
+ declare function otelOnError({ trace, tracer }: OtelOptions): (error: RemoteError) => void;
43
+
44
+ export { type Attributes, type OtelOptions, type SpanLike, otelOnError };
package/dist/otel.js ADDED
@@ -0,0 +1,27 @@
1
+ // src/otel.ts
2
+ function otelOnError({ trace, tracer }) {
3
+ return (error) => {
4
+ const all = {
5
+ "exception.type": error.name,
6
+ "exception.message": error.message,
7
+ "exception.stacktrace": error.stack,
8
+ "vitral.remote": error.remote,
9
+ "vitral.version": error.version,
10
+ "vitral.code": error.code,
11
+ "vitral.entry": error.entry,
12
+ "vitral.route": error.route
13
+ };
14
+ const attributes = {};
15
+ for (const k in all) if (all[k] !== void 0) attributes[k] = all[k];
16
+ const active = trace?.getActiveSpan();
17
+ if (active) return void active.addEvent("exception", attributes);
18
+ const span = tracer?.startSpan("vitral.error", { attributes });
19
+ if (!span) return;
20
+ span.recordException(error);
21
+ span.setStatus({ code: 2, message: error.message });
22
+ span.end();
23
+ };
24
+ }
25
+ export {
26
+ otelOnError
27
+ };
package/dist/preact.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as preact from 'preact';
2
2
  import { VNode, ComponentType } from 'preact';
3
- import { P as Props, I as Isolation, C as CheckedProps, a as RemoteModule, S as Shared } from './types-BV-hUrms.js';
4
- export { R as RemoteContext } from './types-BV-hUrms.js';
5
- import { R as RemoteError } from './errors-KKB8FGCz.js';
6
- import { S as SlotStatus } from './slot-pB276oPt.js';
7
- export { e as events } from './events-DUdjhfps.js';
3
+ import { P as Props, I as Isolation, C as CheckedProps, a as RemoteModule, S as Shared } from './types-Czvm-siZ.js';
4
+ export { R as RemoteContext } from './types-Czvm-siZ.js';
5
+ import { R as RemoteError } from './errors-kjBv6IH_.js';
6
+ import { S as SlotStatus } from './slot-DqXTwGbs.js';
7
+ export { e as events } from './events-D5gs7rff.js';
8
8
  export { n as navigate } from './navigate-BRG1WJUM.js';
9
9
  import { L as Loading, P as Prefetch } from './host-slot-Cz6EiGsB.js';
10
10
 
package/dist/preact.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  hostSlot
3
- } from "./chunk-UTYAX6MU.js";
3
+ } from "./chunk-IHTUM6LT.js";
4
4
  import {
5
5
  defineRemote,
6
6
  events,
@@ -8,10 +8,11 @@ import {
8
8
  navigate,
9
9
  same,
10
10
  shared
11
- } from "./chunk-NCONW6WS.js";
12
- import "./chunk-2XF5BKV3.js";
13
- import "./chunk-SFL6LTP3.js";
14
- import "./chunk-PX7PBCCT.js";
11
+ } from "./chunk-I3VSKSAZ.js";
12
+ import "./chunk-TD4S3IHA.js";
13
+ import "./chunk-ZAC6QQI6.js";
14
+ import "./chunk-GNHCZRQP.js";
15
+ import "./chunk-AKNNHQ2H.js";
15
16
  import "./chunk-GNPFWISJ.js";
16
17
 
17
18
  // src/preact.ts
package/dist/react.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { ReactNode, ComponentType } from 'react';
2
2
  import { L as Loading, P as Prefetch } from './host-slot-Cz6EiGsB.js';
3
3
  import * as JSXRuntime from 'react/jsx-runtime';
4
- import { P as Props, I as Isolation, C as CheckedProps, a as RemoteModule, S as Shared, R as RemoteContext } from './types-BV-hUrms.js';
5
- export { E as EventBus } from './types-BV-hUrms.js';
6
- export { e as events } from './events-DUdjhfps.js';
4
+ import { P as Props, I as Isolation, C as CheckedProps, a as RemoteModule, S as Shared, R as RemoteContext } from './types-Czvm-siZ.js';
5
+ export { E as EventBus } from './types-Czvm-siZ.js';
6
+ export { e as events } from './events-D5gs7rff.js';
7
+ import './errors-kjBv6IH_.js';
7
8
 
8
9
  /**
9
10
  * Adaptador React (funciona em Vite, CRA e Next.js App/Pages Router).
@@ -17,6 +18,13 @@ export { e as events } from './events-DUdjhfps.js';
17
18
  declare function reactRemote<P extends Props>(Component: ComponentType<P>): RemoteModule<P>;
18
19
  /** Dentro de um remote: dá acesso ao contexto (nome, eventos, baseUrl). */
19
20
  declare function useVitral(): RemoteContext | null;
21
+ /**
22
+ * Dentro de um remote: onde renderizar portais. No Shadow DOM é um elemento
23
+ * dentro do shadow root (com os estilos do remote); fora de um remote,
24
+ * `undefined`, e a biblioteca usa o padrão dela (`document.body`). Use em
25
+ * `<Popover.Portal container={usePortalContainer()}>`.
26
+ */
27
+ declare function usePortalContainer(): HTMLElement | undefined;
20
28
  /** Assina um evento do barramento global enquanto o componente estiver montado. */
21
29
  declare function useEvent<T = unknown>(type: string, handler: (payload: T) => void): void;
22
30
  /** Estado derivado do último valor emitido em `type`. */
@@ -60,4 +68,4 @@ interface RemoteProps<P extends Props = Props> {
60
68
  */
61
69
  declare function Remote<P extends Props = Props, N extends string = string>({ name, src, props, isolate, fallback, error, onError, className, loading, prefetch, priority, keepAlive, }: RemoteProps<P> & CheckedProps<N>): JSXRuntime.JSX.Element;
62
70
 
63
- export { Remote, type RemoteProps, reactRemote, useEvent, useEventValue, useShared, useVitral };
71
+ export { Remote, type RemoteProps, reactRemote, useEvent, useEventValue, usePortalContainer, useShared, useVitral };
package/dist/react.js CHANGED
@@ -1,17 +1,18 @@
1
1
  "use client";
2
2
  import {
3
3
  hostSlot
4
- } from "./chunk-UTYAX6MU.js";
4
+ } from "./chunk-IHTUM6LT.js";
5
5
  import {
6
6
  defineRemote,
7
7
  events,
8
8
  memoSelect,
9
9
  same,
10
10
  shared
11
- } from "./chunk-NCONW6WS.js";
12
- import "./chunk-2XF5BKV3.js";
13
- import "./chunk-SFL6LTP3.js";
14
- import "./chunk-PX7PBCCT.js";
11
+ } from "./chunk-I3VSKSAZ.js";
12
+ import "./chunk-TD4S3IHA.js";
13
+ import "./chunk-ZAC6QQI6.js";
14
+ import "./chunk-GNHCZRQP.js";
15
+ import "./chunk-AKNNHQ2H.js";
15
16
  import {
16
17
  protocol
17
18
  } from "./chunk-GNPFWISJ.js";
@@ -65,6 +66,9 @@ function reactRemote(Component) {
65
66
  function useVitral() {
66
67
  return useContext(VitralContext);
67
68
  }
69
+ function usePortalContainer() {
70
+ return useVitral()?.portalContainer;
71
+ }
68
72
  function useEvent(type, handler) {
69
73
  const ref = useRef(handler);
70
74
  ref.current = handler;
@@ -99,7 +103,7 @@ function offerReact() {
99
103
  // O React 19 expõe o react/compiler-runtime pelo próprio react.
100
104
  ...compiler && { "react/compiler-runtime": compiler }
101
105
  };
102
- p.pending(import("./dedupe-IWFIXRWG.js").then((m) => m.offer(p, { react: { version: ReactAll.version, modules } })).catch(() => {
106
+ p.pending(import("./dedupe-S7BHQMOZ.js").then((m) => m.offer(p, { react: { version: ReactAll.version, modules } })).catch(() => {
103
107
  }));
104
108
  }
105
109
  function Remote({
@@ -162,6 +166,7 @@ export {
162
166
  reactRemote,
163
167
  useEvent,
164
168
  useEventValue,
169
+ usePortalContainer,
165
170
  useShared,
166
171
  useVitral
167
172
  };
package/dist/routes.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { P as Props } from './types-BV-hUrms.js';
2
- import { S as SlotStatus } from './slot-pB276oPt.js';
3
- import './errors-KKB8FGCz.js';
1
+ import { P as Props } from './types-Czvm-siZ.js';
2
+ import { S as SlotStatus } from './slot-DqXTwGbs.js';
3
+ import './errors-kjBv6IH_.js';
4
4
 
5
5
  /** Padrão de URL → nome do remote. A primeira rota que bate vence. */
6
6
  type Routes = Record<string, string>;
package/dist/routes.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  createSlot,
3
3
  navigate
4
- } from "./chunk-NCONW6WS.js";
5
- import "./chunk-2XF5BKV3.js";
6
- import "./chunk-SFL6LTP3.js";
7
- import "./chunk-PX7PBCCT.js";
4
+ } from "./chunk-I3VSKSAZ.js";
5
+ import "./chunk-TD4S3IHA.js";
6
+ import "./chunk-ZAC6QQI6.js";
7
+ import "./chunk-GNHCZRQP.js";
8
+ import "./chunk-AKNNHQ2H.js";
8
9
  import "./chunk-GNPFWISJ.js";
9
10
 
10
11
  // src/routes.ts