vitral 0.2.0 → 0.4.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 (66) 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-TT5WBLJ6.js +42 -0
  6. package/dist/channel-2YPYGX3J.js +95 -0
  7. package/dist/chunk-463H6B56.js +50 -0
  8. package/dist/chunk-54CBIZES.js +105 -0
  9. package/dist/chunk-6EX5KYT5.js +64 -0
  10. package/dist/{chunk-6Y3VMWHH.js → chunk-BCC25ANK.js} +11 -5
  11. package/dist/{chunk-2XF5BKV3.js → chunk-EMSB2NVX.js} +26 -13
  12. package/dist/{chunk-HP6QWU6K.js → chunk-IH3ZT3QU.js} +2 -2
  13. package/dist/{chunk-PX7PBCCT.js → chunk-TW7KYJQ6.js} +7 -17
  14. package/dist/{chunk-S5MZT5IT.js → chunk-UYOPJ4XQ.js} +1 -1
  15. package/dist/{chunk-UTYAX6MU.js → chunk-W6322KGP.js} +2 -2
  16. package/dist/{chunk-NCONW6WS.js → chunk-WD4CDGDZ.js} +73 -44
  17. package/dist/cli.js +1196 -31
  18. package/dist/contract-46EZFQPQ.js +17 -0
  19. package/dist/{dedupe-IWFIXRWG.js → dedupe-S7BHQMOZ.js} +4 -3
  20. package/dist/devtools.d.ts +32 -2
  21. package/dist/devtools.js +27 -12
  22. package/dist/element.d.ts +13 -4
  23. package/dist/element.js +7 -6
  24. package/dist/embed.js +2 -0
  25. package/dist/{errors-KKB8FGCz.d.ts → errors-kjBv6IH_.d.ts} +7 -1
  26. package/dist/{events-DUdjhfps.d.ts → events-Dkpkw_Sv.d.ts} +1 -1
  27. package/dist/expose-OVWTPHH5.js +15 -0
  28. package/dist/federation.d.ts +89 -0
  29. package/dist/federation.js +101 -0
  30. package/dist/iframe.d.ts +1 -1
  31. package/dist/iframe.js +13 -10
  32. package/dist/index.d.ts +23 -21
  33. package/dist/index.js +5 -4
  34. package/dist/otel.d.ts +44 -0
  35. package/dist/otel.js +27 -0
  36. package/dist/overrides-NP754HY7.js +27 -0
  37. package/dist/preact.d.ts +5 -5
  38. package/dist/preact.js +6 -5
  39. package/dist/react.d.ts +12 -4
  40. package/dist/react.js +11 -6
  41. package/dist/routes.d.ts +3 -3
  42. package/dist/routes.js +5 -4
  43. package/dist/sentry.d.ts +25 -0
  44. package/dist/sentry.js +11 -0
  45. package/dist/shadow-PVSETNMZ.js +159 -0
  46. package/dist/single-spa.d.ts +40 -0
  47. package/dist/single-spa.js +52 -0
  48. package/dist/{slot-pB276oPt.d.ts → slot-UPg6ob9v.d.ts} +2 -2
  49. package/dist/solid.d.ts +4 -4
  50. package/dist/solid.js +6 -5
  51. package/dist/{sri-BVKZNX5Q.js → sri-M7ZRU57G.js} +43 -11
  52. package/dist/svelte.d.ts +5 -5
  53. package/dist/svelte.js +6 -5
  54. package/dist/testing.d.ts +2 -1
  55. package/dist/testing.js +5 -4
  56. package/dist/{types-BV-hUrms.d.ts → types-CA2p9KHC.d.ts} +174 -4
  57. package/dist/vite.d.ts +26 -0
  58. package/dist/vite.js +686 -51
  59. package/dist/vue.d.ts +11 -4
  60. package/dist/vue.js +10 -5
  61. package/package.json +115 -23
  62. package/dist/chunk-DXORSF4X.js +0 -42
  63. package/dist/chunk-SFL6LTP3.js +0 -56
  64. package/dist/expose-53BEJB34.js +0 -14
  65. package/dist/overrides-NZAIUGK5.js +0 -15
  66. package/dist/shadow-MYRJQLLY.js +0 -72
