vitral 0.3.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 (55) hide show
  1. package/dist/angular.d.ts +2 -2
  2. package/dist/angular.js +7 -7
  3. package/dist/auto.js +7 -7
  4. package/dist/{capture-JYFERAPL.js → capture-TT5WBLJ6.js} +1 -1
  5. package/dist/channel-2YPYGX3J.js +95 -0
  6. package/dist/{chunk-AKNNHQ2H.js → chunk-463H6B56.js} +5 -0
  7. package/dist/chunk-54CBIZES.js +105 -0
  8. package/dist/{chunk-ZAC6QQI6.js → chunk-6EX5KYT5.js} +4 -4
  9. package/dist/{chunk-3YXI3G34.js → chunk-BCC25ANK.js} +11 -5
  10. package/dist/{chunk-TD4S3IHA.js → chunk-EMSB2NVX.js} +10 -8
  11. package/dist/{chunk-SDB5AZEI.js → chunk-IH3ZT3QU.js} +2 -2
  12. package/dist/{chunk-GNHCZRQP.js → chunk-TW7KYJQ6.js} +1 -1
  13. package/dist/{chunk-AH7KNMBW.js → chunk-UYOPJ4XQ.js} +1 -1
  14. package/dist/{chunk-IHTUM6LT.js → chunk-W6322KGP.js} +2 -2
  15. package/dist/{chunk-I3VSKSAZ.js → chunk-WD4CDGDZ.js} +21 -20
  16. package/dist/cli.js +1152 -37
  17. package/dist/devtools.d.ts +32 -2
  18. package/dist/devtools.js +27 -12
  19. package/dist/element.d.ts +12 -3
  20. package/dist/element.js +7 -7
  21. package/dist/embed.js +2 -0
  22. package/dist/{events-D5gs7rff.d.ts → events-Dkpkw_Sv.d.ts} +1 -1
  23. package/dist/expose-OVWTPHH5.js +15 -0
  24. package/dist/federation.d.ts +89 -0
  25. package/dist/federation.js +101 -0
  26. package/dist/iframe.js +7 -7
  27. package/dist/index.d.ts +4 -4
  28. package/dist/index.js +5 -5
  29. package/dist/overrides-NP754HY7.js +27 -0
  30. package/dist/preact.d.ts +4 -4
  31. package/dist/preact.js +6 -6
  32. package/dist/react.d.ts +3 -3
  33. package/dist/react.js +6 -6
  34. package/dist/routes.d.ts +2 -2
  35. package/dist/routes.js +5 -5
  36. package/dist/{shadow-6HELCHCJ.js → shadow-PVSETNMZ.js} +66 -5
  37. package/dist/single-spa.d.ts +40 -0
  38. package/dist/single-spa.js +52 -0
  39. package/dist/{slot-DqXTwGbs.d.ts → slot-UPg6ob9v.d.ts} +1 -1
  40. package/dist/solid.d.ts +3 -3
  41. package/dist/solid.js +6 -6
  42. package/dist/{sri-JMX6JLQP.js → sri-M7ZRU57G.js} +40 -10
  43. package/dist/svelte.d.ts +4 -4
  44. package/dist/svelte.js +6 -6
  45. package/dist/testing.d.ts +1 -1
  46. package/dist/testing.js +5 -5
  47. package/dist/{types-Czvm-siZ.d.ts → types-CA2p9KHC.d.ts} +112 -4
  48. package/dist/vite.d.ts +18 -0
  49. package/dist/vite.js +341 -35
  50. package/dist/vue.d.ts +3 -3
  51. package/dist/vue.js +6 -6
  52. package/package.json +79 -21
  53. package/dist/chunk-DXORSF4X.js +0 -42
  54. package/dist/expose-JUOUN5N5.js +0 -15
  55. package/dist/overrides-NZAIUGK5.js +0 -15
