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.
- package/README.md +1 -1
- package/dist/angular.d.ts +3 -2
- package/dist/angular.js +7 -6
- package/dist/auto.js +7 -6
- package/dist/capture-TT5WBLJ6.js +42 -0
- package/dist/channel-2YPYGX3J.js +95 -0
- package/dist/chunk-463H6B56.js +50 -0
- package/dist/chunk-54CBIZES.js +105 -0
- package/dist/chunk-6EX5KYT5.js +64 -0
- package/dist/{chunk-6Y3VMWHH.js → chunk-BCC25ANK.js} +11 -5
- package/dist/{chunk-2XF5BKV3.js → chunk-EMSB2NVX.js} +26 -13
- package/dist/{chunk-HP6QWU6K.js → chunk-IH3ZT3QU.js} +2 -2
- package/dist/{chunk-PX7PBCCT.js → chunk-TW7KYJQ6.js} +7 -17
- package/dist/{chunk-S5MZT5IT.js → chunk-UYOPJ4XQ.js} +1 -1
- package/dist/{chunk-UTYAX6MU.js → chunk-W6322KGP.js} +2 -2
- package/dist/{chunk-NCONW6WS.js → chunk-WD4CDGDZ.js} +73 -44
- package/dist/cli.js +1196 -31
- package/dist/contract-46EZFQPQ.js +17 -0
- package/dist/{dedupe-IWFIXRWG.js → dedupe-S7BHQMOZ.js} +4 -3
- package/dist/devtools.d.ts +32 -2
- package/dist/devtools.js +27 -12
- package/dist/element.d.ts +13 -4
- package/dist/element.js +7 -6
- package/dist/embed.js +2 -0
- package/dist/{errors-KKB8FGCz.d.ts → errors-kjBv6IH_.d.ts} +7 -1
- package/dist/{events-DUdjhfps.d.ts → events-Dkpkw_Sv.d.ts} +1 -1
- package/dist/expose-OVWTPHH5.js +15 -0
- package/dist/federation.d.ts +89 -0
- package/dist/federation.js +101 -0
- package/dist/iframe.d.ts +1 -1
- package/dist/iframe.js +13 -10
- package/dist/index.d.ts +23 -21
- package/dist/index.js +5 -4
- package/dist/otel.d.ts +44 -0
- package/dist/otel.js +27 -0
- package/dist/overrides-NP754HY7.js +27 -0
- package/dist/preact.d.ts +5 -5
- package/dist/preact.js +6 -5
- package/dist/react.d.ts +12 -4
- package/dist/react.js +11 -6
- package/dist/routes.d.ts +3 -3
- package/dist/routes.js +5 -4
- package/dist/sentry.d.ts +25 -0
- package/dist/sentry.js +11 -0
- package/dist/shadow-PVSETNMZ.js +159 -0
- package/dist/single-spa.d.ts +40 -0
- package/dist/single-spa.js +52 -0
- package/dist/{slot-pB276oPt.d.ts → slot-UPg6ob9v.d.ts} +2 -2
- package/dist/solid.d.ts +4 -4
- package/dist/solid.js +6 -5
- package/dist/{sri-BVKZNX5Q.js → sri-M7ZRU57G.js} +43 -11
- package/dist/svelte.d.ts +5 -5
- package/dist/svelte.js +6 -5
- package/dist/testing.d.ts +2 -1
- package/dist/testing.js +5 -4
- package/dist/{types-BV-hUrms.d.ts → types-CA2p9KHC.d.ts} +174 -4
- package/dist/vite.d.ts +26 -0
- package/dist/vite.js +686 -51
- package/dist/vue.d.ts +11 -4
- package/dist/vue.js +10 -5
- package/package.json +115 -23
- package/dist/chunk-DXORSF4X.js +0 -42
- package/dist/chunk-SFL6LTP3.js +0 -56
- package/dist/expose-53BEJB34.js +0 -14
- package/dist/overrides-NZAIUGK5.js +0 -15
- package/dist/shadow-MYRJQLLY.js +0 -72
package/dist/vite.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/vite.ts
|
|
2
|
-
import { createHash as
|
|
3
|
-
import { readFileSync as
|
|
4
|
-
import { join as
|
|
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";
|
|
@@ -16,6 +16,7 @@ function exposeKeys(exposes) {
|
|
|
16
16
|
}
|
|
17
17
|
return out;
|
|
18
18
|
}
|
|
19
|
+
var EXPOSES_IDS = /(^|[\\/])__vitral_exposes__\.js$/;
|
|
19
20
|
function resolveExposesId(id) {
|
|
20
21
|
return id === EXPOSES_ENTRY || id.endsWith("/" + EXPOSES_ENTRY) || id.endsWith("\\" + EXPOSES_ENTRY) ? ID : null;
|
|
21
22
|
}
|
|
@@ -99,14 +100,154 @@ ${helper()}${code.slice(at)}`;
|
|
|
99
100
|
}
|
|
100
101
|
function withSplit(m, outDir, s, groups2 = []) {
|
|
101
102
|
const files = {};
|
|
102
|
-
for (const f of [m.entry, ...m.css ?? [], ...s?.files ?? []]) files[f] = sri(join(outDir, f));
|
|
103
|
+
for (const f of [m.entry, ...m.css ?? [], ...m.shadow?.css ?? [], ...m.shadow?.global ?? [], ...s?.files ?? []]) files[f] = sri(join(outDir, f));
|
|
103
104
|
const dedupe = groups2.filter((g) => s?.own[g.name]).map(({ name, range, version }) => ({ name, range, version, ...s.own[name] }));
|
|
104
105
|
return { ...m, files, ...s && { split: { entry: s.entry, chunks: s.chunks } }, ...dedupe.length && { dedupe } };
|
|
105
106
|
}
|
|
106
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
|
+
|
|
107
248
|
// src/vite/dedupe.ts
|
|
108
|
-
import { existsSync, readFileSync as
|
|
109
|
-
import { dirname, join as
|
|
249
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3 } from "fs";
|
|
250
|
+
import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
|
|
110
251
|
import { pathToFileURL } from "url";
|
|
111
252
|
var REACT = ["react", "react-dom", "react-dom/client", "react/jsx-runtime", "react/jsx-dev-runtime", "react/compiler-runtime"];
|
|
112
253
|
var BOOT = "virtual:vitral-boot";
|
|
@@ -117,10 +258,10 @@ var pkgOf = (spec) => spec.split("/").slice(0, spec.startsWith("@") ? 2 : 1).joi
|
|
|
117
258
|
var groupOf = (spec) => REACT.includes(spec) || pkgOf(spec) === "scheduler" ? "react" : pkgOf(spec);
|
|
118
259
|
var ident = /^[A-Za-z_$][\w$]*$/;
|
|
119
260
|
function versionOf(file, pkg) {
|
|
120
|
-
for (let dir =
|
|
121
|
-
const json =
|
|
122
|
-
if (!
|
|
123
|
-
const data = JSON.parse(
|
|
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"));
|
|
124
265
|
if (data.name === pkg) return data.version;
|
|
125
266
|
}
|
|
126
267
|
throw new Error(`vitral: vers\xE3o de ${pkg} n\xE3o encontrada`);
|
|
@@ -152,6 +293,11 @@ async function groups(list, root, entry, resolveId) {
|
|
|
152
293
|
}
|
|
153
294
|
return out;
|
|
154
295
|
}
|
|
296
|
+
var escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\0/g, "\\x00");
|
|
297
|
+
function dedupeIds(list) {
|
|
298
|
+
const specs = new Set(list.flatMap((s) => groupOf(s) === "react" ? REACT : [s]));
|
|
299
|
+
return new RegExp(`${escape(BOOT)}$|^(${[DEPS, ...specs].map(escape).join("|")})$|^(${escape(OWN)}|${escape(SHIM)})`);
|
|
300
|
+
}
|
|
155
301
|
function dedupeHooks(entry, getGroups) {
|
|
156
302
|
const keyOf = (id) => getGroups().find((g) => g.keys.includes(id));
|
|
157
303
|
return {
|
|
@@ -389,9 +535,29 @@ function transformCss(css, options, scope) {
|
|
|
389
535
|
if (options.scopeCss !== false) scopeRoot(root, scope);
|
|
390
536
|
return root.toString();
|
|
391
537
|
}
|
|
538
|
+
var RELATIVE_URL = /url\(\s*(['"]?)(?![a-z]+:|\/\/|#)([^'")]+)\1\s*\)/i;
|
|
539
|
+
var IMPORT_URL = /^\s*(?:url\(\s*(['"]?)([^'")]+)\1\s*\)|(['"])(.*?)\3)/i;
|
|
540
|
+
function splitShadowCss(text) {
|
|
541
|
+
const root = postcss2.parse(text);
|
|
542
|
+
const global = [];
|
|
543
|
+
const imports = [];
|
|
544
|
+
root.walkAtRules((rule) => {
|
|
545
|
+
const name = rule.name.toLowerCase();
|
|
546
|
+
if (name === "import" && rule.parent === root) {
|
|
547
|
+
const m = IMPORT_URL.exec(rule.params);
|
|
548
|
+
if (m) imports.push(m[2] ?? m[4]);
|
|
549
|
+
rule.remove();
|
|
550
|
+
} else if (name === "property" || name === "font-face") {
|
|
551
|
+
global.push(rule.toString());
|
|
552
|
+
rule.remove();
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
const css = global.length || imports.length ? root.toString() : text;
|
|
556
|
+
return { css, global: global.join("\n"), imports, rebase: RELATIVE_URL.test(css) };
|
|
557
|
+
}
|
|
392
558
|
|
|
393
559
|
// src/vite/adapter.ts
|
|
394
|
-
import { existsSync as
|
|
560
|
+
import { existsSync as existsSync3 } from "fs";
|
|
395
561
|
import { resolve as resolve3 } from "path";
|
|
396
562
|
var PLUGINS = [
|
|
397
563
|
[/^(preact:|prefresh$)/, "preact"],
|
|
@@ -430,10 +596,14 @@ import { component } from 'vitral'
|
|
|
430
596
|
function wrap(c) {
|
|
431
597
|
if (typeof c === 'function' && typeof HTMLElement !== 'undefined' && c.prototype instanceof HTMLElement) {
|
|
432
598
|
const base = ${JSON.stringify(`${scope}-remote`.toLowerCase().replace(/^[^a-z]+/, "x-"))}
|
|
433
|
-
|
|
434
|
-
//
|
|
435
|
-
|
|
436
|
-
|
|
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
|
+
})
|
|
437
607
|
}
|
|
438
608
|
if (typeof c === 'function') return component(c)
|
|
439
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()')
|
|
@@ -445,33 +615,306 @@ var CANDIDATES = ["src/remote", "src/App", "src/app"];
|
|
|
445
615
|
var EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".vue", ".svelte"];
|
|
446
616
|
function findEntry(root) {
|
|
447
617
|
for (const base of CANDIDATES) {
|
|
448
|
-
for (const ext of EXTENSIONS) if (
|
|
618
|
+
for (const ext of EXTENSIONS) if (existsSync3(resolve3(root, base + ext))) return base + ext;
|
|
449
619
|
}
|
|
450
620
|
}
|
|
451
621
|
|
|
452
622
|
// src/vite/types.ts
|
|
623
|
+
import { createRequire as createRequire2 } from "module";
|
|
624
|
+
import { join as join5 } from "path";
|
|
625
|
+
|
|
626
|
+
// src/vite/oxc.ts
|
|
627
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
453
628
|
import { createRequire } from "module";
|
|
454
|
-
import { join as
|
|
629
|
+
import { dirname as dirname3, join as join4, resolve as resolve4 } from "path";
|
|
630
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
631
|
+
async function loadOxc(root) {
|
|
632
|
+
const req = createRequire(join4(root, "package.json"));
|
|
633
|
+
const ids = [() => req.resolve("oxc-transform"), () => createRequire(req.resolve("vite/package.json")).resolve("rolldown/experimental")];
|
|
634
|
+
for (const id of ids) {
|
|
635
|
+
try {
|
|
636
|
+
const mod = await import(pathToFileURL2(id()).href);
|
|
637
|
+
if (typeof mod.isolatedDeclarationSync === "function") return mod;
|
|
638
|
+
} catch {
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
return null;
|
|
642
|
+
}
|
|
643
|
+
var GLOBAL3 = /^(Date|RegExp|Error|Map|Set|WeakMap|WeakSet|Promise|PromiseLike|Record|Partial|Required|Readonly|Pick|Omit|URL|URLSearchParams|Blob|File|FormData|Headers|AbortSignal|EventTarget|Node|Element|Document|DocumentFragment|ShadowRoot|Window|(HTML|SVG)\w*Element|\w*Event)$/;
|
|
644
|
+
var IDENT = /^[A-Za-z_$][\w$]*$/;
|
|
645
|
+
var Unsupported = class extends Error {
|
|
646
|
+
};
|
|
647
|
+
var unsupported = () => {
|
|
648
|
+
throw new Unsupported();
|
|
649
|
+
};
|
|
650
|
+
function propsFromOxc(ts, oxc, file) {
|
|
651
|
+
try {
|
|
652
|
+
const reader = new Reader(ts, oxc);
|
|
653
|
+
const scope = reader.scope(file);
|
|
654
|
+
const props = reader.defaultProps(scope);
|
|
655
|
+
return props ? reader.print(props.node, props.scope, 0, { top: true }) : "Record<string, unknown>";
|
|
656
|
+
} catch {
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
var Reader = class {
|
|
661
|
+
constructor(ts, oxc) {
|
|
662
|
+
this.ts = ts;
|
|
663
|
+
this.oxc = oxc;
|
|
664
|
+
this.scopes = /* @__PURE__ */ new Map();
|
|
665
|
+
this.seen = /* @__PURE__ */ new Set();
|
|
666
|
+
}
|
|
667
|
+
/** Declarações de um arquivo: `.d.ts` como está, o resto pelo Oxc. */
|
|
668
|
+
scope(file) {
|
|
669
|
+
const cached = this.scopes.get(file);
|
|
670
|
+
if (cached) return cached;
|
|
671
|
+
const { ts } = this;
|
|
672
|
+
let code = readFileSync4(file, "utf8");
|
|
673
|
+
if (!/\.d\.[cm]?ts$/.test(file)) {
|
|
674
|
+
const out = this.oxc.isolatedDeclarationSync(file, code, {});
|
|
675
|
+
if (out.errors.length) unsupported();
|
|
676
|
+
code = out.code;
|
|
677
|
+
}
|
|
678
|
+
const source = ts.createSourceFile(file + ".d.ts", code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
679
|
+
const scope = { file, types: /* @__PURE__ */ new Map(), values: /* @__PURE__ */ new Map(), imports: /* @__PURE__ */ new Map() };
|
|
680
|
+
const isDefault = (n) => ts.canHaveModifiers(n) && !!ts.getModifiers(n)?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword);
|
|
681
|
+
let defaultName;
|
|
682
|
+
for (const st of source.statements) {
|
|
683
|
+
if (ts.isInterfaceDeclaration(st) || ts.isTypeAliasDeclaration(st)) {
|
|
684
|
+
if (scope.types.has(st.name.text)) unsupported();
|
|
685
|
+
scope.types.set(st.name.text, st);
|
|
686
|
+
} else if (ts.isImportDeclaration(st) && ts.isStringLiteral(st.moduleSpecifier)) {
|
|
687
|
+
const from = st.moduleSpecifier.text;
|
|
688
|
+
const clause = st.importClause;
|
|
689
|
+
if (clause?.name) scope.imports.set(clause.name.text, { from, name: "default" });
|
|
690
|
+
const bindings = clause?.namedBindings;
|
|
691
|
+
if (bindings && ts.isNamespaceImport(bindings)) scope.imports.set(bindings.name.text, { from, name: "*" });
|
|
692
|
+
if (bindings && ts.isNamedImports(bindings)) for (const el of bindings.elements) scope.imports.set(el.name.text, { from, name: (el.propertyName ?? el.name).text });
|
|
693
|
+
} else if (ts.isFunctionDeclaration(st) || ts.isClassDeclaration(st)) {
|
|
694
|
+
if (isDefault(st)) scope.default ??= st;
|
|
695
|
+
else if (st.name && !scope.values.has(st.name.text)) scope.values.set(st.name.text, st);
|
|
696
|
+
} else if (ts.isVariableStatement(st)) {
|
|
697
|
+
for (const d of st.declarationList.declarations) if (ts.isIdentifier(d.name)) scope.values.set(d.name.text, d);
|
|
698
|
+
} else if (ts.isExportAssignment(st) && !st.isExportEquals) {
|
|
699
|
+
defaultName = ts.isIdentifier(st.expression) ? st.expression.text : unsupported();
|
|
700
|
+
} else if (ts.isExportDeclaration(st) && !st.moduleSpecifier && st.exportClause && ts.isNamedExports(st.exportClause)) {
|
|
701
|
+
const el = st.exportClause.elements.find((e) => e.name.text === "default");
|
|
702
|
+
if (el) defaultName = (el.propertyName ?? el.name).text;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
if (defaultName) scope.default = scope.values.get(defaultName);
|
|
706
|
+
this.scopes.set(file, scope);
|
|
707
|
+
return scope;
|
|
708
|
+
}
|
|
709
|
+
/** `mount(el, props)`, componente-função `(props)` ou classe com `props`. `undefined`: sem props. */
|
|
710
|
+
defaultProps(scope) {
|
|
711
|
+
const { ts } = this;
|
|
712
|
+
const node = scope.default ?? unsupported();
|
|
713
|
+
const param = (params, i) => {
|
|
714
|
+
const p = params[i];
|
|
715
|
+
return p && { node: p.type ?? unsupported(), scope };
|
|
716
|
+
};
|
|
717
|
+
if (ts.isFunctionDeclaration(node)) return param(node.parameters, 0);
|
|
718
|
+
if (ts.isClassDeclaration(node)) {
|
|
719
|
+
if (node.heritageClauses?.length) unsupported();
|
|
720
|
+
const props = node.members.find((m) => ts.isPropertyDeclaration(m) && m.name.getText() === "props");
|
|
721
|
+
return props && { node: props.type ?? unsupported(), scope };
|
|
722
|
+
}
|
|
723
|
+
if (ts.isVariableDeclaration(node)) return this.propsOfType(node.type ?? unsupported(), scope);
|
|
724
|
+
return unsupported();
|
|
725
|
+
}
|
|
726
|
+
propsOfType(node, scope) {
|
|
727
|
+
const { ts } = this;
|
|
728
|
+
const param = (params, i, at2) => {
|
|
729
|
+
const p = params[i];
|
|
730
|
+
return p && { node: p.type ?? unsupported(), scope: at2 };
|
|
731
|
+
};
|
|
732
|
+
if (ts.isParenthesizedTypeNode(node)) return this.propsOfType(node.type, scope);
|
|
733
|
+
if (ts.isFunctionTypeNode(node)) return param(node.parameters, 0, scope);
|
|
734
|
+
let members;
|
|
735
|
+
let at = scope;
|
|
736
|
+
if (ts.isTypeLiteralNode(node)) members = node.members;
|
|
737
|
+
else if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && !node.typeArguments) {
|
|
738
|
+
const found = this.lookup(node.typeName.text, scope);
|
|
739
|
+
if (!found || found === "package" || found.decl.typeParameters) return unsupported();
|
|
740
|
+
if (ts.isTypeAliasDeclaration(found.decl)) return this.propsOfType(found.decl.type, found.scope);
|
|
741
|
+
if (found.decl.heritageClauses?.length) unsupported();
|
|
742
|
+
members = found.decl.members;
|
|
743
|
+
at = found.scope;
|
|
744
|
+
} else return unsupported();
|
|
745
|
+
const mount = members.find((m) => m.name?.getText() === "mount");
|
|
746
|
+
if (mount) {
|
|
747
|
+
if (ts.isMethodSignature(mount)) return param(mount.parameters, 1, at);
|
|
748
|
+
if (ts.isPropertySignature(mount) && mount.type) return this.mountProps(mount.type, at);
|
|
749
|
+
return unsupported();
|
|
750
|
+
}
|
|
751
|
+
const call = members.find(ts.isCallSignatureDeclaration);
|
|
752
|
+
if (call) return param(call.parameters, 0, at);
|
|
753
|
+
if (members.some(ts.isConstructSignatureDeclaration)) unsupported();
|
|
754
|
+
return void 0;
|
|
755
|
+
}
|
|
756
|
+
mountProps(node, scope) {
|
|
757
|
+
const { ts } = this;
|
|
758
|
+
if (ts.isParenthesizedTypeNode(node)) return this.mountProps(node.type, scope);
|
|
759
|
+
if (!ts.isFunctionTypeNode(node)) return unsupported();
|
|
760
|
+
const p = node.parameters[1];
|
|
761
|
+
return p && { node: p.type ?? unsupported(), scope };
|
|
762
|
+
}
|
|
763
|
+
/** Acha um tipo pelo nome: no arquivo, num import relativo ou num pacote. */
|
|
764
|
+
lookup(name, scope) {
|
|
765
|
+
const decl = scope.types.get(name);
|
|
766
|
+
if (decl) return { decl, scope };
|
|
767
|
+
const imp = scope.imports.get(name);
|
|
768
|
+
if (!imp) return void 0;
|
|
769
|
+
if (!imp.from.startsWith(".")) return "package";
|
|
770
|
+
if (imp.name === "default" || imp.name === "*") return unsupported();
|
|
771
|
+
const found = this.lookup(imp.name, this.scope(resolveFile(scope.file, imp.from)));
|
|
772
|
+
return found ?? unsupported();
|
|
773
|
+
}
|
|
774
|
+
print(node, scope, depth, opts = {}) {
|
|
775
|
+
const { ts } = this;
|
|
776
|
+
const K = ts.SyntaxKind;
|
|
777
|
+
switch (node.kind) {
|
|
778
|
+
case K.AnyKeyword:
|
|
779
|
+
case K.UnknownKeyword:
|
|
780
|
+
return "unknown";
|
|
781
|
+
case K.StringKeyword:
|
|
782
|
+
case K.NumberKeyword:
|
|
783
|
+
case K.BooleanKeyword:
|
|
784
|
+
case K.BigIntKeyword:
|
|
785
|
+
case K.SymbolKeyword:
|
|
786
|
+
case K.UndefinedKeyword:
|
|
787
|
+
case K.VoidKeyword:
|
|
788
|
+
case K.NeverKeyword:
|
|
789
|
+
return node.getText();
|
|
790
|
+
}
|
|
791
|
+
if (ts.isLiteralTypeNode(node)) {
|
|
792
|
+
const lit = node.literal;
|
|
793
|
+
if (ts.isStringLiteral(lit)) return JSON.stringify(lit.text);
|
|
794
|
+
if (lit.kind === K.NullKeyword || lit.kind === K.TrueKeyword || lit.kind === K.FalseKeyword || ts.isNumericLiteral(lit) || ts.isPrefixUnaryExpression(lit)) return lit.getText();
|
|
795
|
+
return unsupported();
|
|
796
|
+
}
|
|
797
|
+
if (ts.isParenthesizedTypeNode(node)) return this.print(node.type, scope, depth, opts);
|
|
798
|
+
if (ts.isUnionTypeNode(node)) {
|
|
799
|
+
const types = opts.nonNull ? node.types.filter((t) => t.kind !== K.UndefinedKeyword && !(ts.isLiteralTypeNode(t) && t.literal.kind === K.NullKeyword)) : node.types;
|
|
800
|
+
const parts = [...new Set(types.map((t) => this.print(t, scope, depth)))];
|
|
801
|
+
if (parts.includes("true") && parts.includes("false")) parts.splice(parts.indexOf("true"), 1, "boolean"), parts.splice(parts.indexOf("false"), 1);
|
|
802
|
+
return parts.join(" | ");
|
|
803
|
+
}
|
|
804
|
+
if (ts.isIntersectionTypeNode(node)) {
|
|
805
|
+
return node.types.map((t) => {
|
|
806
|
+
const s = this.print(t, scope, depth);
|
|
807
|
+
return ts.isUnionTypeNode(t) ? `(${s})` : s;
|
|
808
|
+
}).join(" & ");
|
|
809
|
+
}
|
|
810
|
+
if (depth > 6) return "unknown";
|
|
811
|
+
if (ts.isArrayTypeNode(node)) return `Array<${this.print(node.elementType, scope, depth + 1)}>`;
|
|
812
|
+
if (ts.isTypeOperatorNode(node) && node.operator === K.ReadonlyKeyword && (ts.isArrayTypeNode(node.type) || ts.isTupleTypeNode(node.type))) return this.print(node.type, scope, depth);
|
|
813
|
+
if (ts.isTupleTypeNode(node)) {
|
|
814
|
+
if (node.elements.some((e) => ts.isNamedTupleMember(e) || ts.isOptionalTypeNode(e) || ts.isRestTypeNode(e))) unsupported();
|
|
815
|
+
return `[${node.elements.map((e) => this.print(e, scope, depth + 1)).join(", ")}]`;
|
|
816
|
+
}
|
|
817
|
+
if (ts.isTypeLiteralNode(node)) return this.object(node.members, scope, depth, !!opts.top);
|
|
818
|
+
if (ts.isFunctionTypeNode(node)) return this.signature(node, scope, depth);
|
|
819
|
+
if (ts.isTypeReferenceNode(node)) return this.reference(node, scope, depth, opts);
|
|
820
|
+
return unsupported();
|
|
821
|
+
}
|
|
822
|
+
reference(node, scope, depth, opts) {
|
|
823
|
+
const { ts } = this;
|
|
824
|
+
if (!ts.isIdentifier(node.typeName)) return unsupported();
|
|
825
|
+
const name = node.typeName.text;
|
|
826
|
+
const args = node.typeArguments ?? [];
|
|
827
|
+
const found = this.lookup(name, scope);
|
|
828
|
+
if (found === "package") return "unknown";
|
|
829
|
+
if (found) {
|
|
830
|
+
if (args.length || found.decl.typeParameters) unsupported();
|
|
831
|
+
if (this.seen.has(found.decl)) return "unknown";
|
|
832
|
+
this.seen.add(found.decl);
|
|
833
|
+
try {
|
|
834
|
+
const decl = found.decl;
|
|
835
|
+
if (ts.isTypeAliasDeclaration(decl)) return this.print(decl.type, found.scope, depth, opts);
|
|
836
|
+
if (decl.heritageClauses?.length) unsupported();
|
|
837
|
+
return this.object(decl.members, found.scope, depth, !!opts.top);
|
|
838
|
+
} finally {
|
|
839
|
+
this.seen.delete(found.decl);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
if ((name === "Array" || name === "ReadonlyArray") && args.length === 1) return `Array<${this.print(args[0], scope, depth + 1)}>`;
|
|
843
|
+
if (!GLOBAL3.test(name)) return unsupported();
|
|
844
|
+
return args.length ? `${name}<${args.map((t) => this.print(t, scope, depth + 1)).join(", ")}>` : name;
|
|
845
|
+
}
|
|
846
|
+
object(members, scope, depth, top) {
|
|
847
|
+
const { ts } = this;
|
|
848
|
+
const fields = [];
|
|
849
|
+
const calls = [];
|
|
850
|
+
let index;
|
|
851
|
+
for (const m of members) {
|
|
852
|
+
if (ts.isPropertySignature(m) || ts.isMethodSignature(m)) {
|
|
853
|
+
const name = ts.isIdentifier(m.name) || ts.isStringLiteral(m.name) || ts.isNumericLiteral(m.name) ? m.name.text : unsupported();
|
|
854
|
+
if (top && name === "vitral") continue;
|
|
855
|
+
const optional = m.questionToken ? "?" : "";
|
|
856
|
+
const key = IDENT.test(name) ? name : JSON.stringify(name);
|
|
857
|
+
const type = ts.isMethodSignature(m) ? this.signature(m, scope, depth + 1) : m.type ? this.print(m.type, scope, depth + 1, { nonNull: !!optional }) : "unknown";
|
|
858
|
+
fields.push(`${key}${optional}: ${type}`);
|
|
859
|
+
} else if (ts.isIndexSignatureDeclaration(m)) {
|
|
860
|
+
const key = m.parameters[0]?.type;
|
|
861
|
+
if (!key || key.kind !== ts.SyntaxKind.StringKeyword) unsupported();
|
|
862
|
+
index = `[key: string]: ${this.print(m.type, scope, depth + 1)}`;
|
|
863
|
+
} else if (ts.isCallSignatureDeclaration(m)) {
|
|
864
|
+
calls.push(this.signature(m, scope, depth));
|
|
865
|
+
} else unsupported();
|
|
866
|
+
}
|
|
867
|
+
if (calls.length && !fields.length) return calls[0];
|
|
868
|
+
if (index) fields.push(index);
|
|
869
|
+
for (const c of calls) fields.push(c.replace(" =>", ":"));
|
|
870
|
+
return fields.length ? `{ ${fields.join("; ")} }` : "{}";
|
|
871
|
+
}
|
|
872
|
+
signature(sig, scope, depth) {
|
|
873
|
+
const { ts } = this;
|
|
874
|
+
if (sig.typeParameters?.length || !sig.type) unsupported();
|
|
875
|
+
const params = sig.parameters.map((p, i) => {
|
|
876
|
+
if (p.dotDotDotToken || ts.isIdentifier(p.name) && p.name.text === "this") unsupported();
|
|
877
|
+
const name = ts.isIdentifier(p.name) && IDENT.test(p.name.text) ? p.name.text : `a${i}`;
|
|
878
|
+
const type = p.type ? this.print(p.type, scope, depth + 1) : "unknown";
|
|
879
|
+
return `${name}: ${p.questionToken || p.initializer ? `${type} | undefined` : type}`;
|
|
880
|
+
});
|
|
881
|
+
return `(${params.join(", ")}) => ${this.print(sig.type, scope, depth + 1)}`;
|
|
882
|
+
}
|
|
883
|
+
};
|
|
884
|
+
function resolveFile(from, spec) {
|
|
885
|
+
const base = resolve4(dirname3(from), spec);
|
|
886
|
+
const stem = base.replace(/\.[cm]?jsx?$/, "");
|
|
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));
|
|
889
|
+
return file ?? unsupported();
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
// src/vite/types.ts
|
|
455
893
|
function typesFile(name, props) {
|
|
456
894
|
return `// Props do remote ${JSON.stringify(name)}, geradas pelo vitral. N\xE3o edite.
|
|
457
895
|
export type Props = ${props}
|
|
458
896
|
`;
|
|
459
897
|
}
|
|
460
898
|
async function loadTs(root) {
|
|
899
|
+
const api = (ts) => typeof ts?.createProgram === "function" ? ts : null;
|
|
461
900
|
try {
|
|
462
|
-
|
|
901
|
+
const ts = api(createRequire2(join5(root, "package.json"))("typescript"));
|
|
902
|
+
if (ts) return ts;
|
|
463
903
|
} catch {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
904
|
+
}
|
|
905
|
+
try {
|
|
906
|
+
return api((await import("typescript")).default);
|
|
907
|
+
} catch {
|
|
908
|
+
return null;
|
|
469
909
|
}
|
|
470
910
|
}
|
|
471
911
|
async function extractProps(root, file) {
|
|
472
912
|
if (!/\.[cm]?[jt]sx?$/.test(file)) return null;
|
|
473
913
|
const ts = await loadTs(root);
|
|
474
914
|
if (!ts) return null;
|
|
915
|
+
const oxc = /\.[cm]?tsx?$/.test(file) ? await loadOxc(root) : null;
|
|
916
|
+
const fast = oxc && propsFromOxc(ts, oxc, file);
|
|
917
|
+
if (fast) return fast;
|
|
475
918
|
const configPath = ts.findConfigFile(root, ts.sys.fileExists);
|
|
476
919
|
const base = configPath ? ts.parseJsonConfigFileContent(ts.readConfigFile(configPath, ts.sys.readFile).config, ts.sys, root).options : {};
|
|
477
920
|
const options = {
|
|
@@ -575,6 +1018,116 @@ var Printer = class {
|
|
|
575
1018
|
}
|
|
576
1019
|
};
|
|
577
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 === "<" ? "<" : "&")}</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
|
+
|
|
578
1131
|
// src/vite/dev.ts
|
|
579
1132
|
var DEV_ENTRY = "@vitral/entry.js";
|
|
580
1133
|
var VIRTUAL_DEV_ENTRY = "\0vitral:dev-entry";
|
|
@@ -623,6 +1176,7 @@ if (import.meta.hot) {
|
|
|
623
1176
|
}
|
|
624
1177
|
`;
|
|
625
1178
|
}
|
|
1179
|
+
var DEV_IDS = /^virtual:vitral-react-preamble$|\/@vitral\/entry\.js$/;
|
|
626
1180
|
function resolveDevId(id) {
|
|
627
1181
|
if (id === PREAMBLE_ID) return "\0" + PREAMBLE_ID;
|
|
628
1182
|
if (id.endsWith("/" + DEV_ENTRY)) return VIRTUAL_DEV_ENTRY;
|
|
@@ -633,8 +1187,9 @@ function loadPreamble(id) {
|
|
|
633
1187
|
function devManifest(name, scope) {
|
|
634
1188
|
return { name, entry: DEV_ENTRY, css: [], ...scope ? { scope } : {} };
|
|
635
1189
|
}
|
|
1190
|
+
var DEV_CSS = { include: /\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(\?|$)/, exclude: /[?&](raw|url|inline)\b/ };
|
|
636
1191
|
function scopeDevCss(code, id, scope) {
|
|
637
|
-
if (
|
|
1192
|
+
if (!DEV_CSS.include.test(id) || DEV_CSS.exclude.test(id)) return;
|
|
638
1193
|
return scopeCss(code, scope);
|
|
639
1194
|
}
|
|
640
1195
|
function serveDevManifest(server, manifest) {
|
|
@@ -670,21 +1225,44 @@ function vitral(options = {}) {
|
|
|
670
1225
|
let pkg = {};
|
|
671
1226
|
let manifest;
|
|
672
1227
|
let split;
|
|
1228
|
+
let modules = /* @__PURE__ */ new Set();
|
|
673
1229
|
let entry = options.entry;
|
|
674
1230
|
let adapter = "element";
|
|
675
1231
|
let framework = "element";
|
|
676
|
-
const entryFile = () =>
|
|
1232
|
+
const entryFile = () => resolve5(root, entry);
|
|
677
1233
|
let serve = false;
|
|
678
1234
|
let shared = [];
|
|
679
1235
|
const dedupe = !!options.dedupe?.length;
|
|
680
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
|
+
}
|
|
681
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
|
+
};
|
|
682
1259
|
return {
|
|
683
1260
|
name: "vitral",
|
|
684
1261
|
config(user, { mode, command }) {
|
|
685
|
-
entry ??= findEntry(
|
|
1262
|
+
entry ??= findEntry(resolve5(user.root ?? process.cwd()));
|
|
686
1263
|
if (!entry) throw new Error("[vitral] n\xE3o achei a entrada do remote (src/remote.* ou src/App.*). Use vitral({ entry }).");
|
|
687
1264
|
const rolldown = "rolldownVersion" in this.meta;
|
|
1265
|
+
const dir = options.versionDir ? versionDir(user.root ?? process.cwd(), user.build?.outDir, options.version) : void 0;
|
|
688
1266
|
return {
|
|
689
1267
|
// Código de biblioteca não tem process.env; React e Vue precisam disso.
|
|
690
1268
|
define: { "process.env.NODE_ENV": JSON.stringify(mode === "development" ? "development" : "production") },
|
|
@@ -694,12 +1272,18 @@ function vitral(options = {}) {
|
|
|
694
1272
|
// O remote não tem index.html: sem isso o Vite só descobre as
|
|
695
1273
|
// dependências no primeiro request e recarrega a página do host.
|
|
696
1274
|
optimizeDeps: user.optimizeDeps?.entries ? void 0 : { entries: [entry] },
|
|
697
|
-
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
|
+
} : {
|
|
698
1281
|
// Nomes com hash: cache eterno no CDN. Só o vitral.json muda a cada deploy.
|
|
699
1282
|
lib: { entry: dedupe ? BOOT : options.exposes ? EXPOSES_ENTRY : options.adapter === false ? entry : ENTRY_ID, fileName: () => "remote-[hash].js", cssFileName: "remote" },
|
|
700
1283
|
// Arquivo único (hosts antigos e caminho com blob:) e build dividido (manifesto v2).
|
|
701
1284
|
rollupOptions: { external: options.shared ?? [], output: outputs(rolldown) },
|
|
702
|
-
cssCodeSplit: false
|
|
1285
|
+
cssCodeSplit: false,
|
|
1286
|
+
...dir && { outDir: dir }
|
|
703
1287
|
}
|
|
704
1288
|
};
|
|
705
1289
|
},
|
|
@@ -708,9 +1292,9 @@ function vitral(options = {}) {
|
|
|
708
1292
|
framework = detectAdapter(c.plugins);
|
|
709
1293
|
adapter = options.adapter || framework;
|
|
710
1294
|
serve = c.command === "serve";
|
|
711
|
-
outDir =
|
|
1295
|
+
outDir = resolve5(c.root, c.build.outDir);
|
|
712
1296
|
try {
|
|
713
|
-
pkg = JSON.parse(
|
|
1297
|
+
pkg = JSON.parse(readFileSync5(join6(root, "package.json"), "utf8"));
|
|
714
1298
|
} catch {
|
|
715
1299
|
}
|
|
716
1300
|
},
|
|
@@ -722,8 +1306,11 @@ function vitral(options = {}) {
|
|
|
722
1306
|
const scope = options.scopeCss === false ? void 0 : scopeName();
|
|
723
1307
|
serveDevManifest(server, () => devManifest(options.name ?? pkg.name ?? "remote", scope));
|
|
724
1308
|
},
|
|
1309
|
+
// Filtros de hook (Rolldown, Vite 6.3+): os módulos que não são do vitral
|
|
1310
|
+
// nem chegam ao JS. As checagens nos handlers continuam para Vite 5 e 6.0-6.2.
|
|
725
1311
|
resolveId: {
|
|
726
1312
|
order: "pre",
|
|
1313
|
+
filter: { id: [...dedupe ? [dedupeIds(options.dedupe)] : [], ...options.exposes ? [EXPOSES_IDS] : [], /__vitral_entry__\.js$/, DEV_IDS] },
|
|
727
1314
|
handler(id, importer) {
|
|
728
1315
|
const own = dedupe && !serve ? hooks.resolveId.handler(id, importer) : null;
|
|
729
1316
|
if (own) return own;
|
|
@@ -732,54 +1319,102 @@ function vitral(options = {}) {
|
|
|
732
1319
|
return resolveDevId(id);
|
|
733
1320
|
}
|
|
734
1321
|
},
|
|
735
|
-
load
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
1322
|
+
load: {
|
|
1323
|
+
// Todos os módulos virtuais do vitral: \0vitral... e \0virtual:vitral...
|
|
1324
|
+
filter: { id: /^\x00(virtual:)?vitral/ },
|
|
1325
|
+
handler(id) {
|
|
1326
|
+
const own = dedupe && !serve ? hooks.load(id) : null;
|
|
1327
|
+
if (own != null) return own;
|
|
1328
|
+
const exposed = options.exposes ? loadExposes(id, root, entry, options.exposes, options.adapter === false ? void 0 : ENTRY_ID) : null;
|
|
1329
|
+
if (exposed != null) return exposed;
|
|
1330
|
+
if (id === VIRTUAL_ENTRY) return entryCode(resolve5(root, entry), adapter, scopeName());
|
|
1331
|
+
if (id === VIRTUAL_DEV_ENTRY) return devEntryCode(framework, options.adapter === false ? resolve5(root, entry) : void 0);
|
|
1332
|
+
return loadPreamble(id);
|
|
1333
|
+
}
|
|
743
1334
|
},
|
|
744
|
-
transform
|
|
745
|
-
|
|
1335
|
+
transform: {
|
|
1336
|
+
filter: { id: DEV_CSS },
|
|
1337
|
+
handler(code, id) {
|
|
1338
|
+
if (serve && options.scopeCss !== false) return scopeDevCss(code, id, scopeName());
|
|
1339
|
+
}
|
|
746
1340
|
},
|
|
747
1341
|
writeBundle(_, bundle) {
|
|
1342
|
+
if (options.sbom) bundledFiles(bundle, modules);
|
|
748
1343
|
if (isSplit(bundle)) return void (split = collect(outDir, bundle));
|
|
749
1344
|
const files = Object.values(bundle);
|
|
750
1345
|
const entry2 = files.find((f) => f.type === "chunk" && f.isEntry);
|
|
751
1346
|
if (!entry2) return;
|
|
1347
|
+
if (mcp) return mcpApp(files, entry2.fileName);
|
|
1348
|
+
const emit = (file, text, kind = "") => {
|
|
1349
|
+
const hash = createHash3("sha256").update(text).digest("base64url").slice(0, 8);
|
|
1350
|
+
const name = file.replace(/\.css$/, `${kind}-${hash}.css`);
|
|
1351
|
+
writeFileSync2(join6(outDir, name), text);
|
|
1352
|
+
return name;
|
|
1353
|
+
};
|
|
1354
|
+
const shadow = { css: [] };
|
|
752
1355
|
const css = files.filter((f) => f.type === "asset" && f.fileName.endsWith(".css")).map((f) => {
|
|
753
|
-
const from =
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
const hash = createHash2("sha256").update(text).digest("base64url").slice(0, 8);
|
|
757
|
-
const name = f.fileName.replace(/\.css$/, `-${hash}.css`);
|
|
758
|
-
writeFileSync2(join4(outDir, name), text);
|
|
1356
|
+
const from = join6(outDir, f.fileName);
|
|
1357
|
+
const text = transformCss(readFileSync5(from, "utf8"), options, scopeName());
|
|
1358
|
+
const name = emit(f.fileName, text);
|
|
759
1359
|
if (name !== f.fileName) rmSync2(from);
|
|
1360
|
+
const split2 = splitShadowCss(text);
|
|
1361
|
+
shadow.css.push(split2.css === text ? name : emit(f.fileName, split2.css, "-shadow"));
|
|
1362
|
+
if (split2.global) (shadow.global ??= []).push(emit(f.fileName, split2.global, "-global"));
|
|
1363
|
+
if (split2.imports.length) (shadow.imports ??= []).push(...split2.imports);
|
|
1364
|
+
if (split2.rebase) shadow.rebase = true;
|
|
760
1365
|
return name;
|
|
761
1366
|
});
|
|
762
|
-
const code =
|
|
1367
|
+
const code = readFileSync5(join6(outDir, entry2.fileName));
|
|
763
1368
|
manifest = {
|
|
764
1369
|
name: options.name ?? pkg.name ?? "remote",
|
|
765
1370
|
version: options.version ?? pkg.version,
|
|
766
1371
|
entry: entry2.fileName,
|
|
767
1372
|
css,
|
|
768
|
-
|
|
1373
|
+
...css.length ? { shadow } : {},
|
|
1374
|
+
integrity: "sha384-" + createHash3("sha384").update(code).digest("base64"),
|
|
769
1375
|
...options.scopeCss === false ? {} : { scope: scopeName() },
|
|
770
|
-
...options.exposes ? { exposes: Object.keys(exposeKeys(options.exposes)) } : {}
|
|
1376
|
+
...options.exposes ? { exposes: Object.keys(exposeKeys(options.exposes)) } : {},
|
|
1377
|
+
...contractOf(options.contract?.version, shared)
|
|
771
1378
|
};
|
|
772
1379
|
},
|
|
773
1380
|
async closeBundle() {
|
|
774
1381
|
if (!manifest) return;
|
|
775
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
|
+
}
|
|
776
1388
|
manifest = split = void 0;
|
|
777
|
-
|
|
1389
|
+
modules = /* @__PURE__ */ new Set();
|
|
1390
|
+
writeFileSync2(join6(outDir, "vitral.json"), JSON.stringify(done, null, 2) + "\n");
|
|
778
1391
|
const props = options.types === false ? null : await extractProps(root, entryFile());
|
|
779
|
-
if (props) writeFileSync2(
|
|
1392
|
+
if (props) writeFileSync2(join6(outDir, "vitral.d.ts"), typesFile(done.name, props));
|
|
780
1393
|
}
|
|
781
1394
|
};
|
|
782
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
|
+
}
|
|
1411
|
+
function contractOf(version, groups2) {
|
|
1412
|
+
const contract = {
|
|
1413
|
+
...version && { version },
|
|
1414
|
+
...groups2.length && { peers: Object.fromEntries(groups2.map((g) => [g.name, g.range])) }
|
|
1415
|
+
};
|
|
1416
|
+
return Object.keys(contract).length ? { contract } : {};
|
|
1417
|
+
}
|
|
783
1418
|
export {
|
|
784
1419
|
vitral as default,
|
|
785
1420
|
vitral
|