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,634 @@
|
|
|
1
|
+
import {
|
|
2
|
+
load,
|
|
3
|
+
loadFile,
|
|
4
|
+
registerSrc,
|
|
5
|
+
resolveEntry
|
|
6
|
+
} from "./chunk-TD4S3IHA.js";
|
|
7
|
+
import {
|
|
8
|
+
injectStyles
|
|
9
|
+
} from "./chunk-ZAC6QQI6.js";
|
|
10
|
+
import {
|
|
11
|
+
metric
|
|
12
|
+
} from "./chunk-GNHCZRQP.js";
|
|
13
|
+
import {
|
|
14
|
+
RemoteError,
|
|
15
|
+
fail,
|
|
16
|
+
isRemoteError,
|
|
17
|
+
mounted,
|
|
18
|
+
report
|
|
19
|
+
} from "./chunk-AKNNHQ2H.js";
|
|
20
|
+
import {
|
|
21
|
+
protocol
|
|
22
|
+
} from "./chunk-GNPFWISJ.js";
|
|
23
|
+
|
|
24
|
+
// src/core/events.ts
|
|
25
|
+
var events = {
|
|
26
|
+
emit: (t, p) => protocol().events.emit(t, p),
|
|
27
|
+
on: (t, h) => protocol().events.on(t, h),
|
|
28
|
+
last: (t) => protocol().events.last(t)
|
|
29
|
+
};
|
|
30
|
+
function scopedEvents() {
|
|
31
|
+
const offs = /* @__PURE__ */ new Set();
|
|
32
|
+
const track2 = (off) => {
|
|
33
|
+
const wrapped = () => (offs.delete(wrapped), off());
|
|
34
|
+
offs.add(wrapped);
|
|
35
|
+
return wrapped;
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
bus: {
|
|
39
|
+
emit: (t, p) => events.emit(t, p),
|
|
40
|
+
last: (t) => events.last(t),
|
|
41
|
+
on: (t, h) => track2(events.on(t, h))
|
|
42
|
+
},
|
|
43
|
+
track: track2,
|
|
44
|
+
dispose() {
|
|
45
|
+
for (const off of [...offs]) off();
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/core/hooks.ts
|
|
51
|
+
var ctxHooks = {};
|
|
52
|
+
|
|
53
|
+
// src/core/navigate.ts
|
|
54
|
+
function navigate(url, options = {}) {
|
|
55
|
+
const target = new URL(url, location.href);
|
|
56
|
+
if (target.origin !== location.origin) {
|
|
57
|
+
location.assign(target.href);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (options.replace) history.replaceState(history.state, "", target.href);
|
|
61
|
+
else history.pushState(history.state, "", target.href);
|
|
62
|
+
dispatchEvent(new PopStateEvent("popstate", { state: history.state }));
|
|
63
|
+
events.emit("vitral:navigate", target.pathname + target.search + target.hash);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/core/updates.ts
|
|
67
|
+
var versions = /* @__PURE__ */ new Map();
|
|
68
|
+
var live = /* @__PURE__ */ new Map();
|
|
69
|
+
function track(name, loaded) {
|
|
70
|
+
versions.set(name, loaded.entry);
|
|
71
|
+
mounted.set(name, loaded);
|
|
72
|
+
live.set(name, (live.get(name) ?? 0) + 1);
|
|
73
|
+
return () => {
|
|
74
|
+
const n = live.get(name) - 1;
|
|
75
|
+
if (n) live.set(name, n);
|
|
76
|
+
else live.delete(name), versions.delete(name), mounted.delete(name);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
var swaps = null;
|
|
80
|
+
async function refresh(name) {
|
|
81
|
+
const p = protocol();
|
|
82
|
+
await p.pending();
|
|
83
|
+
const entry = p.entry(name);
|
|
84
|
+
if (entry) p.register(name, entry);
|
|
85
|
+
await loadFile(name);
|
|
86
|
+
const started = swaps = [];
|
|
87
|
+
events.emit("vitral:refresh", name);
|
|
88
|
+
swaps = null;
|
|
89
|
+
await Promise.all(started);
|
|
90
|
+
}
|
|
91
|
+
function refreshable(current, name, props, remount) {
|
|
92
|
+
let gen = 0;
|
|
93
|
+
const off = events.on("vitral:refresh", (n) => {
|
|
94
|
+
if (n !== name && !name.startsWith(n + "/")) return;
|
|
95
|
+
const mine = ++gen;
|
|
96
|
+
const used = props;
|
|
97
|
+
const swap = remount(used).then((next) => {
|
|
98
|
+
if (current.unmount === noop || mine !== gen) return next.unmount();
|
|
99
|
+
const old = current;
|
|
100
|
+
current = next;
|
|
101
|
+
old.unmount();
|
|
102
|
+
if (props !== used) next.update?.(props);
|
|
103
|
+
});
|
|
104
|
+
if (swaps) swaps.push(swap);
|
|
105
|
+
else swap.catch(console.error);
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
update(next) {
|
|
109
|
+
props = next;
|
|
110
|
+
current.update?.(next);
|
|
111
|
+
},
|
|
112
|
+
unmount() {
|
|
113
|
+
off();
|
|
114
|
+
current.unmount();
|
|
115
|
+
current = { unmount: noop };
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
var noop = () => {
|
|
120
|
+
};
|
|
121
|
+
async function checkUpdates() {
|
|
122
|
+
const p = protocol();
|
|
123
|
+
const found = [];
|
|
124
|
+
const { splitName } = await import("./expose-JUOUN5N5.js");
|
|
125
|
+
const remotes = /* @__PURE__ */ new Map();
|
|
126
|
+
for (const name of live.keys()) {
|
|
127
|
+
const root = splitName(name)[0];
|
|
128
|
+
const entry = versions.get(root) ?? versions.get(name);
|
|
129
|
+
if (entry) remotes.set(root, entry);
|
|
130
|
+
}
|
|
131
|
+
for (const [name, entry] of remotes) versions.set(name, entry);
|
|
132
|
+
await Promise.all(
|
|
133
|
+
[...remotes].map(
|
|
134
|
+
([name, current]) => resolveEntry(name, p.entry(name)).then(({ entry }) => {
|
|
135
|
+
if (entry !== current) {
|
|
136
|
+
versions.set(name, entry);
|
|
137
|
+
found.push(name);
|
|
138
|
+
events.emit("vitral:update-available", { name, entry });
|
|
139
|
+
}
|
|
140
|
+
}, noop)
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
return found;
|
|
144
|
+
}
|
|
145
|
+
function watchUpdates() {
|
|
146
|
+
let busy = null;
|
|
147
|
+
const run = () => busy ??= checkUpdates().finally(() => busy = null);
|
|
148
|
+
const nav = globalThis.navigation;
|
|
149
|
+
addEventListener("popstate", run);
|
|
150
|
+
nav?.addEventListener("navigatesuccess", run);
|
|
151
|
+
return () => {
|
|
152
|
+
removeEventListener("popstate", run);
|
|
153
|
+
nav?.removeEventListener("navigatesuccess", run);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/core/mount.ts
|
|
158
|
+
async function mountRemote(target, name, props, options = {}) {
|
|
159
|
+
return refreshable(await mountOnce(target, name, props, options), name, props, (latest) => mountOnce(target, name, latest, options));
|
|
160
|
+
}
|
|
161
|
+
var frames;
|
|
162
|
+
function setFrameMounter(mounter) {
|
|
163
|
+
frames = mounter;
|
|
164
|
+
}
|
|
165
|
+
async function mountOnce(target, name, props, options) {
|
|
166
|
+
const p = protocol();
|
|
167
|
+
await p.pending();
|
|
168
|
+
if ((options.isolate ?? registered(name)?.isolate ?? p.settings().isolate) === "iframe") {
|
|
169
|
+
if (!frames) throw report(new RemoteError("MOUNT_FAILED", name, 'isolate="iframe" precisa de enableIframe(), de vitral/iframe'));
|
|
170
|
+
return frames(target, name, props, options).catch(fail);
|
|
171
|
+
}
|
|
172
|
+
const { module: mod, ...resolved } = await load(name, options.isolate, options.priority);
|
|
173
|
+
const untrack = track(name, resolved);
|
|
174
|
+
const isolate = options.isolate ?? resolved.isolate ?? protocol().settings().isolate;
|
|
175
|
+
const label = resolved.name ?? name;
|
|
176
|
+
let shadowRoot = null;
|
|
177
|
+
const el = document.createElement("div");
|
|
178
|
+
el.setAttribute("data-vitral-root", label);
|
|
179
|
+
if (resolved.scope) el.setAttribute("data-vitral-scope", resolved.scope);
|
|
180
|
+
el.style.display = "contents";
|
|
181
|
+
if (isolate === "shadow") {
|
|
182
|
+
shadowRoot = target.shadowRoot ?? target.attachShadow({ mode: "open" });
|
|
183
|
+
shadowRoot.appendChild(el);
|
|
184
|
+
} else {
|
|
185
|
+
target.appendChild(el);
|
|
186
|
+
}
|
|
187
|
+
let t = performance.now();
|
|
188
|
+
const [release, portal = document.body] = await injectStyles(resolved, shadowRoot, el, options.styles);
|
|
189
|
+
metric(name, "css", t);
|
|
190
|
+
t = performance.now();
|
|
191
|
+
const scoped = scopedEvents();
|
|
192
|
+
const on = (type) => (fn) => (el.addEventListener(type, fn), () => el.removeEventListener(type, fn));
|
|
193
|
+
const ctx = {
|
|
194
|
+
name: label,
|
|
195
|
+
baseUrl: new URL(".", resolved.entry).href,
|
|
196
|
+
events: scoped.bus,
|
|
197
|
+
shadowRoot,
|
|
198
|
+
portalContainer: portal,
|
|
199
|
+
reportError(e) {
|
|
200
|
+
const err = report(isRemoteError(e) ? e : new RemoteError("RENDER_FAILED", label, String(e?.message ?? e), e), resolved);
|
|
201
|
+
if (options.onError) options.onError(err);
|
|
202
|
+
else console.error(err);
|
|
203
|
+
},
|
|
204
|
+
navigate,
|
|
205
|
+
protocol: protocol().protocol,
|
|
206
|
+
onActivate: on("vitral:activate"),
|
|
207
|
+
onDeactivate: on("vitral:deactivate")
|
|
208
|
+
};
|
|
209
|
+
if (ctxHooks.shared) ctx.shared = ctxHooks.shared(name, scoped.track);
|
|
210
|
+
let mounted2;
|
|
211
|
+
try {
|
|
212
|
+
mounted2 = await mod.mount(el, props, ctx);
|
|
213
|
+
metric(name, "mount", t);
|
|
214
|
+
} catch (e) {
|
|
215
|
+
untrack();
|
|
216
|
+
scoped.dispose();
|
|
217
|
+
release();
|
|
218
|
+
el.remove();
|
|
219
|
+
throw report(new RemoteError("MOUNT_FAILED", label, "erro ao montar", e), resolved);
|
|
220
|
+
}
|
|
221
|
+
let alive = true;
|
|
222
|
+
return {
|
|
223
|
+
update(next) {
|
|
224
|
+
if (alive) mounted2.update?.(next);
|
|
225
|
+
},
|
|
226
|
+
unmount() {
|
|
227
|
+
if (!alive) return;
|
|
228
|
+
alive = false;
|
|
229
|
+
try {
|
|
230
|
+
mounted2.unmount();
|
|
231
|
+
} finally {
|
|
232
|
+
untrack();
|
|
233
|
+
scoped.dispose();
|
|
234
|
+
release();
|
|
235
|
+
el.remove();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function registered(name) {
|
|
241
|
+
const p = protocol();
|
|
242
|
+
let n = name;
|
|
243
|
+
while (n && !p.entry(n)) n = n.slice(0, Math.max(0, n.lastIndexOf("/")));
|
|
244
|
+
return n ? p.entry(n) : void 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/core/slot.ts
|
|
248
|
+
function createSlot(target, options) {
|
|
249
|
+
let { isolate } = options;
|
|
250
|
+
const key = (o) => o.src ? registerSrc(o.src, o.name) : o.name ?? "";
|
|
251
|
+
let name = key(options);
|
|
252
|
+
let props = options.props ?? {};
|
|
253
|
+
let handle2 = null;
|
|
254
|
+
let holder = null;
|
|
255
|
+
let token = 0;
|
|
256
|
+
let status = "loading";
|
|
257
|
+
const setStatus = (s, e = null) => {
|
|
258
|
+
status = s;
|
|
259
|
+
if (holder) holder.style.display = s === "error" ? "none" : "";
|
|
260
|
+
options.onStatus?.(s, e);
|
|
261
|
+
};
|
|
262
|
+
const teardown = () => {
|
|
263
|
+
handle2?.unmount();
|
|
264
|
+
handle2 = null;
|
|
265
|
+
holder?.remove();
|
|
266
|
+
holder = null;
|
|
267
|
+
};
|
|
268
|
+
const mount = () => {
|
|
269
|
+
const my = ++token;
|
|
270
|
+
teardown();
|
|
271
|
+
holder = document.createElement("div");
|
|
272
|
+
holder.setAttribute("data-vitral-slot", name);
|
|
273
|
+
target.appendChild(holder);
|
|
274
|
+
setStatus("loading");
|
|
275
|
+
const fail2 = (e) => {
|
|
276
|
+
if (my !== token) return;
|
|
277
|
+
setStatus("error", isRemoteError(e) ? e : new RemoteError("MOUNT_FAILED", name, String(e), e));
|
|
278
|
+
};
|
|
279
|
+
const initial = props;
|
|
280
|
+
mountRemote(holder, name, props, { isolate, priority: options.priority, styles: options.styles, onError: fail2 }).then((h) => {
|
|
281
|
+
if (my !== token) return h.unmount();
|
|
282
|
+
handle2 = h;
|
|
283
|
+
if (props !== initial) h.update?.(props);
|
|
284
|
+
setStatus("ready");
|
|
285
|
+
}, fail2);
|
|
286
|
+
};
|
|
287
|
+
mount();
|
|
288
|
+
return {
|
|
289
|
+
update(next) {
|
|
290
|
+
props = next;
|
|
291
|
+
handle2?.update?.(next);
|
|
292
|
+
},
|
|
293
|
+
set(next) {
|
|
294
|
+
const nextName = next.src || next.name !== void 0 ? key(next) : name;
|
|
295
|
+
const changed = nextName !== name || "isolate" in next && next.isolate !== isolate;
|
|
296
|
+
name = nextName;
|
|
297
|
+
if ("isolate" in next) isolate = next.isolate;
|
|
298
|
+
if (changed) mount();
|
|
299
|
+
},
|
|
300
|
+
retry: mount,
|
|
301
|
+
destroy() {
|
|
302
|
+
token++;
|
|
303
|
+
teardown();
|
|
304
|
+
},
|
|
305
|
+
get status() {
|
|
306
|
+
return status;
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/core/remote.ts
|
|
312
|
+
function defineRemote(remote) {
|
|
313
|
+
return remote;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// src/component.ts
|
|
317
|
+
var TEMPLATE = /* @__PURE__ */ Symbol("vitral.html");
|
|
318
|
+
function html(strings, ...values) {
|
|
319
|
+
return { [TEMPLATE]: true, strings, values };
|
|
320
|
+
}
|
|
321
|
+
function unsafeHTML(markup) {
|
|
322
|
+
return html(Object.assign([markup], { raw: [markup] }));
|
|
323
|
+
}
|
|
324
|
+
var isTemplate = (v) => typeof v === "object" && v !== null && TEMPLATE in v;
|
|
325
|
+
var escape = (s) => s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
326
|
+
var EVENT_ATTR = /\s+on([a-z][\w:-]*)=(["']?)$/i;
|
|
327
|
+
var HANDLER_PREFIX = "data-vitral-h";
|
|
328
|
+
function toMarkup(value, handlers) {
|
|
329
|
+
if (value == null || value === false) return "";
|
|
330
|
+
if (Array.isArray(value)) return value.map((v) => toMarkup(v, handlers)).join("");
|
|
331
|
+
if (!isTemplate(value)) return escape(String(value));
|
|
332
|
+
const strings = [...value.strings];
|
|
333
|
+
let out = "";
|
|
334
|
+
for (let i = 0; i < strings.length; i++) {
|
|
335
|
+
let s = strings[i];
|
|
336
|
+
if (i < value.values.length) {
|
|
337
|
+
const v = value.values[i];
|
|
338
|
+
const event = typeof v === "function" ? EVENT_ATTR.exec(s) : null;
|
|
339
|
+
if (event) {
|
|
340
|
+
s = s.slice(0, s.length - event[0].length) + ` ${HANDLER_PREFIX}${handlers.length}="${event[1].toLowerCase()}"`;
|
|
341
|
+
handlers.push(v);
|
|
342
|
+
if (event[2] && strings[i + 1]?.startsWith(event[2])) strings[i + 1] = strings[i + 1].slice(1);
|
|
343
|
+
out += s;
|
|
344
|
+
} else {
|
|
345
|
+
out += s + toMarkup(v, handlers);
|
|
346
|
+
}
|
|
347
|
+
} else {
|
|
348
|
+
out += s;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return out;
|
|
352
|
+
}
|
|
353
|
+
function render(view, el) {
|
|
354
|
+
if (typeof Node !== "undefined" && view instanceof Node) {
|
|
355
|
+
el.replaceChildren(view);
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
const handlers = [];
|
|
359
|
+
el.innerHTML = toMarkup(view, handlers);
|
|
360
|
+
if (!handlers.length) return;
|
|
361
|
+
for (const node of el.querySelectorAll("*")) {
|
|
362
|
+
for (const attr of [...node.attributes]) {
|
|
363
|
+
if (!attr.name.startsWith(HANDLER_PREFIX)) continue;
|
|
364
|
+
node.addEventListener(attr.value, handlers[Number(attr.name.slice(HANDLER_PREFIX.length))]);
|
|
365
|
+
node.removeAttribute(attr.name);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function component(options) {
|
|
370
|
+
const opts = typeof options === "function" ? { render: options } : options;
|
|
371
|
+
return defineRemote({
|
|
372
|
+
mount(el, props, ctx) {
|
|
373
|
+
let current = props;
|
|
374
|
+
let queued = false;
|
|
375
|
+
let alive = true;
|
|
376
|
+
const draw = () => {
|
|
377
|
+
queued = false;
|
|
378
|
+
if (alive) render(opts.render(current, state, ctx) ?? "", el);
|
|
379
|
+
};
|
|
380
|
+
const initial = typeof opts.state === "function" ? opts.state() : { ...opts.state ?? {} };
|
|
381
|
+
const state = new Proxy(initial, {
|
|
382
|
+
set(target, key, value) {
|
|
383
|
+
if (!Object.is(Reflect.get(target, key), value)) {
|
|
384
|
+
Reflect.set(target, key, value);
|
|
385
|
+
if (!queued) {
|
|
386
|
+
queued = true;
|
|
387
|
+
queueMicrotask(draw);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
draw();
|
|
394
|
+
const cleanup = opts.mounted?.(el, state, ctx);
|
|
395
|
+
return {
|
|
396
|
+
update(next) {
|
|
397
|
+
current = next;
|
|
398
|
+
draw();
|
|
399
|
+
},
|
|
400
|
+
unmount() {
|
|
401
|
+
alive = false;
|
|
402
|
+
cleanup?.();
|
|
403
|
+
el.replaceChildren();
|
|
404
|
+
}
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// src/core/store.ts
|
|
411
|
+
function createStore(seed = {}) {
|
|
412
|
+
const slots = /* @__PURE__ */ new Map();
|
|
413
|
+
const changed = /* @__PURE__ */ new Map();
|
|
414
|
+
let depth = 0;
|
|
415
|
+
const slot = (key) => {
|
|
416
|
+
let x = slots.get(key);
|
|
417
|
+
if (!x) slots.set(key, x = { s: /* @__PURE__ */ new Set() });
|
|
418
|
+
return x;
|
|
419
|
+
};
|
|
420
|
+
const flush = () => {
|
|
421
|
+
if (depth) return;
|
|
422
|
+
const list = [...changed];
|
|
423
|
+
changed.clear();
|
|
424
|
+
for (const [x, before] of list) {
|
|
425
|
+
if (Object.is(x.v, before)) continue;
|
|
426
|
+
for (const fn of [...x.s]) {
|
|
427
|
+
try {
|
|
428
|
+
fn(x.v);
|
|
429
|
+
} catch (e) {
|
|
430
|
+
console.error(e);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
const write = (x, value, by) => {
|
|
436
|
+
if ("v" in x && Object.is(x.v, value)) return;
|
|
437
|
+
if (!changed.has(x)) changed.set(x, x.v);
|
|
438
|
+
x.v = value;
|
|
439
|
+
x.b = by;
|
|
440
|
+
flush();
|
|
441
|
+
};
|
|
442
|
+
for (const key in seed) slots.set(key, { v: seed[key], s: /* @__PURE__ */ new Set(), d: true });
|
|
443
|
+
return {
|
|
444
|
+
get: (key) => slots.get(key)?.v,
|
|
445
|
+
set(key, value, token, by) {
|
|
446
|
+
const x = slot(key);
|
|
447
|
+
if (x.r && token !== x.t) return false;
|
|
448
|
+
write(x, value, by);
|
|
449
|
+
return true;
|
|
450
|
+
},
|
|
451
|
+
subscribe(key, fn) {
|
|
452
|
+
const subs = slot(key).s;
|
|
453
|
+
const f = (v) => fn(v);
|
|
454
|
+
subs.add(f);
|
|
455
|
+
return () => void subs.delete(f);
|
|
456
|
+
},
|
|
457
|
+
own(key, value, writable, by) {
|
|
458
|
+
const x = slot(key);
|
|
459
|
+
if (x.t) return;
|
|
460
|
+
if (!x.d) write(x, value, by);
|
|
461
|
+
x.d = false;
|
|
462
|
+
x.r = !writable;
|
|
463
|
+
x.o = by;
|
|
464
|
+
return x.t = {};
|
|
465
|
+
},
|
|
466
|
+
release(key, token) {
|
|
467
|
+
const x = slots.get(key);
|
|
468
|
+
if (x && x.t === token) x.t = x.r = x.o = void 0;
|
|
469
|
+
},
|
|
470
|
+
batch(fn) {
|
|
471
|
+
depth++;
|
|
472
|
+
try {
|
|
473
|
+
return fn();
|
|
474
|
+
} finally {
|
|
475
|
+
depth--;
|
|
476
|
+
flush();
|
|
477
|
+
}
|
|
478
|
+
},
|
|
479
|
+
list: () => [...slots].filter(([, x]) => "v" in x).map(([key, x]) => ({ key, value: x.v, writable: !x.r, owner: x.o, by: x.b, subscribers: x.s.size }))
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
function hydrate() {
|
|
483
|
+
try {
|
|
484
|
+
return JSON.parse(document.querySelector("script[data-vitral-shared]")?.textContent || "{}");
|
|
485
|
+
} catch (e) {
|
|
486
|
+
console.error(e);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
function pageStore() {
|
|
490
|
+
if (typeof document === "undefined") return createStore();
|
|
491
|
+
const p = protocol();
|
|
492
|
+
if (!p.shared) {
|
|
493
|
+
const store = createStore(hydrate());
|
|
494
|
+
p.shared = () => store;
|
|
495
|
+
}
|
|
496
|
+
return p.shared();
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// src/core/shared.ts
|
|
500
|
+
function isDev() {
|
|
501
|
+
try {
|
|
502
|
+
return process.env.NODE_ENV !== "production";
|
|
503
|
+
} catch {
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
function pageStore2() {
|
|
508
|
+
ctxHooks.shared ??= scopedShared;
|
|
509
|
+
return pageStore();
|
|
510
|
+
}
|
|
511
|
+
function handle(store, key, by, track2 = (off) => off, token) {
|
|
512
|
+
const get = () => store.get(key);
|
|
513
|
+
const set = (value) => {
|
|
514
|
+
if (store.set(key, value, token, by)) return;
|
|
515
|
+
const e = new RemoteError("SHARED_READONLY", by || "shared", `s\xF3 o dono altera "${key}"`);
|
|
516
|
+
if (isDev()) throw e;
|
|
517
|
+
console.warn(e.message);
|
|
518
|
+
};
|
|
519
|
+
return {
|
|
520
|
+
key,
|
|
521
|
+
get,
|
|
522
|
+
set,
|
|
523
|
+
update: (fn) => set(fn(get())),
|
|
524
|
+
subscribe(fn) {
|
|
525
|
+
fn(get());
|
|
526
|
+
return track2(store.subscribe(key, fn));
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function own(key, value, options = {}, by, track2) {
|
|
531
|
+
const store = pageStore2();
|
|
532
|
+
const token = store.own(key, value, options.writable !== false, by);
|
|
533
|
+
if (token) track2?.(() => store.release(key, token));
|
|
534
|
+
return handle(store, key, by, track2, token);
|
|
535
|
+
}
|
|
536
|
+
function shared(key) {
|
|
537
|
+
return handle(pageStore2(), key);
|
|
538
|
+
}
|
|
539
|
+
function provide(key, value, options) {
|
|
540
|
+
return own(key, value, options);
|
|
541
|
+
}
|
|
542
|
+
function batch(fn) {
|
|
543
|
+
return pageStore2().batch(fn);
|
|
544
|
+
}
|
|
545
|
+
function scopedShared(by, track2) {
|
|
546
|
+
const api = ((key) => handle(pageStore2(), key, by, track2));
|
|
547
|
+
api.provide = (key, value, options) => own(key, value, options, by, track2);
|
|
548
|
+
api.batch = batch;
|
|
549
|
+
return api;
|
|
550
|
+
}
|
|
551
|
+
function memoSelect() {
|
|
552
|
+
let last;
|
|
553
|
+
return (value, select) => {
|
|
554
|
+
if (!last || !Object.is(last[0], value) || last[1] !== select) {
|
|
555
|
+
const out = select(value);
|
|
556
|
+
last = [value, select, last && Object.is(last[2], out) ? last[2] : out];
|
|
557
|
+
}
|
|
558
|
+
return last[2];
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
var same = (value) => value;
|
|
562
|
+
|
|
563
|
+
// src/core/persist.ts
|
|
564
|
+
function persist(value, options = {}) {
|
|
565
|
+
const key = `vitral:${value.key}:${options.version ?? 1}`;
|
|
566
|
+
let storage;
|
|
567
|
+
try {
|
|
568
|
+
storage = options.storage === "session" ? sessionStorage : localStorage;
|
|
569
|
+
const saved = storage.getItem(key);
|
|
570
|
+
if (saved !== null) value.set(JSON.parse(saved));
|
|
571
|
+
} catch {
|
|
572
|
+
return value;
|
|
573
|
+
}
|
|
574
|
+
value.subscribe((v) => {
|
|
575
|
+
try {
|
|
576
|
+
storage.setItem(key, JSON.stringify(v));
|
|
577
|
+
} catch (e) {
|
|
578
|
+
console.warn(`[vitral] n\xE3o foi poss\xEDvel guardar "${value.key}"`, e);
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
return value;
|
|
582
|
+
}
|
|
583
|
+
function syncTabs(value) {
|
|
584
|
+
if (typeof BroadcastChannel === "undefined") return value;
|
|
585
|
+
const channel = new BroadcastChannel(`vitral:${value.key}`);
|
|
586
|
+
let receiving = false;
|
|
587
|
+
let first = true;
|
|
588
|
+
channel.onmessage = (e) => {
|
|
589
|
+
receiving = true;
|
|
590
|
+
try {
|
|
591
|
+
value.set(e.data);
|
|
592
|
+
} finally {
|
|
593
|
+
receiving = false;
|
|
594
|
+
}
|
|
595
|
+
};
|
|
596
|
+
value.subscribe((v) => {
|
|
597
|
+
if (first) return void (first = false);
|
|
598
|
+
if (receiving) return;
|
|
599
|
+
try {
|
|
600
|
+
channel.postMessage(v);
|
|
601
|
+
} catch (e) {
|
|
602
|
+
console.warn(`[vitral] "${value.key}" n\xE3o pode ser enviado a outras abas`, e);
|
|
603
|
+
}
|
|
604
|
+
});
|
|
605
|
+
return value;
|
|
606
|
+
}
|
|
607
|
+
function serializeShared(values) {
|
|
608
|
+
return JSON.stringify(values).replace(/</g, "\\u003c");
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
export {
|
|
612
|
+
events,
|
|
613
|
+
navigate,
|
|
614
|
+
track,
|
|
615
|
+
refresh,
|
|
616
|
+
checkUpdates,
|
|
617
|
+
watchUpdates,
|
|
618
|
+
mountRemote,
|
|
619
|
+
setFrameMounter,
|
|
620
|
+
createSlot,
|
|
621
|
+
defineRemote,
|
|
622
|
+
html,
|
|
623
|
+
unsafeHTML,
|
|
624
|
+
render,
|
|
625
|
+
component,
|
|
626
|
+
shared,
|
|
627
|
+
provide,
|
|
628
|
+
batch,
|
|
629
|
+
memoSelect,
|
|
630
|
+
same,
|
|
631
|
+
persist,
|
|
632
|
+
syncTabs,
|
|
633
|
+
serializeShared
|
|
634
|
+
};
|