vitral 0.1.0 → 0.2.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 +15 -4
- package/dist/angular.js +25 -5
- package/dist/auto.d.ts +2 -0
- package/dist/auto.js +12 -0
- package/dist/chunk-2XF5BKV3.js +190 -0
- package/dist/chunk-6Y3VMWHH.js +181 -0
- package/dist/chunk-DXORSF4X.js +42 -0
- package/dist/chunk-GNPFWISJ.js +80 -0
- package/dist/chunk-HP6QWU6K.js +51 -0
- package/dist/chunk-NCONW6WS.js +606 -0
- package/dist/chunk-PX7PBCCT.js +89 -0
- package/dist/chunk-S5MZT5IT.js +20 -0
- package/dist/chunk-SFL6LTP3.js +56 -0
- package/dist/chunk-UTYAX6MU.js +152 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +88 -0
- package/dist/dedupe-IWFIXRWG.js +81 -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 +9 -2
- package/dist/errors-KKB8FGCz.d.ts +11 -0
- package/dist/events-DUdjhfps.d.ts +6 -0
- package/dist/expose-53BEJB34.js +14 -0
- package/dist/host-slot-Cz6EiGsB.d.ts +6 -0
- package/dist/iframe.d.ts +28 -0
- package/dist/iframe.js +236 -0
- package/dist/index.d.ts +142 -147
- package/dist/index.js +39 -10
- package/dist/navigate-BRG1WJUM.d.ts +9 -0
- package/dist/overrides-NZAIUGK5.js +15 -0
- package/dist/preact.d.ts +30 -7
- package/dist/preact.js +37 -9
- package/dist/react.d.ts +38 -7
- package/dist/react.js +92 -42
- package/dist/routes.d.ts +56 -0
- package/dist/routes.js +143 -0
- package/dist/shadow-MYRJQLLY.js +72 -0
- package/dist/slot-pB276oPt.d.ts +36 -0
- package/dist/solid.d.ts +29 -6
- package/dist/solid.js +31 -8
- package/dist/sri-BVKZNX5Q.js +114 -0
- package/dist/state-BDdCwc21.d.ts +4 -0
- package/dist/svelte.d.ts +19 -3
- package/dist/svelte.js +10 -4
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +8 -3
- package/dist/types-BV-hUrms.d.ts +265 -0
- package/dist/vite.d.ts +58 -4
- package/dist/vite.js +714 -24
- package/dist/vue.d.ts +79 -7
- package/dist/vue.js +69 -46
- package/package.json +144 -8
- package/dist/chunk-IZK6ITIJ.js +0 -96
- package/dist/chunk-TTL52BF2.js +0 -547
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { R as RemoteError } from './errors-KKB8FGCz.js';
|
|
2
|
+
import { P as Props, I as Isolation, b as StyleOptions } from './types-BV-hUrms.js';
|
|
3
|
+
|
|
4
|
+
type SlotStatus = 'loading' | 'ready' | 'error';
|
|
5
|
+
interface SlotOptions<P extends Props = Props> {
|
|
6
|
+
/** Nome registrado. Com `src`, é o nome sob o qual a URL é registrada (opcional). */
|
|
7
|
+
name?: string;
|
|
8
|
+
/** URL do `vitral.json` (ou do JS). Registra o remote sem `configure()`. */
|
|
9
|
+
src?: string;
|
|
10
|
+
props?: P;
|
|
11
|
+
isolate?: Isolation;
|
|
12
|
+
/** `'high'` para o remote que aparece logo ao abrir a página. */
|
|
13
|
+
priority?: RequestPriority;
|
|
14
|
+
/** Estilos do host no Shadow DOM (somados aos do `configure`). */
|
|
15
|
+
styles?: StyleOptions;
|
|
16
|
+
/** Chamado a cada mudança de estado (para mostrar fallback / erro). */
|
|
17
|
+
onStatus?: (status: SlotStatus, error: RemoteError | null) => void;
|
|
18
|
+
}
|
|
19
|
+
interface RemoteSlot<P extends Props = Props> {
|
|
20
|
+
/** Atualiza as props sem remontar. */
|
|
21
|
+
update(props: P): void;
|
|
22
|
+
/** Troca de remote ou de isolamento (remonta). */
|
|
23
|
+
set(options: Partial<Pick<SlotOptions<P>, 'name' | 'src' | 'isolate'>>): void;
|
|
24
|
+
/** Remonta do zero (botão "tentar de novo"). */
|
|
25
|
+
retry(): void;
|
|
26
|
+
destroy(): void;
|
|
27
|
+
readonly status: SlotStatus;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Cuida do ciclo de vida de um remote dentro de `target`: monta, atualiza,
|
|
31
|
+
* remonta ao trocar de nome, ignora respostas atrasadas e limpa tudo no fim.
|
|
32
|
+
* Os adaptadores de host (Web Component, Svelte, Solid, Preact…) usam isto.
|
|
33
|
+
*/
|
|
34
|
+
declare function createSlot<P extends Props = Props>(target: HTMLElement, options: SlotOptions<P>): RemoteSlot<P>;
|
|
35
|
+
|
|
36
|
+
export { type RemoteSlot as R, type SlotStatus as S, type SlotOptions as a, createSlot as c };
|
package/dist/solid.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { JSX, Component } from 'solid-js';
|
|
2
|
-
import { Props, Isolation,
|
|
3
|
-
export {
|
|
1
|
+
import { JSX, Component, Accessor } from 'solid-js';
|
|
2
|
+
import { P as Props, I as Isolation, C as CheckedProps, a as RemoteModule, S as Shared } from './types-BV-hUrms.js';
|
|
3
|
+
export { R as RemoteContext } from './types-BV-hUrms.js';
|
|
4
|
+
import { R as RemoteError } from './errors-KKB8FGCz.js';
|
|
5
|
+
export { e as events } from './events-DUdjhfps.js';
|
|
6
|
+
export { n as navigate } from './navigate-BRG1WJUM.js';
|
|
7
|
+
import { L as Loading, P as Prefetch } from './host-slot-Cz6EiGsB.js';
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* Adaptador Solid (e SolidStart).
|
|
@@ -12,13 +16,32 @@ export { RemoteContext, events, navigate } from './index.js';
|
|
|
12
16
|
/** Transforma um componente Solid em um remote. O contexto chega na prop `vitral`. */
|
|
13
17
|
declare function solidRemote<P extends Props>(Comp: Component<any>): RemoteModule<P>;
|
|
14
18
|
interface RemoteProps<P extends Props = Props> {
|
|
15
|
-
name
|
|
19
|
+
name?: string;
|
|
20
|
+
/** URL do `vitral.json`. Dispensa `configure()`. */
|
|
21
|
+
src?: string;
|
|
16
22
|
props?: P;
|
|
17
23
|
isolate?: Isolation;
|
|
18
24
|
fallback?: JSX.Element;
|
|
19
25
|
error?: (error: RemoteError, retry: () => void) => JSX.Element;
|
|
20
26
|
class?: string;
|
|
27
|
+
/** `'lazy'`: monta perto de aparecer na tela; `'idle'`: com o navegador ocioso. */
|
|
28
|
+
loading?: Loading;
|
|
29
|
+
/** Baixa antes de montar: `'hover'`, `'visible'` ou `'idle'`. */
|
|
30
|
+
prefetch?: Prefetch;
|
|
31
|
+
/** `'high'` para o remote que aparece logo ao abrir a página. */
|
|
32
|
+
priority?: RequestPriority;
|
|
33
|
+
/** Ao sair da página, guarda o remote montado (LRU, padrão 5) e na volta só atualiza as props. */
|
|
34
|
+
keepAlive?: boolean | number;
|
|
21
35
|
}
|
|
22
|
-
declare function Remote<P extends Props = Props>(p: RemoteProps<P>): JSX.Element;
|
|
36
|
+
declare function Remote<P extends Props = Props, N extends string = string>(p: RemoteProps<P> & CheckedProps<N>): JSX.Element;
|
|
37
|
+
/**
|
|
38
|
+
* Accessor de uma chave compartilhada (`provide`/`shared`). Com seletor, só
|
|
39
|
+
* muda quando o resultado do seletor muda (`Object.is`). A assinatura acaba
|
|
40
|
+
* junto com o dono reativo (componente ou `createRoot`).
|
|
41
|
+
*
|
|
42
|
+
* const nome = useShared('usuario', (u) => u?.nome)
|
|
43
|
+
*/
|
|
44
|
+
declare function useShared<K extends keyof Shared, S = Shared[K] | undefined>(key: K, select?: (value: Shared[K] | undefined) => S): Accessor<S>;
|
|
45
|
+
declare function useShared<T = unknown, S = T | undefined>(key: string, select?: (value: T | undefined) => S): Accessor<S>;
|
|
23
46
|
|
|
24
|
-
export { Remote, type RemoteProps, solidRemote };
|
|
47
|
+
export { Remote, type RemoteProps, solidRemote, useShared };
|
package/dist/solid.js
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
hostSlot
|
|
3
|
+
} from "./chunk-UTYAX6MU.js";
|
|
4
|
+
import {
|
|
3
5
|
defineRemote,
|
|
4
6
|
events,
|
|
5
|
-
|
|
6
|
-
|
|
7
|
+
memoSelect,
|
|
8
|
+
navigate,
|
|
9
|
+
same,
|
|
10
|
+
shared
|
|
11
|
+
} from "./chunk-NCONW6WS.js";
|
|
12
|
+
import "./chunk-2XF5BKV3.js";
|
|
13
|
+
import "./chunk-SFL6LTP3.js";
|
|
14
|
+
import "./chunk-PX7PBCCT.js";
|
|
15
|
+
import "./chunk-GNPFWISJ.js";
|
|
7
16
|
|
|
8
17
|
// src/solid.ts
|
|
9
|
-
import { createComponent, createEffect, createSignal, mergeProps, on, onCleanup, onMount } from "solid-js";
|
|
18
|
+
import { createComponent, createEffect, createSignal, getOwner, mergeProps, on, onCleanup, onMount } from "solid-js";
|
|
10
19
|
import { createStore, reconcile } from "solid-js/store";
|
|
11
20
|
import { isServer, render } from "solid-js/web";
|
|
12
21
|
function solidRemote(Comp) {
|
|
@@ -26,15 +35,20 @@ function Remote(p) {
|
|
|
26
35
|
const [status, setStatus] = createSignal("loading");
|
|
27
36
|
const [error, setError] = createSignal(null);
|
|
28
37
|
const host = document.createElement("div");
|
|
29
|
-
host.setAttribute("data-vitral", p.name);
|
|
38
|
+
host.setAttribute("data-vitral", p.name ?? p.src ?? "");
|
|
30
39
|
if (p.class) host.className = p.class;
|
|
31
40
|
const target = document.createElement("div");
|
|
32
41
|
let slot = null;
|
|
33
42
|
onMount(() => {
|
|
34
|
-
slot =
|
|
43
|
+
slot = hostSlot(target, {
|
|
35
44
|
name: p.name,
|
|
45
|
+
src: p.src,
|
|
36
46
|
props: p.props ?? {},
|
|
37
47
|
isolate: p.isolate,
|
|
48
|
+
loading: p.loading,
|
|
49
|
+
prefetch: p.prefetch,
|
|
50
|
+
priority: p.priority,
|
|
51
|
+
keepAlive: p.keepAlive,
|
|
38
52
|
onStatus: (s, e) => {
|
|
39
53
|
host.setAttribute("data-vitral-status", s);
|
|
40
54
|
setError(() => e);
|
|
@@ -42,7 +56,7 @@ function Remote(p) {
|
|
|
42
56
|
}
|
|
43
57
|
});
|
|
44
58
|
});
|
|
45
|
-
createEffect(on(() => [p.name, p.isolate], ([name, isolate]) => slot?.set({ name, isolate }), { defer: true }));
|
|
59
|
+
createEffect(on(() => [p.name, p.src, p.isolate], ([name, src, isolate]) => slot?.set({ name, src, isolate }), { defer: true }));
|
|
46
60
|
createEffect(on(() => ({ ...p.props ?? {} }), (props) => slot?.update(props), { defer: true }));
|
|
47
61
|
onCleanup(() => slot?.destroy());
|
|
48
62
|
const retry = () => slot?.retry();
|
|
@@ -52,9 +66,18 @@ function Remote(p) {
|
|
|
52
66
|
(host.appendChild(target), host)
|
|
53
67
|
];
|
|
54
68
|
}
|
|
69
|
+
function useShared(key, select = same) {
|
|
70
|
+
const handle = shared(key);
|
|
71
|
+
const pick = memoSelect();
|
|
72
|
+
const [value, setValue] = createSignal(pick(handle.get(), select), { equals: Object.is });
|
|
73
|
+
const off = handle.subscribe((v) => setValue(() => pick(v, select)));
|
|
74
|
+
if (getOwner()) onCleanup(off);
|
|
75
|
+
return value;
|
|
76
|
+
}
|
|
55
77
|
export {
|
|
56
78
|
Remote,
|
|
57
79
|
events,
|
|
58
80
|
navigate,
|
|
59
|
-
solidRemote
|
|
81
|
+
solidRemote,
|
|
82
|
+
useShared
|
|
60
83
|
};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {
|
|
2
|
+
verifyIntegrity
|
|
3
|
+
} from "./chunk-S5MZT5IT.js";
|
|
4
|
+
import {
|
|
5
|
+
RemoteError,
|
|
6
|
+
addLink,
|
|
7
|
+
fetchBytes,
|
|
8
|
+
withTimeout
|
|
9
|
+
} from "./chunk-PX7PBCCT.js";
|
|
10
|
+
import "./chunk-GNPFWISJ.js";
|
|
11
|
+
|
|
12
|
+
// src/core/sri.ts
|
|
13
|
+
var failed = /* @__PURE__ */ new Set();
|
|
14
|
+
async function importVerified(name, r, run, timeout) {
|
|
15
|
+
const { entry, integrity, priority } = r;
|
|
16
|
+
if (!failed.has(entry)) {
|
|
17
|
+
try {
|
|
18
|
+
const go = async () => {
|
|
19
|
+
const url2 = await verified(r.split ?? { entry, chunks: [], sri: { [entry]: integrity }, priority }, run);
|
|
20
|
+
return url2 && { ns: await run(url2) };
|
|
21
|
+
};
|
|
22
|
+
const done = await withTimeout(timeout, name, go());
|
|
23
|
+
if (done) return done.ns;
|
|
24
|
+
} catch (e) {
|
|
25
|
+
failed.add(entry);
|
|
26
|
+
if (e instanceof RemoteError && e.code === "TIMEOUT") throw e;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
const bytes = await fetchBytes(entry, timeout, name, failed.has(entry) ? { priority, cache: "reload" } : { priority });
|
|
30
|
+
await verifyIntegrity(name, bytes, integrity);
|
|
31
|
+
const url = URL.createObjectURL(new Blob([bytes], { type: "text/javascript" }));
|
|
32
|
+
try {
|
|
33
|
+
return await run(url);
|
|
34
|
+
} finally {
|
|
35
|
+
URL.revokeObjectURL(url);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
var STRICT = /^(sha(256|384|512)-[A-Za-z0-9+/]+={0,2}( +|$))+$/;
|
|
39
|
+
var PROBE = "data:text/javascript,export{}";
|
|
40
|
+
var PROBE_SRI = "sha256-d3bjIZdvLjBurwdLwkSVOnEBPFFly+T1SR9r3VVHBGg=";
|
|
41
|
+
var maps;
|
|
42
|
+
var preloads;
|
|
43
|
+
var tick = () => new Promise((resolve) => {
|
|
44
|
+
const c = new MessageChannel();
|
|
45
|
+
c.port1.onmessage = () => resolve();
|
|
46
|
+
c.port2.postMessage(0);
|
|
47
|
+
});
|
|
48
|
+
async function verified(build, run) {
|
|
49
|
+
const { entry, chunks, sri, priority = "auto", dedupe = [] } = build;
|
|
50
|
+
const own = dedupe.flatMap((d) => [...d.chunks ?? [], d.file]);
|
|
51
|
+
if (![entry, ...chunks, ...own].every((u) => STRICT.test(sri[u] ?? ""))) return;
|
|
52
|
+
const p = globalThis[/* @__PURE__ */ Symbol.for("vitral")];
|
|
53
|
+
const share = async (pre) => {
|
|
54
|
+
if (!run || !dedupe.length) return;
|
|
55
|
+
const { shared } = await import("./dedupe-IWFIXRWG.js");
|
|
56
|
+
for (const d of dedupe)
|
|
57
|
+
shared(p)(d.name, d.range, {
|
|
58
|
+
version: d.version,
|
|
59
|
+
url: d.file,
|
|
60
|
+
load: async () => {
|
|
61
|
+
if (pre) await Promise.all([...d.chunks ?? [], d.file].map((u) => preload(u, sri[u], priority)));
|
|
62
|
+
return (await run(d.file)).default;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
if (maps !== false && (maps = await addMap(sri))) {
|
|
67
|
+
await share();
|
|
68
|
+
for (const u of chunks) fetch(u, { priority }).catch(() => {
|
|
69
|
+
});
|
|
70
|
+
return entry;
|
|
71
|
+
}
|
|
72
|
+
if (await (preloads ??= checkPreloads())) {
|
|
73
|
+
p.sri = { ...p.sri, ...sri };
|
|
74
|
+
await share(true);
|
|
75
|
+
await Promise.all([...chunks, entry].map((u) => preload(u, sri[u], priority)));
|
|
76
|
+
return entry;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async function addMap(integrity) {
|
|
80
|
+
let ok = true;
|
|
81
|
+
try {
|
|
82
|
+
const s = document.createElement("script");
|
|
83
|
+
s.type = "importmap";
|
|
84
|
+
s.nonce = document.querySelector("script[nonce]")?.nonce ?? "";
|
|
85
|
+
s.onerror = () => ok = false;
|
|
86
|
+
s.addEventListener("securitypolicyviolation", () => ok = false);
|
|
87
|
+
s.textContent = JSON.stringify({ integrity });
|
|
88
|
+
document.head.append(s);
|
|
89
|
+
} catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
await tick();
|
|
93
|
+
await tick();
|
|
94
|
+
return ok;
|
|
95
|
+
}
|
|
96
|
+
function preload(href, integrity, fetchPriority = "auto") {
|
|
97
|
+
return new Promise((resolve, reject) => {
|
|
98
|
+
const link = addLink("modulepreload", href, { integrity, fetchPriority });
|
|
99
|
+
link.onload = resolve;
|
|
100
|
+
link.onerror = reject;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
function checkPreloads() {
|
|
104
|
+
if (!document.createElement("link").relList.supports("modulepreload")) return Promise.resolve(false);
|
|
105
|
+
const run = (href, good) => preload(href, PROBE_SRI).then(() => good, () => !good);
|
|
106
|
+
return Promise.race([
|
|
107
|
+
Promise.all([run(PROBE, true), run(PROBE + "//", false)]).then(([a, b]) => a && b),
|
|
108
|
+
new Promise((resolve) => setTimeout(resolve, 3e3, false))
|
|
109
|
+
]);
|
|
110
|
+
}
|
|
111
|
+
export {
|
|
112
|
+
importVerified,
|
|
113
|
+
verified
|
|
114
|
+
};
|
package/dist/svelte.d.ts
CHANGED
|
@@ -1,22 +1,38 @@
|
|
|
1
1
|
import { Component } from 'svelte';
|
|
2
|
-
import { Props, Isolation,
|
|
3
|
-
export {
|
|
2
|
+
import { P as Props, I as Isolation, a as RemoteModule } from './types-BV-hUrms.js';
|
|
3
|
+
export { R as RemoteContext } from './types-BV-hUrms.js';
|
|
4
|
+
import { R as RemoteError } from './errors-KKB8FGCz.js';
|
|
5
|
+
import { S as SlotStatus } from './slot-pB276oPt.js';
|
|
6
|
+
export { e as events } from './events-DUdjhfps.js';
|
|
7
|
+
export { n as navigate } from './navigate-BRG1WJUM.js';
|
|
8
|
+
import { L as Loading, P as Prefetch } from './host-slot-Cz6EiGsB.js';
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
11
|
* Adaptador Svelte 5 (e SvelteKit).
|
|
7
12
|
*
|
|
8
13
|
* Remote: export default svelteRemote(App)
|
|
9
14
|
* Host: <div use:remote={{ name: 'carrinho', props: { userId } }}></div>
|
|
15
|
+
* <div use:remote={{ src: 'https://cdn.exemplo.com/carrinho/vitral.json' }}></div>
|
|
10
16
|
* ou o Web Component <vitral-remote> de 'vitral/element'.
|
|
11
17
|
*/
|
|
12
18
|
|
|
13
19
|
/** Transforma um componente Svelte em um remote. O contexto chega na prop `vitral`. */
|
|
14
20
|
declare function svelteRemote<P extends Props>(component: Component<any>): RemoteModule<P>;
|
|
15
21
|
interface RemoteActionParams<P extends Props = Props> {
|
|
16
|
-
name
|
|
22
|
+
name?: string;
|
|
23
|
+
/** URL do `vitral.json`. Dispensa `configure()`. */
|
|
24
|
+
src?: string;
|
|
17
25
|
props?: P;
|
|
18
26
|
isolate?: Isolation;
|
|
19
27
|
onStatus?: (status: SlotStatus, error: RemoteError | null) => void;
|
|
28
|
+
/** `'lazy'`: monta perto de aparecer na tela; `'idle'`: com o navegador ocioso. */
|
|
29
|
+
loading?: Loading;
|
|
30
|
+
/** Baixa antes de montar: `'hover'`, `'visible'` ou `'idle'`. */
|
|
31
|
+
prefetch?: Prefetch;
|
|
32
|
+
/** `'high'` para o remote que aparece logo ao abrir a página. */
|
|
33
|
+
priority?: RequestPriority;
|
|
34
|
+
/** Ao sair da página, guarda o remote montado (LRU, padrão 5) e na volta só atualiza as props. */
|
|
35
|
+
keepAlive?: boolean | number;
|
|
20
36
|
}
|
|
21
37
|
/** Action Svelte: `<div use:remote={{ name, props }}>`. Funciona também em SvelteKit (só roda no cliente). */
|
|
22
38
|
declare function remote<P extends Props = Props>(node: HTMLElement, params: RemoteActionParams<P>): {
|
package/dist/svelte.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
hostSlot
|
|
3
|
+
} from "./chunk-UTYAX6MU.js";
|
|
4
|
+
import {
|
|
3
5
|
defineRemote,
|
|
4
6
|
events,
|
|
5
7
|
navigate
|
|
6
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-NCONW6WS.js";
|
|
9
|
+
import "./chunk-2XF5BKV3.js";
|
|
10
|
+
import "./chunk-SFL6LTP3.js";
|
|
11
|
+
import "./chunk-PX7PBCCT.js";
|
|
12
|
+
import "./chunk-GNPFWISJ.js";
|
|
7
13
|
|
|
8
14
|
// src/svelte.ts
|
|
9
15
|
import { createClassComponent } from "svelte/legacy";
|
|
@@ -19,10 +25,10 @@ function svelteRemote(component) {
|
|
|
19
25
|
});
|
|
20
26
|
}
|
|
21
27
|
function remote(node, params) {
|
|
22
|
-
const slot =
|
|
28
|
+
const slot = hostSlot(node, params);
|
|
23
29
|
return {
|
|
24
30
|
update(next) {
|
|
25
|
-
slot.set({ name: next.name, isolate: next.isolate });
|
|
31
|
+
slot.set({ name: next.name, src: next.src, isolate: next.isolate });
|
|
26
32
|
slot.update(next.props ?? {});
|
|
27
33
|
},
|
|
28
34
|
destroy: () => slot.destroy()
|
package/dist/testing.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Props, RemoteContext } from './
|
|
2
|
-
export {
|
|
1
|
+
import { P as Props, R as RemoteContext } from './types-BV-hUrms.js';
|
|
2
|
+
export { r as resetVitral } from './state-BDdCwc21.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Utilidades de teste: monte o host sem subir nenhum remote de verdade.
|
package/dist/testing.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import "./chunk-NCONW6WS.js";
|
|
1
2
|
import {
|
|
2
|
-
__reset,
|
|
3
3
|
register
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2XF5BKV3.js";
|
|
5
|
+
import "./chunk-SFL6LTP3.js";
|
|
6
|
+
import "./chunk-PX7PBCCT.js";
|
|
7
|
+
import {
|
|
8
|
+
resetProtocol
|
|
9
|
+
} from "./chunk-GNPFWISJ.js";
|
|
5
10
|
|
|
6
11
|
// src/testing.ts
|
|
7
12
|
function mockRemote(name, render = (el) => {
|
|
@@ -43,5 +48,5 @@ function failingRemote(name, message = "falha simulada") {
|
|
|
43
48
|
export {
|
|
44
49
|
failingRemote,
|
|
45
50
|
mockRemote,
|
|
46
|
-
|
|
51
|
+
resetProtocol as resetVitral
|
|
47
52
|
};
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tipos das chaves compartilhadas. Declare uma vez no projeto:
|
|
3
|
+
*
|
|
4
|
+
* declare module 'vitral' {
|
|
5
|
+
* interface Shared { usuario: { id: number; nome: string } | null; tema: 'claro' | 'escuro' }
|
|
6
|
+
* }
|
|
7
|
+
*/
|
|
8
|
+
interface Shared {
|
|
9
|
+
}
|
|
10
|
+
/** Tipo do valor de `K`: o declarado em `Shared`, ou `unknown`. */
|
|
11
|
+
type SharedType<K extends string> = K extends keyof Shared ? Shared[K] : unknown;
|
|
12
|
+
/**
|
|
13
|
+
* Acesso a uma chave. Segue o contrato de store do Svelte (`$tema` funciona).
|
|
14
|
+
* O valor é tratado como imutável: para mudar, passe um valor novo.
|
|
15
|
+
*/
|
|
16
|
+
interface SharedValue<T> {
|
|
17
|
+
/** A chave. */
|
|
18
|
+
readonly key: string;
|
|
19
|
+
/** Valor atual, ou `undefined` se ninguém deu valor ainda. */
|
|
20
|
+
get(): T | undefined;
|
|
21
|
+
/** Troca o valor. Numa chave com `writable: false`, só o dono pode. */
|
|
22
|
+
set(value: T): void;
|
|
23
|
+
/** `set(fn(get()))`. */
|
|
24
|
+
update(fn: (value: T | undefined) => T): void;
|
|
25
|
+
/** Chama `fn` agora, com o valor atual, e a cada mudança. Devolve a função que cancela. */
|
|
26
|
+
subscribe(fn: (value: T | undefined) => void): () => void;
|
|
27
|
+
}
|
|
28
|
+
/** O que `provide` devolve. Quando é o dono, `set` sempre passa. */
|
|
29
|
+
interface ProvidedValue<T> extends SharedValue<T> {
|
|
30
|
+
get(): T;
|
|
31
|
+
update(fn: (value: T) => T): void;
|
|
32
|
+
subscribe(fn: (value: T) => void): () => void;
|
|
33
|
+
}
|
|
34
|
+
interface ProvideOptions {
|
|
35
|
+
/** `false`: só quem chamou `provide` altera. Padrão `true`. */
|
|
36
|
+
writable?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/** `shared`, com `provide` e `batch`. É também o tipo de `ctx.shared`. */
|
|
39
|
+
interface SharedApi {
|
|
40
|
+
<K extends keyof Shared>(key: K): SharedValue<Shared[K]>;
|
|
41
|
+
<T = unknown>(key: string): SharedValue<T>;
|
|
42
|
+
/**
|
|
43
|
+
* Cria a chave e vira dono dela. Quem chama primeiro é o dono; depois disso,
|
|
44
|
+
* `provide` só devolve um acesso comum e não grava o valor.
|
|
45
|
+
*/
|
|
46
|
+
provide<K extends keyof Shared>(key: K, value: Shared[K], options?: ProvideOptions): ProvidedValue<Shared[K]>;
|
|
47
|
+
provide<T>(key: string, value: T, options?: ProvideOptions): ProvidedValue<T>;
|
|
48
|
+
/** Várias mudanças, uma notificação por chave no fim. */
|
|
49
|
+
batch<R>(fn: () => R): R;
|
|
50
|
+
}
|
|
51
|
+
/** Acesso a uma chave compartilhada: `get()`, `set()`, `update()` e `subscribe()`. */
|
|
52
|
+
declare function shared<K extends keyof Shared>(key: K): SharedValue<Shared[K]>;
|
|
53
|
+
declare function shared<T = unknown>(key: string): SharedValue<T>;
|
|
54
|
+
/**
|
|
55
|
+
* Cria uma chave compartilhada e vira dono dela. Quem chama primeiro é o
|
|
56
|
+
* dono; depois disso, `provide` só devolve um acesso comum e não grava o valor.
|
|
57
|
+
*/
|
|
58
|
+
declare function provide<K extends keyof Shared>(key: K, value: Shared[K], options?: ProvideOptions): ProvidedValue<Shared[K]>;
|
|
59
|
+
declare function provide<T>(key: string, value: T, options?: ProvideOptions): ProvidedValue<T>;
|
|
60
|
+
/** Várias mudanças, uma notificação por chave no fim. */
|
|
61
|
+
declare function batch<R>(fn: () => R): R;
|
|
62
|
+
|
|
63
|
+
type Props = Record<string, unknown>;
|
|
64
|
+
/**
|
|
65
|
+
* Props de cada remote, por nome. `npx vitral types` gera um
|
|
66
|
+
* `vitral-env.d.ts` que preenche esta interface:
|
|
67
|
+
*
|
|
68
|
+
* declare module 'vitral' { interface Remotes { carrinho: { userId: number } } }
|
|
69
|
+
*/
|
|
70
|
+
interface Remotes {
|
|
71
|
+
}
|
|
72
|
+
/** Props do remote `N`: as declaradas em `Remotes`, ou qualquer objeto. */
|
|
73
|
+
type PropsOf<N extends string> = N extends keyof Remotes ? Remotes[N] : Props;
|
|
74
|
+
/** Restrição extra nas props de um componente de host quando o nome está em `Remotes`. */
|
|
75
|
+
type CheckedProps<N extends string> = N extends keyof Remotes ? {
|
|
76
|
+
name?: N;
|
|
77
|
+
props?: Remotes[N];
|
|
78
|
+
} : {
|
|
79
|
+
name?: N;
|
|
80
|
+
};
|
|
81
|
+
interface RemoteContext {
|
|
82
|
+
/** Nome com que o host registrou este remote. */
|
|
83
|
+
name: string;
|
|
84
|
+
/** URL base de onde o remote foi carregado (útil para assets). */
|
|
85
|
+
baseUrl: string;
|
|
86
|
+
/**
|
|
87
|
+
* Barramento de eventos compartilhado entre host e todos os remotes. As
|
|
88
|
+
* assinaturas feitas por aqui são canceladas sozinhas no unmount.
|
|
89
|
+
*/
|
|
90
|
+
events: EventBus;
|
|
91
|
+
/** Shadow root quando o host pediu isolamento, senão `null`. */
|
|
92
|
+
shadowRoot: ShadowRoot | null;
|
|
93
|
+
/** Avisa o host de um erro em tempo de execução (os adaptadores já chamam). */
|
|
94
|
+
reportError(error: unknown): void;
|
|
95
|
+
/** Navega a página inteira (host e todos os roteadores) para `url`. */
|
|
96
|
+
navigate(url: string, options?: {
|
|
97
|
+
replace?: boolean;
|
|
98
|
+
}): void;
|
|
99
|
+
/**
|
|
100
|
+
* Versão do protocolo entre cópias da lib que o host fala (hoje 1). Use
|
|
101
|
+
* para detectar recursos; hosts antigos não mandam este campo.
|
|
102
|
+
*/
|
|
103
|
+
protocol?: number;
|
|
104
|
+
/**
|
|
105
|
+
* Com keep-alive: `fn` roda quando o remote volta para a página. Devolve a
|
|
106
|
+
* função que cancela. Hosts antigos não mandam este campo.
|
|
107
|
+
*/
|
|
108
|
+
onActivate?(fn: () => void): () => void;
|
|
109
|
+
/** Com keep-alive: `fn` roda quando o remote sai da página sem desmontar (pause timers e assinaturas). */
|
|
110
|
+
onDeactivate?(fn: () => void): () => void;
|
|
111
|
+
/**
|
|
112
|
+
* O mesmo `shared` de `import { shared } from 'vitral'`, mas as assinaturas
|
|
113
|
+
* feitas por aqui são canceladas no unmount, e as chaves criadas com
|
|
114
|
+
* `ctx.shared.provide` perdem o dono. Vem quando o host usa o store
|
|
115
|
+
* (`provide`, `shared` ou um hook); senão, importe `shared` de 'vitral'.
|
|
116
|
+
*/
|
|
117
|
+
shared?: SharedApi;
|
|
118
|
+
}
|
|
119
|
+
interface MountedRemote<P extends Props = Props> {
|
|
120
|
+
update?(props: P): void;
|
|
121
|
+
unmount(): void;
|
|
122
|
+
}
|
|
123
|
+
interface RemoteModule<P extends Props = Props> {
|
|
124
|
+
mount(el: HTMLElement, props: P, ctx: RemoteContext): MountedRemote<P> | Promise<MountedRemote<P>>;
|
|
125
|
+
}
|
|
126
|
+
interface RemoteEntry {
|
|
127
|
+
/** URL do módulo JS do remote, ou do `vitral.json` gerado pelo plugin. */
|
|
128
|
+
url?: string;
|
|
129
|
+
/**
|
|
130
|
+
* Remote local, sem rede: o próprio módulo ou uma função que o importa
|
|
131
|
+
* (ex.: `() => import('./carrinho')`). Útil em monorepos e testes.
|
|
132
|
+
*/
|
|
133
|
+
module?: RemoteModule<any> | (() => Promise<RemoteModule<any> | {
|
|
134
|
+
default: RemoteModule<any>;
|
|
135
|
+
}>);
|
|
136
|
+
/** Hash SRI (`sha256-…`, `sha384-…`, `sha512-…`) do JS. Verificado antes de executar. */
|
|
137
|
+
integrity?: string;
|
|
138
|
+
/** CSS extra para carregar junto. */
|
|
139
|
+
css?: string[];
|
|
140
|
+
/** Isolamento padrão para este remote. */
|
|
141
|
+
isolate?: Isolation;
|
|
142
|
+
/**
|
|
143
|
+
* O `vitral.json` já baixado (ex.: por `vitral registry`), para não buscá-lo
|
|
144
|
+
* na hora. Os caminhos dele são relativos a `url`, e os hashes ficam fixos
|
|
145
|
+
* no host.
|
|
146
|
+
*/
|
|
147
|
+
manifest?: RemoteManifest;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* `none`: CSS com escopo. `shadow`: Shadow DOM. `iframe`: iframe com
|
|
151
|
+
* `sandbox`, para código de terceiros (precisa de `enableIframe()`).
|
|
152
|
+
*/
|
|
153
|
+
type Isolation = 'shadow' | 'none' | 'iframe';
|
|
154
|
+
/** Estilos do host dentro do Shadow DOM. Sem efeito no modo escopo. */
|
|
155
|
+
interface StyleOptions {
|
|
156
|
+
/**
|
|
157
|
+
* CSS do host adotado em cada shadow root antes do CSS do remote (ex.:
|
|
158
|
+
* `['/assets/base.css']`). Um `CSSStyleSheet` por arquivo, o mesmo em todos.
|
|
159
|
+
*/
|
|
160
|
+
inherit?: string[];
|
|
161
|
+
/**
|
|
162
|
+
* Copia `class` e `data-theme` do `<html>` para a raiz do remote, para
|
|
163
|
+
* `dark:` e `[data-theme]` funcionarem no Shadow DOM. Padrão `true`.
|
|
164
|
+
*/
|
|
165
|
+
mirrorTheme?: boolean;
|
|
166
|
+
}
|
|
167
|
+
interface VitralConfig {
|
|
168
|
+
/** Mapa nome → URL (ou entrada completa), ou a URL de um JSON com esse mapa. */
|
|
169
|
+
remotes?: Record<string, string | RemoteEntry> | string;
|
|
170
|
+
/**
|
|
171
|
+
* Origens de onde é permitido carregar código. Padrão: a própria origem da
|
|
172
|
+
* página mais as origens das URLs registradas. Use `['*']` para liberar tudo.
|
|
173
|
+
*/
|
|
174
|
+
allowedOrigins?: string[];
|
|
175
|
+
/** Tempo máximo para baixar um remote, em ms. Padrão 15000. */
|
|
176
|
+
timeout?: number;
|
|
177
|
+
/** Tentativas extras se o download falhar. Padrão 1. */
|
|
178
|
+
retries?: number;
|
|
179
|
+
/** Isolamento padrão para todos os remotes. Padrão `'none'`. */
|
|
180
|
+
isolate?: Isolation;
|
|
181
|
+
/**
|
|
182
|
+
* Liga os overrides de desenvolvimento (`?vitral=nome@url` e
|
|
183
|
+
* `localStorage['vitral:overrides']`) fora de localhost. Em localhost já
|
|
184
|
+
* valem. Nunca ligue em produção: um link com `?vitral=` executaria código
|
|
185
|
+
* de qualquer origem.
|
|
186
|
+
*/
|
|
187
|
+
devOverrides?: boolean;
|
|
188
|
+
/** Estilos do host no Shadow DOM: `{ inherit: ['/assets/base.css'] }`. */
|
|
189
|
+
styles?: StyleOptions;
|
|
190
|
+
/** Recebe o tempo de cada etapa do carregamento (para RUM). */
|
|
191
|
+
onMetric?: (metric: RemoteMetric) => void;
|
|
192
|
+
/**
|
|
193
|
+
* Dependências que o host oferece aos remotes com `dedupe`, por grupo:
|
|
194
|
+
* `{ vue: { version: Vue.version, modules: { vue: Vue } } }`. O remote usa
|
|
195
|
+
* a do host se a versão estiver na faixa dele; senão, a própria cópia.
|
|
196
|
+
*/
|
|
197
|
+
dedupe?: Record<string, {
|
|
198
|
+
version: string;
|
|
199
|
+
modules: SharedModules;
|
|
200
|
+
}>;
|
|
201
|
+
}
|
|
202
|
+
/** Módulos de um grupo de `dedupe`, por especificador (`'react-dom/client'`). */
|
|
203
|
+
type SharedModules = Record<string, unknown>;
|
|
204
|
+
/**
|
|
205
|
+
* Tempo de uma etapa do carregamento de um remote. Cada etapa também vira
|
|
206
|
+
* `performance.measure('vitral:<nome>:<etapa>')`, visível no painel
|
|
207
|
+
* Performance do DevTools.
|
|
208
|
+
*/
|
|
209
|
+
interface RemoteMetric {
|
|
210
|
+
name: string;
|
|
211
|
+
stage: 'manifest' | 'js' | 'css' | 'mount';
|
|
212
|
+
/** Início, em ms desde `performance.timeOrigin`. */
|
|
213
|
+
start: number;
|
|
214
|
+
duration: number;
|
|
215
|
+
}
|
|
216
|
+
/** Formato do `vitral.json` emitido pelo plugin de build. */
|
|
217
|
+
interface RemoteManifest {
|
|
218
|
+
name: string;
|
|
219
|
+
version?: string;
|
|
220
|
+
entry: string;
|
|
221
|
+
css?: string[];
|
|
222
|
+
integrity?: string;
|
|
223
|
+
/** Escopo usado pelo plugin para prefixar o CSS (`[data-vitral-scope]`). */
|
|
224
|
+
scope?: string;
|
|
225
|
+
/**
|
|
226
|
+
* Componentes e módulos extras do remote (`./MiniCarrinho`, `./api`). Vêm
|
|
227
|
+
* do mesmo `entry`, no export `exposes`. O host usa `carrinho/MiniCarrinho`.
|
|
228
|
+
*/
|
|
229
|
+
exposes?: string[];
|
|
230
|
+
/**
|
|
231
|
+
* Hash SRI de cada arquivo publicado (CSS e JS do build dividido), pelo
|
|
232
|
+
* caminho relativo ao manifesto.
|
|
233
|
+
*/
|
|
234
|
+
files?: Record<string, string>;
|
|
235
|
+
/**
|
|
236
|
+
* Build dividido, para navegadores que conferem o hash de cada módulo:
|
|
237
|
+
* a entrada e os chunks que ela importa logo. `entry` e `integrity`
|
|
238
|
+
* continuam apontando para o arquivo único, usado por hosts antigos e
|
|
239
|
+
* quando o navegador não confere o hash por módulo.
|
|
240
|
+
*/
|
|
241
|
+
split?: {
|
|
242
|
+
entry: string;
|
|
243
|
+
chunks?: string[];
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Dependências de `dedupe` do build dividido: faixa aceita, versão da
|
|
247
|
+
* cópia própria e o arquivo dela, para o loader baixar junto com a entrada.
|
|
248
|
+
*/
|
|
249
|
+
dedupe?: {
|
|
250
|
+
name: string;
|
|
251
|
+
range: string;
|
|
252
|
+
version: string;
|
|
253
|
+
file: string;
|
|
254
|
+
chunks?: string[];
|
|
255
|
+
}[];
|
|
256
|
+
}
|
|
257
|
+
type Handler<T = unknown> = (payload: T) => void;
|
|
258
|
+
interface EventBus {
|
|
259
|
+
emit<T = unknown>(type: string, payload?: T): void;
|
|
260
|
+
on<T = unknown>(type: string, handler: Handler<T>): () => void;
|
|
261
|
+
/** Último valor emitido em `type` (útil para estado como "usuário logado"). */
|
|
262
|
+
last<T = unknown>(type: string): T | undefined;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export { type CheckedProps as C, type EventBus as E, type Handler as H, type Isolation as I, type MountedRemote as M, type Props as P, type RemoteContext as R, type Shared as S, type VitralConfig as V, type RemoteModule as a, type StyleOptions as b, type RemoteEntry as c, type SharedValue as d, type PropsOf as e, type ProvideOptions as f, type ProvidedValue as g, type RemoteManifest as h, type RemoteMetric as i, type Remotes as j, type SharedApi as k, type SharedModules as l, type SharedType as m, batch as n, provide as p, shared as s };
|