@@ -0,0 +1,52 @@
1
+ // src/single-spa.ts
2
+ async function run(fns, props) {
3
+ for (const fn of [fns ?? []].flat()) await fn(props);
4
+ }
5
+ function singleSpaRemote(lifecycles) {
6
+ const l = "mount" in lifecycles ? lifecycles : lifecycles.default;
7
+ if (typeof l?.mount == "undefined" || typeof l.unmount == "undefined") throw new Error("[vitral] singleSpaRemote: faltam os lifecycles mount e unmount");
8
+ let booted;
9
+ let queue = Promise.resolve();
10
+ const used = /* @__PURE__ */ new Set();
11
+ const step = (fn) => queue = queue.then(fn, fn);
12
+ const boot = (props) => booted ??= run(l.bootstrap, props).catch((e) => {
13
+ booted = void 0;
14
+ throw e;
15
+ });
16
+ return {
17
+ async mount(el, props, ctx) {
18
+ let name = ctx.name;
19
+ for (let i = 2; used.has(name); i++) name = `${ctx.name}-${i}`;
20
+ used.add(name);
21
+ let current = { ...props, name, domElement: el };
22
+ try {
23
+ await step(async () => {
24
+ await boot(current);
25
+ await run(l.mount, current);
26
+ });
27
+ } catch (e) {
28
+ used.delete(name);
29
+ throw e;
30
+ }
31
+ const report = (e) => ctx.reportError(e);
32
+ return {
33
+ update(next) {
34
+ const before = current;
35
+ current = { ...next, name, domElement: el };
36
+ const job = l.update ? step(() => run(l.update, current)) : step(async () => {
37
+ await run(l.unmount, before);
38
+ await run(l.mount, current);
39
+ });
40
+ job.catch(report);
41
+ },
42
+ unmount() {
43
+ used.delete(name);
44
+ step(() => run(l.unmount, current)).catch(report);
45
+ }
46
+ };
47
+ }
48
+ };
49
+ }
50
+ export {
51
+ singleSpaRemote
52
+ };
@@ -1,5 +1,5 @@
1
- import { R as RemoteError } from './errors-KKB8FGCz.js';
2
- import { P as Props, I as Isolation, b as StyleOptions } from './types-BV-hUrms.js';
1
+ import { R as RemoteError } from './errors-kjBv6IH_.js';
2
+ import { P as Props, I as Isolation, d as StyleOptions } from './types-CA2p9KHC.js';
3
3
 
4
4
  type SlotStatus = 'loading' | 'ready' | 'error';
5
5
  interface SlotOptions<P extends Props = Props> {
package/dist/solid.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { JSX, Component, Accessor } from 'solid-js';
2
- import { P as Props, I as Isolation, C as CheckedProps, a as RemoteModule, S as Shared } from './types-BV-hUrms.js';
3
- export { R as RemoteContext } from './types-BV-hUrms.js';
4
- import { R as RemoteError } from './errors-KKB8FGCz.js';
5
- export { e as events } from './events-DUdjhfps.js';
2
+ import { P as Props, I as Isolation, C as CheckedProps, a as RemoteModule, S as Shared } from './types-CA2p9KHC.js';
3
+ export { R as RemoteContext } from './types-CA2p9KHC.js';
4
+ import { R as RemoteError } from './errors-kjBv6IH_.js';
5
+ export { e as events } from './events-Dkpkw_Sv.js';
6
6
  export { n as navigate } from './navigate-BRG1WJUM.js';
7
7
  import { L as Loading, P as Prefetch } from './host-slot-Cz6EiGsB.js';
8
8
 
package/dist/solid.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  hostSlot
3
- } from "./chunk-UTYAX6MU.js";
3
+ } from "./chunk-W6322KGP.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-WD4CDGDZ.js";
12
+ import "./chunk-EMSB2NVX.js";
13
+ import "./chunk-6EX5KYT5.js";
14
+ import "./chunk-TW7KYJQ6.js";
15
+ import "./chunk-463H6B56.js";
15
16
  import "./chunk-GNPFWISJ.js";
