vitral 0.3.0 → 0.5.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/dist/angular.d.ts +2 -2
- package/dist/angular.js +7 -7
- package/dist/auto.js +7 -7
- package/dist/{capture-JYFERAPL.js → capture-TT5WBLJ6.js} +1 -1
- package/dist/channel-2YPYGX3J.js +95 -0
- package/dist/{chunk-AKNNHQ2H.js → chunk-463H6B56.js} +5 -0
- package/dist/{chunk-IHTUM6LT.js → chunk-4Z77XNBR.js} +2 -2
- package/dist/chunk-54CBIZES.js +105 -0
- package/dist/{chunk-TD4S3IHA.js → chunk-5JNV45BB.js} +10 -8
- package/dist/{chunk-SDB5AZEI.js → chunk-C3QOBAUE.js} +2 -2
- package/dist/chunk-DAESKNQ6.js +207 -0
- package/dist/{chunk-3YXI3G34.js → chunk-K6EG7DMO.js} +16 -7
- package/dist/{chunk-ZAC6QQI6.js → chunk-KU6HF2EW.js} +4 -4
- package/dist/{chunk-I3VSKSAZ.js → chunk-KZBH5MPD.js} +29 -27
- package/dist/chunk-NZEQGRBL.js +93 -0
- package/dist/chunk-PY7P5BF4.js +404 -0
- package/dist/{chunk-GNHCZRQP.js → chunk-TW7KYJQ6.js} +1 -1
- package/dist/{chunk-AH7KNMBW.js → chunk-UYOPJ4XQ.js} +1 -1
- package/dist/cli.js +1522 -37
- package/dist/devtools.d.ts +32 -2
- package/dist/devtools.js +27 -12
- package/dist/dict.d.ts +69 -0
- package/dist/dict.js +8 -0
- package/dist/edge.d.ts +118 -0
- package/dist/edge.js +398 -0
- package/dist/element.d.ts +12 -3
- package/dist/element.js +7 -7
- package/dist/embed.js +2 -0
- package/dist/{events-D5gs7rff.d.ts → events-0rxFlWJJ.d.ts} +1 -1
- package/dist/expose-IAKYHJXF.js +15 -0
- package/dist/federation.d.ts +89 -0
- package/dist/federation.js +101 -0
- package/dist/hydrate-YVZDJ2V7.js +168 -0
- package/dist/iframe.js +7 -7
- package/dist/index.d.ts +4 -4
- package/dist/index.js +5 -5
- package/dist/otel.d.ts +29 -1
- package/dist/otel.js +13 -1
- package/dist/overrides-NP754HY7.js +27 -0
- package/dist/preact.d.ts +4 -4
- package/dist/preact.js +6 -6
- package/dist/prefetch.d.ts +25 -0
- package/dist/prefetch.js +178 -0
- package/dist/react.d.ts +3 -3
- package/dist/react.js +6 -6
- package/dist/reframe-LQL4DZYP.js +251 -0
- package/dist/routes.d.ts +2 -2
- package/dist/routes.js +5 -5
- package/dist/{shadow-6HELCHCJ.js → shadow-S4SKHTA7.js} +66 -5
- package/dist/single-spa.d.ts +40 -0
- package/dist/single-spa.js +52 -0
- package/dist/{slot-DqXTwGbs.d.ts → slot-D49L1rdU.d.ts} +1 -1
- package/dist/solid.d.ts +3 -3
- package/dist/solid.js +6 -6
- package/dist/{sri-JMX6JLQP.js → sri-576GTDIA.js} +41 -10
- package/dist/svelte.d.ts +4 -4
- package/dist/svelte.js +6 -6
- package/dist/testing.d.ts +171 -3
- package/dist/testing.js +193 -6
- package/dist/{types-Czvm-siZ.d.ts → types-DUtcF3HO.d.ts} +124 -5
- package/dist/vitals.d.ts +29 -0
- package/dist/vitals.js +152 -0
- package/dist/vite.d.ts +18 -0
- package/dist/vite.js +329 -417
- package/dist/vue.d.ts +3 -3
- package/dist/vue.js +6 -6
- package/package.json +170 -21
- package/dist/chunk-DXORSF4X.js +0 -42
- package/dist/expose-JUOUN5N5.js +0 -15
- package/dist/overrides-NZAIUGK5.js +0 -15
package/dist/vite.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
extractProps,
|
|
3
|
+
typesFile
|
|
4
|
+
} from "./chunk-PY7P5BF4.js";
|
|
5
|
+
|
|
1
6
|
// src/vite.ts
|
|
2
|
-
import { createHash as
|
|
7
|
+
import { createHash as createHash3 } from "crypto";
|
|
3
8
|
import { readFileSync as readFileSync4, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4
|
-
import { join as
|
|
9
|
+
import { join as join4, resolve as resolve4 } from "path";
|
|
5
10
|
|
|
6
11
|
// src/vite-exposes.ts
|
|
7
12
|
import { resolve } from "path";
|
|
@@ -105,9 +110,149 @@ function withSplit(m, outDir, s, groups2 = []) {
|
|
|
105
110
|
return { ...m, files, ...s && { split: { entry: s.entry, chunks: s.chunks } }, ...dedupe.length && { dedupe } };
|
|
106
111
|
}
|
|
107
112
|
|
|
113
|
+
// src/vite/sbom.ts
|
|
114
|
+
import { createHash as createHash2 } from "crypto";
|
|
115
|
+
import { existsSync, readFileSync as readFileSync2, realpathSync } from "fs";
|
|
116
|
+
import { dirname, isAbsolute, join as join2, sep } from "path";
|
|
117
|
+
var SBOM_FILE = "sbom.cdx.json";
|
|
118
|
+
var readPkg = (dir) => {
|
|
119
|
+
try {
|
|
120
|
+
return JSON.parse(readFileSync2(join2(dir, "package.json"), "utf8"));
|
|
121
|
+
} catch {
|
|
122
|
+
return void 0;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
function bundledFiles(bundle, into = /* @__PURE__ */ new Set()) {
|
|
126
|
+
for (const f of Object.values(bundle)) {
|
|
127
|
+
if (f.type !== "chunk" || !f.modules) continue;
|
|
128
|
+
for (const [id, m] of Object.entries(f.modules)) {
|
|
129
|
+
const file = id.split("?")[0];
|
|
130
|
+
if (m.renderedLength > 0 && isAbsolute(file)) into.add(file);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return into;
|
|
134
|
+
}
|
|
135
|
+
function packageDirs(files) {
|
|
136
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
137
|
+
const near = /* @__PURE__ */ new Map();
|
|
138
|
+
const nearest = (dir) => {
|
|
139
|
+
if (near.has(dir)) return near.get(dir);
|
|
140
|
+
const parent = dirname(dir);
|
|
141
|
+
const found = readPkg(dir)?.name ? dir : parent === dir ? null : nearest(parent);
|
|
142
|
+
near.set(dir, found);
|
|
143
|
+
return found;
|
|
144
|
+
};
|
|
145
|
+
const nm = `${sep}node_modules${sep}`;
|
|
146
|
+
for (const file of files) {
|
|
147
|
+
const at = file.lastIndexOf(nm);
|
|
148
|
+
if (at >= 0) {
|
|
149
|
+
const parts = file.slice(at + nm.length).split(sep);
|
|
150
|
+
const name = parts[0].startsWith("@") ? parts.slice(0, 2).join(sep) : parts[0];
|
|
151
|
+
if (parts.length > (parts[0].startsWith("@") ? 2 : 1)) dirs.add(file.slice(0, at + nm.length) + name);
|
|
152
|
+
} else {
|
|
153
|
+
const dir = nearest(dirname(file));
|
|
154
|
+
if (dir) dirs.add(dir);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return dirs;
|
|
158
|
+
}
|
|
159
|
+
function purl(name, version) {
|
|
160
|
+
const path = name.split("/").map(encodeURIComponent).join("/");
|
|
161
|
+
return `pkg:npm/${path}${version ? `@${encodeURIComponent(version)}` : ""}`;
|
|
162
|
+
}
|
|
163
|
+
function licenses(pkg) {
|
|
164
|
+
const raw = typeof pkg.license === "string" ? pkg.license : pkg.license?.type ?? pkg.licenses?.map((l) => l.type).filter(Boolean).join(" OR ");
|
|
165
|
+
if (!raw) return void 0;
|
|
166
|
+
const spdx = /^\(?[A-Za-z0-9.+-]+( (AND|OR|WITH) \(?[A-Za-z0-9.+-]+\)?)*\)?$/.test(raw) && raw !== "UNLICENSED";
|
|
167
|
+
return spdx ? [{ expression: raw }] : [{ license: { name: raw } }];
|
|
168
|
+
}
|
|
169
|
+
function component(pkg, type) {
|
|
170
|
+
const scoped = pkg.name.startsWith("@") && pkg.name.includes("/");
|
|
171
|
+
const ref = purl(pkg.name, pkg.version);
|
|
172
|
+
const license = licenses(pkg);
|
|
173
|
+
return {
|
|
174
|
+
type,
|
|
175
|
+
"bom-ref": ref,
|
|
176
|
+
...scoped && { group: pkg.name.slice(0, pkg.name.indexOf("/")) },
|
|
177
|
+
name: scoped ? pkg.name.slice(pkg.name.indexOf("/") + 1) : pkg.name,
|
|
178
|
+
...pkg.version && { version: pkg.version },
|
|
179
|
+
...pkg.description && { description: pkg.description },
|
|
180
|
+
...license && { licenses: license },
|
|
181
|
+
purl: ref
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
function resolveDir(from, name) {
|
|
185
|
+
for (let dir = from; ; dir = dirname(dir)) {
|
|
186
|
+
const candidate = join2(dir, "node_modules", name);
|
|
187
|
+
if (existsSync(join2(candidate, "package.json"))) {
|
|
188
|
+
try {
|
|
189
|
+
return realpathSync(candidate);
|
|
190
|
+
} catch {
|
|
191
|
+
return candidate;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (dirname(dir) === dir) return void 0;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function createSbom(input) {
|
|
198
|
+
const rootDir = realpathSync(input.root);
|
|
199
|
+
const rootPkg = readPkg(rootDir) ?? {};
|
|
200
|
+
const main = component({ ...rootPkg, name: input.name, version: input.version }, "application");
|
|
201
|
+
const hashes = input.entry && [{ alg: "SHA-512", content: createHash2("sha512").update(input.entry).digest("hex") }];
|
|
202
|
+
const byDir = /* @__PURE__ */ new Map();
|
|
203
|
+
for (const dir of packageDirs(input.files)) {
|
|
204
|
+
let real = dir;
|
|
205
|
+
try {
|
|
206
|
+
real = realpathSync(dir);
|
|
207
|
+
} catch {
|
|
208
|
+
}
|
|
209
|
+
const pkg = readPkg(real);
|
|
210
|
+
if (real === rootDir || !pkg?.name || byDir.has(real)) continue;
|
|
211
|
+
byDir.set(real, { pkg, ref: purl(pkg.name, pkg.version) });
|
|
212
|
+
}
|
|
213
|
+
const deps = (dir, pkg) => {
|
|
214
|
+
const names = Object.keys({ ...pkg.peerDependencies, ...pkg.optionalDependencies, ...pkg.dependencies });
|
|
215
|
+
const refs = /* @__PURE__ */ new Set();
|
|
216
|
+
for (const n of names) {
|
|
217
|
+
const hit = byDir.get(resolveDir(dir, n) ?? "");
|
|
218
|
+
if (hit) refs.add(hit.ref);
|
|
219
|
+
}
|
|
220
|
+
return [...refs].sort();
|
|
221
|
+
};
|
|
222
|
+
const components = /* @__PURE__ */ new Map();
|
|
223
|
+
const graph = /* @__PURE__ */ new Map([[main["bom-ref"], new Set(deps(rootDir, rootPkg))]]);
|
|
224
|
+
for (const [dir, { pkg, ref }] of byDir) {
|
|
225
|
+
if (!components.has(ref)) components.set(ref, component(pkg, "library"));
|
|
226
|
+
const set = graph.get(ref) ?? /* @__PURE__ */ new Set();
|
|
227
|
+
for (const d of deps(dir, pkg)) if (d !== ref) set.add(d);
|
|
228
|
+
graph.set(ref, set);
|
|
229
|
+
}
|
|
230
|
+
const epoch = Number(process.env.SOURCE_DATE_EPOCH);
|
|
231
|
+
const timestamp = input.timestamp ?? (Number.isFinite(epoch) && process.env.SOURCE_DATE_EPOCH ? new Date(epoch * 1e3) : /* @__PURE__ */ new Date());
|
|
232
|
+
const body = {
|
|
233
|
+
metadata: {
|
|
234
|
+
timestamp: timestamp.toISOString().replace(/\.\d{3}Z$/, "Z"),
|
|
235
|
+
tools: { components: [{ type: "application", name: "vitral", ...input.tool && { version: input.tool }, purl: purl("vitral", input.tool) }] },
|
|
236
|
+
component: { ...main, ...hashes && { hashes } }
|
|
237
|
+
},
|
|
238
|
+
components: [...components.values()].sort((a, b) => a["bom-ref"].localeCompare(b["bom-ref"])),
|
|
239
|
+
dependencies: [...graph].map(([ref, set]) => ({ ref, dependsOn: [...set].sort() }))
|
|
240
|
+
};
|
|
241
|
+
const h = createHash2("sha1").update(JSON.stringify(body)).digest("hex");
|
|
242
|
+
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)}`;
|
|
243
|
+
return {
|
|
244
|
+
$schema: "http://cyclonedx.org/schema/bom-1.6.schema.json",
|
|
245
|
+
bomFormat: "CycloneDX",
|
|
246
|
+
specVersion: "1.6",
|
|
247
|
+
serialNumber: serial,
|
|
248
|
+
version: 1,
|
|
249
|
+
...body
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
108
253
|
// src/vite/dedupe.ts
|
|
109
|
-
import { existsSync, readFileSync as
|
|
110
|
-
import { dirname, join as
|
|
254
|
+
import { existsSync as existsSync2, readFileSync as readFileSync3 } from "fs";
|
|
255
|
+
import { dirname as dirname2, join as join3, resolve as resolve2 } from "path";
|
|
111
256
|
import { pathToFileURL } from "url";
|
|
112
257
|
var REACT = ["react", "react-dom", "react-dom/client", "react/jsx-runtime", "react/jsx-dev-runtime", "react/compiler-runtime"];
|
|
113
258
|
var BOOT = "virtual:vitral-boot";
|
|
@@ -118,10 +263,10 @@ var pkgOf = (spec) => spec.split("/").slice(0, spec.startsWith("@") ? 2 : 1).joi
|
|
|
118
263
|
var groupOf = (spec) => REACT.includes(spec) || pkgOf(spec) === "scheduler" ? "react" : pkgOf(spec);
|
|
119
264
|
var ident = /^[A-Za-z_$][\w$]*$/;
|
|
120
265
|
function versionOf(file, pkg) {
|
|
121
|
-
for (let dir =
|
|
122
|
-
const json =
|
|
123
|
-
if (!
|
|
124
|
-
const data = JSON.parse(
|
|
266
|
+
for (let dir = dirname2(file); dir !== dirname2(dir); dir = dirname2(dir)) {
|
|
267
|
+
const json = join3(dir, "package.json");
|
|
268
|
+
if (!existsSync2(json)) continue;
|
|
269
|
+
const data = JSON.parse(readFileSync3(json, "utf8"));
|
|
125
270
|
if (data.name === pkg) return data.version;
|
|
126
271
|
}
|
|
127
272
|
throw new Error(`vitral: vers\xE3o de ${pkg} n\xE3o encontrada`);
|
|
@@ -417,7 +562,7 @@ function splitShadowCss(text) {
|
|
|
417
562
|
}
|
|
418
563
|
|
|
419
564
|
// src/vite/adapter.ts
|
|
420
|
-
import { existsSync as
|
|
565
|
+
import { existsSync as existsSync3 } from "fs";
|
|
421
566
|
import { resolve as resolve3 } from "path";
|
|
422
567
|
var PLUGINS = [
|
|
423
568
|
[/^(preact:|prefresh$)/, "preact"],
|
|
@@ -456,10 +601,14 @@ import { component } from 'vitral'
|
|
|
456
601
|
function wrap(c) {
|
|
457
602
|
if (typeof c === 'function' && typeof HTMLElement !== 'undefined' && c.prototype instanceof HTMLElement) {
|
|
458
603
|
const base = ${JSON.stringify(`${scope}-remote`.toLowerCase().replace(/^[^a-z]+/, "x-"))}
|
|
459
|
-
|
|
460
|
-
//
|
|
461
|
-
|
|
462
|
-
|
|
604
|
+
// No registro do remote (ctx.customElements). Uma tag n\xE3o aceita outra
|
|
605
|
+
// classe: no HMR, a classe nova ganha tag nova.
|
|
606
|
+
return elementRemote(base, (r) => {
|
|
607
|
+
let tag = r.getName?.(c) || base
|
|
608
|
+
for (let n = 2; r.get(tag) && r.get(tag) !== c; n++) tag = base + '-' + n
|
|
609
|
+
r.get(tag) || r.define(tag, c)
|
|
610
|
+
return tag
|
|
611
|
+
})
|
|
463
612
|
}
|
|
464
613
|
if (typeof c === 'function') return component(c)
|
|
465
614
|
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,408 +620,119 @@ var CANDIDATES = ["src/remote", "src/App", "src/app"];
|
|
|
471
620
|
var EXTENSIONS = [".tsx", ".ts", ".jsx", ".js", ".vue", ".svelte"];
|
|
472
621
|
function findEntry(root) {
|
|
473
622
|
for (const base of CANDIDATES) {
|
|
474
|
-
for (const ext of EXTENSIONS) if (
|
|
623
|
+
for (const ext of EXTENSIONS) if (existsSync3(resolve3(root, base + ext))) return base + ext;
|
|
475
624
|
}
|
|
476
625
|
}
|
|
477
626
|
|
|
478
|
-
// src/vite/
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
try {
|
|
492
|
-
const mod = await import(pathToFileURL2(id()).href);
|
|
493
|
-
if (typeof mod.isolatedDeclarationSync === "function") return mod;
|
|
494
|
-
} catch {
|
|
495
|
-
}
|
|
627
|
+
// src/vite/mcp-app.ts
|
|
628
|
+
var MCP_APP_PROTOCOL = "2026-01-26";
|
|
629
|
+
var MCP_APP_GLOBAL = "__vitral_remote__";
|
|
630
|
+
var MCP_RUNTIME = `function (w, mod, info) {
|
|
631
|
+
var parent = w.parent, doc = w.document, seq = 0, pending = {}, handlers = {}, last = {}, context = {}
|
|
632
|
+
var props = {}, mounted = null, ready = false, dirty = false
|
|
633
|
+
function send(m) { m.jsonrpc = '2.0'; parent.postMessage(m, '*') }
|
|
634
|
+
function request(method, params) {
|
|
635
|
+
var id = ++seq
|
|
636
|
+
return new Promise(function (ok, fail) {
|
|
637
|
+
pending[id] = [ok, fail]
|
|
638
|
+
send({ id: id, method: method, params: params || {} })
|
|
639
|
+
})
|
|
496
640
|
}
|
|
497
|
-
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
const reader = new Reader(ts, oxc);
|
|
509
|
-
const scope = reader.scope(file);
|
|
510
|
-
const props = reader.defaultProps(scope);
|
|
511
|
-
return props ? reader.print(props.node, props.scope, 0, { top: true }) : "Record<string, unknown>";
|
|
512
|
-
} catch {
|
|
513
|
-
return null;
|
|
641
|
+
function notify(method, params) { send({ method: method, params: params || {} }) }
|
|
642
|
+
function report(e) { notify('notifications/message', { level: 'error', logger: info.name, data: String((e && e.message) || e) }) }
|
|
643
|
+
function text(p, key) { return typeof p === 'string' ? p : p && p[key] }
|
|
644
|
+
function push() { if (mounted && mounted.update) { try { mounted.update(Object.assign({}, props)) } catch (e) { report(e) } } }
|
|
645
|
+
// Antes do mount terminar, s\xF3 guarda: o update sai uma vez, logo depois.
|
|
646
|
+
function set(key, value) { props[key] = value; if (ready) push(); else dirty = true }
|
|
647
|
+
function theme(c) {
|
|
648
|
+
if (!c) return
|
|
649
|
+
var root = doc.documentElement, vars = c.styles && c.styles.variables
|
|
650
|
+
if (c.theme) { root.setAttribute('data-theme', c.theme); root.style.colorScheme = c.theme }
|
|
651
|
+
for (var k in vars) if (vars[k] != null) root.style.setProperty(k, vars[k])
|
|
514
652
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
scope(file) {
|
|
525
|
-
const cached = this.scopes.get(file);
|
|
526
|
-
if (cached) return cached;
|
|
527
|
-
const { ts } = this;
|
|
528
|
-
let code = readFileSync3(file, "utf8");
|
|
529
|
-
if (!/\.d\.[cm]?ts$/.test(file)) {
|
|
530
|
-
const out = this.oxc.isolatedDeclarationSync(file, code, {});
|
|
531
|
-
if (out.errors.length) unsupported();
|
|
532
|
-
code = out.code;
|
|
533
|
-
}
|
|
534
|
-
const source = ts.createSourceFile(file + ".d.ts", code, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
535
|
-
const scope = { file, types: /* @__PURE__ */ new Map(), values: /* @__PURE__ */ new Map(), imports: /* @__PURE__ */ new Map() };
|
|
536
|
-
const isDefault = (n) => ts.canHaveModifiers(n) && !!ts.getModifiers(n)?.some((m) => m.kind === ts.SyntaxKind.DefaultKeyword);
|
|
537
|
-
let defaultName;
|
|
538
|
-
for (const st of source.statements) {
|
|
539
|
-
if (ts.isInterfaceDeclaration(st) || ts.isTypeAliasDeclaration(st)) {
|
|
540
|
-
if (scope.types.has(st.name.text)) unsupported();
|
|
541
|
-
scope.types.set(st.name.text, st);
|
|
542
|
-
} else if (ts.isImportDeclaration(st) && ts.isStringLiteral(st.moduleSpecifier)) {
|
|
543
|
-
const from = st.moduleSpecifier.text;
|
|
544
|
-
const clause = st.importClause;
|
|
545
|
-
if (clause?.name) scope.imports.set(clause.name.text, { from, name: "default" });
|
|
546
|
-
const bindings = clause?.namedBindings;
|
|
547
|
-
if (bindings && ts.isNamespaceImport(bindings)) scope.imports.set(bindings.name.text, { from, name: "*" });
|
|
548
|
-
if (bindings && ts.isNamedImports(bindings)) for (const el of bindings.elements) scope.imports.set(el.name.text, { from, name: (el.propertyName ?? el.name).text });
|
|
549
|
-
} else if (ts.isFunctionDeclaration(st) || ts.isClassDeclaration(st)) {
|
|
550
|
-
if (isDefault(st)) scope.default ??= st;
|
|
551
|
-
else if (st.name && !scope.values.has(st.name.text)) scope.values.set(st.name.text, st);
|
|
552
|
-
} else if (ts.isVariableStatement(st)) {
|
|
553
|
-
for (const d of st.declarationList.declarations) if (ts.isIdentifier(d.name)) scope.values.set(d.name.text, d);
|
|
554
|
-
} else if (ts.isExportAssignment(st) && !st.isExportEquals) {
|
|
555
|
-
defaultName = ts.isIdentifier(st.expression) ? st.expression.text : unsupported();
|
|
556
|
-
} else if (ts.isExportDeclaration(st) && !st.moduleSpecifier && st.exportClause && ts.isNamedExports(st.exportClause)) {
|
|
557
|
-
const el = st.exportClause.elements.find((e) => e.name.text === "default");
|
|
558
|
-
if (el) defaultName = (el.propertyName ?? el.name).text;
|
|
653
|
+
var events = {
|
|
654
|
+
emit: function (type, payload) {
|
|
655
|
+
last[type] = payload
|
|
656
|
+
;(handlers[type] || []).slice().forEach(function (h) { try { h(payload) } catch (e) { w.console.error(e) } })
|
|
657
|
+
if (type === 'mcp:message') request('ui/message', { role: 'user', content: [{ type: 'text', text: String(text(payload, 'text')) }] }).catch(report)
|
|
658
|
+
else if (type === 'mcp:open-link') request('ui/open-link', { url: String(text(payload, 'url')) }).catch(report)
|
|
659
|
+
else {
|
|
660
|
+
context[type] = payload
|
|
661
|
+
request('ui/update-model-context', { structuredContent: context, content: [{ type: 'text', text: JSON.stringify(context) }] }).catch(report)
|
|
559
662
|
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
defaultProps(scope) {
|
|
567
|
-
const { ts } = this;
|
|
568
|
-
const node = scope.default ?? unsupported();
|
|
569
|
-
const param = (params, i) => {
|
|
570
|
-
const p = params[i];
|
|
571
|
-
return p && { node: p.type ?? unsupported(), scope };
|
|
572
|
-
};
|
|
573
|
-
if (ts.isFunctionDeclaration(node)) return param(node.parameters, 0);
|
|
574
|
-
if (ts.isClassDeclaration(node)) {
|
|
575
|
-
if (node.heritageClauses?.length) unsupported();
|
|
576
|
-
const props = node.members.find((m) => ts.isPropertyDeclaration(m) && m.name.getText() === "props");
|
|
577
|
-
return props && { node: props.type ?? unsupported(), scope };
|
|
578
|
-
}
|
|
579
|
-
if (ts.isVariableDeclaration(node)) return this.propsOfType(node.type ?? unsupported(), scope);
|
|
580
|
-
return unsupported();
|
|
581
|
-
}
|
|
582
|
-
propsOfType(node, scope) {
|
|
583
|
-
const { ts } = this;
|
|
584
|
-
const param = (params, i, at2) => {
|
|
585
|
-
const p = params[i];
|
|
586
|
-
return p && { node: p.type ?? unsupported(), scope: at2 };
|
|
587
|
-
};
|
|
588
|
-
if (ts.isParenthesizedTypeNode(node)) return this.propsOfType(node.type, scope);
|
|
589
|
-
if (ts.isFunctionTypeNode(node)) return param(node.parameters, 0, scope);
|
|
590
|
-
let members;
|
|
591
|
-
let at = scope;
|
|
592
|
-
if (ts.isTypeLiteralNode(node)) members = node.members;
|
|
593
|
-
else if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && !node.typeArguments) {
|
|
594
|
-
const found = this.lookup(node.typeName.text, scope);
|
|
595
|
-
if (!found || found === "package" || found.decl.typeParameters) return unsupported();
|
|
596
|
-
if (ts.isTypeAliasDeclaration(found.decl)) return this.propsOfType(found.decl.type, found.scope);
|
|
597
|
-
if (found.decl.heritageClauses?.length) unsupported();
|
|
598
|
-
members = found.decl.members;
|
|
599
|
-
at = found.scope;
|
|
600
|
-
} else return unsupported();
|
|
601
|
-
const mount = members.find((m) => m.name?.getText() === "mount");
|
|
602
|
-
if (mount) {
|
|
603
|
-
if (ts.isMethodSignature(mount)) return param(mount.parameters, 1, at);
|
|
604
|
-
if (ts.isPropertySignature(mount) && mount.type) return this.mountProps(mount.type, at);
|
|
605
|
-
return unsupported();
|
|
606
|
-
}
|
|
607
|
-
const call = members.find(ts.isCallSignatureDeclaration);
|
|
608
|
-
if (call) return param(call.parameters, 0, at);
|
|
609
|
-
if (members.some(ts.isConstructSignatureDeclaration)) unsupported();
|
|
610
|
-
return void 0;
|
|
663
|
+
},
|
|
664
|
+
on: function (type, fn) {
|
|
665
|
+
;(handlers[type] = handlers[type] || []).push(fn)
|
|
666
|
+
return function () { handlers[type] = handlers[type].filter(function (h) { return h !== fn }) }
|
|
667
|
+
},
|
|
668
|
+
last: function (type) { return last[type] }
|
|
611
669
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
670
|
+
var root = doc.createElement('div')
|
|
671
|
+
root.setAttribute('data-vitral-root', info.name)
|
|
672
|
+
if (info.scope) root.setAttribute('data-vitral-scope', info.scope)
|
|
673
|
+
var ctx = {
|
|
674
|
+
name: info.name, baseUrl: w.location.href, events: events, shadowRoot: null, portalContainer: doc.body, protocol: 1,
|
|
675
|
+
reportError: report,
|
|
676
|
+
navigate: function (url) { request('ui/open-link', { url: String(url) }).catch(report) },
|
|
677
|
+
mcp: { request: request, notify: notify, hostContext: function () { return props.hostContext } }
|
|
618
678
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
if (!imp.from.startsWith(".")) return "package";
|
|
626
|
-
if (imp.name === "default" || imp.name === "*") return unsupported();
|
|
627
|
-
const found = this.lookup(imp.name, this.scope(resolveFile(scope.file, imp.from)));
|
|
628
|
-
return found ?? unsupported();
|
|
679
|
+
function size() {
|
|
680
|
+
var h = doc.documentElement, old = h.style.height
|
|
681
|
+
h.style.height = 'max-content'
|
|
682
|
+
var height = Math.ceil(h.getBoundingClientRect().height)
|
|
683
|
+
h.style.height = old
|
|
684
|
+
notify('ui/notifications/size-changed', { width: Math.ceil(w.innerWidth), height: height })
|
|
629
685
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
case K.NumberKeyword:
|
|
639
|
-
case K.BooleanKeyword:
|
|
640
|
-
case K.BigIntKeyword:
|
|
641
|
-
case K.SymbolKeyword:
|
|
642
|
-
case K.UndefinedKeyword:
|
|
643
|
-
case K.VoidKeyword:
|
|
644
|
-
case K.NeverKeyword:
|
|
645
|
-
return node.getText();
|
|
646
|
-
}
|
|
647
|
-
if (ts.isLiteralTypeNode(node)) {
|
|
648
|
-
const lit = node.literal;
|
|
649
|
-
if (ts.isStringLiteral(lit)) return JSON.stringify(lit.text);
|
|
650
|
-
if (lit.kind === K.NullKeyword || lit.kind === K.TrueKeyword || lit.kind === K.FalseKeyword || ts.isNumericLiteral(lit) || ts.isPrefixUnaryExpression(lit)) return lit.getText();
|
|
651
|
-
return unsupported();
|
|
652
|
-
}
|
|
653
|
-
if (ts.isParenthesizedTypeNode(node)) return this.print(node.type, scope, depth, opts);
|
|
654
|
-
if (ts.isUnionTypeNode(node)) {
|
|
655
|
-
const types = opts.nonNull ? node.types.filter((t) => t.kind !== K.UndefinedKeyword && !(ts.isLiteralTypeNode(t) && t.literal.kind === K.NullKeyword)) : node.types;
|
|
656
|
-
const parts = [...new Set(types.map((t) => this.print(t, scope, depth)))];
|
|
657
|
-
if (parts.includes("true") && parts.includes("false")) parts.splice(parts.indexOf("true"), 1, "boolean"), parts.splice(parts.indexOf("false"), 1);
|
|
658
|
-
return parts.join(" | ");
|
|
659
|
-
}
|
|
660
|
-
if (ts.isIntersectionTypeNode(node)) {
|
|
661
|
-
return node.types.map((t) => {
|
|
662
|
-
const s = this.print(t, scope, depth);
|
|
663
|
-
return ts.isUnionTypeNode(t) ? `(${s})` : s;
|
|
664
|
-
}).join(" & ");
|
|
665
|
-
}
|
|
666
|
-
if (depth > 6) return "unknown";
|
|
667
|
-
if (ts.isArrayTypeNode(node)) return `Array<${this.print(node.elementType, scope, depth + 1)}>`;
|
|
668
|
-
if (ts.isTypeOperatorNode(node) && node.operator === K.ReadonlyKeyword && (ts.isArrayTypeNode(node.type) || ts.isTupleTypeNode(node.type))) return this.print(node.type, scope, depth);
|
|
669
|
-
if (ts.isTupleTypeNode(node)) {
|
|
670
|
-
if (node.elements.some((e) => ts.isNamedTupleMember(e) || ts.isOptionalTypeNode(e) || ts.isRestTypeNode(e))) unsupported();
|
|
671
|
-
return `[${node.elements.map((e) => this.print(e, scope, depth + 1)).join(", ")}]`;
|
|
672
|
-
}
|
|
673
|
-
if (ts.isTypeLiteralNode(node)) return this.object(node.members, scope, depth, !!opts.top);
|
|
674
|
-
if (ts.isFunctionTypeNode(node)) return this.signature(node, scope, depth);
|
|
675
|
-
if (ts.isTypeReferenceNode(node)) return this.reference(node, scope, depth, opts);
|
|
676
|
-
return unsupported();
|
|
686
|
+
var on = {
|
|
687
|
+
'ui/notifications/tool-input': function (p) { set('toolInput', p.arguments) },
|
|
688
|
+
'ui/notifications/tool-input-partial': function (p) { set('toolInputPartial', p.arguments) },
|
|
689
|
+
'ui/notifications/tool-result': function (p) { set('toolResult', p) },
|
|
690
|
+
'ui/notifications/tool-cancelled': function (p) { set('toolCancelled', p.reason || true) },
|
|
691
|
+
'ui/notifications/host-context-changed': function (p) { theme(p); set('hostContext', Object.assign({}, props.hostContext, p)) },
|
|
692
|
+
'ui/resource-teardown': function () { if (mounted) mounted.unmount(); mounted = null; return {} },
|
|
693
|
+
ping: function () { return {} }
|
|
677
694
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
if (!
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
if (args.length || found.decl.typeParameters) unsupported();
|
|
687
|
-
if (this.seen.has(found.decl)) return "unknown";
|
|
688
|
-
this.seen.add(found.decl);
|
|
689
|
-
try {
|
|
690
|
-
const decl = found.decl;
|
|
691
|
-
if (ts.isTypeAliasDeclaration(decl)) return this.print(decl.type, found.scope, depth, opts);
|
|
692
|
-
if (decl.heritageClauses?.length) unsupported();
|
|
693
|
-
return this.object(decl.members, found.scope, depth, !!opts.top);
|
|
694
|
-
} finally {
|
|
695
|
-
this.seen.delete(found.decl);
|
|
696
|
-
}
|
|
697
|
-
}
|
|
698
|
-
if ((name === "Array" || name === "ReadonlyArray") && args.length === 1) return `Array<${this.print(args[0], scope, depth + 1)}>`;
|
|
699
|
-
if (!GLOBAL3.test(name)) return unsupported();
|
|
700
|
-
return args.length ? `${name}<${args.map((t) => this.print(t, scope, depth + 1)).join(", ")}>` : name;
|
|
701
|
-
}
|
|
702
|
-
object(members, scope, depth, top) {
|
|
703
|
-
const { ts } = this;
|
|
704
|
-
const fields = [];
|
|
705
|
-
const calls = [];
|
|
706
|
-
let index;
|
|
707
|
-
for (const m of members) {
|
|
708
|
-
if (ts.isPropertySignature(m) || ts.isMethodSignature(m)) {
|
|
709
|
-
const name = ts.isIdentifier(m.name) || ts.isStringLiteral(m.name) || ts.isNumericLiteral(m.name) ? m.name.text : unsupported();
|
|
710
|
-
if (top && name === "vitral") continue;
|
|
711
|
-
const optional = m.questionToken ? "?" : "";
|
|
712
|
-
const key = IDENT.test(name) ? name : JSON.stringify(name);
|
|
713
|
-
const type = ts.isMethodSignature(m) ? this.signature(m, scope, depth + 1) : m.type ? this.print(m.type, scope, depth + 1, { nonNull: !!optional }) : "unknown";
|
|
714
|
-
fields.push(`${key}${optional}: ${type}`);
|
|
715
|
-
} else if (ts.isIndexSignatureDeclaration(m)) {
|
|
716
|
-
const key = m.parameters[0]?.type;
|
|
717
|
-
if (!key || key.kind !== ts.SyntaxKind.StringKeyword) unsupported();
|
|
718
|
-
index = `[key: string]: ${this.print(m.type, scope, depth + 1)}`;
|
|
719
|
-
} else if (ts.isCallSignatureDeclaration(m)) {
|
|
720
|
-
calls.push(this.signature(m, scope, depth));
|
|
721
|
-
} else unsupported();
|
|
695
|
+
w.addEventListener('message', function (e) {
|
|
696
|
+
var m = e.data
|
|
697
|
+
if (e.source !== parent || !m || m.jsonrpc !== '2.0') return
|
|
698
|
+
if (m.method === undefined) {
|
|
699
|
+
var p = pending[m.id]
|
|
700
|
+
if (!p) return
|
|
701
|
+
delete pending[m.id]
|
|
702
|
+
return m.error ? p[1](new Error(m.error.message)) : p[0](m.result)
|
|
722
703
|
}
|
|
723
|
-
|
|
724
|
-
if (
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
}
|
|
740
|
-
function
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
function
|
|
750
|
-
|
|
751
|
-
|
|
704
|
+
var fn = on[m.method], result
|
|
705
|
+
if (m.id === undefined) return void (fn && fn(m.params || {}))
|
|
706
|
+
if (!fn) return send({ id: m.id, error: { code: -32601, message: 'm\xE9todo desconhecido: ' + m.method } })
|
|
707
|
+
try { result = fn(m.params || {}) } catch (err) { return send({ id: m.id, error: { code: -32603, message: String(err && err.message || err) } }) }
|
|
708
|
+
send({ id: m.id, result: result })
|
|
709
|
+
})
|
|
710
|
+
request('ui/initialize', {
|
|
711
|
+
appInfo: { name: info.name, version: info.version || '0.0.0' }, appCapabilities: {}, protocolVersion: '${MCP_APP_PROTOCOL}'
|
|
712
|
+
}).then(function (r) {
|
|
713
|
+
props.hostContext = r && r.hostContext
|
|
714
|
+
theme(props.hostContext)
|
|
715
|
+
notify('ui/notifications/initialized')
|
|
716
|
+
doc.body.appendChild(root)
|
|
717
|
+
var remote = (mod && mod.default) || mod
|
|
718
|
+
if (!remote || typeof remote.mount !== 'function') throw new Error('o m\xF3dulo n\xE3o exporta mount()')
|
|
719
|
+
dirty = false
|
|
720
|
+
return remote.mount(root, Object.assign({}, props), ctx)
|
|
721
|
+
}).then(function (handle) {
|
|
722
|
+
mounted = handle
|
|
723
|
+
ready = true
|
|
724
|
+
if (dirty) push()
|
|
725
|
+
size()
|
|
726
|
+
if (w.ResizeObserver) { var ro = new w.ResizeObserver(size); ro.observe(doc.documentElement); ro.observe(doc.body) }
|
|
727
|
+
}).catch(report)
|
|
728
|
+
}`;
|
|
729
|
+
var inline = (text, tag) => text.replace(new RegExp(`</(${tag})`, "gi"), "<\\/$1").replace(/<!--/g, "<\\!--");
|
|
730
|
+
function mcpAppHtml(page) {
|
|
731
|
+
const info = JSON.stringify({ name: page.name, version: page.version, scope: page.scope });
|
|
732
|
+
const styles = page.css.map((css) => `<style>${inline(css, "style")}</style>`).join("");
|
|
733
|
+
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>
|
|
752
734
|
`;
|
|
753
735
|
}
|
|
754
|
-
async function loadTs(root) {
|
|
755
|
-
const api = (ts) => typeof ts?.createProgram === "function" ? ts : null;
|
|
756
|
-
try {
|
|
757
|
-
const ts = api(createRequire2(join4(root, "package.json"))("typescript"));
|
|
758
|
-
if (ts) return ts;
|
|
759
|
-
} catch {
|
|
760
|
-
}
|
|
761
|
-
try {
|
|
762
|
-
return api((await import("typescript")).default);
|
|
763
|
-
} catch {
|
|
764
|
-
return null;
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
async function extractProps(root, file) {
|
|
768
|
-
if (!/\.[cm]?[jt]sx?$/.test(file)) return null;
|
|
769
|
-
const ts = await loadTs(root);
|
|
770
|
-
if (!ts) return null;
|
|
771
|
-
const oxc = /\.[cm]?tsx?$/.test(file) ? await loadOxc(root) : null;
|
|
772
|
-
const fast = oxc && propsFromOxc(ts, oxc, file);
|
|
773
|
-
if (fast) return fast;
|
|
774
|
-
const configPath = ts.findConfigFile(root, ts.sys.fileExists);
|
|
775
|
-
const base = configPath ? ts.parseJsonConfigFileContent(ts.readConfigFile(configPath, ts.sys.readFile).config, ts.sys, root).options : {};
|
|
776
|
-
const options = {
|
|
777
|
-
target: ts.ScriptTarget.ES2022,
|
|
778
|
-
module: ts.ModuleKind.ESNext,
|
|
779
|
-
moduleResolution: ts.ModuleResolutionKind.Bundler,
|
|
780
|
-
jsx: ts.JsxEmit.Preserve,
|
|
781
|
-
strict: true,
|
|
782
|
-
...base,
|
|
783
|
-
allowJs: true,
|
|
784
|
-
skipLibCheck: true,
|
|
785
|
-
noEmit: true
|
|
786
|
-
};
|
|
787
|
-
const program = ts.createProgram([file], options);
|
|
788
|
-
const checker = program.getTypeChecker();
|
|
789
|
-
const source = program.getSourceFile(file);
|
|
790
|
-
const moduleSymbol = source && checker.getSymbolAtLocation(source);
|
|
791
|
-
let symbol = moduleSymbol && checker.getExportsOfModule(moduleSymbol).find((s) => s.escapedName === "default");
|
|
792
|
-
if (!source || !symbol) return null;
|
|
793
|
-
if (symbol.flags & ts.SymbolFlags.Alias) symbol = checker.getAliasedSymbol(symbol);
|
|
794
|
-
const type = checker.getTypeOfSymbolAtLocation(symbol, source);
|
|
795
|
-
const props = propsOf(checker, type, source);
|
|
796
|
-
return props ? new Printer(ts, checker, program).print(props, 0, true) : "Record<string, unknown>";
|
|
797
|
-
}
|
|
798
|
-
function propsOf(checker, type, at) {
|
|
799
|
-
const param = (t, i) => {
|
|
800
|
-
const p = t.getCallSignatures()[0]?.parameters[i];
|
|
801
|
-
return p && checker.getTypeOfSymbolAtLocation(p, at);
|
|
802
|
-
};
|
|
803
|
-
const mount = type.getProperty("mount");
|
|
804
|
-
if (mount) return param(checker.getTypeOfSymbolAtLocation(mount, at), 1);
|
|
805
|
-
if (type.getCallSignatures().length) return param(type, 0);
|
|
806
|
-
const ctor = type.getConstructSignatures()[0];
|
|
807
|
-
const props = ctor?.getReturnType().getProperty("props");
|
|
808
|
-
return props && checker.getTypeOfSymbolAtLocation(props, at);
|
|
809
|
-
}
|
|
810
|
-
var Printer = class {
|
|
811
|
-
constructor(ts, checker, program) {
|
|
812
|
-
this.ts = ts;
|
|
813
|
-
this.checker = checker;
|
|
814
|
-
this.program = program;
|
|
815
|
-
this.seen = /* @__PURE__ */ new Set();
|
|
816
|
-
}
|
|
817
|
-
/** Declarado na lib padrão (Date, Map…): vale em qualquer projeto pelo nome. */
|
|
818
|
-
fromLib(type) {
|
|
819
|
-
const decl = (type.aliasSymbol ?? type.getSymbol())?.declarations?.[0];
|
|
820
|
-
return !!decl && this.program.isSourceFileDefaultLibrary(decl.getSourceFile());
|
|
821
|
-
}
|
|
822
|
-
fromPackage(type) {
|
|
823
|
-
const decl = (type.aliasSymbol ?? type.getSymbol())?.declarations?.[0];
|
|
824
|
-
return !!decl && /[/\\]node_modules[/\\]/.test(decl.getSourceFile().fileName);
|
|
825
|
-
}
|
|
826
|
-
print(type, depth, top = false) {
|
|
827
|
-
const { ts, checker } = this;
|
|
828
|
-
const f = type.flags;
|
|
829
|
-
if (f & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) return "unknown";
|
|
830
|
-
if (f & (ts.TypeFlags.StringLike | ts.TypeFlags.NumberLike | ts.TypeFlags.BooleanLike | ts.TypeFlags.BigIntLike | ts.TypeFlags.Null | ts.TypeFlags.Undefined | ts.TypeFlags.Void | ts.TypeFlags.Never | ts.TypeFlags.ESSymbolLike)) {
|
|
831
|
-
return checker.typeToString(type);
|
|
832
|
-
}
|
|
833
|
-
if (type.isUnion()) {
|
|
834
|
-
const parts = [...new Set(type.types.map((t) => this.print(t, depth)))];
|
|
835
|
-
if (parts.includes("true") && parts.includes("false")) parts.splice(parts.indexOf("true"), 1, "boolean"), parts.splice(parts.indexOf("false"), 1);
|
|
836
|
-
return parts.join(" | ");
|
|
837
|
-
}
|
|
838
|
-
if (type.isIntersection()) return type.types.map((t) => this.wrap(t, depth)).join(" & ");
|
|
839
|
-
if (depth > 6 || this.seen.has(type)) return "unknown";
|
|
840
|
-
if (checker.isArrayType(type)) return `Array<${this.print(checker.getTypeArguments(type)[0], depth + 1)}>`;
|
|
841
|
-
if (checker.isTupleType(type)) return `[${checker.getTypeArguments(type).map((t) => this.print(t, depth + 1)).join(", ")}]`;
|
|
842
|
-
if (this.fromLib(type)) {
|
|
843
|
-
const args = type.aliasTypeArguments ?? (type.objectFlags & ts.ObjectFlags.Reference ? checker.getTypeArguments(type) : []);
|
|
844
|
-
const name = (type.aliasSymbol ?? type.getSymbol()).name;
|
|
845
|
-
return args.length ? `${name}<${args.map((t) => this.print(t, depth + 1)).join(", ")}>` : checker.typeToString(type);
|
|
846
|
-
}
|
|
847
|
-
if (this.fromPackage(type)) return "unknown";
|
|
848
|
-
this.seen.add(type);
|
|
849
|
-
try {
|
|
850
|
-
const calls = type.getCallSignatures();
|
|
851
|
-
const props = checker.getPropertiesOfType(type).filter((p) => !(top && p.name === "vitral"));
|
|
852
|
-
if (calls.length && !props.length) return this.signature(calls[0], depth);
|
|
853
|
-
const fields = props.map((p) => {
|
|
854
|
-
const optional = p.flags & ts.SymbolFlags.Optional ? "?" : "";
|
|
855
|
-
const key = /^[A-Za-z_$][\w$]*$/.test(p.name) ? p.name : JSON.stringify(p.name);
|
|
856
|
-
const t = checker.getTypeOfSymbol(p);
|
|
857
|
-
return `${key}${optional}: ${this.print(optional ? checker.getNonNullableType(t) : t, depth + 1)}`;
|
|
858
|
-
});
|
|
859
|
-
const index = type.getStringIndexType();
|
|
860
|
-
if (index) fields.push(`[key: string]: ${this.print(index, depth + 1)}`);
|
|
861
|
-
for (const c of calls) fields.push(this.signature(c, depth).replace(" =>", ":"));
|
|
862
|
-
return fields.length ? `{ ${fields.join("; ")} }` : "{}";
|
|
863
|
-
} finally {
|
|
864
|
-
this.seen.delete(type);
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
wrap(type, depth) {
|
|
868
|
-
const s = this.print(type, depth);
|
|
869
|
-
return type.isUnion() ? `(${s})` : s;
|
|
870
|
-
}
|
|
871
|
-
signature(sig, depth) {
|
|
872
|
-
const params = sig.parameters.map((p, i) => `${/^[A-Za-z_$][\w$]*$/.test(p.name) ? p.name : `a${i}`}: ${this.print(this.checker.getTypeOfSymbol(p), depth + 1)}`);
|
|
873
|
-
return `(${params.join(", ")}) => ${this.print(sig.getReturnType(), depth + 1)}`;
|
|
874
|
-
}
|
|
875
|
-
};
|
|
876
736
|
|
|
877
737
|
// src/vite/dev.ts
|
|
878
738
|
var DEV_ENTRY = "@vitral/entry.js";
|
|
@@ -971,21 +831,44 @@ function vitral(options = {}) {
|
|
|
971
831
|
let pkg = {};
|
|
972
832
|
let manifest;
|
|
973
833
|
let split;
|
|
834
|
+
let modules = /* @__PURE__ */ new Set();
|
|
974
835
|
let entry = options.entry;
|
|
975
836
|
let adapter = "element";
|
|
976
837
|
let framework = "element";
|
|
977
|
-
const entryFile = () =>
|
|
838
|
+
const entryFile = () => resolve4(root, entry);
|
|
978
839
|
let serve = false;
|
|
979
840
|
let shared = [];
|
|
980
841
|
const dedupe = !!options.dedupe?.length;
|
|
981
842
|
const hooks = dedupeHooks(() => options.exposes ? EXPOSES_ENTRY : options.adapter === false ? entryFile() : ENTRY_ID, () => shared);
|
|
843
|
+
const mcp = options.target === "mcp-app";
|
|
844
|
+
if (mcp && (options.exposes || dedupe || options.shared?.length)) {
|
|
845
|
+
throw new Error("[vitral] target: 'mcp-app' gera um HTML \xFAnico: n\xE3o combina com exposes, dedupe nem shared.");
|
|
846
|
+
}
|
|
982
847
|
const scopeName = () => (options.name ?? pkg.name ?? "remote").replace(/[^a-zA-Z0-9_-]/g, "-");
|
|
848
|
+
const mcpApp = (files, js) => {
|
|
849
|
+
const css = files.filter((f) => f.type === "asset" && f.fileName.endsWith(".css")).map((f) => f.fileName);
|
|
850
|
+
const read = (file) => {
|
|
851
|
+
const text = readFileSync4(join4(outDir, file), "utf8");
|
|
852
|
+
rmSync2(join4(outDir, file));
|
|
853
|
+
return text;
|
|
854
|
+
};
|
|
855
|
+
const scope = options.scopeCss === false ? void 0 : scopeName();
|
|
856
|
+
const html = mcpAppHtml({
|
|
857
|
+
name: options.name ?? pkg.name ?? "remote",
|
|
858
|
+
version: options.version ?? pkg.version,
|
|
859
|
+
scope,
|
|
860
|
+
code: read(js),
|
|
861
|
+
css: css.map((f) => transformCss(read(f), options, scopeName()))
|
|
862
|
+
});
|
|
863
|
+
writeFileSync2(join4(outDir, "mcp-app.html"), html);
|
|
864
|
+
};
|
|
983
865
|
return {
|
|
984
866
|
name: "vitral",
|
|
985
867
|
config(user, { mode, command }) {
|
|
986
|
-
entry ??= findEntry(
|
|
868
|
+
entry ??= findEntry(resolve4(user.root ?? process.cwd()));
|
|
987
869
|
if (!entry) throw new Error("[vitral] n\xE3o achei a entrada do remote (src/remote.* ou src/App.*). Use vitral({ entry }).");
|
|
988
870
|
const rolldown = "rolldownVersion" in this.meta;
|
|
871
|
+
const dir = options.versionDir ? versionDir(user.root ?? process.cwd(), user.build?.outDir, options.version) : void 0;
|
|
989
872
|
return {
|
|
990
873
|
// Código de biblioteca não tem process.env; React e Vue precisam disso.
|
|
991
874
|
define: { "process.env.NODE_ENV": JSON.stringify(mode === "development" ? "development" : "production") },
|
|
@@ -995,12 +878,18 @@ function vitral(options = {}) {
|
|
|
995
878
|
// O remote não tem index.html: sem isso o Vite só descobre as
|
|
996
879
|
// dependências no primeiro request e recarrega a página do host.
|
|
997
880
|
optimizeDeps: user.optimizeDeps?.entries ? void 0 : { entries: [entry] },
|
|
998
|
-
build: {
|
|
881
|
+
build: mcp ? {
|
|
882
|
+
// Um IIFE só, sem chunks: o HTML do MCP App não pode buscar arquivos.
|
|
883
|
+
lib: { entry: options.adapter === false ? entry : ENTRY_ID, formats: ["iife"], name: MCP_APP_GLOBAL, fileName: () => "mcp-app.js", cssFileName: "remote" },
|
|
884
|
+
rollupOptions: { output: rolldown ? { codeSplitting: false } : { inlineDynamicImports: true } },
|
|
885
|
+
cssCodeSplit: false
|
|
886
|
+
} : {
|
|
999
887
|
// Nomes com hash: cache eterno no CDN. Só o vitral.json muda a cada deploy.
|
|
1000
888
|
lib: { entry: dedupe ? BOOT : options.exposes ? EXPOSES_ENTRY : options.adapter === false ? entry : ENTRY_ID, fileName: () => "remote-[hash].js", cssFileName: "remote" },
|
|
1001
889
|
// Arquivo único (hosts antigos e caminho com blob:) e build dividido (manifesto v2).
|
|
1002
890
|
rollupOptions: { external: options.shared ?? [], output: outputs(rolldown) },
|
|
1003
|
-
cssCodeSplit: false
|
|
891
|
+
cssCodeSplit: false,
|
|
892
|
+
...dir && { outDir: dir }
|
|
1004
893
|
}
|
|
1005
894
|
};
|
|
1006
895
|
},
|
|
@@ -1009,9 +898,9 @@ function vitral(options = {}) {
|
|
|
1009
898
|
framework = detectAdapter(c.plugins);
|
|
1010
899
|
adapter = options.adapter || framework;
|
|
1011
900
|
serve = c.command === "serve";
|
|
1012
|
-
outDir =
|
|
901
|
+
outDir = resolve4(c.root, c.build.outDir);
|
|
1013
902
|
try {
|
|
1014
|
-
pkg = JSON.parse(readFileSync4(
|
|
903
|
+
pkg = JSON.parse(readFileSync4(join4(root, "package.json"), "utf8"));
|
|
1015
904
|
} catch {
|
|
1016
905
|
}
|
|
1017
906
|
},
|
|
@@ -1044,8 +933,8 @@ function vitral(options = {}) {
|
|
|
1044
933
|
if (own != null) return own;
|
|
1045
934
|
const exposed = options.exposes ? loadExposes(id, root, entry, options.exposes, options.adapter === false ? void 0 : ENTRY_ID) : null;
|
|
1046
935
|
if (exposed != null) return exposed;
|
|
1047
|
-
if (id === VIRTUAL_ENTRY) return entryCode(
|
|
1048
|
-
if (id === VIRTUAL_DEV_ENTRY) return devEntryCode(framework, options.adapter === false ?
|
|
936
|
+
if (id === VIRTUAL_ENTRY) return entryCode(resolve4(root, entry), adapter, scopeName());
|
|
937
|
+
if (id === VIRTUAL_DEV_ENTRY) return devEntryCode(framework, options.adapter === false ? resolve4(root, entry) : void 0);
|
|
1049
938
|
return loadPreamble(id);
|
|
1050
939
|
}
|
|
1051
940
|
},
|
|
@@ -1056,19 +945,21 @@ function vitral(options = {}) {
|
|
|
1056
945
|
}
|
|
1057
946
|
},
|
|
1058
947
|
writeBundle(_, bundle) {
|
|
948
|
+
if (options.sbom) bundledFiles(bundle, modules);
|
|
1059
949
|
if (isSplit(bundle)) return void (split = collect(outDir, bundle));
|
|
1060
950
|
const files = Object.values(bundle);
|
|
1061
951
|
const entry2 = files.find((f) => f.type === "chunk" && f.isEntry);
|
|
1062
952
|
if (!entry2) return;
|
|
953
|
+
if (mcp) return mcpApp(files, entry2.fileName);
|
|
1063
954
|
const emit = (file, text, kind = "") => {
|
|
1064
|
-
const hash =
|
|
955
|
+
const hash = createHash3("sha256").update(text).digest("base64url").slice(0, 8);
|
|
1065
956
|
const name = file.replace(/\.css$/, `${kind}-${hash}.css`);
|
|
1066
|
-
writeFileSync2(
|
|
957
|
+
writeFileSync2(join4(outDir, name), text);
|
|
1067
958
|
return name;
|
|
1068
959
|
};
|
|
1069
960
|
const shadow = { css: [] };
|
|
1070
961
|
const css = files.filter((f) => f.type === "asset" && f.fileName.endsWith(".css")).map((f) => {
|
|
1071
|
-
const from =
|
|
962
|
+
const from = join4(outDir, f.fileName);
|
|
1072
963
|
const text = transformCss(readFileSync4(from, "utf8"), options, scopeName());
|
|
1073
964
|
const name = emit(f.fileName, text);
|
|
1074
965
|
if (name !== f.fileName) rmSync2(from);
|
|
@@ -1079,14 +970,14 @@ function vitral(options = {}) {
|
|
|
1079
970
|
if (split2.rebase) shadow.rebase = true;
|
|
1080
971
|
return name;
|
|
1081
972
|
});
|
|
1082
|
-
const code = readFileSync4(
|
|
973
|
+
const code = readFileSync4(join4(outDir, entry2.fileName));
|
|
1083
974
|
manifest = {
|
|
1084
975
|
name: options.name ?? pkg.name ?? "remote",
|
|
1085
976
|
version: options.version ?? pkg.version,
|
|
1086
977
|
entry: entry2.fileName,
|
|
1087
978
|
css,
|
|
1088
979
|
...css.length ? { shadow } : {},
|
|
1089
|
-
integrity: "sha384-" +
|
|
980
|
+
integrity: "sha384-" + createHash3("sha384").update(code).digest("base64"),
|
|
1090
981
|
...options.scopeCss === false ? {} : { scope: scopeName() },
|
|
1091
982
|
...options.exposes ? { exposes: Object.keys(exposeKeys(options.exposes)) } : {},
|
|
1092
983
|
...contractOf(options.contract?.version, shared)
|
|
@@ -1095,13 +986,34 @@ function vitral(options = {}) {
|
|
|
1095
986
|
async closeBundle() {
|
|
1096
987
|
if (!manifest) return;
|
|
1097
988
|
const done = withSplit(manifest, outDir, split, shared);
|
|
989
|
+
if (options.sbom) {
|
|
990
|
+
const bom = createSbom({ root, name: done.name, version: done.version, files: modules, entry: readFileSync4(join4(outDir, done.entry)), tool: ownVersion() });
|
|
991
|
+
writeFileSync2(join4(outDir, SBOM_FILE), JSON.stringify(bom, null, 2) + "\n");
|
|
992
|
+
done.sbom = { file: SBOM_FILE, integrity: sri(join4(outDir, SBOM_FILE)) };
|
|
993
|
+
}
|
|
1098
994
|
manifest = split = void 0;
|
|
1099
|
-
|
|
995
|
+
modules = /* @__PURE__ */ new Set();
|
|
996
|
+
writeFileSync2(join4(outDir, "vitral.json"), JSON.stringify(done, null, 2) + "\n");
|
|
1100
997
|
const props = options.types === false ? null : await extractProps(root, entryFile());
|
|
1101
|
-
if (props) writeFileSync2(
|
|
998
|
+
if (props) writeFileSync2(join4(outDir, "vitral.d.ts"), typesFile(done.name, props));
|
|
1102
999
|
}
|
|
1103
1000
|
};
|
|
1104
1001
|
}
|
|
1002
|
+
function ownVersion() {
|
|
1003
|
+
try {
|
|
1004
|
+
return JSON.parse(readFileSync4(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
1005
|
+
} catch {
|
|
1006
|
+
return void 0;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
function versionDir(root, outDir = "dist", version) {
|
|
1010
|
+
try {
|
|
1011
|
+
version ??= JSON.parse(readFileSync4(join4(resolve4(root), "package.json"), "utf8")).version;
|
|
1012
|
+
} catch {
|
|
1013
|
+
}
|
|
1014
|
+
if (!version) throw new Error('[vitral] versionDir precisa de uma vers\xE3o: use vitral({ version }) ou "version" no package.json.');
|
|
1015
|
+
return join4(outDir, version);
|
|
1016
|
+
}
|
|
1105
1017
|
function contractOf(version, groups2) {
|
|
1106
1018
|
const contract = {
|
|
1107
1019
|
...version && { version },
|