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
package/dist/angular.js
CHANGED
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
2
|
defineVitralElement
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3YXI3G34.js";
|
|
4
|
+
import "./chunk-IHTUM6LT.js";
|
|
4
5
|
import {
|
|
5
|
-
configure,
|
|
6
6
|
defineRemote,
|
|
7
7
|
events,
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
memoSelect,
|
|
9
|
+
navigate,
|
|
10
|
+
same,
|
|
11
|
+
shared
|
|
12
|
+
} from "./chunk-I3VSKSAZ.js";
|
|
13
|
+
import {
|
|
14
|
+
configure
|
|
15
|
+
} from "./chunk-TD4S3IHA.js";
|
|
16
|
+
import "./chunk-ZAC6QQI6.js";
|
|
17
|
+
import "./chunk-GNHCZRQP.js";
|
|
18
|
+
import "./chunk-AKNNHQ2H.js";
|
|
19
|
+
import "./chunk-GNPFWISJ.js";
|
|
10
20
|
|
|
11
21
|
// src/angular.ts
|
|
12
22
|
import {
|
|
23
|
+
DestroyRef,
|
|
13
24
|
InjectionToken,
|
|
14
25
|
createComponent,
|
|
15
26
|
inject,
|
|
16
27
|
provideAppInitializer,
|
|
17
28
|
provideZonelessChangeDetection,
|
|
18
|
-
reflectComponentType
|
|
29
|
+
reflectComponentType,
|
|
30
|
+
signal
|
|
19
31
|
} from "@angular/core";
|
|
20
32
|
import { createApplication } from "@angular/platform-browser";
|
|
21
33
|
var VITRAL_CONTEXT = new InjectionToken("vitral.context");
|
|
@@ -51,6 +63,14 @@ function angularRemote(component, config = {}) {
|
|
|
51
63
|
function injectVitral() {
|
|
52
64
|
return inject(VITRAL_CONTEXT, { optional: true });
|
|
53
65
|
}
|
|
66
|
+
function injectShared(key, select = same) {
|
|
67
|
+
const destroy = inject(DestroyRef);
|
|
68
|
+
const handle = shared(key);
|
|
69
|
+
const pick = memoSelect();
|
|
70
|
+
const value = signal(pick(handle.get(), select), { equal: Object.is });
|
|
71
|
+
destroy.onDestroy(handle.subscribe((v) => value.set(pick(v, select))));
|
|
72
|
+
return value.asReadonly();
|
|
73
|
+
}
|
|
54
74
|
function provideVitral(config = {}) {
|
|
55
75
|
return [
|
|
56
76
|
provideAppInitializer(() => {
|
|
@@ -64,6 +84,7 @@ export {
|
|
|
64
84
|
VITRAL_CONTEXT,
|
|
65
85
|
angularRemote,
|
|
66
86
|
events,
|
|
87
|
+
injectShared,
|
|
67
88
|
injectVitral,
|
|
68
89
|
navigate,
|
|
69
90
|
provideVitral
|
package/dist/auto.d.ts
ADDED
package/dist/auto.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineVitralElement
|
|
3
|
+
} from "./chunk-3YXI3G34.js";
|
|
4
|
+
import "./chunk-IHTUM6LT.js";
|
|
5
|
+
import "./chunk-I3VSKSAZ.js";
|
|
6
|
+
import "./chunk-TD4S3IHA.js";
|
|
7
|
+
import "./chunk-ZAC6QQI6.js";
|
|
8
|
+
import "./chunk-GNHCZRQP.js";
|
|
9
|
+
import "./chunk-AKNNHQ2H.js";
|
|
10
|
+
import "./chunk-GNPFWISJ.js";
|
|
11
|
+
|
|
12
|
+
// src/auto.ts
|
|
13
|
+
defineVitralElement();
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RemoteError,
|
|
3
|
+
isRemoteError,
|
|
4
|
+
mounted,
|
|
5
|
+
report,
|
|
6
|
+
reported
|
|
7
|
+
} from "./chunk-AKNNHQ2H.js";
|
|
8
|
+
import {
|
|
9
|
+
protocol
|
|
10
|
+
} from "./chunk-GNPFWISJ.js";
|
|
11
|
+
|
|
12
|
+
// src/core/capture.ts
|
|
13
|
+
var on = false;
|
|
14
|
+
function capture() {
|
|
15
|
+
if (on || typeof addEventListener == "undefined") return;
|
|
16
|
+
on = true;
|
|
17
|
+
addEventListener("error", (e) => attribute(e.error, e.filename));
|
|
18
|
+
addEventListener("unhandledrejection", (e) => attribute(e.reason));
|
|
19
|
+
}
|
|
20
|
+
function owner(error, file) {
|
|
21
|
+
const url = file || String(error?.stack ?? "").match(/(?:https?|file):\/\/[^\s)'"]+/)?.[0];
|
|
22
|
+
if (!url) return;
|
|
23
|
+
const host = [...document.querySelectorAll("script[src],link[rel=modulepreload]")].map(
|
|
24
|
+
(el) => el.src || el.href
|
|
25
|
+
);
|
|
26
|
+
let best;
|
|
27
|
+
let size = 0;
|
|
28
|
+
for (const [name, { entry }] of mounted) {
|
|
29
|
+
const dir = new URL(".", entry).href;
|
|
30
|
+
if (dir.length > size && url.startsWith(dir) && !host.some((u) => u.startsWith(dir))) best = name, size = dir.length;
|
|
31
|
+
}
|
|
32
|
+
return best;
|
|
33
|
+
}
|
|
34
|
+
function attribute(error, file) {
|
|
35
|
+
if (!protocol().settings().captureGlobalErrors || isRemoteError(error) || error instanceof Object && reported.has(error)) return;
|
|
36
|
+
const name = owner(error, file);
|
|
37
|
+
if (name) report(new RemoteError("RENDER_FAILED", name, String(error?.message ?? error), error), mounted.get(name));
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
capture,
|
|
41
|
+
owner
|
|
42
|
+
};
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import {
|
|
2
|
+
hostSlot,
|
|
3
|
+
timings
|
|
4
|
+
} from "./chunk-IHTUM6LT.js";
|
|
5
|
+
import {
|
|
6
|
+
defineRemote,
|
|
7
|
+
memoSelect,
|
|
8
|
+
same,
|
|
9
|
+
shared
|
|
10
|
+
} from "./chunk-I3VSKSAZ.js";
|
|
11
|
+
import {
|
|
12
|
+
registerSrc
|
|
13
|
+
} from "./chunk-TD4S3IHA.js";
|
|
14
|
+
|
|
15
|
+
// src/element.ts
|
|
16
|
+
var Base = typeof HTMLElement === "undefined" ? class {
|
|
17
|
+
} : HTMLElement;
|
|
18
|
+
var VitralRemoteElement = class extends Base {
|
|
19
|
+
static {
|
|
20
|
+
this.observedAttributes = ["name", "src", "props", "isolate"];
|
|
21
|
+
}
|
|
22
|
+
#slot = null;
|
|
23
|
+
#props = {};
|
|
24
|
+
get props() {
|
|
25
|
+
return this.#props;
|
|
26
|
+
}
|
|
27
|
+
set props(value) {
|
|
28
|
+
this.#props = value ?? {};
|
|
29
|
+
this.#slot?.update(this.#props);
|
|
30
|
+
}
|
|
31
|
+
get status() {
|
|
32
|
+
return this.#slot?.status ?? "loading";
|
|
33
|
+
}
|
|
34
|
+
retry() {
|
|
35
|
+
this.#slot?.retry();
|
|
36
|
+
}
|
|
37
|
+
connectedCallback() {
|
|
38
|
+
if (this.#slot) return;
|
|
39
|
+
const name = this.#name();
|
|
40
|
+
if (!name) return;
|
|
41
|
+
if (this.hasAttribute("props") && !Object.keys(this.#props).length) this.#props = parseProps(this.getAttribute("props"));
|
|
42
|
+
const keep = this.getAttribute("keep-alive");
|
|
43
|
+
this.#slot = hostSlot(this, {
|
|
44
|
+
name,
|
|
45
|
+
props: this.#props,
|
|
46
|
+
isolate: this.getAttribute("isolate") || void 0,
|
|
47
|
+
loading: this.getAttribute("loading"),
|
|
48
|
+
prefetch: this.getAttribute("prefetch"),
|
|
49
|
+
priority: this.getAttribute("priority") || void 0,
|
|
50
|
+
keepAlive: keep === null ? false : Number(keep) || true,
|
|
51
|
+
styles: { inherit: this.getAttribute("inherit-styles")?.split(/\s+/).filter(Boolean) },
|
|
52
|
+
onStatus: (status, error) => {
|
|
53
|
+
this.setAttribute("data-vitral-status", status);
|
|
54
|
+
if (status === "loading") this.setAttribute("aria-busy", "true");
|
|
55
|
+
else this.removeAttribute("aria-busy");
|
|
56
|
+
const has = (slot) => {
|
|
57
|
+
const els = this.querySelectorAll(`:scope > [slot="${slot}"]`);
|
|
58
|
+
for (const el of els) el.hidden = status !== (slot === "fallback" ? "loading" : "error");
|
|
59
|
+
return els.length > 0;
|
|
60
|
+
};
|
|
61
|
+
queueMicrotask(() => {
|
|
62
|
+
if (this.#slot?.status !== status) return;
|
|
63
|
+
const custom = { loading: has("fallback"), error: has("error"), ready: true };
|
|
64
|
+
this.#showDefault(custom[status] ? null : status);
|
|
65
|
+
});
|
|
66
|
+
if (status === "ready") this.dispatchEvent(new CustomEvent("vitral-ready", { bubbles: true, detail: { timings: timings(name) } }));
|
|
67
|
+
if (status === "error") this.dispatchEvent(new CustomEvent("vitral-error", { bubbles: true, detail: { error } }));
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Nome para montar. `src` em atributo é registrado sem entrar na allowlist:
|
|
73
|
+
* HTML injetado não pode liberar uma origem nova quando há `allowedOrigins`.
|
|
74
|
+
*/
|
|
75
|
+
#name() {
|
|
76
|
+
const src = this.getAttribute("src");
|
|
77
|
+
const name = this.getAttribute("name");
|
|
78
|
+
return src ? registerSrc(src, name ?? void 0, false) : name;
|
|
79
|
+
}
|
|
80
|
+
#default = null;
|
|
81
|
+
/** Carregando e erro padrão, só quando não há slot próprio. */
|
|
82
|
+
#showDefault(status) {
|
|
83
|
+
this.#default?.remove();
|
|
84
|
+
this.#default = null;
|
|
85
|
+
if (!status) return;
|
|
86
|
+
const box = document.createElement("div");
|
|
87
|
+
box.setAttribute("data-vitral-default", status);
|
|
88
|
+
if (status === "loading") {
|
|
89
|
+
box.setAttribute("role", "status");
|
|
90
|
+
box.textContent = "Carregando\u2026";
|
|
91
|
+
} else {
|
|
92
|
+
box.setAttribute("role", "alert");
|
|
93
|
+
const button = document.createElement("button");
|
|
94
|
+
button.type = "button";
|
|
95
|
+
button.textContent = "Tentar de novo";
|
|
96
|
+
button.onclick = () => this.retry();
|
|
97
|
+
box.append("N\xE3o foi poss\xEDvel carregar. ", button);
|
|
98
|
+
}
|
|
99
|
+
this.prepend(this.#default = box);
|
|
100
|
+
}
|
|
101
|
+
disconnectedCallback() {
|
|
102
|
+
queueMicrotask(() => {
|
|
103
|
+
if (!this.isConnected) {
|
|
104
|
+
this.#slot?.destroy();
|
|
105
|
+
this.#slot = null;
|
|
106
|
+
this.#showDefault(null);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
attributeChangedCallback(attr, _old, value) {
|
|
111
|
+
if (attr === "props") return void (this.props = parseProps(value));
|
|
112
|
+
if (!this.#slot) return void (this.isConnected && this.connectedCallback());
|
|
113
|
+
if (attr === "name" || attr === "src") {
|
|
114
|
+
const name = this.#name();
|
|
115
|
+
if (name) this.#slot.set({ name });
|
|
116
|
+
}
|
|
117
|
+
if (attr === "isolate") this.#slot.set({ isolate: value || void 0 });
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
function parseProps(value) {
|
|
121
|
+
if (!value) return {};
|
|
122
|
+
try {
|
|
123
|
+
return JSON.parse(value);
|
|
124
|
+
} catch {
|
|
125
|
+
console.error("[vitral] atributo props n\xE3o \xE9 JSON v\xE1lido:", value);
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function defineVitralElement(tag = "vitral-remote") {
|
|
130
|
+
if (typeof customElements !== "undefined" && !customElements.get(tag)) {
|
|
131
|
+
customElements.define(tag, class extends VitralRemoteElement {
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function elementRemote(tag, setup) {
|
|
136
|
+
return defineRemote({
|
|
137
|
+
mount(el, props, ctx) {
|
|
138
|
+
setup?.();
|
|
139
|
+
const node = document.createElement(tag);
|
|
140
|
+
node.vitral = ctx;
|
|
141
|
+
Object.assign(node, props);
|
|
142
|
+
el.appendChild(node);
|
|
143
|
+
return {
|
|
144
|
+
update: (next) => Object.assign(node, next),
|
|
145
|
+
unmount: () => node.remove()
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
var SharedController = class {
|
|
151
|
+
#host;
|
|
152
|
+
#handle;
|
|
153
|
+
#select;
|
|
154
|
+
#pick = memoSelect();
|
|
155
|
+
#off;
|
|
156
|
+
constructor(host, key, select) {
|
|
157
|
+
this.#host = host;
|
|
158
|
+
this.#handle = shared(key);
|
|
159
|
+
this.#select = select ?? same;
|
|
160
|
+
this.value = this.#pick(this.#handle.get(), this.#select);
|
|
161
|
+
host.addController(this);
|
|
162
|
+
}
|
|
163
|
+
hostConnected() {
|
|
164
|
+
this.#off = this.#handle.subscribe((v) => {
|
|
165
|
+
const next = this.#pick(v, this.#select);
|
|
166
|
+
if (Object.is(next, this.value)) return;
|
|
167
|
+
this.value = next;
|
|
168
|
+
this.#host.requestUpdate();
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
hostDisconnected() {
|
|
172
|
+
this.#off?.();
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export {
|
|
177
|
+
VitralRemoteElement,
|
|
178
|
+
defineVitralElement,
|
|
179
|
+
elementRemote,
|
|
180
|
+
SharedController
|
|
181
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RemoteError
|
|
3
|
+
} from "./chunk-AKNNHQ2H.js";
|
|
4
|
+
|
|
5
|
+
// src/core/integrity.ts
|
|
6
|
+
var clean = (b64) => b64.replace(/-/g, "+").replace(/_/g, "/").replace(/=/g, "");
|
|
7
|
+
async function verifyIntegrity(name, bytes, integrity) {
|
|
8
|
+
const hashes = integrity.split(/\s+/).map((token) => /^sha(256|384|512)-([\w+/=-]+)/.exec(token)).filter((m) => !!m);
|
|
9
|
+
if (!hashes.length) throw new RemoteError("INTEGRITY", name, `formato de integrity inv\xE1lido: ${integrity}`);
|
|
10
|
+
const bits = Math.max(...hashes.map((m) => +m[1]));
|
|
11
|
+
const actual = btoa(String.fromCharCode(...new Uint8Array(await crypto.subtle.digest("SHA-" + bits, bytes))));
|
|
12
|
+
const expected = hashes.filter((m) => +m[1] === bits).map((m) => m[2]);
|
|
13
|
+
if (!expected.some((h) => clean(h) === clean(actual))) {
|
|
14
|
+
throw new RemoteError("INTEGRITY", name, `o hash n\xE3o confere: esperado sha${bits}-${expected.join(" ou ")}, obtido sha${bits}-${actual}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
verifyIntegrity
|
|
20
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
protocol
|
|
3
|
+
} from "./chunk-GNPFWISJ.js";
|
|
4
|
+
|
|
5
|
+
// src/core/errors.ts
|
|
6
|
+
var ERROR_DOCS = "https://joaogabriel15.github.io/vitral/erros/";
|
|
7
|
+
var RemoteError = class extends Error {
|
|
8
|
+
constructor(code, remote, message, cause) {
|
|
9
|
+
super(`[vitral] ${remote}: ${message} (${ERROR_DOCS}${code})`);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.remote = remote;
|
|
12
|
+
this.cause = cause;
|
|
13
|
+
this.name = "RemoteError";
|
|
14
|
+
this.docs = `${ERROR_DOCS}${code}`;
|
|
15
|
+
if (typeof location != "undefined") this.route = location.pathname;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var isRemoteError = (e) => e?.name === "RemoteError";
|
|
19
|
+
var mounted = /* @__PURE__ */ new Map();
|
|
20
|
+
var reported = /* @__PURE__ */ new WeakSet();
|
|
21
|
+
function report(e, from) {
|
|
22
|
+
if (isRemoteError(e) && !reported.has(e)) {
|
|
23
|
+
reported.add(e);
|
|
24
|
+
if (e.cause instanceof Object) reported.add(e.cause);
|
|
25
|
+
e.entry ??= from?.entry ?? protocol().entry(e.remote)?.url;
|
|
26
|
+
e.version ??= from?.version;
|
|
27
|
+
try {
|
|
28
|
+
protocol().settings().onError?.(e);
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return e;
|
|
33
|
+
}
|
|
34
|
+
var fail = (e) => {
|
|
35
|
+
throw report(e);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export {
|
|
39
|
+
RemoteError,
|
|
40
|
+
isRemoteError,
|
|
41
|
+
mounted,
|
|
42
|
+
reported,
|
|
43
|
+
report,
|
|
44
|
+
fail
|
|
45
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
protocol
|
|
3
|
+
} from "./chunk-GNPFWISJ.js";
|
|
4
|
+
|
|
5
|
+
// src/core/overrides.ts
|
|
6
|
+
var OVERRIDES_KEY = "vitral:overrides";
|
|
7
|
+
function overridesEnabled() {
|
|
8
|
+
return !!protocol().settings().devOverrides || typeof location !== "undefined" && /^(localhost|127\.0\.0\.1|\[::1\])$/.test(location.hostname);
|
|
9
|
+
}
|
|
10
|
+
var manifestUrl = (url) => /\.(json|m?js)(\?|$)/.test(url) ? url : url.replace(/\/?$/, "/vitral.json");
|
|
11
|
+
function storedOverrides() {
|
|
12
|
+
try {
|
|
13
|
+
return JSON.parse(localStorage.getItem(OVERRIDES_KEY) ?? "{}") ?? {};
|
|
14
|
+
} catch {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
var warned = /* @__PURE__ */ new Set();
|
|
19
|
+
function overrideFor(name) {
|
|
20
|
+
if (!overridesEnabled()) return;
|
|
21
|
+
const all = storedOverrides();
|
|
22
|
+
for (const pair of new URLSearchParams(location.search).getAll("vitral").join(",").split(",")) {
|
|
23
|
+
const at = pair.indexOf("@");
|
|
24
|
+
if (at > 0) all[pair.slice(0, at)] = pair.slice(at + 1);
|
|
25
|
+
}
|
|
26
|
+
if (!all[name]) return;
|
|
27
|
+
const url = new URL(manifestUrl(all[name]), location.href).href;
|
|
28
|
+
const p = protocol();
|
|
29
|
+
const trusted = p.settings().trusted ?? [];
|
|
30
|
+
const origin = new URL(url).origin;
|
|
31
|
+
if (!trusted.includes(origin)) p.configure({ trusted: [...trusted, origin] });
|
|
32
|
+
if (!warned.has(name)) console.warn(`[vitral] override ativo: ${name} \u2192 ${url}`), warned.add(name);
|
|
33
|
+
return { url };
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export {
|
|
37
|
+
OVERRIDES_KEY,
|
|
38
|
+
overridesEnabled,
|
|
39
|
+
manifestUrl,
|
|
40
|
+
storedOverrides,
|
|
41
|
+
overrideFor
|
|
42
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RemoteError,
|
|
3
|
+
isRemoteError
|
|
4
|
+
} from "./chunk-AKNNHQ2H.js";
|
|
5
|
+
import {
|
|
6
|
+
protocol
|
|
7
|
+
} from "./chunk-GNPFWISJ.js";
|
|
8
|
+
|
|
9
|
+
// src/core/util.ts
|
|
10
|
+
function pageOrigin() {
|
|
11
|
+
return typeof location !== "undefined" ? location.origin : null;
|
|
12
|
+
}
|
|
13
|
+
function absolute(url, base) {
|
|
14
|
+
return new URL(url, base ?? (typeof location !== "undefined" ? location.href : void 0)).href;
|
|
15
|
+
}
|
|
16
|
+
async function withRetry(retries, fn) {
|
|
17
|
+
for (let i = 0; ; i++) {
|
|
18
|
+
try {
|
|
19
|
+
return await fn();
|
|
20
|
+
} catch (e) {
|
|
21
|
+
const retryable = isRemoteError(e) && (e.code === "LOAD_FAILED" || e.code === "TIMEOUT");
|
|
22
|
+
if (!retryable || i >= retries) throw e;
|
|
23
|
+
await new Promise((r) => setTimeout(r, 200 * 2 ** i));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function withTimeout(ms, name, p) {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
const t = setTimeout(() => reject(new RemoteError("TIMEOUT", name, `n\xE3o respondeu em ${ms}ms`)), ms);
|
|
30
|
+
p.then(resolve, reject).finally(() => clearTimeout(t));
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
function fetchBytes(url, timeout, name, init) {
|
|
34
|
+
const ctrl = new AbortController();
|
|
35
|
+
const got = fetch(url, { signal: ctrl.signal, credentials: "omit", ...init }).then(
|
|
36
|
+
(res) => {
|
|
37
|
+
if (!res.ok) throw new RemoteError("LOAD_FAILED", name, `HTTP ${res.status} em ${url}`);
|
|
38
|
+
return res.arrayBuffer();
|
|
39
|
+
},
|
|
40
|
+
(e) => {
|
|
41
|
+
throw new RemoteError("LOAD_FAILED", name, `falha ao baixar ${url}`, e);
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
return withTimeout(timeout, name, got).catch((e) => {
|
|
45
|
+
ctrl.abort();
|
|
46
|
+
throw e;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
async function fetchJson(url, timeout, name, init) {
|
|
50
|
+
const text = new TextDecoder().decode(await fetchBytes(url, timeout, name, init));
|
|
51
|
+
try {
|
|
52
|
+
return JSON.parse(text);
|
|
53
|
+
} catch (e) {
|
|
54
|
+
throw new RemoteError("INVALID_MODULE", name, `JSON inv\xE1lido em ${url}`, e);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function addLink(rel, href, props = {}, parent = document.head) {
|
|
58
|
+
return parent.appendChild(Object.assign(document.createElement("link"), { rel, crossOrigin: "anonymous", href }, props));
|
|
59
|
+
}
|
|
60
|
+
function metric(name, stage, start) {
|
|
61
|
+
try {
|
|
62
|
+
const label = `vitral:${name}:${stage}`;
|
|
63
|
+
performance.clearMeasures(label);
|
|
64
|
+
performance.measure(label, { start });
|
|
65
|
+
protocol().settings().onMetric?.({ name, stage, start, duration: performance.now() - start });
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export {
|
|
71
|
+
pageOrigin,
|
|
72
|
+
absolute,
|
|
73
|
+
withRetry,
|
|
74
|
+
withTimeout,
|
|
75
|
+
fetchBytes,
|
|
76
|
+
fetchJson,
|
|
77
|
+
addLink,
|
|
78
|
+
metric
|
|
79
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// src/core/bus.ts
|
|
2
|
+
function createEventBus() {
|
|
3
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
4
|
+
const lastValues = /* @__PURE__ */ new Map();
|
|
5
|
+
return {
|
|
6
|
+
emit(type, payload) {
|
|
7
|
+
lastValues.set(type, payload);
|
|
8
|
+
for (const h of [...handlers.get(type) ?? []]) {
|
|
9
|
+
try {
|
|
10
|
+
h(payload);
|
|
11
|
+
} catch (e) {
|
|
12
|
+
console.error(`[vitral] handler de "${type}" falhou`, e);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
on(type, handler) {
|
|
17
|
+
let set = handlers.get(type);
|
|
18
|
+
if (!set) handlers.set(type, set = /* @__PURE__ */ new Set());
|
|
19
|
+
set.add(handler);
|
|
20
|
+
return () => set.delete(handler);
|
|
21
|
+
},
|
|
22
|
+
last(type) {
|
|
23
|
+
return lastValues.get(type);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/core/state.ts
|
|
29
|
+
var PROTOCOL = 1;
|
|
30
|
+
var KEY = /* @__PURE__ */ Symbol.for("vitral");
|
|
31
|
+
var g = globalThis;
|
|
32
|
+
function createProtocol() {
|
|
33
|
+
const settings = { timeout: 15e3, retries: 1, isolate: "none", allowedOrigins: null };
|
|
34
|
+
const entries = /* @__PURE__ */ new Map();
|
|
35
|
+
const modules = /* @__PURE__ */ new Map();
|
|
36
|
+
let ready = Promise.resolve();
|
|
37
|
+
return {
|
|
38
|
+
protocol: PROTOCOL,
|
|
39
|
+
events: createEventBus(),
|
|
40
|
+
settings: () => settings,
|
|
41
|
+
configure(patch) {
|
|
42
|
+
Object.assign(settings, patch);
|
|
43
|
+
},
|
|
44
|
+
register(name, entry) {
|
|
45
|
+
entries.set(name, entry);
|
|
46
|
+
modules.delete(name);
|
|
47
|
+
},
|
|
48
|
+
entry: (name) => entries.get(name),
|
|
49
|
+
origins: () => [...entries.values()].filter((e) => e.url).map((e) => new URL(e.url).origin),
|
|
50
|
+
pending(p) {
|
|
51
|
+
if (p) ready = Promise.all([ready, p]);
|
|
52
|
+
return ready.then(() => {
|
|
53
|
+
});
|
|
54
|
+
},
|
|
55
|
+
load(name, fetcher) {
|
|
56
|
+
let p = modules.get(name);
|
|
57
|
+
if (!p) {
|
|
58
|
+
p = fetcher();
|
|
59
|
+
const mine = p;
|
|
60
|
+
mine.catch(() => modules.get(name) === mine && modules.delete(name));
|
|
61
|
+
modules.set(name, p);
|
|
62
|
+
}
|
|
63
|
+
return p;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
function protocol() {
|
|
68
|
+
const found = g[KEY];
|
|
69
|
+
if (found && typeof found.protocol === "number" && found.protocol >= PROTOCOL) return found;
|
|
70
|
+
return g[KEY] = createProtocol();
|
|
71
|
+
}
|
|
72
|
+
function resetProtocol() {
|
|
73
|
+
delete g[KEY];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export {
|
|
77
|
+
createEventBus,
|
|
78
|
+
protocol,
|
|
79
|
+
resetProtocol
|
|
80
|
+
};
|