package/dist/vite.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/vite.ts
2
- import { createHash as createHash2 } from "crypto";
3
- import { readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
4
- import { join as join5, resolve as resolve5 } from "path";
2
+ import { createHash as createHash3 } from "crypto";
3
+ import { readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
4
+ import { join as join6, resolve as resolve5 } from "path";
5
5
 
6
6
  // src/vite-exposes.ts
7
7
  import { resolve } from "path";
@@ -105,9 +105,149 @@ function withSplit(m, outDir, s, groups2 = []) {
105
105
  return { ...m, files, ...s && { split: { entry: s.entry, chunks: s.chunks } }, ...dedupe.length && { dedupe } };
106
106
  }
107
107
 
108
+ // src/vite/sbom.ts
109
+ import { createHash as createHash2 } from "crypto";
110
+ import { existsSync, readFileSync as readFileSync2, realpathSync } from "fs";
111
+ import { dirname, isAbsolute, join as join2, sep } from "path";
112
+ var SBOM_FILE = "sbom.cdx.json";
113
+ var readPkg = (dir) => {
114
+ try {
115
+ return JSON.parse(readFileSync2(join2(dir, "package.json"), "utf8"));
116
+ } catch {
117
+ return void 0;
118
+ }
119
+ };
120
+ function bundledFiles(bundle, into = /* @__PURE__ */ new Set()) {
121
+ for (const f of Object.values(bundle)) {
122
+ if (f.type !== "chunk" || !f.modules) continue;
123
+ for (const [id, m] of Object.entries(f.modules)) {
124
+ const file = id.split("?")[0];
125
+ if (m.renderedLength > 0 && isAbsolute(file)) into.add(file);
126
+ }
127
+ }
128
+ return into;
129
+ }
130
+ function packageDirs(files) {
131
+ const dirs = /* @__PURE__ */ new Set();
132
+ const near = /* @__PURE__ */ new Map();
133
+ const nearest = (dir) => {
134
+ if (near.has(dir)) return near.get(dir);
135
+ const parent = dirname(dir);
136
+ const found = readPkg(dir)?.name ? dir : parent === dir ? null : nearest(parent);
137
+ near.set(dir, found);
138
+ return found;
139
+ };
140
+ const nm = `${sep}node_modules${sep}`;
141
+ for (const file of files) {
142
+ const at = file.lastIndexOf(nm);
143
+ if (at >= 0) {
144
+ const parts = file.slice(at + nm.length).split(sep);
145
+ const name = parts[0].startsWith("@") ? parts.slice(0, 2).join(sep) : parts[0];
146
+ if (parts.length > (parts[0].startsWith("@") ? 2 : 1)) dirs.add(file.slice(0, at + nm.length) + name);
147
+ } else {
148
+ const dir = nearest(dirname(file));
149
+ if (dir) dirs.add(dir);
150
+ }
151
+ }
152
+ return dirs;
153
+ }
154
+ function purl(name, version) {
155
+ const path = name.split("/").map(encodeURIComponent).join("/");
156
+ return `pkg:npm/${path}${version ? `@${encodeURIComponent(version)}` : ""}`;
157
+ }
158
+ function licenses(pkg) {
159
+ const raw = typeof pkg.license === "string" ? pkg.license : pkg.license?.type ?? pkg.licenses?.map((l) => l.type).filter(Boolean).join(" OR ");
160
+ if (!raw) return void 0;
161
+ const spdx = /^\(?[A-Za-z0-9.+-]+( (AND|OR|WITH) \(?[A-Za-z0-9.+-]+\)?)*\)?$/.test(raw) && raw !== "UNLICENSED";
162
+ return spdx ? [{ expression: raw }] : [{ license: { name: raw } }];
163
+ }
164
+ function component(pkg, type) {
165
+ const scoped = pkg.name.startsWith("@") && pkg.name.includes("/");
166
+ const ref = purl(pkg.name, pkg.version);
167
+ const license = licenses(pkg);
168
+ return {
169
+ type,
170
+ "bom-ref": ref,
171
+ ...scoped && { group: pkg.name.slice(0, pkg.name.indexOf("/")) },
172
+ name: scoped ? pkg.name.slice(pkg.name.indexOf("/") + 1) : pkg.name,
173
+ ...pkg.version && { version: pkg.version },
174
+ ...pkg.description && { description: pkg.description },
175
+ ...license && { licenses: license },
176
+ purl: ref
177
+ };
178
+ }
179
+ function resolveDir(from, name) {
180
+ for (let dir = from; ; dir = dirname(dir)) {
181
+ const candidate = join2(dir, "node_modules", name);
182
+ if (existsSync(join2(candidate, "package.json"))) {
183
+ try {
184
+ return realpathSync(candidate);
185
+ } catch {
186
+ return candidate;
187
+ }
188
+ }
189
+ if (dirname(dir) === dir) return void 0;
190
+ }
191
+ }
192
+ function createSbom(input) {
193
+ const rootDir = realpathSync(input.root);
194
+ const rootPkg = readPkg(rootDir) ?? {};
195
+ const main = component({ ...rootPkg, name: input.name, version: input.version }, "application");
196
+ const hashes = input.entry && [{ alg: "SHA-512", content: createHash2("sha512").update(input.entry).digest("hex") }];
197
+ const byDir = /* @__PURE__ */ new Map();
198
+ for (const dir of packageDirs(input.files)) {
199
+ let real = dir;
200
+ try {
201
+ real = realpathSync(dir);
202
+ } catch {
203
+ }
204
+ const pkg = readPkg(real);
205
+ if (real === rootDir || !pkg?.name || byDir.has(real)) continue;
206
+ byDir.set(real, { pkg, ref: purl(pkg.name, pkg.version) });
207
+ }
208
+ const deps = (dir, pkg) => {
209
+ const names = Object.keys({ ...pkg.peerDependencies, ...pkg.optionalDependencies, ...pkg.dependencies });
210
+ const refs = /* @__PURE__ */ new Set();
211
+ for (const n of names) {
212
+ const hit = byDir.get(resolveDir(dir, n) ?? "");
213
+ if (hit) refs.add(hit.ref);
214
+ }
215
+ return [...refs].sort();
216
+ };
217
+ const components = /* @__PURE__ */ new Map();
218
+ const graph = /* @__PURE__ */ new Map([[main["bom-ref"], new Set(deps(rootDir, rootPkg))]]);
219
+ for (const [dir, { pkg, ref }] of byDir) {
220
+ if (!components.has(ref)) components.set(ref, component(pkg, "library"));
221
+ const set = graph.get(ref) ?? /* @__PURE__ */ new Set();
222
+ for (const d of deps(dir, pkg)) if (d !== ref) set.add(d);
223
+ graph.set(ref, set);
224
+ }
225
+ const epoch = Number(process.env.SOURCE_DATE_EPOCH);
226
+ const timestamp = input.timestamp ?? (Number.isFinite(epoch) && process.env.SOURCE_DATE_EPOCH ? new Date(epoch * 1e3) : /* @__PURE__ */ new Date());
227
+ const body = {
228
+ metadata: {
229
+ timestamp: timestamp.toISOString().replace(/\.\d{3}Z$/, "Z"),
230
+ tools: { components: [{ type: "application", name: "vitral", ...input.tool && { version: input.tool }, purl: purl("vitral", input.tool) }] },
231
+ component: { ...main, ...hashes && { hashes } }
232
+ },
233
+ components: [...components.values()].sort((a, b) => a["bom-ref"].localeCompare(b["bom-ref"])),
234
+ dependencies: [...graph].map(([ref, set]) => ({ ref, dependsOn: [...set].sort() }))
235
+ };
236
+ const h = createHash2("sha1").update(JSON.stringify(body)).digest("hex");
237
+ const serial = `urn:uuid:${h.slice(0, 8)}-${h.slice(8, 12)}-5${h.slice(13, 16)}-${(parseInt(h[16], 16) & 3 | 8).toString(16)}${h.slice(17, 20)}-${h.slice(20, 32)}`;
238
+ return {
239
+ $schema: "http://cyclonedx.org/schema/bom-1.6.schema.json",
240
+ bomFormat: "CycloneDX",
241
+ specVersion: "1.6",
242
+ serialNumber: serial,
243
+ version: 1,
244
+ ...body
245
+ };
246
+ }
247
+
108
248
  // src/vite/dedupe.ts
109
- import { existsSync, readFileSync as readFileSync2 } from "fs";
110
- import { dirname, join as join2, resolve as resolve2 } from "path";
249
+ import { existsSync as existsSync2, readFileSync as readFileSync3 } from "fs";
250
+ import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
111
251
  import { pathToFileURL } from "url";
112
252
  var REACT = ["react", "react-dom", "react-dom/client", "react/jsx-runtime", "react/jsx-dev-runtime", "react/compiler-runtime"];
113
253
  var BOOT = "virtual:vitral-boot";
@@ -118,10 +258,10 @@ var pkgOf = (spec) => spec.split("/").slice(0, spec.startsWith("@") ? 2 : 1).joi
118
258
  var groupOf = (spec) => REACT.includes(spec) || pkgOf(spec) === "scheduler" ? "react" : pkgOf(spec);
119
259
  var ident = /^[A-Za-z_$][\w$]*$/;
120
260
  function versionOf(file, pkg) {
121
- for (let dir = dirname(file); dir !== dirname(dir); dir = dirname(dir)) {
122
- const json = join2(dir, "package.json");
123
- if (!existsSync(json)) continue;
124
- const data = JSON.parse(readFileSync2(json, "utf8"));
261
+ for (let dir = dirname2(file); dir !== dirname2(dir); dir = dirname2(dir)) {
262
+ const json = join3(dir, "package.json");
263
+ if (!existsSync2(json)) continue;
264
+ const data = JSON.parse(readFileSync3(json, "utf8"));
125
265
  if (data.name === pkg) return data.version;
126
266
  }
127
267
  throw new Error(`vitral: vers\xE3o de ${pkg} n\xE3o encontrada`);
@@ -417,7 +557,7 @@ function splitShadowCss(text) {
417
557
  }
418
558
 
419
559
  // src/vite/adapter.ts
420
- import { existsSync as existsSync2 } from "fs";
560
+ import { existsSync as existsSync3 } from "fs";
421
561
  import { resolve as resolve3 } from "path";
422
562
  var PLUGINS = [
423
563
  [/^(preact:|prefresh$)/, "preact"],
@@ -456,10 +596,14 @@ import { component } from 'vitral'
456
596
  function wrap(c) {
457
597
  if (typeof c === 'function' && typeof HTMLElement !== 'undefined' && c.prototype instanceof HTMLElement) {
458
598
  const base = ${JSON.stringify(`${scope}-remote`.toLowerCase().replace(/^[^a-z]+/, "x-"))}
459
- let tag = customElements.getName?.(c) || base
460
- // Uma tag n\xE3o aceita outra classe: no HMR, a classe nova ganha tag nova.
461
- for (let n = 2; customElements.get(tag) && customElements.get(tag) !== c; n++) tag = base + '-' + n
462
- return elementRemote(tag, () => customElements.get(tag) || customElements.define(tag, c))
599
+ // No registro do remote (ctx.customElements). Uma tag n\xE3o aceita outra
600
+ // classe: no HMR, a classe nova ganha tag nova.
601
+ return elementRemote(base, (r) => {
602
+ let tag = r.getName?.(c) || base
603
+ for (let n = 2; r.get(tag) && r.get(tag) !== c; n++) tag = base + '-' + n
604
+ r.get(tag) || r.define(tag, c)
605
+ return tag
606
+ })
463
607
  }
464
608
  if (typeof c === 'function') return component(c)
465
609
  throw new Error('[vitral] o export default n\xE3o \xE9 um remote: exporte um componente, uma fun\xE7\xE3o ou um objeto com mount()')
@@ -471,21 +615,21 @@ var CANDIDATES = ["src/remote", "src/App", "src/app"];
471
615
  var EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".vue", ".svelte"];
472
616
  function findEntry(root) {
473
617
  for (const base of CANDIDATES) {
474
- for (const ext of EXTENSIONS) if (existsSync2(resolve3(root, base + ext))) return base + ext;
618
+ for (const ext of EXTENSIONS) if (existsSync3(resolve3(root, base + ext))) return base + ext;
475
619
  }
476
620
  }
477
621
 
478
622
  // src/vite/types.ts
479
623
  import { createRequire as createRequire2 } from "module";
480
- import { join as join4 } from "path";
624
+ import { join as join5 } from "path";
481
625
 
482
626
  // src/vite/oxc.ts
483
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
627
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
484
628
  import { createRequire } from "module";
485
- import { dirname as dirname2, join as join3, resolve as resolve4 } from "path";
629
+ import { dirname as dirname3, join as join4, resolve as resolve4 } from "path";
486
630
  import { pathToFileURL as pathToFileURL2 } from "url";
487
631
  async function loadOxc(root) {
488
- const req = createRequire(join3(root, "package.json"));
632
+ const req = createRequire(join4(root, "package.json"));
489
633
  const ids = [() => req.resolve("oxc-transform"), () => createRequire(req.resolve("vite/package.json")).resolve("rolldown/experimental")];
490
634
  for (const id of ids) {
491
635
  try {
@@ -525,7 +669,7 @@ var Reader = class {
525
669
  const cached = this.scopes.get(file);
526
670
  if (cached) return cached;
527
671
  const { ts } = this;
528
- let code = readFileSync3(file, "utf8");
672
+ let code = readFileSync4(file, "utf8");
529
673
  if (!/\.d\.[cm]?ts$/.test(file)) {
530
674
  const out = this.oxc.isolatedDeclarationSync(file, code, {});
531
675
  if (out.errors.length) unsupported();
@@ -738,10 +882,10 @@ var Reader = class {
738
882
  }
739
883
  };
740
884
  function resolveFile(from, spec) {
741
- const base = resolve4(dirname2(from), spec);
885
+ const base = resolve4(dirname3(from), spec);
742
886
  const stem = base.replace(/\.[cm]?jsx?$/, "");
743
- const candidates = [base, ...[".ts", ".tsx", ".mts", ".cts", ".d.ts"].map((ext) => stem + ext), ...["index.ts", "index.tsx", "index.d.ts"].map((f) => join3(base, f))];
744
- const file = candidates.find((f) => /\.[cm]?tsx?$/.test(f) && existsSync3(f));
887
+ const candidates = [base, ...[".ts", ".tsx", ".mts", ".cts", ".d.ts"].map((ext) => stem + ext), ...["index.ts", "index.tsx", "index.d.ts"].map((f) => join4(base, f))];
888
+ const file = candidates.find((f) => /\.[cm]?tsx?$/.test(f) && existsSync4(f));
745
889
  return file ?? unsupported();
746
890
  }
747
891
 
@@ -754,7 +898,7 @@ export type Props = ${props}
754
898
  async function loadTs(root) {
755
899
  const api = (ts) => typeof ts?.createProgram === "function" ? ts : null;
756
900
  try {
757
- const ts = api(createRequire2(join4(root, "package.json"))("typescript"));
901
+ const ts = api(createRequire2(join5(root, "package.json"))("typescript"));
758
902
  if (ts) return ts;
759
903
  } catch {
760
904
  }
@@ -874,6 +1018,116 @@ var Printer = class {
874
1018
  }
875
1019
  };
876
1020
 
1021
+ // src/vite/mcp-app.ts
1022
+ var MCP_APP_PROTOCOL = "2026-01-26";
1023
+ var MCP_APP_GLOBAL = "__vitral_remote__";
1024
+ var MCP_RUNTIME = `function (w, mod, info) {
1025
+ var parent = w.parent, doc = w.document, seq = 0, pending = {}, handlers = {}, last = {}, context = {}
1026
+ var props = {}, mounted = null, ready = false, dirty = false
1027
+ function send(m) { m.jsonrpc = '2.0'; parent.postMessage(m, '*') }
1028
+ function request(method, params) {
1029
+ var id = ++seq
1030
+ return new Promise(function (ok, fail) {
1031
+ pending[id] = [ok, fail]
1032
+ send({ id: id, method: method, params: params || {} })
1033
+ })
1034
+ }
1035
+ function notify(method, params) { send({ method: method, params: params || {} }) }
1036
+ function report(e) { notify('notifications/message', { level: 'error', logger: info.name, data: String((e && e.message) || e) }) }
1037
+ function text(p, key) { return typeof p === 'string' ? p : p && p[key] }
1038
+ function push() { if (mounted && mounted.update) { try { mounted.update(Object.assign({}, props)) } catch (e) { report(e) } } }
1039
+ // Antes do mount terminar, s\xF3 guarda: o update sai uma vez, logo depois.
1040
+ function set(key, value) { props[key] = value; if (ready) push(); else dirty = true }
1041
+ function theme(c) {
1042
+ if (!c) return
1043
+ var root = doc.documentElement, vars = c.styles && c.styles.variables
1044
+ if (c.theme) { root.setAttribute('data-theme', c.theme); root.style.colorScheme = c.theme }
1045
+ for (var k in vars) if (vars[k] != null) root.style.setProperty(k, vars[k])
1046
+ }
1047
+ var events = {
1048
+ emit: function (type, payload) {
1049
+ last[type] = payload
1050
+ ;(handlers[type] || []).slice().forEach(function (h) { try { h(payload) } catch (e) { w.console.error(e) } })
1051
+ if (type === 'mcp:message') request('ui/message', { role: 'user', content: [{ type: 'text', text: String(text(payload, 'text')) }] }).catch(report)
1052
+ else if (type === 'mcp:open-link') request('ui/open-link', { url: String(text(payload, 'url')) }).catch(report)
1053
+ else {
1054
+ context[type] = payload
1055
+ request('ui/update-model-context', { structuredContent: context, content: [{ type: 'text', text: JSON.stringify(context) }] }).catch(report)
1056
+ }
1057
+ },
1058
+ on: function (type, fn) {
1059
+ ;(handlers[type] = handlers[type] || []).push(fn)
1060
+ return function () { handlers[type] = handlers[type].filter(function (h) { return h !== fn }) }
1061
+ },
1062
+ last: function (type) { return last[type] }
1063
+ }
1064
+ var root = doc.createElement('div')
1065
+ root.setAttribute('data-vitral-root', info.name)
1066
+ if (info.scope) root.setAttribute('data-vitral-scope', info.scope)
1067
+ var ctx = {
1068
+ name: info.name, baseUrl: w.location.href, events: events, shadowRoot: null, portalContainer: doc.body, protocol: 1,
1069
+ reportError: report,
1070
+ navigate: function (url) { request('ui/open-link', { url: String(url) }).catch(report) },
1071
+ mcp: { request: request, notify: notify, hostContext: function () { return props.hostContext } }
1072
+ }
1073
+ function size() {
1074
+ var h = doc.documentElement, old = h.style.height
1075
+ h.style.height = 'max-content'
1076
+ var height = Math.ceil(h.getBoundingClientRect().height)
1077
+ h.style.height = old
1078
+ notify('ui/notifications/size-changed', { width: Math.ceil(w.innerWidth), height: height })
1079
+ }
1080
+ var on = {
1081
+ 'ui/notifications/tool-input': function (p) { set('toolInput', p.arguments) },
1082
+ 'ui/notifications/tool-input-partial': function (p) { set('toolInputPartial', p.arguments) },
1083
+ 'ui/notifications/tool-result': function (p) { set('toolResult', p) },
1084
+ 'ui/notifications/tool-cancelled': function (p) { set('toolCancelled', p.reason || true) },
1085
+ 'ui/notifications/host-context-changed': function (p) { theme(p); set('hostContext', Object.assign({}, props.hostContext, p)) },
1086
+ 'ui/resource-teardown': function () { if (mounted) mounted.unmount(); mounted = null; return {} },
1087
+ ping: function () { return {} }
1088
+ }
1089
+ w.addEventListener('message', function (e) {
1090
+ var m = e.data
1091
+ if (e.source !== parent || !m || m.jsonrpc !== '2.0') return
1092
+ if (m.method === undefined) {
1093
+ var p = pending[m.id]
1094
+ if (!p) return
1095
+ delete pending[m.id]
1096
+ return m.error ? p[1](new Error(m.error.message)) : p[0](m.result)
1097
+ }
1098
+ var fn = on[m.method], result
1099
+ if (m.id === undefined) return void (fn && fn(m.params || {}))
1100
+ if (!fn) return send({ id: m.id, error: { code: -32601, message: 'm\xE9todo desconhecido: ' + m.method } })
1101
+ try { result = fn(m.params || {}) } catch (err) { return send({ id: m.id, error: { code: -32603, message: String(err && err.message || err) } }) }
1102
+ send({ id: m.id, result: result })
1103
+ })
1104
+ request('ui/initialize', {
1105
+ appInfo: { name: info.name, version: info.version || '0.0.0' }, appCapabilities: {}, protocolVersion: '${MCP_APP_PROTOCOL}'
1106
+ }).then(function (r) {
1107
+ props.hostContext = r && r.hostContext
1108
+ theme(props.hostContext)
1109
+ notify('ui/notifications/initialized')
1110
+ doc.body.appendChild(root)
1111
+ var remote = (mod && mod.default) || mod
1112
+ if (!remote || typeof remote.mount !== 'function') throw new Error('o m\xF3dulo n\xE3o exporta mount()')
1113
+ dirty = false
1114
+ return remote.mount(root, Object.assign({}, props), ctx)
1115
+ }).then(function (handle) {
1116
+ mounted = handle
1117
+ ready = true
1118
+ if (dirty) push()
1119
+ size()
1120
+ if (w.ResizeObserver) { var ro = new w.ResizeObserver(size); ro.observe(doc.documentElement); ro.observe(doc.body) }
1121
+ }).catch(report)
1122
+ }`;
1123
+ var inline = (text, tag) => text.replace(new RegExp(`</(${tag})`, "gi"), "<\\/$1").replace(/<!--/g, "<\\!--");
1124
+ function mcpAppHtml(page) {
1125
+ const info = JSON.stringify({ name: page.name, version: page.version, scope: page.scope });
1126
+ const styles = page.css.map((css) => `<style>${inline(css, "style")}</style>`).join("");
1127
+ return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>${page.name.replace(/[<&]/g, (c) => c === "<" ? "&lt;" : "&amp;")}</title><style>html,body{margin:0}body{display:flow-root}</style>${styles}</head><body><script>${inline(page.code, "script")}</script><script>(${MCP_RUNTIME})(window, ${MCP_APP_GLOBAL}, ${inline(info, "script")})</script></body></html>
1128
+ `;
1129
+ }
1130
+
877
1131
  // src/vite/dev.ts
878
1132
  var DEV_ENTRY = "@vitral/entry.js";
879
1133
  var VIRTUAL_DEV_ENTRY = "\0vitral:dev-entry";
@@ -971,6 +1225,7 @@ function vitral(options = {}) {
971
1225
  let pkg = {};
972
1226
  let manifest;
973
1227
  let split;
1228
+ let modules = /* @__PURE__ */ new Set();
974
1229
  let entry = options.entry;
975
1230
  let adapter = "element";
976
1231
  let framework = "element";
@@ -979,13 +1234,35 @@ function vitral(options = {}) {
979
1234
  let shared = [];
980
1235
  const dedupe = !!options.dedupe?.length;
981
1236
  const hooks = dedupeHooks(() => options.exposes ? EXPOSES_ENTRY : options.adapter === false ? entryFile() : ENTRY_ID, () => shared);
1237
+ const mcp = options.target === "mcp-app";
1238
+ if (mcp && (options.exposes || dedupe || options.shared?.length)) {
1239
+ throw new Error("[vitral] target: 'mcp-app' gera um HTML \xFAnico: n\xE3o combina com exposes, dedupe nem shared.");
1240
+ }
982
1241
  const scopeName = () => (options.name ?? pkg.name ?? "remote").replace(/[^a-zA-Z0-9_-]/g, "-");
1242
+ const mcpApp = (files, js) => {
1243
+ const css = files.filter((f) => f.type === "asset" && f.fileName.endsWith(".css")).map((f) => f.fileName);
1244
+ const read = (file) => {
1245
+ const text = readFileSync5(join6(outDir, file), "utf8");
1246
+ rmSync2(join6(outDir, file));
1247
+ return text;
1248
+ };
1249
+ const scope = options.scopeCss === false ? void 0 : scopeName();
1250
+ const html = mcpAppHtml({
1251
+ name: options.name ?? pkg.name ?? "remote",
1252
+ version: options.version ?? pkg.version,
1253
+ scope,
1254
+ code: read(js),
1255
+ css: css.map((f) => transformCss(read(f), options, scopeName()))
1256
+ });
1257
+ writeFileSync2(join6(outDir, "mcp-app.html"), html);
1258
+ };
983
1259
  return {
984
1260
  name: "vitral",
985
1261
  config(user, { mode, command }) {
986
1262
  entry ??= findEntry(resolve5(user.root ?? process.cwd()));
987
1263
  if (!entry) throw new Error("[vitral] n\xE3o achei a entrada do remote (src/remote.* ou src/App.*). Use vitral({ entry }).");
988
1264
  const rolldown = "rolldownVersion" in this.meta;
1265
+ const dir = options.versionDir ? versionDir(user.root ?? process.cwd(), user.build?.outDir, options.version) : void 0;
989
1266
  return {
990
1267
  // Código de biblioteca não tem process.env; React e Vue precisam disso.
991
1268
  define: { "process.env.NODE_ENV": JSON.stringify(mode === "development" ? "development" : "production") },
@@ -995,12 +1272,18 @@ function vitral(options = {}) {
995
1272
  // O remote não tem index.html: sem isso o Vite só descobre as
996
1273
  // dependências no primeiro request e recarrega a página do host.
997
1274
  optimizeDeps: user.optimizeDeps?.entries ? void 0 : { entries: [entry] },
998
- build: {
1275
+ build: mcp ? {
1276
+ // Um IIFE só, sem chunks: o HTML do MCP App não pode buscar arquivos.
1277
+ lib: { entry: options.adapter === false ? entry : ENTRY_ID, formats: ["iife"], name: MCP_APP_GLOBAL, fileName: () => "mcp-app.js", cssFileName: "remote" },
1278
+ rollupOptions: { output: rolldown ? { codeSplitting: false } : { inlineDynamicImports: true } },
1279
+ cssCodeSplit: false
1280
+ } : {
999
1281
  // Nomes com hash: cache eterno no CDN. Só o vitral.json muda a cada deploy.
1000
1282
  lib: { entry: dedupe ? BOOT : options.exposes ? EXPOSES_ENTRY : options.adapter === false ? entry : ENTRY_ID, fileName: () => "remote-[hash].js", cssFileName: "remote" },
1001
1283
  // Arquivo único (hosts antigos e caminho com blob:) e build dividido (manifesto v2).
1002
1284
  rollupOptions: { external: options.shared ?? [], output: outputs(rolldown) },
1003
- cssCodeSplit: false
1285
+ cssCodeSplit: false,
1286
+ ...dir && { outDir: dir }
1004
1287
  }
1005
1288
  };
1006
1289
  },
@@ -1011,7 +1294,7 @@ function vitral(options = {}) {
1011
1294
  serve = c.command === "serve";
1012
1295
  outDir = resolve5(c.root, c.build.outDir);
1013
1296
  try {
1014
- pkg = JSON.parse(readFileSync4(join5(root, "package.json"), "utf8"));
1297
+ pkg = JSON.parse(readFileSync5(join6(root, "package.json"), "utf8"));
1015
1298
  } catch {
1016
1299
  }
1017
1300
  },
@@ -1056,20 +1339,22 @@ function vitral(options = {}) {
1056
1339
  }
1057
1340
  },
1058
1341
  writeBundle(_, bundle) {
1342
+ if (options.sbom) bundledFiles(bundle, modules);
1059
1343
  if (isSplit(bundle)) return void (split = collect(outDir, bundle));
1060
1344
  const files = Object.values(bundle);
1061
1345
  const entry2 = files.find((f) => f.type === "chunk" && f.isEntry);
1062
1346
  if (!entry2) return;
1347
+ if (mcp) return mcpApp(files, entry2.fileName);
1063
1348
  const emit = (file, text, kind = "") => {
1064
- const hash = createHash2("sha256").update(text).digest("base64url").slice(0, 8);
1349
+ const hash = createHash3("sha256").update(text).digest("base64url").slice(0, 8);
1065
1350
  const name = file.replace(/\.css$/, `${kind}-${hash}.css`);
1066
- writeFileSync2(join5(outDir, name), text);
1351
+ writeFileSync2(join6(outDir, name), text);
1067
1352
  return name;
1068
1353
  };
1069
1354
  const shadow = { css: [] };
1070
1355
  const css = files.filter((f) => f.type === "asset" && f.fileName.endsWith(".css")).map((f) => {
1071
- const from = join5(outDir, f.fileName);
1072
- const text = transformCss(readFileSync4(from, "utf8"), options, scopeName());
1356
+ const from = join6(outDir, f.fileName);
1357
+ const text = transformCss(readFileSync5(from, "utf8"), options, scopeName());
1073
1358
  const name = emit(f.fileName, text);
1074
1359
  if (name !== f.fileName) rmSync2(from);
1075
1360
  const split2 = splitShadowCss(text);
@@ -1079,14 +1364,14 @@ function vitral(options = {}) {
1079
1364
  if (split2.rebase) shadow.rebase = true;
1080
1365
  return name;
1081
1366
  });
1082
- const code = readFileSync4(join5(outDir, entry2.fileName));
1367
+ const code = readFileSync5(join6(outDir, entry2.fileName));
1083
1368
  manifest = {
1084
1369
  name: options.name ?? pkg.name ?? "remote",
1085
1370
  version: options.version ?? pkg.version,
1086
1371
  entry: entry2.fileName,
1087
1372
  css,
1088
1373
  ...css.length ? { shadow } : {},
1089
- integrity: "sha384-" + createHash2("sha384").update(code).digest("base64"),
1374
+ integrity: "sha384-" + createHash3("sha384").update(code).digest("base64"),
1090
1375
  ...options.scopeCss === false ? {} : { scope: scopeName() },
1091
1376
  ...options.exposes ? { exposes: Object.keys(exposeKeys(options.exposes)) } : {},
1092
1377
  ...contractOf(options.contract?.version, shared)
@@ -1095,13 +1380,34 @@ function vitral(options = {}) {
1095
1380
  async closeBundle() {
1096
1381
  if (!manifest) return;
1097
1382
  const done = withSplit(manifest, outDir, split, shared);
1383
+ if (options.sbom) {
1384
+ const bom = createSbom({ root, name: done.name, version: done.version, files: modules, entry: readFileSync5(join6(outDir, done.entry)), tool: ownVersion() });
1385
+ writeFileSync2(join6(outDir, SBOM_FILE), JSON.stringify(bom, null, 2) + "\n");
1386
+ done.sbom = { file: SBOM_FILE, integrity: sri(join6(outDir, SBOM_FILE)) };
1387
+ }
1098
1388
  manifest = split = void 0;
1099
- writeFileSync2(join5(outDir, "vitral.json"), JSON.stringify(done, null, 2) + "\n");
1389
+ modules = /* @__PURE__ */ new Set();
1390
+ writeFileSync2(join6(outDir, "vitral.json"), JSON.stringify(done, null, 2) + "\n");
1100
1391
  const props = options.types === false ? null : await extractProps(root, entryFile());
1101
- if (props) writeFileSync2(join5(outDir, "vitral.d.ts"), typesFile(done.name, props));
1392
+ if (props) writeFileSync2(join6(outDir, "vitral.d.ts"), typesFile(done.name, props));
1102
1393
  }
1103
1394
  };
1104
1395
  }
1396
+ function ownVersion() {
1397
+ try {
1398
+ return JSON.parse(readFileSync5(new URL("../package.json", import.meta.url), "utf8")).version;
1399
+ } catch {
1400
+ return void 0;
1401
+ }
1402
+ }
1403
+ function versionDir(root, outDir = "dist", version) {
1404
+ try {
1405
+ version ??= JSON.parse(readFileSync5(join6(resolve5(root), "package.json"), "utf8")).version;
1406
+ } catch {
1407
+ }
1408
+ if (!version) throw new Error('[vitral] versionDir precisa de uma vers\xE3o: use vitral({ version }) ou "version" no package.json.');
1409
+ return join6(outDir, version);
1410
+ }
1105
1411
  function contractOf(version, groups2) {
1106
1412
  const contract = {
1107
1413
  ...version && { version },
package/dist/vue.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as vue from 'vue';
2
2
  import { PropType, App, ShallowRef, WritableComputedRef, ComputedRef, Component } from 'vue';
3
- import { P as Props, I as Isolation, R as RemoteContext, S as Shared, a as RemoteModule } from './types-Czvm-siZ.js';
4
- export { e as events } from './events-D5gs7rff.js';
3
+ import { P as Props, I as Isolation, R as RemoteContext, S as Shared, a as RemoteModule } from './types-CA2p9KHC.js';
4
+ export { e as events } from './events-Dkpkw_Sv.js';
5
5
  import { L as Loading, P as Prefetch } from './host-slot-Cz6EiGsB.js';
6
6
  import './errors-kjBv6IH_.js';
7
7
 
@@ -127,8 +127,8 @@ declare const VitralRemote: vue.DefineComponent<vue.ExtractPropTypes<{
127
127
  onError?: ((...args: any[]) => any) | undefined;
128
128
  onReady?: ((...args: any[]) => any) | undefined;
129
129
  }>, {
130
- isolate: Isolation;
131
130
  name: string;
131
+ isolate: Isolation;
132
132
  priority: RequestPriority;
133
133
  loading: Loading;
134
134
  src: string;
package/dist/vue.js CHANGED
@@ -1,20 +1,20 @@
1
1
  import {
2
2
  hostSlot,
3
3
  timings
4
- } from "./chunk-IHTUM6LT.js";
4
+ } from "./chunk-W6322KGP.js";
5
5
  import {
6
6
  defineRemote,
7
7
  events,
8
8
  memoSelect,
9
9
  same,
10
10
  shared
11
- } from "./chunk-I3VSKSAZ.js";
12
- import "./chunk-TD4S3IHA.js";
13
- import "./chunk-ZAC6QQI6.js";
11
+ } from "./chunk-WD4CDGDZ.js";
12
+ import "./chunk-EMSB2NVX.js";
13
+ import "./chunk-6EX5KYT5.js";
14
14
  import {
15
15
  absolute
16
- } from "./chunk-GNHCZRQP.js";
17
- import "./chunk-AKNNHQ2H.js";
16
+ } from "./chunk-TW7KYJQ6.js";
17
+ import "./chunk-463H6B56.js";
18
18
  import "./chunk-GNPFWISJ.js";
19
19
 
20
20
  // src/vue.ts