vitral 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +250 -217
- package/dist/angular.d.ts +16 -4
- package/dist/angular.js +26 -5
- package/dist/auto.d.ts +2 -0
- package/dist/auto.js +13 -0
- package/dist/capture-JYFERAPL.js +42 -0
- package/dist/chunk-3YXI3G34.js +181 -0
- package/dist/chunk-AH7KNMBW.js +20 -0
- package/dist/chunk-AKNNHQ2H.js +45 -0
- package/dist/chunk-DXORSF4X.js +42 -0
- package/dist/chunk-GNHCZRQP.js +79 -0
- package/dist/chunk-GNPFWISJ.js +80 -0
- package/dist/chunk-I3VSKSAZ.js +634 -0
- package/dist/chunk-IHTUM6LT.js +152 -0
- package/dist/chunk-SDB5AZEI.js +51 -0
- package/dist/chunk-TD4S3IHA.js +201 -0
- package/dist/chunk-ZAC6QQI6.js +64 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +138 -0
- package/dist/contract-46EZFQPQ.js +17 -0
- package/dist/dedupe-S7BHQMOZ.js +82 -0
- package/dist/devtools.d.ts +12 -0
- package/dist/devtools.js +86 -0
- package/dist/element.d.ts +60 -2
- package/dist/element.js +10 -2
- package/dist/errors-kjBv6IH_.d.ts +17 -0
- package/dist/events-D5gs7rff.d.ts +6 -0
- package/dist/expose-JUOUN5N5.js +15 -0
- package/dist/host-slot-Cz6EiGsB.d.ts +6 -0
- package/dist/iframe.d.ts +28 -0
- package/dist/iframe.js +239 -0
- package/dist/index.d.ts +144 -147
- package/dist/index.js +40 -10
- package/dist/navigate-BRG1WJUM.d.ts +9 -0
- package/dist/otel.d.ts +44 -0
- package/dist/otel.js +27 -0
- package/dist/overrides-NZAIUGK5.js +15 -0
- package/dist/preact.d.ts +30 -7
- package/dist/preact.js +38 -9
- package/dist/react.d.ts +46 -7
- package/dist/react.js +97 -42
- package/dist/routes.d.ts +56 -0
- package/dist/routes.js +144 -0
- package/dist/sentry.d.ts +25 -0
- package/dist/sentry.js +11 -0
- package/dist/shadow-6HELCHCJ.js +98 -0
- package/dist/slot-DqXTwGbs.d.ts +36 -0
- package/dist/solid.d.ts +29 -6
- package/dist/solid.js +32 -8
- package/dist/sri-JMX6JLQP.js +116 -0
- package/dist/state-BDdCwc21.d.ts +4 -0
- package/dist/svelte.d.ts +19 -3
- package/dist/svelte.js +11 -4
- package/dist/testing.d.ts +3 -2
- package/dist/testing.js +9 -3
- package/dist/types-Czvm-siZ.d.ts +327 -0
- package/dist/vite.d.ts +66 -4
- package/dist/vite.js +1044 -25
- package/dist/vue.d.ts +86 -7
- package/dist/vue.js +74 -46
- package/package.json +181 -11
- package/dist/chunk-IZK6ITIJ.js +0 -96
- package/dist/chunk-TTL52BF2.js +0 -547
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createSlot
|
|
3
|
+
} from "./chunk-I3VSKSAZ.js";
|
|
4
|
+
import {
|
|
5
|
+
preload,
|
|
6
|
+
registerSrc
|
|
7
|
+
} from "./chunk-TD4S3IHA.js";
|
|
8
|
+
|
|
9
|
+
// src/core/host-slot.ts
|
|
10
|
+
var noop = () => {
|
|
11
|
+
};
|
|
12
|
+
function timings(name) {
|
|
13
|
+
const out = {};
|
|
14
|
+
if (typeof performance === "undefined" || !performance.getEntriesByName) return out;
|
|
15
|
+
for (const stage of ["manifest", "js", "css", "mount"]) {
|
|
16
|
+
const m = performance.getEntriesByName(`vitral:${name}:${stage}`, "measure").pop();
|
|
17
|
+
if (m) out[stage] = Math.round(m.duration * 10) / 10;
|
|
18
|
+
}
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
21
|
+
function when(el, mode, fn) {
|
|
22
|
+
if (mode === "lazy" || mode === "visible") {
|
|
23
|
+
if (typeof IntersectionObserver === "undefined") return fn(), noop;
|
|
24
|
+
const io = new IntersectionObserver(
|
|
25
|
+
(entries) => {
|
|
26
|
+
if (entries.some((e) => e.isIntersecting)) io.disconnect(), fn();
|
|
27
|
+
},
|
|
28
|
+
{ rootMargin: "200px" }
|
|
29
|
+
);
|
|
30
|
+
io.observe(el);
|
|
31
|
+
return () => io.disconnect();
|
|
32
|
+
}
|
|
33
|
+
if (mode === "idle") {
|
|
34
|
+
if (typeof requestIdleCallback === "undefined") {
|
|
35
|
+
const t = setTimeout(fn, 1);
|
|
36
|
+
return () => clearTimeout(t);
|
|
37
|
+
}
|
|
38
|
+
const id = requestIdleCallback(fn, { timeout: 2e3 });
|
|
39
|
+
return () => cancelIdleCallback(id);
|
|
40
|
+
}
|
|
41
|
+
if (mode === "hover") {
|
|
42
|
+
const go = () => (off(), fn());
|
|
43
|
+
const off = () => {
|
|
44
|
+
el.removeEventListener("pointerenter", go);
|
|
45
|
+
el.removeEventListener("focusin", go);
|
|
46
|
+
};
|
|
47
|
+
el.addEventListener("pointerenter", go);
|
|
48
|
+
el.addEventListener("focusin", go);
|
|
49
|
+
return off;
|
|
50
|
+
}
|
|
51
|
+
fn();
|
|
52
|
+
return noop;
|
|
53
|
+
}
|
|
54
|
+
var kept = /* @__PURE__ */ new Map();
|
|
55
|
+
var shelf = null;
|
|
56
|
+
function move(parent, node) {
|
|
57
|
+
try {
|
|
58
|
+
;
|
|
59
|
+
parent.moveBefore(node, null);
|
|
60
|
+
} catch {
|
|
61
|
+
parent.appendChild(node);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function signal(node, type) {
|
|
65
|
+
for (const el of node.querySelectorAll("*")) {
|
|
66
|
+
if (el.hasAttribute("data-vitral-root")) el.dispatchEvent(new Event(type));
|
|
67
|
+
if (el.shadowRoot) signal(el.shadowRoot, type);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function park(key, item, max) {
|
|
71
|
+
kept.get(key)?.slot.destroy();
|
|
72
|
+
kept.delete(key);
|
|
73
|
+
if (!shelf?.isConnected) {
|
|
74
|
+
shelf = document.createElement("div");
|
|
75
|
+
shelf.hidden = true;
|
|
76
|
+
shelf.setAttribute("data-vitral-keep-alive", "");
|
|
77
|
+
document.body.appendChild(shelf);
|
|
78
|
+
}
|
|
79
|
+
move(shelf, item.box);
|
|
80
|
+
signal(item.box, "vitral:deactivate");
|
|
81
|
+
kept.set(key, item);
|
|
82
|
+
for (const [k, old] of kept) {
|
|
83
|
+
if (kept.size <= max) break;
|
|
84
|
+
kept.delete(k);
|
|
85
|
+
old.slot.destroy();
|
|
86
|
+
old.box.remove();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function hostSlot(target, options) {
|
|
90
|
+
let { props = {}, keepAlive } = options;
|
|
91
|
+
const key = (o) => o.src ? registerSrc(o.src, o.name) : o.name ?? "";
|
|
92
|
+
let name = key(options);
|
|
93
|
+
let status = "loading";
|
|
94
|
+
let item = null;
|
|
95
|
+
const onStatus = (s, e) => {
|
|
96
|
+
status = s;
|
|
97
|
+
options.onStatus?.(s, e);
|
|
98
|
+
};
|
|
99
|
+
const cancelPrefetch = options.prefetch ? when(target, options.prefetch, () => preload(name)) : noop;
|
|
100
|
+
const cancel = when(target, options.loading, () => {
|
|
101
|
+
cancelPrefetch();
|
|
102
|
+
const found = keepAlive ? kept.get(name) : void 0;
|
|
103
|
+
if (found) {
|
|
104
|
+
kept.delete(name);
|
|
105
|
+
item = found;
|
|
106
|
+
item.on = onStatus;
|
|
107
|
+
move(target, item.box);
|
|
108
|
+
item.slot.update(props);
|
|
109
|
+
signal(item.box, "vitral:activate");
|
|
110
|
+
onStatus(item.slot.status, null);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
let box = target;
|
|
114
|
+
if (keepAlive) {
|
|
115
|
+
box = target.appendChild(document.createElement("div"));
|
|
116
|
+
box.style.display = "contents";
|
|
117
|
+
}
|
|
118
|
+
const it = { box, on: onStatus, slot: null };
|
|
119
|
+
it.slot = createSlot(box, { ...options, name, src: void 0, props, onStatus: (s, e) => it.on(s, e) });
|
|
120
|
+
item = it;
|
|
121
|
+
});
|
|
122
|
+
return {
|
|
123
|
+
update(next) {
|
|
124
|
+
props = next;
|
|
125
|
+
item?.slot.update(next);
|
|
126
|
+
},
|
|
127
|
+
set(next) {
|
|
128
|
+
if (next.src || next.name !== void 0) name = key(next);
|
|
129
|
+
item?.slot.set({ ...next, src: void 0, name });
|
|
130
|
+
},
|
|
131
|
+
retry: () => item?.slot.retry(),
|
|
132
|
+
destroy() {
|
|
133
|
+
cancel();
|
|
134
|
+
cancelPrefetch();
|
|
135
|
+
if (!item) return;
|
|
136
|
+
if (keepAlive && status === "ready") park(name, item, keepAlive === true ? 5 : keepAlive);
|
|
137
|
+
else {
|
|
138
|
+
item.slot.destroy();
|
|
139
|
+
if (item.box !== target) item.box.remove();
|
|
140
|
+
}
|
|
141
|
+
item = null;
|
|
142
|
+
},
|
|
143
|
+
get status() {
|
|
144
|
+
return status;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export {
|
|
150
|
+
timings,
|
|
151
|
+
hostSlot
|
|
152
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mountable
|
|
3
|
+
} from "./chunk-TD4S3IHA.js";
|
|
4
|
+
import {
|
|
5
|
+
RemoteError
|
|
6
|
+
} from "./chunk-AKNNHQ2H.js";
|
|
7
|
+
import {
|
|
8
|
+
protocol
|
|
9
|
+
} from "./chunk-GNPFWISJ.js";
|
|
10
|
+
|
|
11
|
+
// src/core/expose.ts
|
|
12
|
+
function splitName(name) {
|
|
13
|
+
const p = protocol();
|
|
14
|
+
let i = name.length;
|
|
15
|
+
if (!p.entry(name)) while ((i = name.lastIndexOf("/", i - 1)) > 0 && !p.entry(name.slice(0, i))) ;
|
|
16
|
+
return i > 0 && i < name.length ? [name.slice(0, i), "." + name.slice(i)] : [name, null];
|
|
17
|
+
}
|
|
18
|
+
function resolveTarget(name, loadFile) {
|
|
19
|
+
return resolveAny(name, loadFile).then((r) => mountable(name, r));
|
|
20
|
+
}
|
|
21
|
+
function resolveAny(name, loadFile) {
|
|
22
|
+
const p = protocol();
|
|
23
|
+
if (p.entry(name) || !name.includes("/")) return loadFile(name);
|
|
24
|
+
return p.pending().then(async () => {
|
|
25
|
+
const [remote, key] = splitName(name);
|
|
26
|
+
if (!key) return loadFile(name);
|
|
27
|
+
const r = await loadFile(remote);
|
|
28
|
+
const table = r.exports?.exposes;
|
|
29
|
+
if (!table?.[key]) throw new RemoteError("NOT_EXPOSED", name, `${remote} n\xE3o exp\xF5e ${key}. Expostos: ${Object.keys(table ?? {}).join(", ")}`);
|
|
30
|
+
try {
|
|
31
|
+
const value = table[key];
|
|
32
|
+
const ns = await (typeof value == "function" ? value() : value);
|
|
33
|
+
return { ...r, module: ns?.default ?? ns, exports: ns };
|
|
34
|
+
} catch (e) {
|
|
35
|
+
throw new RemoteError("LOAD_FAILED", name, String(e), e);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
async function resolveModule(name, loadFile) {
|
|
40
|
+
const r = await resolveAny(name, loadFile);
|
|
41
|
+
if (!r.exports) {
|
|
42
|
+
throw new RemoteError("INVALID_MODULE", name, "o remote foi carregado por uma c\xF3pia antiga da lib, que n\xE3o guarda os exports");
|
|
43
|
+
}
|
|
44
|
+
return r.exports;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
splitName,
|
|
49
|
+
resolveTarget,
|
|
50
|
+
resolveModule
|
|
51
|
+
};
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import {
|
|
2
|
+
prefetchCss
|
|
3
|
+
} from "./chunk-ZAC6QQI6.js";
|
|
4
|
+
import {
|
|
5
|
+
absolute,
|
|
6
|
+
addLink,
|
|
7
|
+
fetchJson,
|
|
8
|
+
metric,
|
|
9
|
+
pageOrigin,
|
|
10
|
+
withRetry,
|
|
11
|
+
withTimeout
|
|
12
|
+
} from "./chunk-GNHCZRQP.js";
|
|
13
|
+
import {
|
|
14
|
+
RemoteError,
|
|
15
|
+
fail,
|
|
16
|
+
isRemoteError,
|
|
17
|
+
report
|
|
18
|
+
} from "./chunk-AKNNHQ2H.js";
|
|
19
|
+
import {
|
|
20
|
+
protocol
|
|
21
|
+
} from "./chunk-GNPFWISJ.js";
|
|
22
|
+
|
|
23
|
+
// src/core/registry.ts
|
|
24
|
+
function configure(config) {
|
|
25
|
+
const p = protocol();
|
|
26
|
+
const { remotes, dedupe, ...rest } = config;
|
|
27
|
+
p.configure(rest);
|
|
28
|
+
if (rest.captureGlobalErrors) import("./capture-JYFERAPL.js").then((m) => m.capture());
|
|
29
|
+
if (dedupe) p.pending(import("./dedupe-S7BHQMOZ.js").then((m) => m.offer(p, dedupe)).catch(() => {
|
|
30
|
+
}));
|
|
31
|
+
if (typeof remotes === "string") {
|
|
32
|
+
const url = absolute(remotes);
|
|
33
|
+
p.pending(
|
|
34
|
+
fetchJson(url, p.settings().timeout, "remotes", { cache: "no-cache" }).then((map) => registerAll(map, url))
|
|
35
|
+
).catch(() => {
|
|
36
|
+
});
|
|
37
|
+
} else if (remotes) {
|
|
38
|
+
registerAll(remotes);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function register(name, entry) {
|
|
42
|
+
const e = typeof entry === "string" ? { url: entry } : entry;
|
|
43
|
+
if (!e.url && !e.module) throw new RemoteError("NOT_REGISTERED", name, "informe url ou module");
|
|
44
|
+
if (!e.url) return protocol().register(name, e);
|
|
45
|
+
const url = absolute(e.url);
|
|
46
|
+
protocol().register(name, { ...e, url });
|
|
47
|
+
const { origin } = new URL(url);
|
|
48
|
+
if (typeof document !== "undefined" && origin !== pageOrigin() && origin !== "null" && !document.querySelector(`link[href="${origin}"]`)) {
|
|
49
|
+
addLink("preconnect", origin);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function registerSrc(src, name, trusted = true) {
|
|
53
|
+
const p = protocol();
|
|
54
|
+
const url = absolute(src);
|
|
55
|
+
const key = name || url;
|
|
56
|
+
if (p.entry(key)?.url !== url) p.register(key, { url });
|
|
57
|
+
const origin = new URL(url).origin;
|
|
58
|
+
const list = p.settings().trusted ?? [];
|
|
59
|
+
if (trusted && !list.includes(origin)) p.configure({ trusted: [...list, origin] });
|
|
60
|
+
return key;
|
|
61
|
+
}
|
|
62
|
+
function registerAll(map, base) {
|
|
63
|
+
for (const [name, entry] of Object.entries(map)) {
|
|
64
|
+
const e = typeof entry === "string" ? { url: entry } : entry;
|
|
65
|
+
register(name, e.url ? { ...e, url: absolute(e.url, base) } : e);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function checkOrigin(name, url) {
|
|
69
|
+
const p = protocol();
|
|
70
|
+
const origin = new URL(url).origin;
|
|
71
|
+
const { allowedOrigins, trusted = [] } = p.settings();
|
|
72
|
+
const allowed = [...allowedOrigins ?? [pageOrigin(), ...p.origins()].filter(Boolean), ...trusted];
|
|
73
|
+
if (allowed.includes("*") || allowed.includes(origin) || url.startsWith("blob:")) return;
|
|
74
|
+
throw new RemoteError("ORIGIN_BLOCKED", name, `origem ${origin} n\xE3o est\xE1 em allowedOrigins`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/core/loader.ts
|
|
78
|
+
function loadRemote(name) {
|
|
79
|
+
return load(name).then((r) => r.module);
|
|
80
|
+
}
|
|
81
|
+
function loadModule(name) {
|
|
82
|
+
return import("./expose-JUOUN5N5.js").then((m) => m.resolveModule(name, (n) => loadFile(n))).catch(fail);
|
|
83
|
+
}
|
|
84
|
+
function preload(name) {
|
|
85
|
+
load(name).catch(() => {
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
var paths;
|
|
89
|
+
function load(name, isolate, priority) {
|
|
90
|
+
const file = (n) => loadFile(n, isolate, priority);
|
|
91
|
+
return (protocol().entry(name) || !name.includes("/") ? file(name).then((r) => mountable(name, r)) : import("./expose-JUOUN5N5.js").then((m) => m.resolveTarget(name, file))).catch(fail);
|
|
92
|
+
}
|
|
93
|
+
function loadFile(name, isolate, priority) {
|
|
94
|
+
const p = protocol();
|
|
95
|
+
return p.load(name, async () => {
|
|
96
|
+
paths ??= import("./sri-JMX6JLQP.js").catch(() => null);
|
|
97
|
+
let resolved;
|
|
98
|
+
try {
|
|
99
|
+
await p.pending();
|
|
100
|
+
const override = await devOverride(name);
|
|
101
|
+
const entry = override ? { isolate: p.entry(name)?.isolate, ...override } : p.entry(name);
|
|
102
|
+
if (!entry) throw new RemoteError("NOT_REGISTERED", name, "remote n\xE3o registrado. Use configure({ remotes }).");
|
|
103
|
+
if (entry.module) return await loadLocal(name, entry);
|
|
104
|
+
let t = performance.now();
|
|
105
|
+
resolved = await resolveEntry(name, entry, priority);
|
|
106
|
+
metric(name, "manifest", t);
|
|
107
|
+
prefetchCss(resolved, (isolate ?? resolved.isolate ?? p.settings().isolate) === "shadow", priority);
|
|
108
|
+
t = performance.now();
|
|
109
|
+
const ns = await withRetry(p.settings().retries, () => importModule(name, resolved));
|
|
110
|
+
metric(name, "js", t);
|
|
111
|
+
return { ...resolved, module: ns?.default ?? ns, exports: ns };
|
|
112
|
+
} catch (e) {
|
|
113
|
+
throw report(isRemoteError(e) ? e : new RemoteError("LOAD_FAILED", name, String(e?.message ?? e), e), resolved);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function devOverride(name) {
|
|
118
|
+
try {
|
|
119
|
+
if (/vitral/.test(location.search + localStorage.getItem("vitral:overrides"))) return import("./overrides-NZAIUGK5.js").then((m) => m.overrideFor(name));
|
|
120
|
+
} catch {
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function loadLocal(name, entry) {
|
|
124
|
+
let ns = entry.module;
|
|
125
|
+
if (typeof ns === "function") ns = await ns();
|
|
126
|
+
return { module: ns?.default ?? ns, exports: ns, entry: typeof location !== "undefined" ? location.href : "http://localhost/", css: entry.css ?? [], isolate: entry.isolate };
|
|
127
|
+
}
|
|
128
|
+
async function resolveEntry(name, entry, priority) {
|
|
129
|
+
checkOrigin(name, entry.url);
|
|
130
|
+
const m = entry.manifest ?? (new URL(entry.url).pathname.endsWith(".json") ? await fetchJson(entry.url, protocol().settings().timeout, name, { cache: "no-cache", priority }) : { name, entry: entry.url });
|
|
131
|
+
if (typeof m?.entry !== "string") throw new RemoteError("INVALID_MODULE", name, `manifesto inv\xE1lido em ${entry.url}`);
|
|
132
|
+
if (m.contract && (entry.contract || protocol().settings().contract)) {
|
|
133
|
+
const why = await (await import("./contract-46EZFQPQ.js")).checkContract(m.contract, entry.contract);
|
|
134
|
+
if (why) throw new RemoteError("CONTRACT_MISMATCH", name, why);
|
|
135
|
+
}
|
|
136
|
+
const abs = (u) => absolute(u, entry.url);
|
|
137
|
+
const sri = {};
|
|
138
|
+
for (const file in m.files ?? {}) sri[abs(file)] = m.files[file];
|
|
139
|
+
const resolved = {
|
|
140
|
+
entry: abs(m.entry),
|
|
141
|
+
css: [...m.css ?? [], ...entry.css ?? []].map(abs),
|
|
142
|
+
shadow: m.shadow,
|
|
143
|
+
// A integridade declarada pelo host vence a do manifesto, e aí só o
|
|
144
|
+
// arquivo único (o que ela descreve) é usado.
|
|
145
|
+
integrity: entry.integrity ?? m.integrity,
|
|
146
|
+
isolate: entry.isolate,
|
|
147
|
+
scope: m.scope,
|
|
148
|
+
version: m.version,
|
|
149
|
+
sri,
|
|
150
|
+
priority,
|
|
151
|
+
split: m.split && !entry.integrity ? {
|
|
152
|
+
entry: abs(m.split.entry),
|
|
153
|
+
chunks: (m.split.chunks ?? []).map(abs),
|
|
154
|
+
sri,
|
|
155
|
+
priority,
|
|
156
|
+
dedupe: m.dedupe?.map((d) => ({ ...d, file: abs(d.file), chunks: d.chunks?.map(abs) }))
|
|
157
|
+
} : void 0
|
|
158
|
+
};
|
|
159
|
+
checkOrigin(name, resolved.entry);
|
|
160
|
+
for (const u of [resolved.split?.entry, ...(resolved.split?.dedupe ?? []).map((d) => d.file)]) if (u) checkOrigin(name, u);
|
|
161
|
+
if (name === entry.url && m.name) {
|
|
162
|
+
const override = await devOverride(m.name);
|
|
163
|
+
if (override) return { ...await resolveEntry(name, override), name: m.name };
|
|
164
|
+
resolved.name = m.name;
|
|
165
|
+
if (!protocol().entry(m.name)) protocol().register(m.name, entry);
|
|
166
|
+
}
|
|
167
|
+
return resolved;
|
|
168
|
+
}
|
|
169
|
+
async function importModule(name, r) {
|
|
170
|
+
const { timeout } = protocol().settings();
|
|
171
|
+
const run = (url) => withTimeout(timeout, name, import(
|
|
172
|
+
/* @vite-ignore */
|
|
173
|
+
/* webpackIgnore: true */
|
|
174
|
+
url
|
|
175
|
+
)).catch((e) => {
|
|
176
|
+
throw isRemoteError(e) ? e : new RemoteError("LOAD_FAILED", name, `falha ao importar ${r.entry}`, e);
|
|
177
|
+
});
|
|
178
|
+
if (!r.integrity) return run(r.entry);
|
|
179
|
+
const sri = await paths;
|
|
180
|
+
if (!sri) throw new RemoteError("LOAD_FAILED", name, "n\xE3o foi poss\xEDvel carregar o verificador de integrity");
|
|
181
|
+
return sri.importVerified(name, r, run, timeout);
|
|
182
|
+
}
|
|
183
|
+
function mountable(name, r) {
|
|
184
|
+
if (typeof r.module?.mount != "function") {
|
|
185
|
+
throw new RemoteError("INVALID_MODULE", name, "o m\xF3dulo n\xE3o exporta mount(). Use defineRemote(), ou loadModule() para m\xF3dulo sem UI.");
|
|
186
|
+
}
|
|
187
|
+
return r;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export {
|
|
191
|
+
configure,
|
|
192
|
+
register,
|
|
193
|
+
registerSrc,
|
|
194
|
+
loadRemote,
|
|
195
|
+
loadModule,
|
|
196
|
+
preload,
|
|
197
|
+
load,
|
|
198
|
+
loadFile,
|
|
199
|
+
resolveEntry,
|
|
200
|
+
mountable
|
|
201
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addLink,
|
|
3
|
+
fetchBytes
|
|
4
|
+
} from "./chunk-GNHCZRQP.js";
|
|
5
|
+
import {
|
|
6
|
+
protocol
|
|
7
|
+
} from "./chunk-GNPFWISJ.js";
|
|
8
|
+
|
|
9
|
+
// src/core/css.ts
|
|
10
|
+
var loadedCss = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
var cssText = /* @__PURE__ */ new Map();
|
|
12
|
+
var noop = () => {
|
|
13
|
+
};
|
|
14
|
+
var adopts = () => typeof CSSStyleSheet !== "undefined" && "replaceSync" in CSSStyleSheet.prototype;
|
|
15
|
+
function fetchCssText(href, integrity, priority) {
|
|
16
|
+
const key = `${href} ${integrity ?? ""}`;
|
|
17
|
+
let p = cssText.get(key);
|
|
18
|
+
if (!p) {
|
|
19
|
+
p = fetchBytes(href, protocol().settings().timeout, href, { integrity, priority }).then((b) => new TextDecoder().decode(b));
|
|
20
|
+
p.catch(() => cssText.delete(key));
|
|
21
|
+
cssText.set(key, p);
|
|
22
|
+
}
|
|
23
|
+
return p;
|
|
24
|
+
}
|
|
25
|
+
function prefetchCss(r, shadow, priority = "auto") {
|
|
26
|
+
if (shadow && adopts()) import("./shadow-6HELCHCJ.js").then((m) => m.prefetch(r, priority), noop);
|
|
27
|
+
else for (const href of r.css) if (!document.querySelector(`link[href="${href}"]`)) addLink("preload", href, { as: "style", integrity: r.sri?.[href] ?? "", fetchPriority: priority });
|
|
28
|
+
}
|
|
29
|
+
function injectStyles(r, root, el, styles) {
|
|
30
|
+
return root ? import("./shadow-6HELCHCJ.js").then((m) => m.attachStyles(root, el, r, protocol().settings().styles, styles)) : injectCss(r.css, null, r.sri).then(() => [noop]);
|
|
31
|
+
}
|
|
32
|
+
function injectCss(urls, root, sri = {}) {
|
|
33
|
+
const owner = root ?? document;
|
|
34
|
+
let seen = loadedCss.get(owner);
|
|
35
|
+
if (!seen) loadedCss.set(owner, seen = /* @__PURE__ */ new Map());
|
|
36
|
+
const parent = root ?? document.head;
|
|
37
|
+
const timeout = protocol().settings().timeout;
|
|
38
|
+
return Promise.all(
|
|
39
|
+
urls.map((href) => {
|
|
40
|
+
let p = seen.get(href);
|
|
41
|
+
if (!p) {
|
|
42
|
+
p = new Promise((resolve) => {
|
|
43
|
+
const link = addLink("stylesheet", href, { integrity: sri[href] ?? "" }, parent);
|
|
44
|
+
setTimeout(resolve, timeout);
|
|
45
|
+
link.onload = () => resolve();
|
|
46
|
+
link.onerror = () => {
|
|
47
|
+
link.remove();
|
|
48
|
+
seen.delete(href);
|
|
49
|
+
resolve();
|
|
50
|
+
};
|
|
51
|
+
});
|
|
52
|
+
seen.set(href, p);
|
|
53
|
+
}
|
|
54
|
+
return p;
|
|
55
|
+
})
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
fetchCssText,
|
|
61
|
+
prefetchCss,
|
|
62
|
+
injectStyles,
|
|
63
|
+
injectCss
|
|
64
|
+
};
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/types.ts
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
5
|
+
import { resolve } from "path";
|
|
6
|
+
var PROPS = /export type Props =\s*([\s\S]*?)\s*$/;
|
|
7
|
+
function parseProps(dts) {
|
|
8
|
+
return PROPS.exec(dts.replace(/^\s*\/\/.*$/gm, "").trim())?.[1]?.replace(/;$/, "") || null;
|
|
9
|
+
}
|
|
10
|
+
var HASH = /^\/\/ vitral:hash ("(?:[^"\\]|\\.)*") (\S+)$/gm;
|
|
11
|
+
function envFile(props, hashes = {}) {
|
|
12
|
+
const lines = Object.entries(props).map(([name, type]) => ` ${JSON.stringify(name)}: ${type}`);
|
|
13
|
+
const marks = Object.entries(hashes).map(([name, hash]) => `// vitral:hash ${JSON.stringify(name)} ${hash}
|
|
14
|
+
`);
|
|
15
|
+
return `// Gerado por \`npx vitral types\`. N\xE3o edite.
|
|
16
|
+
${marks.join("")}import 'vitral'
|
|
17
|
+
|
|
18
|
+
declare module 'vitral' {
|
|
19
|
+
interface Remotes {
|
|
20
|
+
${lines.join("\n")}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
}
|
|
25
|
+
function readHashes(env) {
|
|
26
|
+
return Object.fromEntries([...env.matchAll(HASH)].map((m) => [JSON.parse(m[1]), m[2]]));
|
|
27
|
+
}
|
|
28
|
+
async function manifestHash(get, url) {
|
|
29
|
+
try {
|
|
30
|
+
const res = await get(url);
|
|
31
|
+
if (!res.ok) return void 0;
|
|
32
|
+
const { integrity } = await res.json();
|
|
33
|
+
return typeof integrity === "string" ? integrity : void 0;
|
|
34
|
+
} catch {
|
|
35
|
+
return void 0;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function check(remotes, out, get, log) {
|
|
39
|
+
if (!existsSync(out)) {
|
|
40
|
+
log(`[vitral] ${out} n\xE3o existe. Rode \`npx vitral types\`.`);
|
|
41
|
+
return 1;
|
|
42
|
+
}
|
|
43
|
+
const recorded = readHashes(readFileSync(out, "utf8"));
|
|
44
|
+
let stale = 0;
|
|
45
|
+
for (const [name, url] of Object.entries(remotes)) {
|
|
46
|
+
const hash = await manifestHash(get, url);
|
|
47
|
+
if (!hash) log(`[vitral] ${name}: manifesto sem hash, n\xE3o deu para conferir.`);
|
|
48
|
+
else if (recorded[name] !== hash) {
|
|
49
|
+
log(`[vitral] ${name}: tipos desatualizados (${recorded[name] ? "o manifesto mudou" : "sem hash registrado"}).`);
|
|
50
|
+
stale++;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const name of Object.keys(recorded)) {
|
|
54
|
+
if (!(name in remotes)) {
|
|
55
|
+
log(`[vitral] ${name}: n\xE3o est\xE1 mais no remotes.json.`);
|
|
56
|
+
stale++;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
log(stale ? `[vitral] ${stale} remote(s) com tipos desatualizados. Rode \`npx vitral types\`.` : `[vitral] tipos em dia com os manifestos.`);
|
|
60
|
+
return stale;
|
|
61
|
+
}
|
|
62
|
+
function readRemotes(cwd, args2, base) {
|
|
63
|
+
const pairs = args2.filter((a) => a.includes("="));
|
|
64
|
+
if (pairs.length) return Object.fromEntries(pairs.map((p) => [p.slice(0, p.indexOf("=")), p.slice(p.indexOf("=") + 1)]));
|
|
65
|
+
const file = [args2[0], "public/remotes.json", "remotes.json"].find((f) => f && existsSync(resolve(cwd, f)));
|
|
66
|
+
if (!file) throw new Error("[vitral] remotes.json n\xE3o encontrado. Passe o caminho ou pares nome=url.");
|
|
67
|
+
const map = JSON.parse(readFileSync(resolve(cwd, file), "utf8"));
|
|
68
|
+
return Object.fromEntries(
|
|
69
|
+
Object.entries(map).map(([name, v]) => {
|
|
70
|
+
const url = typeof v === "string" ? v : v.url;
|
|
71
|
+
return [name, base ? new URL(url, base).href : url];
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
async function types(options = {}) {
|
|
76
|
+
const cwd = options.cwd ?? process.cwd();
|
|
77
|
+
const get = options.fetch ?? fetch;
|
|
78
|
+
const log = options.log ?? console.log;
|
|
79
|
+
const remotes = readRemotes(cwd, options.args ?? [], options.base);
|
|
80
|
+
const out = resolve(cwd, options.out ?? "vitral-env.d.ts");
|
|
81
|
+
if (options.check) return check(remotes, out, get, log);
|
|
82
|
+
const props = {};
|
|
83
|
+
const hashes = {};
|
|
84
|
+
let falhas = 0;
|
|
85
|
+
for (const [name, url] of Object.entries(remotes)) {
|
|
86
|
+
let dts;
|
|
87
|
+
try {
|
|
88
|
+
const res = await get(new URL("vitral.d.ts", url).href);
|
|
89
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
90
|
+
dts = await res.text();
|
|
91
|
+
} catch (err) {
|
|
92
|
+
log(`[vitral] ${name}: sem tipos (${err.message}).`);
|
|
93
|
+
falhas++;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
const type = parseProps(dts);
|
|
97
|
+
if (!type) {
|
|
98
|
+
log(`[vitral] ${name}: vitral.d.ts sem "export type Props".`);
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
props[name] = type;
|
|
102
|
+
const hash = await manifestHash(get, url);
|
|
103
|
+
if (hash) hashes[name] = hash;
|
|
104
|
+
}
|
|
105
|
+
writeFileSync(out, envFile(props, hashes));
|
|
106
|
+
log(`[vitral] ${Object.keys(props).length} remote(s) em ${out}`);
|
|
107
|
+
return falhas;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// src/cli.ts
|
|
111
|
+
var AJUDA = `Uso: vitral types [remotes.json | nome=url ...] [--base url] [--out arquivo] [--check]
|
|
112
|
+
|
|
113
|
+
Baixa o vitral.d.ts de cada remote e gera vitral-env.d.ts.
|
|
114
|
+
--check s\xF3 confere se o hash de cada manifesto ainda \xE9 o registrado;
|
|
115
|
+
sai com erro se algum mudou (\xFAtil no CI).`;
|
|
116
|
+
function flag(args2, name) {
|
|
117
|
+
const i = args2.indexOf(name);
|
|
118
|
+
if (i < 0) return void 0;
|
|
119
|
+
const value = args2[i + 1];
|
|
120
|
+
args2.splice(i, 2);
|
|
121
|
+
return value;
|
|
122
|
+
}
|
|
123
|
+
var [command, ...args] = process.argv.slice(2);
|
|
124
|
+
if (command === "types") {
|
|
125
|
+
const base = flag(args, "--base");
|
|
126
|
+
const out = flag(args, "--out");
|
|
127
|
+
const check2 = args.includes("--check");
|
|
128
|
+
types({ args: args.filter((a) => a !== "--check"), base, out, check: check2 }).then(
|
|
129
|
+
(falhas) => process.exitCode = falhas ? 1 : 0,
|
|
130
|
+
(err) => {
|
|
131
|
+
console.error(err.message);
|
|
132
|
+
process.exitCode = 1;
|
|
133
|
+
}
|
|
134
|
+
);
|
|
135
|
+
} else {
|
|
136
|
+
console.log(AJUDA);
|
|
137
|
+
process.exitCode = command && command !== "--help" ? 1 : 0;
|
|
138
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
protocol
|
|
3
|
+
} from "./chunk-GNPFWISJ.js";
|
|
4
|
+
|
|
5
|
+
// src/core/contract.ts
|
|
6
|
+
async function checkContract(c, range = protocol().settings().contract) {
|
|
7
|
+
const { satisfies } = await import("./dedupe-S7BHQMOZ.js");
|
|
8
|
+
if (c.version && !satisfies(c.version, range)) return `o host aceita contrato ${range}, o remote publica ${c.version}`;
|
|
9
|
+
const offered = protocol().settings().offered ?? {};
|
|
10
|
+
for (const dep in c.peers) {
|
|
11
|
+
const have = offered[dep];
|
|
12
|
+
if (have && !satisfies(have, c.peers[dep])) return `o remote espera ${dep} ${c.peers[dep]}, o host oferece ${have}`;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
checkContract
|
|
17
|
+
};
|