16
17
 
17
18
  // src/solid.ts
@@ -1,12 +1,14 @@
1
1
  import {
2
2
  verifyIntegrity
3
- } from "./chunk-S5MZT5IT.js";
3
+ } from "./chunk-UYOPJ4XQ.js";
4
4
  import {
5
- RemoteError,
6
5
  addLink,
7
6
  fetchBytes,
8
7
  withTimeout
9
- } from "./chunk-PX7PBCCT.js";
8
+ } from "./chunk-TW7KYJQ6.js";
9
+ import {
10
+ RemoteError
11
+ } from "./chunk-463H6B56.js";
10
12
  import "./chunk-GNPFWISJ.js";
11
13
 
12
14
  // src/core/sri.ts
@@ -39,7 +41,24 @@ var STRICT = /^(sha(256|384|512)-[A-Za-z0-9+/]+={0,2}( +|$))+$/;
39
41
  var PROBE = "data:text/javascript,export{}";
40
42
  var PROBE_SRI = "sha256-d3bjIZdvLjBurwdLwkSVOnEBPFFly+T1SR9r3VVHBGg=";
41
43
  var maps;
44
+ var probing;
42
45
  var preloads;
46
+ var KEY = "vitral:sri-map";
47
+ async function useMap(sri) {
48
+ if (probing) return await probing && addMap(sri, false);
49
+ let seen = false;
50
+ try {
51
+ seen = localStorage[KEY] === navigator.userAgent;
52
+ } catch {
53
+ }
54
+ const ok = await (probing = addMap(sri, !seen));
55
+ if (ok && !seen)
56
+ try {
57
+ localStorage[KEY] = navigator.userAgent;
58
+ } catch {
59
+ }
60
+ return ok;
61
+ }
43
62
  var tick = () => new Promise((resolve) => {
44
63
  const c = new MessageChannel();
45
64
  c.port1.onmessage = () => resolve();
@@ -52,7 +71,7 @@ async function verified(build, run) {
52
71
  const p = globalThis[/* @__PURE__ */ Symbol.for("vitral")];
53
72
  const share = async (pre) => {
54
73
  if (!run || !dedupe.length) return;
55
- const { shared } = await import("./dedupe-IWFIXRWG.js");
74
+ const { shared } = await import("./dedupe-S7BHQMOZ.js");
56
75
  for (const d of dedupe)
57
76
  shared(p)(d.name, d.range, {
58
77
  version: d.version,
@@ -63,7 +82,7 @@ async function verified(build, run) {
63
82
  }
64
83
  });
65
84
  };
66
- if (maps !== false && (maps = await addMap(sri))) {
85
+ if (maps !== false && (maps = await useMap(sri))) {
67
86
  await share();
68
87
  for (const u of chunks) fetch(u, { priority }).catch(() => {
69
88
  });
@@ -76,7 +95,12 @@ async function verified(build, run) {
76
95
  return entry;
77
96
  }
78
97
  }
79
- async function addMap(integrity) {
98
+ async function addMap(sri, probe) {
99
+ if (!HTMLScriptElement.supports?.("importmap")) return false;
100
+ const integrity = {};
101
+ for (const u in sri) if (!/\.css([?#]|$)/.test(u)) integrity[u] = sri[u];
102
+ const urls = probe ? ["export{}", "export{}//"].map((c) => URL.createObjectURL(new Blob([c], { type: "text/javascript" }))) : [];
103
+ for (const u of urls) integrity[u] = PROBE_SRI;
80
104
  let ok = true;
81
105
  try {
82
106
  const s = document.createElement("script");
@@ -86,11 +110,17 @@ async function addMap(integrity) {
86
110
  s.addEventListener("securitypolicyviolation", () => ok = false);
87
111
  s.textContent = JSON.stringify({ integrity });
88
112
  document.head.append(s);
113
+ await tick();
114
+ await tick();
115
+ if (ok && probe) ok = await check((u) => import(
116
+ /* @vite-ignore */
117
+ /* webpackIgnore: true */
118
+ u
119
+ ), urls[0], urls[1]);
89
120
  } catch {
90
- return false;
121
+ ok = false;
91
122
  }
92
- await tick();
93
- await tick();
123
+ for (const u of urls) URL.revokeObjectURL(u);
94
124
  return ok;
95
125
  }
96
126
  function preload(href, integrity, fetchPriority = "auto") {
@@ -102,9 +132,11 @@ function preload(href, integrity, fetchPriority = "auto") {
102
132
  }
103
133
  function checkPreloads() {
104
134
  if (!document.createElement("link").relList.supports("modulepreload")) return Promise.resolve(false);
105
- const run = (href, good) => preload(href, PROBE_SRI).then(() => good, () => !good);
135
+ return check((href) => preload(href, PROBE_SRI), PROBE, PROBE + "//");
136
+ }
137
+ function check(load, good, bad) {
106
138
  return Promise.race([
107
- Promise.all([run(PROBE, true), run(PROBE + "//", false)]).then(([a, b]) => a && b),
139
+ Promise.all([load(good).then(() => true, () => false), load(bad).then(() => false, () => true)]).then(([a, b]) => a && b),
108
140
  new Promise((resolve) => setTimeout(resolve, 3e3, false))
109
141
  ]);
110
142
  }
package/dist/svelte.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { Component } from 'svelte';
2
- import { P as Props, I as Isolation, a as RemoteModule } from './types-BV-hUrms.js';
3
- export { R as RemoteContext } from './types-BV-hUrms.js';
4
- import { R as RemoteError } from './errors-KKB8FGCz.js';
5
- import { S as SlotStatus } from './slot-pB276oPt.js';
6
- export { e as events } from './events-DUdjhfps.js';
2
+ import { P as Props, I as Isolation, a as RemoteModule } from './types-CA2p9KHC.js';
3
+ export { R as RemoteContext } from './types-CA2p9KHC.js';
4
+ import { R as RemoteError } from './errors-kjBv6IH_.js';
5
+ import { S as SlotStatus } from './slot-UPg6ob9v.js';
6
+ export { e as events } from './events-Dkpkw_Sv.js';
7
7
  export { n as navigate } from './navigate-BRG1WJUM.js';
8
8
  import { L as Loading, P as Prefetch } from './host-slot-Cz6EiGsB.js';
9
9
 
package/dist/svelte.js CHANGED
@@ -1,14 +1,15 @@
1
1
  import {
2
2
  hostSlot
3
- } from "./chunk-UTYAX6MU.js";
3
+ } from "./chunk-W6322KGP.js";
4
4
  import {
5
5
  defineRemote,
6
6
  events,
7
7
  navigate
8
- } from "./chunk-NCONW6WS.js";
9
- import "./chunk-2XF5BKV3.js";
10
- import "./chunk-SFL6LTP3.js";
11
- import "./chunk-PX7PBCCT.js";
8
+ } from "./chunk-WD4CDGDZ.js";
9
+ import "./chunk-EMSB2NVX.js";
10
+ import "./chunk-6EX5KYT5.js";
11
+ import "./chunk-TW7KYJQ6.js";
12
+ import "./chunk-463H6B56.js";
12
13
  import "./chunk-GNPFWISJ.js";
13
14
 
14
15
  // src/svelte.ts
package/dist/testing.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { P as Props, R as RemoteContext } from './types-BV-hUrms.js';
1
+ import { P as Props, R as RemoteContext } from './types-CA2p9KHC.js';
2
2
  export { r as resetVitral } from './state-BDdCwc21.js';
3
+ import './errors-kjBv6IH_.js';
3
4
 
4
5
  /**
5
6
  * Utilidades de teste: monte o host sem subir nenhum remote de verdade.
package/dist/testing.js CHANGED
@@ -1,9 +1,10 @@
1
- import "./chunk-NCONW6WS.js";
1
+ import "./chunk-WD4CDGDZ.js";
2
2
  import {
3
3
  register
4
- } from "./chunk-2XF5BKV3.js";
5
- import "./chunk-SFL6LTP3.js";
6
- import "./chunk-PX7PBCCT.js";
4
+ } from "./chunk-EMSB2NVX.js";
5
+ import "./chunk-6EX5KYT5.js";
6
+ import "./chunk-TW7KYJQ6.js";
7
+ import "./chunk-463H6B56.js";
7
8
  import {
8
9
  resetProtocol
9
10
  } from "./chunk-GNPFWISJ.js";
@@ -1,3 +1,5 @@
1
+ import { R as RemoteError } from './errors-kjBv6IH_.js';
2
+
1
3
  /**
2
4
  * Tipos das chaves compartilhadas. Declare uma vez no projeto:
3
5
  *
@@ -90,6 +92,24 @@ interface RemoteContext {
90
92
  events: EventBus;
91
93
  /** Shadow root quando o host pediu isolamento, senão `null`. */
92
94
  shadowRoot: ShadowRoot | null;
95
+ /**
96
+ * Onde popovers, menus e dialogs devem ser renderizados (`container` do
97
+ * Radix e do MUI, `Teleport` do Vue). No Shadow DOM é um elemento dentro do
98
+ * shadow root, com os estilos e o tema do remote; senão, `document.body`.
99
+ * Hosts antigos não mandam este campo.
100
+ */
101
+ portalContainer?: HTMLElement;
102
+ /**
103
+ * Registro de custom elements do remote. No Shadow DOM, onde o navegador
104
+ * tem Scoped Custom Element Registries (Chrome 146+, Safari 26+), é um
105
+ * registro só deste remote, usado pelo shadow root e pelo elemento `el`:
106
+ * dois remotes podem definir `<ds-button>` de versões diferentes. Sem
107
+ * suporte, e fora do Shadow DOM, é o `customElements` global. No Shadow
108
+ * DOM, `define` de uma tag já definida não lança: fica a definição que já
109
+ * existe, com um aviso em dev quando ela veio de outro remote. Hosts
110
+ * antigos não mandam este campo: use `ctx.customElements ?? customElements`.
111
+ */
112
+ customElements?: CustomElementRegistry;
93
113
  /** Avisa o host de um erro em tempo de execução (os adaptadores já chamam). */
94
114
  reportError(error: unknown): void;
95
115
  /** Navega a página inteira (host e todos os roteadores) para `url`. */
@@ -115,6 +135,21 @@ interface RemoteContext {
115
135
  * (`provide`, `shared` ou um hook); senão, importe `shared` de 'vitral'.
116
136
  */
117
137
  shared?: SharedApi;
138
+ /**
139
+ * Só quando o remote roda como MCP App (`vitral({ target: 'mcp-app' })`):
140
+ * fala JSON-RPC direto com o host MCP, para o que `events` não cobre
141
+ * (`tools/call`, `resources/read`, `ui/request-display-mode`…).
142
+ */
143
+ mcp?: McpAppBridge;
144
+ }
145
+ /** `ctx.mcp` de um remote empacotado como MCP App. */
146
+ interface McpAppBridge {
147
+ /** Pedido ao host; resolve com `result` ou rejeita com `error.message`. */
148
+ request<T = unknown>(method: string, params?: Record<string, unknown>): Promise<T>;
149
+ /** Notificação ao host (sem resposta). */
150
+ notify(method: string, params?: Record<string, unknown>): void;
151
+ /** O `hostContext` atual (tema, idioma, tamanho do container…), já com as mudanças. */
152
+ hostContext(): Record<string, unknown> | undefined;
118
153
  }
119
154
  interface MountedRemote<P extends Props = Props> {
120
155
  update?(props: P): void;
@@ -140,11 +175,70 @@ interface RemoteEntry {
140
175
  /** Isolamento padrão para este remote. */
141
176
  isolate?: Isolation;
142
177
  /**
143
- * O `vitral.json` já baixado (ex.: por `vitral registry`), para não buscá-lo
178
+ * O `vitral.json` já baixado (ex.: no build do host), para não buscá-lo
144
179
  * na hora. Os caminhos dele são relativos a `url`, e os hashes ficam fixos
145
180
  * no host.
146
181
  */
147
182
  manifest?: RemoteManifest;
183
+ /**
184
+ * Faixa de versão do contrato do remote que o host aceita (ex.: `'^2'`).
185
+ * Vence a de `configure`. Veja `VitralConfig.contract`.
186
+ */
187
+ contract?: string;
188
+ /**
189
+ * Com `url` apontando para um canal (`canal.json`): escolhe a versão deste
190
+ * usuário. Devolve a versão (`'1.5.0'`) ou a URL de um `vitral.json`;
191
+ * `undefined` usa a regra padrão (`canary.percent`). Veja `Channel`.
192
+ */
193
+ resolve?: (channel: Channel, ctx: ChannelContext) => string | undefined | Promise<string | undefined>;
194
+ /**
195
+ * Volta para a estável, até o fim da sessão, quando a versão que não é a
196
+ * estável gera `errors` erros numa janela de `mounts` montagens. Padrão
197
+ * `{ errors: 3, mounts: 20 }`. `false` desliga.
198
+ */
199
+ rollback?: {
200
+ errors?: number;
201
+ mounts?: number;
202
+ } | false;
203
+ }
204
+ /**
205
+ * Arquivo-ponteiro de um remote (o canal, ex.: `canal.json`): diz que versão
206
+ * cada usuário recebe. Cada versão fica na própria pasta, ao lado do canal
207
+ * (`'1.4.0'` → `1.4.0/vitral.json`), ou é a URL de um `vitral.json`.
208
+ *
209
+ * { "stable": "1.4.0", "canary": { "version": "1.5.0", "percent": 10 } }
210
+ */
211
+ interface Channel {
212
+ /** Versão de todos os usuários fora da canary. */
213
+ stable: string;
214
+ /** Versão nova para `percent`% dos usuários (0 a 100). */
215
+ canary?: {
216
+ version: string;
217
+ percent: number;
218
+ };
219
+ /** Campos próprios, para o `resolve` do host ler (ex.: `"beta": "1.6.0"`). */
220
+ [key: string]: unknown;
221
+ }
222
+ /** O que o `resolve` de um canal recebe além do canal. */
223
+ interface ChannelContext {
224
+ /** Nome do remote. */
225
+ name: string;
226
+ /**
227
+ * Número de 0 a 99, sempre o mesmo para este navegador (ou para
228
+ * `canaryKey`) e este remote. A regra padrão dá a canary a quem tem
229
+ * `bucket < percent`.
230
+ */
231
+ bucket: number;
232
+ }
233
+ /** Aviso de rollback automático, para `configure({ onRollback })`. */
234
+ interface RollbackInfo {
235
+ name: string;
236
+ /** Versão abandonada (como o canal ou o `resolve` a escreveram). */
237
+ from: string;
238
+ /** Versão estável, usada daqui até o fim da sessão. */
239
+ to: string;
240
+ errors: number;
241
+ mounts: number;
148
242
  }
149
243
  /**
150
244
  * `none`: CSS com escopo. `shadow`: Shadow DOM. `iframe`: iframe com
@@ -164,6 +258,15 @@ interface StyleOptions {
164
258
  */
165
259
  mirrorTheme?: boolean;
166
260
  }
261
+ /** Opções de `configure({ devOverrides })`. */
262
+ interface DevOverrides {
263
+ /**
264
+ * Modelo da URL de um apelido: `?vitral=checkout@pr-123` com
265
+ * `'https://{name}-{ref}.preview.empresa.com'` vira
266
+ * `https://checkout-pr-123.preview.empresa.com/vitral.json`.
267
+ */
268
+ preview?: string;
269
+ }
167
270
  interface VitralConfig {
168
271
  /** Mapa nome → URL (ou entrada completa), ou a URL de um JSON com esse mapa. */
169
272
  remotes?: Record<string, string | RemoteEntry> | string;
@@ -182,13 +285,26 @@ interface VitralConfig {
182
285
  * Liga os overrides de desenvolvimento (`?vitral=nome@url` e
183
286
  * `localStorage['vitral:overrides']`) fora de localhost. Em localhost já
184
287
  * valem. Nunca ligue em produção: um link com `?vitral=` executaria código
185
- * de qualquer origem.
288
+ * de qualquer origem. O objeto também liga e aceita `preview`, o modelo de
289
+ * URL dos apelidos (`?vitral=checkout@pr-123`).
186
290
  */
187
- devOverrides?: boolean;
291
+ devOverrides?: boolean | DevOverrides;
188
292
  /** Estilos do host no Shadow DOM: `{ inherit: ['/assets/base.css'] }`. */
189
293
  styles?: StyleOptions;
190
294
  /** Recebe o tempo de cada etapa do carregamento (para RUM). */
191
295
  onMetric?: (metric: RemoteMetric) => void;
296
+ /**
297
+ * Recebe cada `RemoteError` de qualquer remote (falha de download, de
298
+ * `mount`, erro de render), uma vez só por erro, além do `onError` de cada
299
+ * montagem. Use para mandar os erros ao seu monitoramento.
300
+ */
301
+ onError?: (error: RemoteError) => void;
302
+ /**
303
+ * Atribui a um remote os erros sem tratamento (`error` e
304
+ * `unhandledrejection` da janela) cujo topo da pilha é um arquivo dele, e
305
+ * entrega como `RENDER_FAILED` ao `onError`. Padrão `false`.
306
+ */
307
+ captureGlobalErrors?: boolean;
192
308
  /**
193
309
  * Dependências que o host oferece aos remotes com `dedupe`, por grupo:
194
310
  * `{ vue: { version: Vue.version, modules: { vue: Vue } } }`. O remote usa
@@ -198,6 +314,24 @@ interface VitralConfig {
198
314
  version: string;
199
315
  modules: SharedModules;
200
316
  }>;
317
+ /**
318
+ * Faixa de versão do contrato que o host aceita dos remotes (ex.: `'^2'`).
319
+ * Antes de executar o remote, o host confere a versão do `contract` do
320
+ * manifesto e as dependências que ele espera do host; se não servir, o
321
+ * remote não monta (`CONTRACT_MISMATCH`). Sem contrato no manifesto, nada é
322
+ * conferido. `'*'` confere só as dependências.
323
+ */
324
+ contract?: string;
325
+ /**
326
+ * Chave estável do usuário (ex.: o id dele) para sortear quem recebe a
327
+ * canary de um canal. Padrão: um id aleatório guardado no `localStorage`.
328
+ */
329
+ canaryKey?: string;
330
+ /**
331
+ * Chamado quando a versão canary de um canal passa do limite de erros e o
332
+ * host volta para a estável (veja `RemoteEntry.rollback`).
333
+ */
334
+ onRollback?: (info: RollbackInfo) => void;
201
335
  }
202
336
  /** Módulos de um grupo de `dedupe`, por especificador (`'react-dom/client'`). */
203
337
  type SharedModules = Record<string, unknown>;
@@ -253,6 +387,42 @@ interface RemoteManifest {
253
387
  file: string;
254
388
  chunks?: string[];
255
389
  }[];
390
+ /** O que o remote declara para o host conferir antes de montar. */
391
+ contract?: RemoteContract;
392
+ /**
393
+ * CSS já preparado no build para o Shadow DOM. Sem este campo (manifestos
394
+ * antigos), o runtime faz esse trabalho em cada página.
395
+ */
396
+ shadow?: ShadowCss;
397
+ /**
398
+ * SBOM CycloneDX do remote (opção `sbom` do plugin): o arquivo, relativo
399
+ * ao manifesto, e o hash dele. O runtime não usa; é para auditoria.
400
+ */
401
+ sbom?: {
402
+ file: string;
403
+ integrity: string;
404
+ };
405
+ }
406
+ /** Contrato do remote no `vitral.json`. */
407
+ interface RemoteContract {
408
+ /** Versão do contrato (opção `contract.version` do plugin). */
409
+ version?: string;
410
+ /** Faixa aceita de cada dependência de `dedupe`, por grupo (`{ react: '^19.0.0' }`). */
411
+ peers?: Record<string, string>;
412
+ }
413
+ /**
414
+ * CSS do remote preparado no build para `isolate: 'shadow'`. Os caminhos são
415
+ * relativos ao primeiro arquivo de `css` (o plugin grava tudo na mesma pasta).
416
+ */
417
+ interface ShadowCss {
418
+ /** Cada arquivo de `css`, na mesma ordem, sem `@import`, `@property` e `@font-face`. */
419
+ css: string[];
420
+ /** `@property` e `@font-face`, que só valem no documento (vão num `<link>`). */
421
+ global?: string[];
422
+ /** `@import` que o build não embutiu (outra origem), adotados antes de `css`. */
423
+ imports?: string[];
424
+ /** O CSS ainda tem `url()` relativa, que precisa apontar para o remote. */
425
+ rebase?: boolean;
256
426
  }
257
427
  type Handler<T = unknown> = (payload: T) => void;
258
428
  interface EventBus {
@@ -262,4 +432,4 @@ interface EventBus {
262
432
  last<T = unknown>(type: string): T | undefined;
263
433
  }
264
434
 
265
- export { type CheckedProps as C, type EventBus as E, type Handler as H, type Isolation as I, type MountedRemote as M, type Props as P, type RemoteContext as R, type Shared as S, type VitralConfig as V, type RemoteModule as a, type StyleOptions as b, type RemoteEntry as c, type SharedValue as d, type PropsOf as e, type ProvideOptions as f, type ProvidedValue as g, type RemoteManifest as h, type RemoteMetric as i, type Remotes as j, type SharedApi as k, type SharedModules as l, type SharedType as m, batch as n, provide as p, shared as s };
435
+ export { type CheckedProps as C, type DevOverrides as D, type EventBus as E, type Handler as H, type Isolation as I, type MountedRemote as M, type Props as P, type RemoteContext as R, type Shared as S, type VitralConfig as V, type RemoteModule as a, type SharedModules as b, type RemoteEntry as c, type StyleOptions as d, type SharedValue as e, type Channel as f, type ChannelContext as g, type McpAppBridge as h, type PropsOf as i, type ProvideOptions as j, type ProvidedValue as k, type RemoteContract as l, type RemoteManifest as m, type RemoteMetric as n, type Remotes as o, type RollbackInfo as p, type SharedApi as q, type SharedType as r, batch as s, provide as t, shared as u };
package/dist/vite.d.ts CHANGED
@@ -72,6 +72,32 @@ interface VitralViteOptions extends CssBuildOptions {
72
72
  * projeto e de entrada .ts/.tsx/.js/.jsx. Padrão: true.
73
73
  */
74
74
  types?: boolean;
75
+ /**
76
+ * Contrato publicado no `vitral.json`. O host que declara
77
+ * `contract: '^2'` só monta o remote se `version` estiver na faixa. As
78
+ * faixas de `dedupe` entram sozinhas, em `peers`. Padrão: sem versão.
79
+ */
80
+ contract?: {
81
+ version?: string;
82
+ };
83
+ /**
84
+ * Gera `sbom.cdx.json` (CycloneDX 1.6) com os pacotes npm que entraram no
85
+ * bundle, e o `vitral.json` aponta para ele em `sbom`. Padrão: false.
86
+ */
87
+ sbom?: boolean;
88
+ /**
89
+ * `'mcp-app'`: o build gera só `mcp-app.html`, um HTML único com o JS e o
90
+ * CSS inline, para um servidor MCP servir como recurso `ui://` (MCP Apps).
91
+ * As notificações do host viram props e `ctx.events.emit` vira mensagem
92
+ * para o host. Não combina com `exposes`, `dedupe` nem `shared`.
93
+ */
94
+ target?: 'mcp-app';
95
+ /**
96
+ * Grava o build em uma pasta por versão (`dist/1.5.0/`), para publicar
97
+ * cada versão sem apagar as anteriores e escolher qual vale num canal
98
+ * (`canal.json`). Usa `version` (ou a do package.json). Padrão: false.
99
+ */
100
+ versionDir?: boolean;
75
101
  }
76
102
  declare function vitral(options?: VitralViteOptions): Plugin;
77
103