@manyducks.co/dolla 2.0.0-alpha.48 → 2.0.0-alpha.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +52 -52
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
var
|
|
1
|
+
var zt = Object.defineProperty;
|
|
2
2
|
var St = (i) => {
|
|
3
3
|
throw TypeError(i);
|
|
4
4
|
};
|
|
5
|
-
var
|
|
6
|
-
var g = (i, t, e) =>
|
|
5
|
+
var Bt = (i, t, e) => t in i ? zt(i, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : i[t] = e;
|
|
6
|
+
var g = (i, t, e) => Bt(i, typeof t != "symbol" ? t + "" : t, e), gt = (i, t, e) => t.has(i) || St("Cannot " + e);
|
|
7
7
|
var a = (i, t, e) => (gt(i, t, "read from private field"), e ? e.call(i) : t.get(i)), f = (i, t, e) => t.has(i) ? St("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(i) : t.set(i, e), p = (i, t, e, s) => (gt(i, t, "write to private field"), s ? s.call(i, e) : t.set(i, e), e), d = (i, t, e) => (gt(i, t, "access private method"), e);
|
|
8
8
|
var _t = (i, t, e, s) => ({
|
|
9
9
|
set _(n) {
|
|
@@ -13,17 +13,17 @@ var _t = (i, t, e, s) => ({
|
|
|
13
13
|
return a(i, t, s);
|
|
14
14
|
}
|
|
15
15
|
});
|
|
16
|
-
import { a as
|
|
16
|
+
import { a as Kt, b as Ft, i as H, I as Ot, $ as R, c as Jt, p as Mt, d as Xt, e as D, f as q, s as xt, g as Yt, t as Pt, h as ht, m as M, w as Zt, j as Tt, S as te, k as qt, l as Lt, V as ee, n as se, o as re, q as ne, r as ie } from "./markup-D67RWnAp.js";
|
|
17
17
|
import { u as Ce, x as Ve, y as De, v as Ae, z as We } from "./markup-D67RWnAp.js";
|
|
18
|
-
function
|
|
18
|
+
function Nt(i, t) {
|
|
19
19
|
return t.outlet();
|
|
20
20
|
}
|
|
21
21
|
function K(i) {
|
|
22
|
-
return
|
|
22
|
+
return Ft(i, "Expected `path` to be a string. Got type: %t, value: %v"), i.split("/").map((t) => t.trim()).filter((t) => t !== "");
|
|
23
23
|
}
|
|
24
24
|
function z(i) {
|
|
25
25
|
var e;
|
|
26
|
-
|
|
26
|
+
Kt(
|
|
27
27
|
(s) => H(s == null ? void 0 : s.toString),
|
|
28
28
|
i,
|
|
29
29
|
"Expected `parts` to be an array of objects with a .toString() method. Got type: %t, value: %v"
|
|
@@ -37,7 +37,7 @@ function z(i) {
|
|
|
37
37
|
return t ?? "";
|
|
38
38
|
}
|
|
39
39
|
function ut(i, t) {
|
|
40
|
-
if (
|
|
40
|
+
if (Ft(i, "Expected `base` to be a string. Got type: %t, value: %v"), t == null && (t = i, i = ""), t.startsWith("/"))
|
|
41
41
|
return t;
|
|
42
42
|
let e = i;
|
|
43
43
|
for (; ; )
|
|
@@ -61,7 +61,7 @@ function ae(i) {
|
|
|
61
61
|
);
|
|
62
62
|
return Object.fromEntries(t);
|
|
63
63
|
}
|
|
64
|
-
function
|
|
64
|
+
function Ut(i, t, e = {}) {
|
|
65
65
|
var o;
|
|
66
66
|
const [s, n] = t.split("?"), r = K(s);
|
|
67
67
|
t: for (const c of i) {
|
|
@@ -174,21 +174,21 @@ function fe(i, t) {
|
|
|
174
174
|
function Le(i) {
|
|
175
175
|
return new pe(i);
|
|
176
176
|
}
|
|
177
|
-
const
|
|
177
|
+
const It = Symbol.for("DollaRouterMountMethod"), Ct = Symbol.for("DollaRouterUnmountMethod");
|
|
178
178
|
function yt(i) {
|
|
179
|
-
return (i == null ? void 0 : i[
|
|
179
|
+
return (i == null ? void 0 : i[Ot]) === !0;
|
|
180
180
|
}
|
|
181
181
|
async function de(i, t) {
|
|
182
|
-
return i[
|
|
182
|
+
return i[It](t);
|
|
183
183
|
}
|
|
184
184
|
async function me(i) {
|
|
185
|
-
return i[
|
|
185
|
+
return i[Ct]();
|
|
186
186
|
}
|
|
187
|
-
var
|
|
187
|
+
var jt, J, P, ft, L, U, X, T, I, S, w, Vt, Dt, At, B, Wt, bt, vt;
|
|
188
188
|
class pe {
|
|
189
189
|
constructor(t) {
|
|
190
190
|
f(this, w);
|
|
191
|
-
g(this,
|
|
191
|
+
g(this, jt, !0);
|
|
192
192
|
f(this, J);
|
|
193
193
|
f(this, P);
|
|
194
194
|
f(this, ft, 0);
|
|
@@ -225,15 +225,15 @@ class pe {
|
|
|
225
225
|
g(this, "params", R(() => {
|
|
226
226
|
var t;
|
|
227
227
|
return ((t = a(this, S).call(this)) == null ? void 0 : t.params) ?? {};
|
|
228
|
-
}, { equals:
|
|
228
|
+
}, { equals: xt }));
|
|
229
229
|
/**
|
|
230
230
|
* The current query params. Changes to this object will be reflected in the URL.
|
|
231
231
|
*/
|
|
232
232
|
g(this, "query", R(() => {
|
|
233
233
|
var t;
|
|
234
234
|
return ((t = a(this, S).call(this)) == null ? void 0 : t.query) ?? {};
|
|
235
|
-
}, { equals:
|
|
236
|
-
|
|
235
|
+
}, { equals: xt }));
|
|
236
|
+
Jt(t, "Options must be an object. Got: %t"), t.hash && p(this, T, !0), p(this, U, oe(
|
|
237
237
|
t.routes.flatMap((e) => d(this, w, vt).call(this, e)).map((e) => ({
|
|
238
238
|
pattern: e.pattern,
|
|
239
239
|
meta: e.meta,
|
|
@@ -241,7 +241,7 @@ class pe {
|
|
|
241
241
|
}))
|
|
242
242
|
)), console.log({ routes: t.routes, prepared: a(this, U) }), we(a(this, U));
|
|
243
243
|
}
|
|
244
|
-
async [(
|
|
244
|
+
async [(jt = Ot, It)](t) {
|
|
245
245
|
p(this, J, t), p(this, P, t.createLogger("Dolla.router"));
|
|
246
246
|
const e = () => {
|
|
247
247
|
d(this, w, B).call(this, void 0, {});
|
|
@@ -259,7 +259,7 @@ class pe {
|
|
|
259
259
|
})
|
|
260
260
|
), a(this, P).info("will intercept clicks on <a> tags within root element", s), p(this, X, !0), await d(this, w, B).call(this, void 0, {});
|
|
261
261
|
}
|
|
262
|
-
async [
|
|
262
|
+
async [Ct]() {
|
|
263
263
|
for (const t of a(this, I))
|
|
264
264
|
t();
|
|
265
265
|
p(this, I, []);
|
|
@@ -285,13 +285,13 @@ class pe {
|
|
|
285
285
|
*/
|
|
286
286
|
go(t, e = {}) {
|
|
287
287
|
let s;
|
|
288
|
-
Array.isArray(t) ? s = z(t) : s = t.toString(), s = ut(window.location.pathname, s), e.replace ? d(this, w,
|
|
288
|
+
Array.isArray(t) ? s = z(t) : s = t.toString(), s = ut(window.location.pathname, s), e.replace ? d(this, w, Dt).call(this, s, e) : d(this, w, Vt).call(this, s, e);
|
|
289
289
|
}
|
|
290
290
|
/**
|
|
291
291
|
* Updates query params, keeping existing ones and applying new ones. Removes the query param if value is set to `null`.
|
|
292
292
|
*/
|
|
293
293
|
updateQuery(t) {
|
|
294
|
-
const e = a(this, S)
|
|
294
|
+
const e = Mt(a(this, S)), s = { ...this.query() };
|
|
295
295
|
for (const o in t) {
|
|
296
296
|
const c = t[o];
|
|
297
297
|
c === null ? delete s[o] : s[o] = c.toString();
|
|
@@ -303,17 +303,17 @@ class pe {
|
|
|
303
303
|
a(this, S).call(this, { ...e, query: s }), window.history.replaceState(null, "", a(this, T) ? "/#" + e.path + r : e.path + r);
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
|
-
J = new WeakMap(), P = new WeakMap(), ft = new WeakMap(), L = new WeakMap(), U = new WeakMap(), X = new WeakMap(), T = new WeakMap(), I = new WeakMap(), S = new WeakMap(), w = new WeakSet(),
|
|
306
|
+
J = new WeakMap(), P = new WeakMap(), ft = new WeakMap(), L = new WeakMap(), U = new WeakMap(), X = new WeakMap(), T = new WeakMap(), I = new WeakMap(), S = new WeakMap(), w = new WeakSet(), Vt = function(t, e) {
|
|
307
307
|
var s;
|
|
308
308
|
(s = a(this, P)) == null || s.info("(push)", t), window.history.pushState(null, "", a(this, T) ? "/#" + t : t), d(this, w, B).call(this, t, e);
|
|
309
|
-
},
|
|
309
|
+
}, Dt = function(t, e) {
|
|
310
310
|
var s;
|
|
311
311
|
(s = a(this, P)) == null || s.info("(replace)", t), window.history.replaceState(null, "", a(this, T) ? "/#" + t : t), d(this, w, B).call(this, t, e);
|
|
312
|
-
},
|
|
312
|
+
}, At = function() {
|
|
313
313
|
return a(this, T) ? new URL(window.location.hash.slice(1), window.location.origin) : new URL(window.location.pathname, window.location.origin);
|
|
314
314
|
}, B = async function(t, e) {
|
|
315
315
|
var l;
|
|
316
|
-
const s = a(this, P), n = (l = a(this, J)) == null ? void 0 : l.getRootView(), r = t ? new URL(t, window.location.origin) : d(this, w,
|
|
316
|
+
const s = a(this, P), n = (l = a(this, J)) == null ? void 0 : l.getRootView(), r = t ? new URL(t, window.location.origin) : d(this, w, At).call(this), { match: o, journey: c } = await d(this, w, bt).call(this, r);
|
|
317
317
|
for (const u of c)
|
|
318
318
|
switch (u.kind) {
|
|
319
319
|
case "match":
|
|
@@ -327,7 +327,7 @@ J = new WeakMap(), P = new WeakMap(), ft = new WeakMap(), L = new WeakMap(), U =
|
|
|
327
327
|
break;
|
|
328
328
|
}
|
|
329
329
|
if (o) {
|
|
330
|
-
const u =
|
|
330
|
+
const u = Mt(this.pattern);
|
|
331
331
|
let m = o.query, y = [];
|
|
332
332
|
if (e.preserveQuery === !0)
|
|
333
333
|
m = Object.assign({}, this.query(), o.query);
|
|
@@ -340,14 +340,14 @@ J = new WeakMap(), P = new WeakMap(), ft = new WeakMap(), L = new WeakMap(), U =
|
|
|
340
340
|
for (const k in m)
|
|
341
341
|
y.push(`${k}=${m[k]}`);
|
|
342
342
|
const h = y.length > 0 ? "?" + y.join("&") : "";
|
|
343
|
-
a(this, S).call(this, { ...o, query: m }), n && (o.path !== location.pathname || location.search !== h) && window.history.replaceState(null, "", a(this, T) ? "/#" + o.path + h : o.path + h), n && o.pattern !== u && d(this, w,
|
|
343
|
+
a(this, S).call(this, { ...o, query: m }), n && (o.path !== location.pathname || location.search !== h) && window.history.replaceState(null, "", a(this, T) ? "/#" + o.path + h : o.path + h), n && o.pattern !== u && d(this, w, Wt).call(this, n, o);
|
|
344
344
|
} else
|
|
345
345
|
a(this, X) && s.crash(new ye(`Failed to match route '${r.pathname}'`));
|
|
346
346
|
return { match: o, journey: c };
|
|
347
347
|
}, /**
|
|
348
348
|
* Takes a matched route and mounts it.
|
|
349
349
|
*/
|
|
350
|
-
|
|
350
|
+
Wt = function(t, e) {
|
|
351
351
|
const s = e.meta.layers;
|
|
352
352
|
for (let n = 0; n < s.length; n++) {
|
|
353
353
|
const r = s[n], o = a(this, L)[n];
|
|
@@ -360,7 +360,7 @@ At = function(t, e) {
|
|
|
360
360
|
}, bt = async function(t, e = []) {
|
|
361
361
|
return new Promise((s, n) => {
|
|
362
362
|
var l;
|
|
363
|
-
const r =
|
|
363
|
+
const r = Ut(a(this, U), t.pathname);
|
|
364
364
|
if (!r)
|
|
365
365
|
return s({
|
|
366
366
|
match: null,
|
|
@@ -442,7 +442,7 @@ vt = function(t, e = [], s = []) {
|
|
|
442
442
|
}
|
|
443
443
|
}), r;
|
|
444
444
|
}
|
|
445
|
-
let o =
|
|
445
|
+
let o = Nt;
|
|
446
446
|
if (H(t.view))
|
|
447
447
|
o = t.view;
|
|
448
448
|
else if (t.view)
|
|
@@ -467,7 +467,7 @@ function we(i) {
|
|
|
467
467
|
if (t.meta.redirect) {
|
|
468
468
|
let e;
|
|
469
469
|
if (!H(t.meta.redirect)) if (q(t.meta.redirect)) {
|
|
470
|
-
if (e = t.meta.redirect, !
|
|
470
|
+
if (e = t.meta.redirect, !Ut(i, e, {
|
|
471
471
|
willMatch(n) {
|
|
472
472
|
return n !== t;
|
|
473
473
|
}
|
|
@@ -637,7 +637,7 @@ class $e {
|
|
|
637
637
|
};
|
|
638
638
|
}
|
|
639
639
|
}
|
|
640
|
-
var mt, W, A, kt,
|
|
640
|
+
var mt, W, A, kt, Gt;
|
|
641
641
|
class Re {
|
|
642
642
|
constructor(t, e) {
|
|
643
643
|
f(this, A);
|
|
@@ -688,20 +688,20 @@ class Re {
|
|
|
688
688
|
mt = new WeakMap(), W = new WeakMap(), A = new WeakSet(), kt = function(t, e = []) {
|
|
689
689
|
const s = [];
|
|
690
690
|
for (const n in t)
|
|
691
|
-
switch (
|
|
691
|
+
switch (Pt(t[n])) {
|
|
692
692
|
case "string":
|
|
693
|
-
s.push([[...e, n].join("."), d(this, A,
|
|
693
|
+
s.push([[...e, n].join("."), d(this, A, Gt).call(this, t[n])]);
|
|
694
694
|
break;
|
|
695
695
|
case "object":
|
|
696
696
|
s.push(...d(this, A, kt).call(this, t[n], [...e, n]));
|
|
697
697
|
break;
|
|
698
698
|
default:
|
|
699
699
|
throw new Error(
|
|
700
|
-
`Expected to find a string or object at ${[...e, n].join(".")}. Got: ${
|
|
700
|
+
`Expected to find a string or object at ${[...e, n].join(".")}. Got: ${Pt(t[n])}`
|
|
701
701
|
);
|
|
702
702
|
}
|
|
703
703
|
return s;
|
|
704
|
-
},
|
|
704
|
+
}, Gt = function(t) {
|
|
705
705
|
let e;
|
|
706
706
|
((h) => {
|
|
707
707
|
h[h.Static = 0] = "Static", h[h.ValueName = 1] = "ValueName", h[h.FormatName = 2] = "FormatName", h[h.FormatOptionName = 3] = "FormatOptionName", h[h.FormatOptionValue = 4] = "FormatOptionValue", h[h.FormatOptionEnd = 5] = "FormatOptionEnd";
|
|
@@ -750,7 +750,7 @@ mt = new WeakMap(), W = new WeakMap(), A = new WeakSet(), kt = function(t, e = [
|
|
|
750
750
|
}
|
|
751
751
|
return o === 0 && n.length > 0 && s.segments.push({ type: 0, text: n }), s;
|
|
752
752
|
};
|
|
753
|
-
var Y, j, b, Z, tt, et, _, v,
|
|
753
|
+
var Y, j, b, Z, tt, et, _, v, Ht, Et, $t, Rt, Qt;
|
|
754
754
|
class Se {
|
|
755
755
|
constructor(t) {
|
|
756
756
|
f(this, v);
|
|
@@ -760,7 +760,7 @@ class Se {
|
|
|
760
760
|
f(this, Z, []);
|
|
761
761
|
f(this, tt, /* @__PURE__ */ new Map());
|
|
762
762
|
f(this, et, "auto");
|
|
763
|
-
f(this, _, R(""));
|
|
763
|
+
f(this, _, R("en"));
|
|
764
764
|
g(this, "locale", R(a(this, _)));
|
|
765
765
|
p(this, Y, t), p(this, j, t.createLogger("Dolla.i18n")), this.addFormat("number", (e, s, n) => d(this, v, Et).call(this, Number(s), n)), this.addFormat("datetime", (e, s, n) => d(this, v, $t).call(this, s, n)), this.addFormat("list", (e, s, n) => d(this, v, Rt).call(this, s, n)), t.beforeMount(async () => {
|
|
766
766
|
a(this, b).size > 0 && await this.setLocale(a(this, et));
|
|
@@ -825,7 +825,7 @@ class Se {
|
|
|
825
825
|
const s = {};
|
|
826
826
|
for (const n in e)
|
|
827
827
|
s[n] = ht(e[n]);
|
|
828
|
-
return d(this, v,
|
|
828
|
+
return d(this, v, Ht).call(this, a(this, _).call(this), t, s);
|
|
829
829
|
});
|
|
830
830
|
}
|
|
831
831
|
/**
|
|
@@ -887,9 +887,9 @@ class Se {
|
|
|
887
887
|
return R(() => d(this, v, Rt).call(this, ht(t), e));
|
|
888
888
|
}
|
|
889
889
|
}
|
|
890
|
-
Y = new WeakMap(), j = new WeakMap(), b = new WeakMap(), Z = new WeakMap(), tt = new WeakMap(), et = new WeakMap(), _ = new WeakMap(), v = new WeakSet(),
|
|
890
|
+
Y = new WeakMap(), j = new WeakMap(), b = new WeakMap(), Z = new WeakMap(), tt = new WeakMap(), et = new WeakMap(), _ = new WeakMap(), v = new WeakSet(), Ht = function(t, e, s) {
|
|
891
891
|
var l;
|
|
892
|
-
const n = d(this, v,
|
|
892
|
+
const n = d(this, v, Qt).call(this, e, s);
|
|
893
893
|
if (n) return n;
|
|
894
894
|
const r = a(this, b).get(t);
|
|
895
895
|
if (s.context != null && (e += "_" + s.context), s.count != null)
|
|
@@ -930,7 +930,7 @@ Y = new WeakMap(), j = new WeakMap(), b = new WeakMap(), Z = new WeakMap(), tt =
|
|
|
930
930
|
return new Intl.ListFormat(a(this, _).call(this), e).format(t);
|
|
931
931
|
}, // relativeTime(): State<string> {
|
|
932
932
|
// }
|
|
933
|
-
|
|
933
|
+
Qt = function(t, e) {
|
|
934
934
|
for (const s of a(this, Z))
|
|
935
935
|
if (s[0] === t && Yt(s[1], e))
|
|
936
936
|
return s[2];
|
|
@@ -1023,7 +1023,7 @@ class xe {
|
|
|
1023
1023
|
warn: "development",
|
|
1024
1024
|
error: !0
|
|
1025
1025
|
});
|
|
1026
|
-
f(this, ct,
|
|
1026
|
+
f(this, ct, Tt("*,-Dolla.*"));
|
|
1027
1027
|
// Registration functions for modules.
|
|
1028
1028
|
// All modules will be registered before mount.
|
|
1029
1029
|
f(this, pt, []);
|
|
@@ -1084,21 +1084,21 @@ class xe {
|
|
|
1084
1084
|
if (H(t)) {
|
|
1085
1085
|
const e = a(this, N).stores.get(t);
|
|
1086
1086
|
if (e == null)
|
|
1087
|
-
throw new
|
|
1087
|
+
throw new qt("Store not found on this context.");
|
|
1088
1088
|
return e.value;
|
|
1089
1089
|
} else
|
|
1090
|
-
throw new
|
|
1090
|
+
throw new qt("Invalid store.");
|
|
1091
1091
|
}
|
|
1092
1092
|
async mount(t, e) {
|
|
1093
1093
|
if (a(this, F))
|
|
1094
1094
|
throw new Error("Dolla is already mounted.");
|
|
1095
1095
|
if (q(t)) {
|
|
1096
1096
|
const r = document.querySelector(t);
|
|
1097
|
-
|
|
1097
|
+
Lt(HTMLElement, r, `Selector '${t}' did not match any element.`), p(this, O, r);
|
|
1098
1098
|
} else
|
|
1099
|
-
|
|
1099
|
+
Lt(HTMLElement, t, "Expected an HTML element or a selector string. Got type: %t, value: %v"), p(this, O, t);
|
|
1100
1100
|
yt(e) && p(this, G, e);
|
|
1101
|
-
const s = yt(e) ?
|
|
1101
|
+
const s = yt(e) ? Nt : e, n = M(s);
|
|
1102
1102
|
p(this, V, this.constructView(n.type, n.props)), await Promise.all(a(this, pt).map((r) => r())), await Promise.all(a(this, nt).map((r) => r()));
|
|
1103
1103
|
for (const r of a(this, N).stores.values())
|
|
1104
1104
|
r.handleMount();
|
|
@@ -1150,7 +1150,7 @@ class xe {
|
|
|
1150
1150
|
}
|
|
1151
1151
|
}
|
|
1152
1152
|
setLogFilter(t) {
|
|
1153
|
-
p(this, ct,
|
|
1153
|
+
p(this, ct, Tt(t));
|
|
1154
1154
|
}
|
|
1155
1155
|
createLogger(t, e) {
|
|
1156
1156
|
const s = (e == null ? void 0 : e.console) ?? Pe(), n = this, r = a(this, lt), o = (c) => {
|
|
@@ -1225,10 +1225,10 @@ export {
|
|
|
1225
1225
|
Oe as http,
|
|
1226
1226
|
Fe as i18n,
|
|
1227
1227
|
M as markup,
|
|
1228
|
-
|
|
1228
|
+
Mt as peek,
|
|
1229
1229
|
Ve as portal,
|
|
1230
1230
|
De as repeat,
|
|
1231
|
-
|
|
1231
|
+
xt as shallowEqual,
|
|
1232
1232
|
Ae as strictEqual,
|
|
1233
1233
|
je as t,
|
|
1234
1234
|
We as unless,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/core/views/passthrough.ts","../src/router/router.utils.ts","../src/router/index.ts","../src/http/index.ts","../src/translate/index.ts","../src/core/views/default-crash-view.ts","../src/core/dolla.ts","../src/index.ts"],"sourcesContent":["import { type ViewContext } from \"../nodes/view.js\";\n\n/**\n * A utility view that simply displays a route.\n */\nexport function Passthrough(_: {}, ctx: ViewContext) {\n return ctx.outlet();\n}\n","import { assertString, assertArrayOf, isFunction } from \"../typeChecking.js\";\n\nexport type RouteMatch<T = Record<string, any>> = {\n /**\n * The path string that triggered this match.\n */\n path: string;\n\n /**\n * The pattern satisfied by `path`.\n */\n pattern: string;\n\n /**\n * Named params as parsed from `path`.\n */\n params: Record<string, string>;\n\n /**\n * Query params as parsed from `path`.\n */\n query: Record<string, string>;\n\n /**\n * Metadata registered to this route.\n */\n meta: T;\n};\n\nexport enum FragTypes {\n Literal = 1,\n Param = 2,\n Wildcard = 3,\n NumericParam = 4,\n}\n\nexport type RouteFragment = {\n name: string;\n type: FragTypes;\n value: string | number | null;\n};\n\nexport type ParsedRoute<T> = {\n pattern: string;\n fragments: RouteFragment[];\n meta: T;\n};\n\nexport type RouteMatchOptions<T> = {\n willMatch?: (route: ParsedRoute<T>) => boolean;\n};\n\n/**\n * Separates a URL path into multiple fragments.\n *\n * @param path - A path string (e.g. `\"/api/users/5\"`)\n * @returns an array of fragments (e.g. `[\"api\", \"users\", \"5\"]`)\n */\nexport function splitPath(path: string): string[] {\n assertString(path, \"Expected `path` to be a string. Got type: %t, value: %v\");\n\n return path\n .split(\"/\")\n .map((f) => f.trim())\n .filter((f) => f !== \"\");\n}\n\n/**\n * Joins multiple URL path fragments into a single string.\n *\n * @param parts - One or more URL fragments (e.g. `[\"api\", \"users\", 5]`)\n * @returns a joined path (e.g. `\"api/users/5\"`)\n */\nexport function joinPath(parts: { toString(): string }[]): string {\n assertArrayOf(\n (part) => isFunction(part?.toString),\n parts,\n \"Expected `parts` to be an array of objects with a .toString() method. Got type: %t, value: %v\",\n );\n\n parts = parts.filter((x) => x).flatMap(String);\n\n let joined = parts.shift()?.toString();\n\n if (joined) {\n for (const part of parts.map((p) => p.toString())) {\n if (part.startsWith(\".\")) {\n // Resolve relative path against joined\n joined = resolvePath(joined, part);\n } else if (joined[joined.length - 1] !== \"/\") {\n if (part[0] !== \"/\") {\n joined += \"/\" + part;\n } else {\n joined += part;\n }\n } else {\n if (part[0] === \"/\") {\n joined += part.slice(1);\n } else {\n joined += part;\n }\n }\n }\n\n // Remove trailing slash (unless path is just '/')\n if (joined && joined !== \"/\" && joined.endsWith(\"/\")) {\n joined = joined.slice(0, joined.length - 1);\n }\n }\n\n return joined ?? \"\";\n}\n\nexport function resolvePath(base: string, part: string | null) {\n assertString(base, \"Expected `base` to be a string. Got type: %t, value: %v\");\n\n if (part == null) {\n part = base;\n base = \"\";\n }\n\n if (part.startsWith(\"/\")) {\n return part;\n }\n\n let resolved = base;\n\n while (true) {\n if (part.startsWith(\"..\")) {\n for (let i = resolved.length; i > 0; --i) {\n if (resolved[i] === \"/\" || i === 0) {\n resolved = resolved.slice(0, i);\n part = part.replace(/^\\.\\.\\/?/, \"\");\n break;\n }\n }\n } else if (part.startsWith(\".\")) {\n part = part.replace(/^\\.\\/?/, \"\");\n } else {\n break;\n }\n }\n\n return joinPath([resolved, part]);\n}\n\nexport function parseQueryParams(query: string): Record<string, string> {\n if (!query) return {};\n\n if (query.startsWith(\"?\")) {\n query = query.slice(1);\n }\n\n const entries = query\n .split(\"&\")\n .filter((x) => x.trim() !== \"\")\n .map((entry) =>\n entry\n .split(\"=\")\n .map((x) => x.trim())\n .slice(0, 2),\n );\n\n return Object.fromEntries(entries);\n}\n\n/**\n * Returns the nearest match, or undefined if the path matches no route.\n *\n * @param url - Path to match against routes.\n * @param options - Options to customize how matching operates.\n */\nexport function matchRoutes<T>(\n routes: ParsedRoute<T>[],\n url: string,\n options: RouteMatchOptions<T> = {},\n): RouteMatch<T> | undefined {\n const [path, query] = url.split(\"?\");\n const parts = splitPath(path);\n\n routes: for (const route of routes) {\n const { fragments } = route;\n const hasWildcard = fragments[fragments.length - 1]?.type === FragTypes.Wildcard;\n\n if (!hasWildcard && fragments.length !== parts.length) {\n continue routes;\n }\n\n if (options.willMatch && !options.willMatch(route)) {\n continue routes;\n }\n\n const matched: RouteFragment[] = [];\n\n fragments: for (let i = 0; i < fragments.length; i++) {\n const part = parts[i];\n const frag = fragments[i];\n\n if (part == null && frag.type !== FragTypes.Wildcard) {\n continue routes;\n }\n\n switch (frag.type) {\n case FragTypes.Literal:\n if (frag.name.toLowerCase() === part.toLowerCase()) {\n matched.push(frag);\n break;\n } else {\n continue routes;\n }\n case FragTypes.Param:\n matched.push({ ...frag, value: part });\n break;\n case FragTypes.Wildcard:\n matched.push({ ...frag, value: parts.slice(i).join(\"/\") });\n break fragments;\n case FragTypes.NumericParam:\n if (!isNaN(Number(part))) {\n matched.push({ ...frag, value: part });\n break;\n } else {\n continue routes;\n }\n default:\n throw new Error(`Unknown fragment type: ${frag.type}`);\n }\n }\n\n const params: Record<string, string> = {};\n\n for (const frag of matched) {\n if (frag.type === FragTypes.Param) {\n params[frag.name] = decodeURIComponent(frag.value as string);\n }\n\n if (frag.type === FragTypes.NumericParam) {\n params[frag.name] = String(frag.value);\n }\n\n if (frag.type === FragTypes.Wildcard) {\n params.wildcard = \"/\" + decodeURIComponent(frag.value as string);\n }\n }\n\n return {\n path: \"/\" + matched.map((f) => f.value).join(\"/\"),\n pattern:\n \"/\" +\n fragments\n .map((f) => {\n if (f.type === FragTypes.Param) {\n return `{${f.name}}`;\n }\n\n if (f.type === FragTypes.NumericParam) {\n return `{#${f.name}}`;\n }\n\n return f.name;\n })\n .join(\"/\"),\n params,\n query: parseQueryParams(query),\n meta: route.meta,\n };\n }\n}\n\n/**\n * Sort routes descending by specificity. Guarantees that the most specific route matches first\n * no matter the order in which they were added.\n *\n * Routes without named params and routes with more fragments are weighted more heavily.\n */\nexport function sortRoutes<T>(routes: ParsedRoute<T>[]): ParsedRoute<T>[] {\n const withoutParams = [];\n const withNumericParams = [];\n const withParams = [];\n const wildcard = [];\n\n for (const route of routes) {\n const { fragments } = route;\n\n if (fragments.some((f) => f.type === FragTypes.Wildcard)) {\n wildcard.push(route);\n } else if (fragments.some((f) => f.type === FragTypes.NumericParam)) {\n withNumericParams.push(route);\n } else if (fragments.some((f) => f.type === FragTypes.Param)) {\n withParams.push(route);\n } else {\n withoutParams.push(route);\n }\n }\n\n const bySizeDesc = (a: ParsedRoute<T>, b: ParsedRoute<T>) => {\n if (a.fragments.length > b.fragments.length) {\n return -1;\n } else {\n return 1;\n }\n };\n\n withoutParams.sort(bySizeDesc);\n withNumericParams.sort(bySizeDesc);\n withParams.sort(bySizeDesc);\n wildcard.sort(bySizeDesc);\n\n return [...withoutParams, ...withNumericParams, ...withParams, ...wildcard];\n}\n\n/**\n * Converts a route pattern into a set of matchable fragments.\n *\n * @param route - A route string (e.g. \"/api/users/{id}\")\n */\nexport function patternToFragments(pattern: string): RouteFragment[] {\n const parts = splitPath(pattern);\n const fragments = [];\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n\n if (part === \"*\") {\n if (i !== parts.length - 1) {\n throw new Error(`Wildcard must be at the end of a pattern. Received: ${pattern}`);\n }\n fragments.push({\n type: FragTypes.Wildcard,\n name: \"*\",\n value: null,\n });\n } else if (part.at(0) === \"{\" && part.at(-1) === \"}\") {\n fragments.push({\n type: part[1] === \"#\" ? FragTypes.NumericParam : FragTypes.Param,\n name: part[1] === \"#\" ? part.slice(2, -1) : part.slice(1, -1),\n value: null,\n });\n } else {\n fragments.push({\n type: FragTypes.Literal,\n name: part,\n value: part,\n });\n }\n }\n\n return fragments;\n}\n\nconst safeExternalLink = /(noopener|noreferrer) (noopener|noreferrer)/;\nconst protocolLink = /^[\\w-_]+:/;\n\n/**\n * Intercepts links within the root node.\n *\n * This is adapted from https://github.com/choojs/nanohref/blob/master/index.js\n *\n * @param root - Element under which to intercept link clicks\n * @param callback - Function to call when a click event is intercepted\n * @param _window - (optional) Override for global window object\n */\nexport function catchLinks(root: Element, callback: (anchor: HTMLAnchorElement) => void, _window = window) {\n function traverse(node: HTMLElement | null): HTMLAnchorElement | null {\n if (!node || node === root) {\n return null;\n }\n\n if (node.localName !== \"a\" || (node as any).href === undefined) {\n return traverse(node.parentNode as HTMLElement | null);\n }\n\n return node as HTMLAnchorElement;\n }\n\n function handler(e: MouseEvent) {\n if ((e.button && e.button !== 0) || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.defaultPrevented) {\n return;\n }\n\n const anchor = traverse(e.target as HTMLElement);\n\n if (!anchor) {\n return;\n }\n\n if (\n _window.location.protocol !== anchor.protocol ||\n _window.location.hostname !== anchor.hostname ||\n _window.location.port !== anchor.port ||\n anchor.hasAttribute(\"data-router-ignore\") ||\n anchor.hasAttribute(\"download\") ||\n (anchor.getAttribute(\"target\") === \"_blank\" && safeExternalLink.test(anchor.getAttribute(\"rel\")!)) ||\n protocolLink.test(anchor.getAttribute(\"href\")!)\n ) {\n return;\n }\n\n e.preventDefault();\n callback(anchor);\n }\n\n root.addEventListener(\"click\", handler as any);\n\n return function cancel() {\n root.removeEventListener(\"click\", handler as any);\n };\n}\n\n/**\n * Replace route pattern param placeholders with real matched values.\n */\nexport function replaceParams(path: string, params: Record<string, string | number>) {\n for (const key in params) {\n const value = params[key].toString();\n path = path.replace(`{${key}}`, value).replace(`{#${key}}`, value);\n }\n\n return path;\n}\n","import type { Dolla, Logger } from \"../core/dolla.js\";\nimport type { ViewElement, ViewFunction } from \"../core/nodes/view.js\";\nimport { $, peek, type UnsubscribeFunction } from \"../core/signals-api.js\";\nimport { IS_ROUTER } from \"../core/symbols.js\";\nimport { Passthrough } from \"../core/views/passthrough.js\";\nimport { assertObject, isArray, isFunction, isObject, isString } from \"../typeChecking.js\";\nimport type { Stringable } from \"../types.js\";\nimport { shallowEqual } from \"../utils.js\";\nimport {\n catchLinks,\n joinPath,\n matchRoutes,\n patternToFragments,\n replaceParams,\n resolvePath,\n sortRoutes,\n splitPath,\n type ParsedRoute,\n type RouteMatch,\n} from \"./router.utils.js\";\n\n// ----- Types ----- //\n\nexport interface RouteMatchContext {\n path: string;\n pattern: string;\n params: Record<string, string>;\n query: Record<string, string>;\n\n /**\n * Redirects the user to a different route instead of matching the current one.\n */\n redirect(path: string): void;\n\n /**\n * Triggers the next beforeMatch function, or mounts the route.\n */\n next(): void;\n}\n\nexport interface Route {\n /**\n * The path or path fragment to match.\n */\n path: string;\n\n /**\n * Path to redirect to when this route is matched, or a callback function that returns such path.\n */\n redirect?: string | ((ctx: RouteRedirectContext) => string) | ((ctx: RouteRedirectContext) => Promise<string>);\n\n /**\n * View to display when this route is matched.\n */\n view?: ViewFunction<any>;\n\n /**\n * Subroutes.\n */\n routes?: Route[];\n\n /**\n * Called after the match is identified but before it is acted on. Use this to set state, load data, etc.\n */\n beforeMatch?: (ctx: RouteMatchContext) => void | Promise<void>;\n}\n\nexport interface RouteMeta {\n redirect?: string | ((ctx: RouteRedirectContext) => string) | ((ctx: RouteRedirectContext) => Promise<string>);\n pattern?: string;\n layers?: RouteLayer[];\n beforeMatch?: ((ctx: RouteMatchContext) => void | Promise<void>)[];\n}\n\nexport interface RouteConfig {\n pattern: string;\n meta: RouteMeta;\n}\n\nexport interface RouteLayer {\n id: number;\n view: ViewFunction<{}>;\n}\n\n/**\n * An active route layer whose markup has been initialized into a view.\n */\ninterface ActiveLayer {\n id: number;\n view: ViewElement;\n}\n\n/**\n * Object passed to redirect callbacks. Contains information useful for determining how to redirect.\n */\nexport interface RouteRedirectContext {\n /**\n * The path as it appears in the URL bar.\n */\n path: string;\n\n /**\n * The pattern that this path was matched with.\n */\n pattern: string;\n\n /**\n * Named route params parsed from `path`.\n */\n params: Record<string, string>;\n\n /**\n * Query params parsed from `path`.\n */\n query: Record<string, string>;\n}\n\n/**\n * A log for a single step in the route resolution process.\n */\ninterface JourneyStep {\n kind: \"match\" | \"redirect\" | \"miss\";\n message: string;\n}\n\nexport interface NavigateOptions {\n /**\n * Replace the current item in the history stack instead of adding a new one.\n * The back button will send the user to the page they visited before this. Defaults to false.\n */\n replace?: boolean;\n\n /**\n * Preserve existing query params (if any) when navigating. Defaults to false.\n * If true, all existing query params are preserved and merged with new ones.\n * If an array of strings is passed only those keys will be preserved, then merged with any new ones.\n */\n preserveQuery?: boolean | string[];\n}\n\nexport interface RouterOptions {\n routes: Route[];\n\n /**\n * When true, the router will construct routes like \"https://www.example.com/#/sub/route\" which work without any backend intervention.\n */\n hash?: boolean;\n}\n\n// ----- Code ----- //\n\nexport function createRouter(options: RouterOptions): Router {\n return new Router(options);\n}\n\nconst ROUTER_MOUNT = Symbol.for(\"DollaRouterMountMethod\");\nconst ROUTER_UNMOUNT = Symbol.for(\"DollaRouterUnmountMethod\");\n\nexport function _isRouter(value: any): value is Router {\n return value?.[IS_ROUTER] === true;\n}\n\nexport async function _mountRouter(router: Router, dolla: Dolla) {\n return router[ROUTER_MOUNT](dolla);\n}\n\nexport async function _unmountRouter(router: Router) {\n return router[ROUTER_UNMOUNT]();\n}\n\nexport class Router {\n [IS_ROUTER] = true;\n\n #dolla?: Dolla;\n #logger?: Logger;\n\n #layerId = 0;\n #activeLayers: ActiveLayer[] = [];\n #routes: ParsedRoute<RouteMeta>[] = [];\n\n #isMounted = false;\n\n /**\n * Use hash routing when true. Configured in router options.\n */\n #hash = false;\n\n // Callbacks that need to be called on unmount.\n #unsubscribers: UnsubscribeFunction[] = [];\n\n /**\n * The current match object.\n */\n #match = $<RouteMatch>();\n\n /**\n * The currently matched route pattern, if any.\n */\n readonly pattern = $(() => this.#match()?.pattern);\n\n /**\n * The current URL path.\n */\n readonly path = $(() => this.#match()?.path ?? window.location.pathname);\n\n /**\n * The current named path params.\n */\n readonly params = $(() => this.#match()?.params ?? {}, { equals: shallowEqual });\n\n /**\n * The current query params. Changes to this object will be reflected in the URL.\n */\n readonly query = $(() => this.#match()?.query ?? {}, { equals: shallowEqual });\n\n constructor(options: RouterOptions) {\n assertObject(options, \"Options must be an object. Got: %t\");\n\n if (options.hash) {\n this.#hash = true;\n }\n\n // Add routes.\n this.#routes = sortRoutes(\n options.routes\n .flatMap((route) => this.#prepareRoute(route))\n .map((route) => ({\n pattern: route.pattern,\n meta: route.meta,\n fragments: patternToFragments(route.pattern),\n })),\n );\n\n console.log({ routes: options.routes, prepared: this.#routes });\n assertValidRedirects(this.#routes);\n }\n\n async [ROUTER_MOUNT](dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.router\");\n\n // Listen for popstate events and update route accordingly.\n const onPopState = () => {\n this.#updateRoute(undefined, {});\n };\n window.addEventListener(\"popstate\", onPopState);\n this.#unsubscribers.push(() => window.removeEventListener(\"popstate\", onPopState));\n\n const rootElement = dolla.getRootElement()!;\n\n // Listen for clicks on <a> tags within the app.\n this.#unsubscribers.push(\n catchLinks(rootElement, (anchor) => {\n let href = anchor.getAttribute(\"href\")!;\n this.#logger!.info(\"intercepted click on <a> tag\", anchor);\n\n const preserve = anchor.getAttribute(\"data-router-preserve-query\");\n\n this.go(href, {\n preserveQuery: parsePreserveQueryAttribute(preserve),\n });\n }),\n );\n this.#logger.info(\"will intercept clicks on <a> tags within root element\", rootElement);\n\n this.#isMounted = true;\n\n // Setup initial route content.\n await this.#updateRoute(undefined, {});\n }\n\n async [ROUTER_UNMOUNT]() {\n for (const callback of this.#unsubscribers) {\n callback();\n }\n this.#unsubscribers = [];\n }\n\n /**\n * Navigate backward. Pass a number of steps to hit the back button that many times.\n */\n back(steps = 1) {\n window.history.go(-steps);\n }\n\n /**\n * Navigate forward. Pass a number of steps to hit the forward button that many times.\n */\n forward(steps = 1) {\n window.history.go(steps);\n }\n\n /**\n * Navigates to another route.\n *\n * @example\n * router.go(\"/login\"); // navigate to `/login`\n * router.go[\"/users\", 215], { replace: true }); // replace current history entry with `/users/215`\n */\n go(path: Stringable | Stringable[], options: NavigateOptions = {}) {\n let joined: string;\n\n if (Array.isArray(path)) {\n joined = joinPath(path);\n } else {\n joined = path.toString();\n }\n\n joined = resolvePath(window.location.pathname, joined);\n\n if (options.replace) {\n this.#replace(joined, options);\n } else {\n this.#push(joined, options);\n }\n }\n\n /**\n * Updates query params, keeping existing ones and applying new ones. Removes the query param if value is set to `null`.\n */\n updateQuery(values: Record<string, Stringable | null>) {\n const match = this.#match()!;\n const query = { ...this.query() };\n\n for (const key in values) {\n const value = values[key];\n if (value === null) {\n delete query[key];\n } else {\n query[key] = value.toString();\n }\n }\n\n let queryParts: string[] = [];\n\n for (const key in query) {\n queryParts.push(`${key}=${query[key]}`);\n }\n const queryString = queryParts.length > 0 ? \"?\" + queryParts.join(\"&\") : \"\";\n\n this.#match({ ...match, query });\n\n window.history.replaceState(null, \"\", this.#hash ? \"/#\" + match.path + queryString : match.path + queryString);\n }\n\n #push(href: string, options: NavigateOptions) {\n this.#logger?.info(\"(push)\", href);\n\n window.history.pushState(null, \"\", this.#hash ? \"/#\" + href : href);\n this.#updateRoute(href, options);\n }\n\n #replace(href: string, options: NavigateOptions) {\n this.#logger?.info(\"(replace)\", href);\n\n window.history.replaceState(null, \"\", this.#hash ? \"/#\" + href : href);\n this.#updateRoute(href, options);\n }\n\n #getCurrentURL(): URL {\n if (this.#hash) {\n return new URL(window.location.hash.slice(1), window.location.origin);\n } else {\n return new URL(window.location.pathname, window.location.origin);\n }\n }\n\n /**\n * Run when the location changes. Diffs and mounts new routes and updates\n * the $path, $route, $params and $query states accordingly.\n */\n async #updateRoute(href: string | undefined, options: NavigateOptions) {\n const logger = this.#logger;\n const rootView = this.#dolla?.getRootView();\n const url = href ? new URL(href, window.location.origin) : this.#getCurrentURL();\n\n const { match, journey } = await this.#resolveRoute(url);\n\n for (const step of journey) {\n switch (step.kind) {\n case \"match\":\n logger?.info(`📍 ${step.message}`);\n break;\n case \"redirect\":\n logger?.info(`↩️ ${step.message}`);\n break;\n case \"miss\":\n logger?.info(`💀 ${step.message}`);\n break;\n default:\n break;\n }\n }\n\n if (match) {\n const oldPattern = peek(this.pattern);\n\n // Merge query params.\n let query = match.query;\n let queryParts: string[] = [];\n\n if (options.preserveQuery === true) {\n query = Object.assign({}, this.query(), match.query);\n } else if (isArray(options.preserveQuery)) {\n const preserved: Record<string, any> = {};\n const current = this.query();\n for (const key in current) {\n if (options.preserveQuery.includes(key)) {\n preserved[key] = current[key];\n }\n }\n query = Object.assign({}, preserved, match.query);\n }\n\n for (const key in query) {\n queryParts.push(`${key}=${query[key]}`);\n }\n const queryString = queryParts.length > 0 ? \"?\" + queryParts.join(\"&\") : \"\";\n\n this.#match({ ...match, query });\n\n // Update the URL if matched path differs from navigator path.\n // This happens if route resolution involved redirects.\n if (rootView && (match.path !== location.pathname || location.search !== queryString)) {\n window.history.replaceState(null, \"\", this.#hash ? \"/#\" + match.path + queryString : match.path + queryString);\n }\n\n if (rootView && match.pattern !== oldPattern) {\n this.#mountRoute(rootView, match);\n }\n } else {\n // Only crash if routing has been configured.\n if (this.#isMounted) {\n logger!.crash(new NoRouteError(`Failed to match route '${url.pathname}'`));\n }\n }\n\n return { match, journey };\n }\n\n /**\n * Takes a matched route and mounts it.\n */\n #mountRoute(rootView: ViewElement, match: RouteMatch<RouteMeta>) {\n const layers = match.meta.layers!;\n\n // Diff and update route layers.\n for (let i = 0; i < layers.length; i++) {\n const matchedLayer = layers[i];\n const activeLayer = this.#activeLayers[i];\n\n if (activeLayer?.id !== matchedLayer.id) {\n // Discard all previously active layers starting at this depth.\n this.#activeLayers = this.#activeLayers.slice(0, i);\n activeLayer?.view.unmount();\n\n const parentLayer = this.#activeLayers.at(-1);\n const parent = parentLayer?.view ?? rootView;\n\n const view = parent.setRouteView(matchedLayer.view);\n this.#activeLayers.push({ id: matchedLayer.id, view });\n }\n }\n }\n\n /**\n * Takes a URL and finds a match, following redirects.\n */\n async #resolveRoute(\n url: URL,\n journey: JourneyStep[] = [],\n ): Promise<{\n match: RouteMatch<RouteMeta> | null;\n journey: JourneyStep[];\n }> {\n return new Promise((resolve, reject) => {\n const match = matchRoutes(this.#routes, url.pathname);\n\n if (!match) {\n return resolve({\n match: null,\n journey: [...journey, { kind: \"miss\", message: `no match for '${url.pathname}'` }],\n });\n }\n\n let redirect = match.meta.redirect;\n\n const finalize = async () => {\n if (redirect != null) {\n let path: string;\n\n if (isString(redirect)) {\n path = replaceParams(redirect, match.params);\n } else if (isFunction(redirect)) {\n const redirectContext: RouteRedirectContext = {\n path: match.path,\n pattern: match.pattern,\n params: match.params,\n query: match.query,\n };\n path = await redirect(redirectContext);\n if (!isString(path)) {\n return reject(new Error(`Redirect function must return a path to redirect to.`));\n }\n if (!path.startsWith(\"/\")) {\n // Not absolute. Resolve against matched path.\n path = resolvePath(match.path, path);\n }\n } else {\n return reject(new TypeError(`Redirect must either be a path string or a function.`));\n }\n\n resolve(\n this.#resolveRoute(new URL(path, window.location.origin), [\n ...journey,\n { kind: \"redirect\", message: `redirecting '${match.path}' -> '${path}'` },\n ]),\n );\n } else {\n resolve({ match, journey: [...journey, { kind: \"match\", message: `matched route '${match.path}'` }] });\n }\n };\n\n if (match.meta.beforeMatch?.length) {\n const callbacks = match.meta.beforeMatch;\n let i = -1;\n const next = () => {\n i++;\n if (i === callbacks.length) {\n // Mount route\n finalize();\n } else {\n // Next callback\n callbacks[i]({\n path: match.path,\n pattern: match.pattern,\n params: match.params,\n query: match.query,\n\n // TODO: Allow setting context variables from here? Would apply to the context of the matched view.\n redirect: (path) => {\n redirect = path;\n finalize();\n },\n\n next,\n });\n }\n };\n\n next();\n\n // TODO: Show warning after timeout if next hasn't been called?\n } else {\n finalize();\n }\n });\n }\n\n /**\n * Parses a route definition object into a set of matchable routes.\n *\n * @param route - Route config object.\n * @param layers - Array of parent layers. Passed when this function calls itself on nested routes.\n */\n #prepareRoute(route: Route, parents: Route[] = [], layers: RouteLayer[] = []) {\n if (!isObject(route) || !isString(route.path)) {\n throw new TypeError(`Route configs must be objects with a 'path' string property. Got: ${route}`);\n }\n\n if (route.redirect && route.routes) {\n throw new Error(`Route cannot have both a 'redirect' and nested 'routes'.`);\n } else if (route.redirect && route.view) {\n throw new Error(`Route cannot have both a 'redirect' and a 'view'.`);\n } else if (!route.view && !route.routes && !route.redirect) {\n throw new Error(`Route must have a 'view', a 'redirect', or a set of nested 'routes'.`);\n }\n\n let parts: string[] = [];\n\n for (const parent of parents) {\n parts.push(...splitPath(parent.path));\n }\n\n parts.push(...splitPath(route.path));\n\n // Remove trailing wildcard for joining with nested routes.\n if (parts[parts.length - 1] === \"*\") {\n parts.pop();\n }\n\n const routes: RouteConfig[] = [];\n\n if (route.redirect) {\n let redirect = route.redirect;\n\n if (isString(redirect)) {\n redirect = resolvePath(joinPath(parts), redirect);\n\n if (!redirect.startsWith(\"/\")) {\n redirect = \"/\" + redirect;\n }\n }\n\n routes.push({\n pattern: \"/\" + joinPath([...parts, ...splitPath(route.path)]),\n meta: {\n redirect,\n },\n });\n\n return routes;\n }\n\n let view: ViewFunction<any> = Passthrough;\n\n if (isFunction(route.view)) {\n view = route.view;\n } else if (route.view) {\n throw new TypeError(`Route '${route.path}' expected a view function or undefined. Got: ${route.view}`);\n }\n\n const layer: RouteLayer = { id: this.#layerId++, view };\n\n // Parse nested routes if they exist.\n if (route.routes) {\n for (const subroute of route.routes) {\n routes.push(...this.#prepareRoute(subroute, [...parents, route], [...layers, layer]));\n }\n } else {\n routes.push({\n pattern: parent ? joinPath([...parents.map((p) => p.path), route.path]) : route.path,\n meta: {\n pattern: route.path,\n layers: [...layers, layer],\n beforeMatch: parents\n .flatMap((parent) => parent.beforeMatch)\n .concat(route.beforeMatch)\n .filter((x) => x != null),\n },\n });\n }\n\n return routes;\n }\n}\n\nfunction assertValidRedirects(routes: ParsedRoute<RouteMeta>[]) {\n // Test redirects to make sure all possible redirect targets actually exist.\n for (const route of routes) {\n if (route.meta.redirect) {\n let redirectPath: string;\n\n if (isFunction(route.meta.redirect)) {\n // throw new Error(`Redirect functions are not yet supported.`);\n // Just allow, though it could fail later. Best not to call the function and cause potential side effects.\n } else if (isString(route.meta.redirect)) {\n redirectPath = route.meta.redirect;\n\n const match = matchRoutes(routes, redirectPath, {\n willMatch(r) {\n return r !== route;\n },\n });\n\n if (!match) {\n throw new Error(`Found a redirect to an undefined URL. From '${route.pattern}' to '${route.meta.redirect}'`);\n }\n } else {\n throw new TypeError(`Expected a string or redirect function. Got: ${route.meta.redirect}`);\n }\n }\n }\n}\n\n/**\n * Parses the data-router-preserve-query attribute from a link.\n */\nfunction parsePreserveQueryAttribute(value: null | string | boolean): boolean | string[] {\n if (value === null) {\n return false;\n } else if (value === true || value === false) {\n return value;\n } else if (typeof value === \"string\") {\n value = value.trim();\n if (value === \"\" || value === \"true\") {\n return true;\n } else if (value === \"false\") {\n return false;\n }\n\n return value\n .split(\",\")\n .map((k) => k.trim())\n .filter((k) => k.length > 0);\n } else {\n throw new Error(`Invalid type for data-router-preserve-query attribute: ${typeof value} (value: ${value})`);\n }\n}\n\nclass NoRouteError extends Error {}\n","import { isObject } from \"../typeChecking.js\";\n\n/**\n * A simple HTTP client with middleware support. Middleware applies to all requests made through this store,\n * so it's the perfect way to handle things like auth headers and permission checks for API calls.\n */\nexport class HTTP {\n #middleware: HTTPMiddleware[] = [];\n #fetch = getDefaultFetch();\n\n /**\n * Adds a new middleware that will apply to subsequent requests.\n * Returns a function to remove this middleware.\n *\n * @param middleware - A middleware function that will intercept requests.\n */\n use(fn: HTTPMiddleware) {\n this.#middleware.push(fn);\n\n // Call returned function to remove this middleware for subsequent requests.\n return () => {\n this.#middleware.splice(this.#middleware.indexOf(fn), 1);\n };\n }\n\n async get<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"get\", uri, options);\n }\n\n async put<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"put\", uri, options);\n }\n\n async patch<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"patch\", uri, options);\n }\n\n async post<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"post\", uri, options);\n }\n\n async delete<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"delete\", uri, options);\n }\n\n async head<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"head\", uri, options);\n }\n\n async options<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"options\", uri, options);\n }\n\n async trace<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"trace\", uri, options);\n }\n\n async #request<ResBody, ReqBody>(method: string, uri: string, options?: RequestOptions<any>) {\n const runner = new Runner<ResBody, ReqBody>({\n ...options,\n method,\n uri,\n middleware: this.#middleware,\n fetch: this.#fetch,\n });\n return runner.fetch();\n }\n}\n\nfunction getDefaultFetch(): typeof window.fetch {\n if (typeof window !== \"undefined\" && window.fetch) {\n return window.fetch.bind(window);\n }\n\n if (typeof global !== \"undefined\" && global.fetch) {\n return global.fetch.bind(global);\n }\n\n throw new Error(\"Running in neither browser nor node. Please run this app in one of the supported environments.\");\n}\n\n/*====================*\\\n|| Request ||\n\\*====================*/\n\nexport type HTTPMiddleware = (\n request: HTTPRequest<unknown>,\n next: () => Promise<HTTPResponse<unknown>>,\n) => void | Promise<void>;\n\nexport interface RequestOptions<ReqBody> {\n /**\n * Body to send with the request.\n */\n body?: ReqBody;\n\n /**\n * Headers to send with the request.\n */\n headers?: Record<string, any> | Headers;\n\n /**\n * Query params to interpolate into the URL.\n */\n query?: Record<string, any> | URLSearchParams;\n}\n\nexport interface HTTPRequest<Body> {\n method: string;\n url: URL;\n headers: Headers;\n body: Body;\n}\n\nexport interface HTTPResponse<Body> {\n method: string;\n url: URL;\n headers: Headers;\n status: number;\n statusText: string;\n body: Body;\n}\n\ninterface MakeRequestConfig<ReqBody> extends RequestOptions<ReqBody> {\n method: string;\n uri: string;\n middleware: HTTPMiddleware[];\n fetch: typeof window.fetch;\n}\n\nexport class HTTPResponseError extends Error {\n response;\n\n constructor(response: HTTPResponse<any>) {\n const { status, statusText, method, url } = response;\n const message = `${status} ${statusText}: Request failed (${method.toUpperCase()} ${url.toString()})`;\n\n super(message);\n\n this.response = response;\n }\n}\n\nclass Request<ReqBody> implements HTTPRequest<ReqBody> {\n method: string;\n url: URL;\n headers = new Headers();\n body!: ReqBody;\n\n get isSameOrigin() {\n return this.url.origin === window.location.origin;\n }\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this.method = config.method;\n this.body = config.body!;\n if (config.uri.startsWith(\"http\")) {\n this.url = new URL(config.uri);\n } else {\n this.url = new URL(config.uri, window.location.origin);\n }\n\n this._applyHeaders(config.headers);\n this._applyQueryParams(config.query);\n }\n\n private _applyHeaders(headers: any) {\n if (headers == null) return;\n\n if (headers instanceof Map || headers instanceof Headers) {\n headers.forEach((value, key) => {\n this.headers.set(key, value);\n });\n } else if (isObject(headers)) {\n for (const name in headers) {\n const value = headers[name];\n if (value instanceof Date) {\n this.headers.set(name, value.toISOString());\n } else if (value != null) {\n this.headers.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown headers type. Got: ${headers}`);\n }\n }\n\n private _applyQueryParams(query: any) {\n if (query == null) return;\n\n if (query instanceof Map || query instanceof URLSearchParams) {\n query.forEach((value, key) => {\n this.url.searchParams.set(key, value);\n });\n } else if (isObject(query)) {\n for (const name in query) {\n const value = query[name];\n if (value instanceof Date) {\n this.url.searchParams.set(name, value.toISOString());\n } else if (value != null) {\n this.url.searchParams.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown query params type. Got: ${query}`);\n }\n }\n}\n\nclass Runner<ResBody, ReqBody> {\n private _middleware;\n private _fetch;\n\n private _request: Request<ReqBody>;\n private _response?: HTTPResponse<ResBody>;\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this._middleware = config.middleware;\n this._fetch = config.fetch;\n\n this._request = new Request(config);\n }\n\n async fetch() {\n if (this._middleware.length > 0) {\n const mount = (index = 0) => {\n const current = this._middleware[index];\n const next = this._middleware[index + 1] ? mount(index + 1) : this._handler.bind(this);\n\n return async () =>\n current(this._request, async () => {\n await next();\n return this._response!;\n });\n };\n\n await mount()();\n } else {\n await this._handler();\n }\n\n if (this._response!.status < 200 || this._response!.status >= 400) {\n throw new HTTPResponseError(this._response!);\n }\n\n return this._response!;\n }\n\n // This is the function that performs the actual request after the final middleware.\n private async _handler() {\n let reqBody: BodyInit;\n\n const req = this._request;\n\n if (!req.headers.has(\"content-type\") && isObject(req.body)) {\n // Auto-detect JSON bodies and encode as a string with correct headers.\n req.headers.set(\"content-type\", \"application/json\");\n reqBody = JSON.stringify(req.body);\n } else {\n reqBody = req.body as BodyInit;\n }\n\n const fetched = await this._fetch(req.url.toString(), {\n method: req.method,\n headers: req.headers,\n body: reqBody,\n });\n\n // Auto-parse response body based on content-type header\n const contentType = fetched.headers.get(\"content-type\");\n\n let body: ResBody;\n\n if (contentType?.includes(\"application/json\")) {\n body = await fetched.json();\n } else if (contentType?.includes(\"application/x-www-form-urlencoded\")) {\n body = (await fetched.formData()) as ResBody;\n } else {\n body = (await fetched.text()) as ResBody;\n }\n\n this._response = {\n method: req.method,\n url: req.url,\n status: fetched.status,\n statusText: fetched.statusText,\n headers: fetched.headers,\n body,\n };\n }\n}\n","import type { Dolla, Logger } from \"../core/dolla.js\";\nimport { $, get, type MaybeSignal, type Signal } from \"../core/signals-api.js\";\nimport { isFunction, isObject, isString, typeOf } from \"../typeChecking.js\";\nimport { deepEqual } from \"../utils.js\";\n\n// ----- Types ----- //\n\n/**\n * A JSON object of translated strings. Values can be string templates or nested objects.\n */\ninterface LocalizedStrings extends Record<string, string | LocalizedStrings> {}\n\nenum SegmentType {\n Static,\n Variable,\n}\ntype StringTemplate = { segments: (StaticSegment | VariableSegment)[] };\n/**\n * A string segment with literal text to be appended without processing.\n */\ntype StaticSegment = {\n type: SegmentType.Static;\n text: string;\n};\n/**\n * A variable passed to the t() function. Needs to be formatted before it is appended.\n */\ntype VariableSegment = {\n type: SegmentType.Variable;\n name: string;\n formats: Format[];\n};\n/**\n * A formatter to be applied to a variable.\n */\ntype Format = {\n name: string;\n options: Record<string, any>;\n};\n\nexport interface TranslationConfig {\n /**\n * Name of the locale this translation is for (BCP 47 locale names recommended).\n */\n locale: string;\n\n /**\n * An object with translated strings for this language.\n */\n strings?: LocalizedStrings;\n\n /**\n * A callback function that returns a Promise that resolves to the translation object for this language.\n */\n fetch?: () => Promise<LocalizedStrings>;\n\n /**\n * Path to a JSON file with translated strings for this language.\n */\n path?: string;\n}\n\nexport type I18nSetupOptions = {\n /**\n * Default locale to load on startup\n */\n locale?: string | null;\n\n translations: TranslationConfig[];\n};\n\nexport type TOptions = {\n /**\n *\n */\n count?: MaybeSignal<number>;\n\n /**\n *\n */\n context?: MaybeSignal<string>;\n\n /**\n * Override formats specified in the template with the ones in the array for each named variable.\n *\n * @example\n * t(\"example_key\", {\n * count: 5,\n * formatOverrides: {\n * count: [ { name: \"datetime\", options: { style: \"currency\", currency: \"JPY\" } } ]\n * }\n * });\n */\n formatOverrides?: MaybeSignal<Record<string, Record<string, Format[]>>>;\n\n [value: string]: MaybeSignal<any>;\n};\n\nexport type Formatter = (locale: string, value: unknown, options: Record<string, any>) => string;\n\n// ----- Code ----- //\n\nclass Translation {\n dolla: Dolla;\n config: TranslationConfig;\n\n #isLoaded = false;\n\n #templates = new Map<string, StringTemplate>();\n\n constructor(config: TranslationConfig, dolla: Dolla) {\n this.config = config;\n this.dolla = dolla;\n }\n\n async load(): Promise<void> {\n let strings: LocalizedStrings | undefined;\n\n if (!this.#isLoaded) {\n if (isObject(this.config.strings)) {\n strings = this.config.strings;\n } else if (isFunction(this.config.fetch)) {\n strings = await this.config.fetch();\n if (!isObject(strings)) {\n throw new Error(`Fetch function did not return an object of language strings: ${strings}`);\n }\n } else if (isString(this.config.path)) {\n const res = await fetch(this.config.path);\n if (res.ok) {\n const body = await res.json();\n if (isObject(body)) {\n strings = body as LocalizedStrings;\n } else {\n throw new Error(\n `Language path '${this.config.path}' did not return an object of language strings: ${body}`,\n );\n }\n } else {\n throw new Error(`HTTP request failed.`);\n }\n }\n }\n\n if (strings) {\n const entries = this.#compile(strings);\n for (const entry of entries) {\n this.#templates.set(entry[0], entry[1]);\n }\n } else {\n throw new Error(`Language could not be loaded.`);\n }\n }\n\n getTemplate(selector: string): StringTemplate {\n return (\n this.#templates.get(selector) ?? {\n segments: [{ type: SegmentType.Static, text: `[MISSING: ${selector}]` }],\n }\n );\n }\n\n hasTemplate(selector: string): boolean {\n return this.#templates.has(selector);\n }\n\n #compile(strings: { [key: string]: any }, path: string[] = []): [string, StringTemplate][] {\n const entries: [string, StringTemplate][] = [];\n\n for (const key in strings) {\n switch (typeOf(strings[key])) {\n case \"string\":\n entries.push([[...path, key].join(\".\"), this.#parseTemplate(strings[key])]);\n break;\n case \"object\":\n entries.push(...this.#compile(strings[key], [...path, key]));\n break;\n default:\n throw new Error(\n `Expected to find a string or object at ${[...path, key].join(\".\")}. Got: ${typeOf(strings[key])}`,\n );\n }\n }\n\n return entries;\n }\n\n #parseTemplate(template: string): StringTemplate {\n // \"{{itemName}} costs {{amount | number(style: currency, currency: USD)}}.\"\n\n enum Loc {\n /**\n * Outside value braces.\n */\n Static,\n /**\n * Inside value braces; currently parsing the name of the value. e.g. `{{ [name] | number(style: currency, currency: USD) }}`\n */\n ValueName,\n /**\n * Inside value braces; currently parsing the name of a format function. e.g. `{{ name | [number](style: currency, currency: USD) }}`\n */\n FormatName,\n /**\n * Inside value braces; currently parsing the name of a format option. e.g. `{{ name | number([style]: currency, currency: USD) }}`\n */\n FormatOptionName,\n /**\n * Inside value braces; currently parsing the value of a format option. e.g. `{{ name | number(style: [currency], currency: USD ) }}`\n */\n FormatOptionValue,\n /**\n * Inside value braces; just reached the closing bracket of a format option. e.g. `{{ name | number(style: [currency], currency: USD) [] }}`\n */\n FormatOptionEnd,\n }\n\n const parsed: StringTemplate = {\n segments: [],\n };\n\n let buffer = \"\";\n let i = 0;\n let loc: Loc = Loc.Static;\n let segment!: VariableSegment;\n let format!: VariableSegment[\"formats\"][0];\n\n let formatOptionName!: string;\n\n const startSegment = () => {\n segment = {\n type: SegmentType.Variable,\n name: \"\",\n formats: [],\n };\n };\n\n const startFormat = () => {\n format = {\n name: \"\",\n options: {},\n };\n };\n\n while (i < template.length) {\n // Skip spaces (unless we're in static)\n if (loc !== Loc.Static && template[i] === \" \") {\n i++;\n continue;\n }\n\n switch (loc) {\n case Loc.Static:\n if (template[i] === \"{\" && template[i + 1] === \"{\") {\n loc = Loc.ValueName;\n i += 2;\n // close static segment\n if (buffer.length > 0) {\n parsed.segments.push({ type: SegmentType.Static, text: buffer });\n buffer = \"\";\n }\n startSegment();\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.ValueName:\n if (template[i] === \"|\") {\n loc = Loc.FormatName;\n i += 1;\n // add name to value segment\n segment.name = buffer;\n buffer = \"\";\n startFormat();\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // close value segment\n segment.name = buffer;\n buffer = \"\";\n parsed.segments.push(segment);\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatName:\n if (template[i] === \"(\") {\n loc = Loc.FormatOptionName;\n i += 1;\n // add name to format object\n format.name = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // close format and value segment\n segment.formats.push(format);\n parsed.segments.push(segment);\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionName:\n if (template[i] === \")\") {\n // TODO: error - no value provided for option\n } else if (template[i] === \":\") {\n loc = Loc.FormatOptionValue;\n i += 1;\n // add name to format option object\n formatOptionName = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n // TODO: error - format options parenthesis not closed\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionValue:\n if (template[i] === \")\") {\n loc = Loc.FormatOptionEnd;\n i += 1;\n // add value to format option object\n // add format option to format object; we're done with this format\n format.options[formatOptionName] = buffer;\n buffer = \"\";\n segment.formats.push(format);\n } else if (template[i] === \",\") {\n loc = Loc.FormatOptionName;\n i += 1;\n // add value to format option object\n // add format option to format object; we're adding another option\n format.options[formatOptionName] = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n // TODO: error - format options parenthesis not closed\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionEnd:\n if (template[i] === \"|\") {\n loc = Loc.FormatName;\n i += 1;\n startFormat();\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // add value segment\n parsed.segments.push(segment);\n } else {\n // TODO: error - no other valid characters\n }\n break;\n }\n }\n\n if (loc === Loc.Static && buffer.length > 0) {\n parsed.segments.push({ type: SegmentType.Static, text: buffer });\n }\n\n return parsed;\n }\n}\n\n/**\n * Dolla's I(nternationalizatio)n module. Manages language translations and locale-based formatting.\n */\nexport class I18n {\n #dolla: Dolla;\n #logger: Logger;\n #translations = new Map<string, Translation>();\n #cache: [key: string, values: Record<string, any> | undefined, output: string][] = [];\n #formats = new Map<string, Formatter>();\n\n #initialLocale = \"auto\";\n\n #locale = $<string>(\"\");\n\n readonly locale = $(this.#locale);\n\n constructor(dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.i18n\");\n\n this.addFormat(\"number\", (_, value, options) => {\n return this.#formatNumber(Number(value), options);\n });\n this.addFormat(\"datetime\", (_, value, options) => {\n return this.#formatDateTime(value as any, options);\n });\n this.addFormat(\"list\", (_, value, options) => {\n return this.#formatList(value as any, options);\n });\n\n /**\n * Load language before the app mounts.\n */\n dolla.beforeMount(async () => {\n if (this.#translations.size > 0) {\n await this.setLocale(this.#initialLocale);\n }\n });\n }\n\n get locales() {\n return [...this.#translations.keys()];\n }\n\n setup(options: I18nSetupOptions) {\n // Convert languages into Language instances.\n options.translations.forEach((entry) => {\n this.#translations.set(entry.locale, new Translation(entry, this.#dolla));\n });\n\n // Check that initialLanguage is actually registered.\n if (options.locale && options.locale !== \"auto\") {\n const isRegistered = options.translations.some((entry) => entry.locale === options.locale);\n if (!isRegistered) {\n throw new Error(`Initial locale '${options.locale}' is not registered in the locales array.`);\n }\n this.#initialLocale = options.locale;\n }\n\n this.#logger.info(\n `${this.#translations.size} language${this.#translations.size === 1 ? \"\" : \"s\"} supported: '${[...this.#translations.keys()].join(\"', '\")}'`,\n );\n }\n\n async setLocale(name: string) {\n let realName!: string;\n\n if (name === \"auto\") {\n let names = [];\n\n if (typeof navigator !== \"undefined\") {\n const nav = navigator as any;\n\n if (nav.languages?.length > 0) {\n names.push(...nav.languages);\n } else if (nav.language) {\n names.push(nav.language);\n } else if (nav.browserLanguage) {\n names.push(nav.browserLanguage);\n } else if (nav.userLanguage) {\n names.push(nav.userLanguage);\n }\n }\n\n for (const name of names) {\n if (this.#translations.has(name)) {\n // Found a matching language.\n realName = name;\n }\n }\n } else {\n // Tag is the actual tag to set.\n if (this.#translations.has(name)) {\n realName = name;\n }\n }\n\n if (realName == null) {\n const firstLanguage = this.#translations.keys().next().value;\n if (firstLanguage) {\n realName = firstLanguage;\n }\n }\n\n if (!realName || !this.#translations.has(realName)) {\n throw new Error(`Locale '${name}' has no translation.`);\n }\n\n const translation = this.#translations.get(realName)!;\n\n try {\n await translation.load();\n\n this.#cache = [];\n this.#locale(realName);\n\n this.#logger.info(\"set language to \" + realName);\n } catch (error) {\n if (error instanceof Error) {\n this.#logger.crash(error);\n }\n }\n }\n\n /**\n * Returns a State containing the value at `key`.\n\n * @param selector - Key to the translated value.\n * @param options - A map of `{{placeholder}}` names and the values to replace them with.\n *\n * @example\n * const $value = t(\"your.key.here\", { count: 5 });\n */\n t(selector: string, options?: TOptions): Signal<string> {\n if (this === undefined) {\n throw new Error(\n `The 't' function cannot be destructured. If you need a standalone version you can import it like so: 'import { t } from \"@manyducks.co/dolla\"'`,\n );\n }\n\n return $(() => {\n const values: Record<string, any> = {};\n\n // Track all option values.\n for (const key in options) {\n values[key] = get(options[key]);\n }\n\n return this.#getValue(this.#locale(), selector, values);\n });\n }\n\n #getValue(locale: string, selector: string, options: Record<string, any>): string {\n const cached = this.#getCached(selector, options);\n if (cached) return cached;\n\n const translation = this.#translations.get(locale)!;\n\n // Handle count (pluralization) and context. Keys become \"key_context_pluralization\".\n\n if (options.context != null) {\n selector += \"_\" + options.context;\n }\n if (options.count != null) {\n if (options.ordinal) {\n // Try to match the exact number key if there is one (e.g. \"myExampleKey_ordinal_(=2)\" when count is 2).\n const exact = `${selector}_ordinal_(=${options.count})`;\n if (translation.hasTemplate(exact)) {\n selector = exact;\n } else {\n selector += \"_ordinal_\" + new Intl.PluralRules(locale, { type: \"ordinal\" }).select(options.count);\n }\n } else {\n // Try to match the exact number key if there is one (e.g. \"myExampleKey_(=2)\" when count is 2).\n const exact = `${selector}_(=${options.count})`;\n if (translation.hasTemplate(exact)) {\n selector = exact;\n } else {\n selector += \"_\" + new Intl.PluralRules(locale).select(options.count);\n }\n }\n }\n\n const template = translation.getTemplate(selector);\n let output = \"\";\n\n for (const segment of template.segments) {\n if (segment.type === SegmentType.Static) {\n output += segment.text;\n } else if (segment.type === SegmentType.Variable) {\n let value = resolve(options, segment.name);\n\n const formats = options.formatOverrides?.[segment.name] ?? [...segment.formats];\n\n if (segment.name === \"count\" && formats.length === 0) {\n formats.push({ name: \"number\", options: {} });\n }\n\n for (const format of formats) {\n const fn = this.#formats.get(format.name);\n if (fn == null) {\n const error = new Error(\n `Failed to load format '${format.name}' when processing '${selector}', template: ${template}`,\n );\n this.#logger.crash(error);\n throw error;\n }\n value = fn(locale, value, format.options);\n }\n\n output += value;\n }\n }\n\n return output;\n }\n\n /**\n * Add a custom format callback.\n *\n * @example\n * Dolla.i18n.addFormat(\"uppercase\", (locale, value, options) => {\n * return value.toUpperCase();\n * });\n *\n * {\n * \"greeting\": \"Hello, {{name|uppercase}}!\"\n * }\n *\n * t(\"greeting\", {name: \"world\"}); // State<\"Hello, WORLD!\">\n */\n addFormat(name: string, callback: (locale: string, value: unknown, options: Record<string, any>) => string) {\n this.#formats.set(name, callback);\n }\n\n /**\n * Creates an `Intl.Collator` configured for the current locale.\n * NOTE: The locale is tracked if called within a signal tracking context.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator#options\n */\n collator(options?: Intl.CollatorOptions) {\n return new Intl.Collator(this.#locale(), options);\n }\n\n /**\n * Formats a number for the current locale. Uses `Intl.NumberFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options\n */\n number(count: MaybeSignal<number | bigint>, options?: Intl.NumberFormatOptions): Signal<string> {\n return $(() => this.#formatNumber(get(count), options));\n }\n\n #formatNumber(count: number | bigint, options?: Intl.NumberFormatOptions): string {\n // NOTE: Locale is tracked if called within a tracking context.\n return new Intl.NumberFormat(this.#locale(), options).format(count);\n }\n\n /**\n * Formats a date for the current locale. Uses `Intl.DateTimeFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options\n *\n * @example\n * const date = new Date();\n * const $formatted = Dolla.i18n.dateTime(date, { dateFormat: \"short\" });\n */\n dateTime(\n date?: MaybeSignal<string | number | Date | undefined>,\n options?: Intl.DateTimeFormatOptions,\n ): Signal<string> {\n return $(() => this.#formatDateTime(get(date), options));\n }\n\n #formatDateTime(date?: string | number | Date, options?: Intl.DateTimeFormatOptions): string {\n // NOTE: Locale is tracked if called within a tracking context.\n return new Intl.DateTimeFormat(this.#locale(), options).format(isString(date) ? new Date(date) : date);\n }\n\n /**\n * Formats a list for the current locale. Uses `Intl.ListFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options\n *\n * @example\n * const list = new Date();\n * const $formatted = Dolla.i18n.list(list, { });\n */\n list(list: MaybeSignal<Iterable<string>>, options?: Intl.ListFormatOptions): Signal<string> {\n return $(() => this.#formatList(get(list), options));\n }\n\n #formatList(list: Iterable<string>, options?: Intl.ListFormatOptions): string {\n // NOTE: Locale is tracked if called within a tracking context.\n return new Intl.ListFormat(this.#locale(), options).format(list);\n }\n\n // relativeTime(): State<string> {\n\n // }\n\n #getCached(key: string, values?: Record<string, any>): string | undefined {\n for (const entry of this.#cache) {\n if (entry[0] === key && deepEqual(entry[1], values)) {\n return entry[2];\n }\n }\n }\n}\n\nfunction resolve(object: any, key: string) {\n const parsed = String(key)\n .split(/[\\.\\[\\]]/)\n .filter((part) => part.trim() !== \"\");\n let value = object;\n\n while (parsed.length > 0) {\n const part = parsed.shift()!;\n\n if (value != null) {\n value = value[part];\n } else {\n value = undefined;\n }\n }\n\n return value;\n}\n","import { when, markup as m } from \"../markup.js\";\n\n/**\n * Props passed to the crash view when a crash occurs.\n */\nexport type CrashViewProps = {\n /**\n * JavaScript Error object.\n */\n error: Error;\n\n /**\n * A string to identify the logger that reported this error.\n */\n loggerName: string;\n\n /**\n * Unique identifier to pinpoint the specific view that reported the crash.\n */\n uid?: string;\n};\n\nexport function DefaultCrashView(props: CrashViewProps) {\n return m(\n \"div\",\n {\n style: {\n backgroundColor: \"#880000\",\n color: \"#fff\",\n padding: \"2rem\",\n position: \"fixed\",\n inset: 0,\n fontSize: \"20px\",\n },\n },\n m(\"h1\", { style: { marginBottom: \"0.5rem\" } }, \"The app has crashed\"),\n m(\n \"p\",\n { style: { marginBottom: \"0.25rem\" } },\n m(\"span\", { style: { fontFamily: \"monospace\" } }, props.loggerName),\n when(props.uid, m(\"span\", { style: { fontFamily: \"monospace\", opacity: 0.5 } }, ` [uid: ${props.uid}]`)),\n \" says:\",\n ),\n m(\n \"blockquote\",\n {\n style: {\n backgroundColor: \"#991111\",\n padding: \"0.25em\",\n borderRadius: \"6px\",\n fontFamily: \"monospace\",\n marginBottom: \"1rem\",\n },\n },\n m(\n \"span\",\n {\n style: {\n display: \"inline-block\",\n backgroundColor: \"red\",\n padding: \"0.1em 0.4em\",\n marginRight: \"0.5em\",\n borderRadius: \"4px\",\n fontSize: \"0.9em\",\n fontWeight: \"bold\",\n },\n },\n props.error.name,\n ),\n props.error.message,\n ),\n m(\"p\", {}, \"Please see the browser console for details.\"),\n );\n}\n","import { HTTP } from \"../http/index.js\";\nimport { _isRouter, _mountRouter, _unmountRouter, type Router } from \"../router/index.js\";\nimport { I18n } from \"../translate/index.js\";\nimport { assertInstanceOf, isFunction, isString } from \"../typeChecking.js\";\nimport { okhash, createMatcher, noOp } from \"../utils.js\";\nimport type { ElementContext, StoreConsumerContext, StoreProviderContext } from \"./context.js\";\nimport { constructMarkup, markup, groupElements, type Markup, type MarkupElement } from \"./markup.js\";\nimport { View, type ViewElement, type ViewFunction } from \"./nodes/view.js\";\nimport { Store, StoreError, StoreFunction } from \"./store.js\";\nimport { DefaultCrashView, type CrashViewProps } from \"./views/default-crash-view.js\";\nimport { Passthrough } from \"./views/passthrough.js\";\n\n// Affects which log messages will print and how much debugging info is included in the DOM.\nexport type Environment = \"development\" | \"production\";\n\n/**\n * Log type toggles. Each message category can be turned on or off or enabled only in a specific environment.\n */\nexport type Loggles = {\n info: boolean | Environment;\n log: boolean | Environment;\n warn: boolean | Environment;\n error: boolean | Environment;\n};\n\nexport interface Logger {\n info(...args: any[]): void;\n log(...args: any[]): void;\n warn(...args: any[]): void;\n error(...args: any[]): void;\n crash(error: Error): void;\n\n setName(name: string): Logger;\n}\n\nexport interface LoggerErrorContext {\n error: Error;\n loggerName: string;\n uid?: string;\n}\n\nexport type LoggerOptions = {\n /**\n * Console object to use for logging (mostly for testing). Uses window.console by default.\n */\n console?: any;\n\n /**\n * Unique ID to print with logs. Makes it easier to track down messages from specific view instances.\n */\n uid?: string;\n};\n\nexport class Dolla implements StoreProviderContext, StoreConsumerContext {\n // TODO: Take these off the global Dolla object.\n readonly http: HTTP;\n readonly i18n: I18n;\n\n #isMounted = false;\n #env: Environment = \"production\";\n #rootElement?: Element;\n #rootView?: ViewElement;\n #crashView: ViewFunction<CrashViewProps> = DefaultCrashView;\n\n #router?: Router;\n\n #beforeMountCallbacks: Array<() => void | Promise<void>> = [];\n #onMountCallbacks: Array<() => void> = [];\n #beforeUnmountCallbacks: Array<() => void | Promise<void>> = [];\n #onUnmountCallbacks: Array<() => void> = [];\n\n #rootElementContext: ElementContext = {\n root: this,\n stores: new Map(),\n viewName: \"Dolla\",\n };\n\n #loggles: Loggles = {\n info: \"development\",\n log: \"development\",\n warn: \"development\",\n error: true,\n };\n #match = createMatcher(\"*,-Dolla.*\");\n\n // Registration functions for modules.\n // All modules will be registered before mount.\n #modules: (() => Promise<any>)[] = [];\n\n constructor() {\n this.http = new HTTP();\n this.i18n = new I18n(this);\n }\n\n /**\n * True when the app is connected to a DOM node and displayed to the user.\n */\n get isMounted() {\n return this.#isMounted;\n }\n\n /**\n * Get the current environment that this app is running in.\n * Environment affects which log messages will print and how much debugging info is included in the DOM.\n */\n getEnv() {\n return this.#env;\n }\n\n /**\n * Sets the environment that this app is running in.\n * Environment affects which log messages will print and how much debugging info is included in the DOM.\n */\n setEnv(value: Environment) {\n this.#env = value;\n }\n\n /**\n * Sets the view that will be shown when the `crash` method is called on any logger.\n * When a crash is reported the app will be unmounted and replaced with this crash page.\n */\n setCrashView(view: ViewFunction<CrashViewProps>) {\n this.#crashView = view;\n }\n\n /**\n * Returns the HTMLElement Dolla is mounted to. This will return undefined until Dolla.mount() is called.\n */\n getRootElement() {\n return this.#rootElement;\n }\n\n /**\n * Returns the top level view Dolla is rendering inside the root element. This will return undefined until Dolla.mount() is called.\n */\n getRootView() {\n return this.#rootView;\n }\n\n /**\n * Attaches a new store to this context.\n */\n provide<Value>(store: StoreFunction<{}, Value>): Value;\n\n /**\n * Attaches a new store to this context.\n */\n provide<Value>(store: StoreFunction<undefined, Value>): Value;\n\n /**\n * Attaches a new store to this context.\n */\n provide<Options, Value>(store: StoreFunction<Options, Value>, options: Options): Value;\n\n provide<Options, Value>(store: StoreFunction<Options, Value>, options?: Options): Value {\n const instance = new Store(store, options!);\n const attached = instance.attach(this.#rootElementContext);\n if (!attached) {\n let name = store.name ? `'${store.name}'` : \"this store\";\n console.warn(`An instance of ${name} was already attached to this context.`);\n return this.get(store);\n } else {\n return instance.value;\n }\n }\n\n /**\n * Gets the nearest instance of a store. Throws an error if the store isn't provided higher in the tree.\n */\n get<Value>(store: StoreFunction<any, Value>): Value {\n if (isFunction(store)) {\n const instance = this.#rootElementContext.stores.get(store);\n if (instance == null) {\n throw new StoreError(`Store not found on this context.`);\n } else {\n return instance.value;\n }\n } else {\n throw new StoreError(`Invalid store.`);\n }\n }\n\n async mount(selector: string, router: Router): Promise<void>;\n async mount(selector: string, view: ViewFunction<any>): Promise<void>;\n async mount(element: Element, router: Router): Promise<void>;\n async mount(element: Element, view: ViewFunction<any>): Promise<void>;\n\n async mount(target: string | Element, root: ViewFunction<any> | Router) {\n if (this.#isMounted) {\n throw new Error(`Dolla is already mounted.`);\n }\n\n if (isString(target)) {\n const match = document.querySelector<Element>(target);\n assertInstanceOf(HTMLElement, match, `Selector '${target}' did not match any element.`);\n this.#rootElement = match!;\n } else {\n assertInstanceOf(HTMLElement, target, \"Expected an HTML element or a selector string. Got type: %t, value: %v\");\n this.#rootElement = target;\n }\n\n if (_isRouter(root)) {\n this.#router = root;\n }\n\n const view = _isRouter(root) ? Passthrough : root;\n\n // First, initialize the root view. The router store needs this to connect the initial route.\n const rootViewMarkup = markup(view);\n this.#rootView = this.constructView(rootViewMarkup.type as ViewFunction<any>, rootViewMarkup.props);\n\n // Register modules\n // TODO: Handle errors\n await Promise.all(this.#modules.map((register) => register()));\n\n // TODO: Run effects for stores\n\n // Run beforeMount\n // TODO: Handle errors\n await Promise.all(this.#beforeMountCallbacks.map((callback) => callback()));\n\n // Run onMount for stores.\n for (const store of this.#rootElementContext.stores.values()) {\n store.handleMount();\n }\n\n if (_isRouter(root)) {\n await _mountRouter(root, this);\n }\n\n this.#rootView.mount(this.#rootElement);\n this.#isMounted = true;\n\n // Run onMount\n // TODO: Handle errors\n for (const callback of this.#onMountCallbacks) {\n callback();\n }\n }\n\n async unmount() {\n if (!this.#isMounted) return;\n\n // Run beforeUnmount\n await Promise.all(this.#beforeUnmountCallbacks.map((callback) => callback()));\n\n this.#rootView?.unmount(false);\n\n if (this.#router) {\n await _unmountRouter(this.#router);\n }\n\n this.#isMounted = false;\n\n // Run onUnmount\n for (const callback of this.#onUnmountCallbacks) {\n callback();\n }\n }\n\n /**\n * Registers a `callback` to run after `Dolla.mount` is called, before the app is mounted. If `callback` returns a Promise,\n * it will be awaited before mounting finishes. Use this to perform initial setup before the app is displayed to the user.\n */\n beforeMount(callback: () => void | Promise<void>) {\n this.#beforeMountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after the app is mounted.\n */\n onMount(callback: () => void) {\n this.#onMountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after `Dolla.unmount` is called, before the app is unmounted. If `callback` returns a Promise,\n * it will be awaited before unmounting finishes. Use this to perform cleanup.\n */\n beforeUnmount(callback: () => void | Promise<void>) {\n this.#beforeUnmountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after the app is unmounted.\n */\n onUnmount(callback: () => void) {\n this.#onUnmountCallbacks.push(callback);\n }\n\n /**\n * Update log type toggles. Values that are not passed will remain unchanged.\n */\n setLoggles(options: Partial<Loggles>) {\n for (const key in options) {\n const value = options[key as keyof Loggles];\n if (value) {\n this.#loggles[key as keyof Loggles] = value;\n }\n }\n }\n\n setLogFilter(filter: string | RegExp) {\n this.#match = createMatcher(filter);\n }\n\n createLogger(name: string, options?: LoggerOptions): Logger {\n const _console = options?.console ?? getDefaultConsole();\n\n const self = this;\n const loggles = this.#loggles;\n\n const bind = (method: keyof Loggles) => {\n if (\n loggles[method] === false ||\n (isString(loggles[method]) && loggles[method] !== self.getEnv()) ||\n !this.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console[method].bind(\n _console,\n label,\n `color:${okhash(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n };\n\n return {\n setName(newName: string) {\n name = newName;\n return this;\n },\n get info() {\n return bind(\"info\");\n },\n get log() {\n return bind(\"log\");\n },\n get warn() {\n return bind(\"warn\");\n },\n get error() {\n return bind(\"error\");\n },\n crash(error: Error) {\n if (self.isMounted) {\n // Unmount the app.\n self.unmount();\n\n // Mount the crash page\n const crashPage = self.constructView(self.#crashView, {\n error,\n loggerName: name,\n uid: options?.uid,\n });\n crashPage.mount(self.#rootElement!);\n }\n\n // throw error;\n },\n };\n }\n\n /**\n *\n */\n constructView<P>(view: ViewFunction<P>, props: P, children: Markup[] = []): ViewElement {\n return new View(this.#rootElementContext, view, props, children);\n }\n\n /**\n *\n */\n constructMarkup(markup: Markup | Markup[]): MarkupElement {\n return groupElements(constructMarkup(this.#rootElementContext, markup));\n }\n}\n\nexport function getDefaultConsole() {\n if (typeof window !== \"undefined\" && window.console) {\n return window.console;\n }\n if (typeof global !== \"undefined\" && global.console) {\n return global.console;\n }\n}\n","// Signals\nexport { $, effect, get, peek } from \"./core/signals-api.js\";\nexport type { MaybeSignal, Signal, Source } from \"./core/signals-api.js\";\n\n// Equality checks\nexport { deepEqual, shallowEqual, strictEqual } from \"./utils.js\";\n\n// Store\nexport { type StoreContext, type StoreFunction } from \"./core/store.js\";\n\n// Router\nexport { createRouter, type Router, type RouterOptions } from \"./router/index.js\";\n\n// Markup\nexport { markup, portal, repeat, unless, when } from \"./core/markup.js\";\nexport type { Markup, MarkupElement } from \"./core/markup.js\";\n\nimport { Dolla } from \"./core/dolla.js\";\nconst dolla = new Dolla();\n\nexport default dolla;\n\nexport const t = dolla.i18n.t.bind(dolla.i18n);\nexport const i18n = dolla.i18n;\nexport const http = dolla.http;\n\nexport const createLogger = dolla.createLogger.bind(dolla);\n\n// Other types\nexport type { Dolla, Environment, Logger, LoggerErrorContext, LoggerOptions, Loggles } from \"./core/dolla.js\";\nexport type { ViewContext, ViewElement, ViewFunction } from \"./core/nodes/view.js\";\n// export type { HTTPRequest, HTTPResponse } from \"./modules/http.js\";\nexport type { CrashViewProps } from \"./core/views/default-crash-view.js\";\nexport type { InputType, Renderable } from \"./types.js\";\n\nimport type { IntrinsicElements as Elements } from \"./types\";\n\ndeclare global {\n namespace JSX {\n interface IntrinsicElements extends Elements {\n // Catch all for custom elements\n [tag: string]: any;\n }\n }\n}\n"],"names":["Passthrough","_","ctx","splitPath","path","assertString","f","joinPath","parts","assertArrayOf","part","isFunction","x","joined","_a","p","resolvePath","base","resolved","i","parseQueryParams","query","entries","entry","matchRoutes","routes","url","options","route","fragments","matched","frag","params","sortRoutes","withoutParams","withNumericParams","withParams","wildcard","bySizeDesc","a","b","patternToFragments","pattern","safeExternalLink","protocolLink","catchLinks","root","callback","_window","traverse","node","handler","e","anchor","replaceParams","key","value","createRouter","Router","ROUTER_MOUNT","ROUTER_UNMOUNT","_isRouter","IS_ROUTER","_mountRouter","router","dolla","_unmountRouter","__privateAdd","_Router_instances","__publicField","_dolla","_logger","_layerId","_activeLayers","_routes","_isMounted","_hash","_unsubscribers","_match","$","__privateGet","shallowEqual","assertObject","__privateSet","__privateMethod","prepareRoute_fn","assertValidRedirects","onPopState","updateRoute_fn","rootElement","href","preserve","parsePreserveQueryAttribute","steps","replace_fn","push_fn","values","match","queryParts","queryString","getCurrentURL_fn","logger","rootView","journey","resolveRoute_fn","step","oldPattern","peek","isArray","preserved","current","mountRoute_fn","NoRouteError","layers","matchedLayer","activeLayer","parentLayer","view","resolve","reject","redirect","finalize","isString","redirectContext","callbacks","next","parents","isObject","parent","layer","__privateWrapper","subroute","redirectPath","r","k","HTTP","_HTTP_instances","_middleware","_fetch","getDefaultFetch","fn","uri","request_fn","method","Runner","HTTPResponseError","response","status","statusText","message","Request","config","headers","name","mount","index","reqBody","req","fetched","contentType","body","Translation","_Translation_instances","_isLoaded","_templates","strings","res","compile_fn","selector","typeOf","parseTemplate_fn","template","Loc","Loc2","parsed","buffer","loc","segment","format","formatOptionName","startSegment","startFormat","I18n","_I18n_instances","_translations","_cache","_formats","_initialLocale","_locale","formatNumber_fn","formatDateTime_fn","formatList_fn","realName","names","nav","firstLanguage","translation","error","get","getValue_fn","count","date","list","locale","cached","getCached_fn","exact","output","formats","deepEqual","object","DefaultCrashView","props","m","when","Dolla","_env","_rootElement","_rootView","_crashView","_router","_beforeMountCallbacks","_onMountCallbacks","_beforeUnmountCallbacks","_onUnmountCallbacks","_rootElementContext","_loggles","createMatcher","_modules","store","instance","Store","StoreError","target","assertInstanceOf","rootViewMarkup","markup","register","filter","_console","getDefaultConsole","self","loggles","bind","noOp","label","okhash","newName","children","View","groupElements","constructMarkup","t","i18n","http","createLogger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/core/views/passthrough.ts","../src/router/router.utils.ts","../src/router/index.ts","../src/http/index.ts","../src/translate/index.ts","../src/core/views/default-crash-view.ts","../src/core/dolla.ts","../src/index.ts"],"sourcesContent":["import { type ViewContext } from \"../nodes/view.js\";\n\n/**\n * A utility view that simply displays a route.\n */\nexport function Passthrough(_: {}, ctx: ViewContext) {\n return ctx.outlet();\n}\n","import { assertString, assertArrayOf, isFunction } from \"../typeChecking.js\";\n\nexport type RouteMatch<T = Record<string, any>> = {\n /**\n * The path string that triggered this match.\n */\n path: string;\n\n /**\n * The pattern satisfied by `path`.\n */\n pattern: string;\n\n /**\n * Named params as parsed from `path`.\n */\n params: Record<string, string>;\n\n /**\n * Query params as parsed from `path`.\n */\n query: Record<string, string>;\n\n /**\n * Metadata registered to this route.\n */\n meta: T;\n};\n\nexport enum FragTypes {\n Literal = 1,\n Param = 2,\n Wildcard = 3,\n NumericParam = 4,\n}\n\nexport type RouteFragment = {\n name: string;\n type: FragTypes;\n value: string | number | null;\n};\n\nexport type ParsedRoute<T> = {\n pattern: string;\n fragments: RouteFragment[];\n meta: T;\n};\n\nexport type RouteMatchOptions<T> = {\n willMatch?: (route: ParsedRoute<T>) => boolean;\n};\n\n/**\n * Separates a URL path into multiple fragments.\n *\n * @param path - A path string (e.g. `\"/api/users/5\"`)\n * @returns an array of fragments (e.g. `[\"api\", \"users\", \"5\"]`)\n */\nexport function splitPath(path: string): string[] {\n assertString(path, \"Expected `path` to be a string. Got type: %t, value: %v\");\n\n return path\n .split(\"/\")\n .map((f) => f.trim())\n .filter((f) => f !== \"\");\n}\n\n/**\n * Joins multiple URL path fragments into a single string.\n *\n * @param parts - One or more URL fragments (e.g. `[\"api\", \"users\", 5]`)\n * @returns a joined path (e.g. `\"api/users/5\"`)\n */\nexport function joinPath(parts: { toString(): string }[]): string {\n assertArrayOf(\n (part) => isFunction(part?.toString),\n parts,\n \"Expected `parts` to be an array of objects with a .toString() method. Got type: %t, value: %v\",\n );\n\n parts = parts.filter((x) => x).flatMap(String);\n\n let joined = parts.shift()?.toString();\n\n if (joined) {\n for (const part of parts.map((p) => p.toString())) {\n if (part.startsWith(\".\")) {\n // Resolve relative path against joined\n joined = resolvePath(joined, part);\n } else if (joined[joined.length - 1] !== \"/\") {\n if (part[0] !== \"/\") {\n joined += \"/\" + part;\n } else {\n joined += part;\n }\n } else {\n if (part[0] === \"/\") {\n joined += part.slice(1);\n } else {\n joined += part;\n }\n }\n }\n\n // Remove trailing slash (unless path is just '/')\n if (joined && joined !== \"/\" && joined.endsWith(\"/\")) {\n joined = joined.slice(0, joined.length - 1);\n }\n }\n\n return joined ?? \"\";\n}\n\nexport function resolvePath(base: string, part: string | null) {\n assertString(base, \"Expected `base` to be a string. Got type: %t, value: %v\");\n\n if (part == null) {\n part = base;\n base = \"\";\n }\n\n if (part.startsWith(\"/\")) {\n return part;\n }\n\n let resolved = base;\n\n while (true) {\n if (part.startsWith(\"..\")) {\n for (let i = resolved.length; i > 0; --i) {\n if (resolved[i] === \"/\" || i === 0) {\n resolved = resolved.slice(0, i);\n part = part.replace(/^\\.\\.\\/?/, \"\");\n break;\n }\n }\n } else if (part.startsWith(\".\")) {\n part = part.replace(/^\\.\\/?/, \"\");\n } else {\n break;\n }\n }\n\n return joinPath([resolved, part]);\n}\n\nexport function parseQueryParams(query: string): Record<string, string> {\n if (!query) return {};\n\n if (query.startsWith(\"?\")) {\n query = query.slice(1);\n }\n\n const entries = query\n .split(\"&\")\n .filter((x) => x.trim() !== \"\")\n .map((entry) =>\n entry\n .split(\"=\")\n .map((x) => x.trim())\n .slice(0, 2),\n );\n\n return Object.fromEntries(entries);\n}\n\n/**\n * Returns the nearest match, or undefined if the path matches no route.\n *\n * @param url - Path to match against routes.\n * @param options - Options to customize how matching operates.\n */\nexport function matchRoutes<T>(\n routes: ParsedRoute<T>[],\n url: string,\n options: RouteMatchOptions<T> = {},\n): RouteMatch<T> | undefined {\n const [path, query] = url.split(\"?\");\n const parts = splitPath(path);\n\n routes: for (const route of routes) {\n const { fragments } = route;\n const hasWildcard = fragments[fragments.length - 1]?.type === FragTypes.Wildcard;\n\n if (!hasWildcard && fragments.length !== parts.length) {\n continue routes;\n }\n\n if (options.willMatch && !options.willMatch(route)) {\n continue routes;\n }\n\n const matched: RouteFragment[] = [];\n\n fragments: for (let i = 0; i < fragments.length; i++) {\n const part = parts[i];\n const frag = fragments[i];\n\n if (part == null && frag.type !== FragTypes.Wildcard) {\n continue routes;\n }\n\n switch (frag.type) {\n case FragTypes.Literal:\n if (frag.name.toLowerCase() === part.toLowerCase()) {\n matched.push(frag);\n break;\n } else {\n continue routes;\n }\n case FragTypes.Param:\n matched.push({ ...frag, value: part });\n break;\n case FragTypes.Wildcard:\n matched.push({ ...frag, value: parts.slice(i).join(\"/\") });\n break fragments;\n case FragTypes.NumericParam:\n if (!isNaN(Number(part))) {\n matched.push({ ...frag, value: part });\n break;\n } else {\n continue routes;\n }\n default:\n throw new Error(`Unknown fragment type: ${frag.type}`);\n }\n }\n\n const params: Record<string, string> = {};\n\n for (const frag of matched) {\n if (frag.type === FragTypes.Param) {\n params[frag.name] = decodeURIComponent(frag.value as string);\n }\n\n if (frag.type === FragTypes.NumericParam) {\n params[frag.name] = String(frag.value);\n }\n\n if (frag.type === FragTypes.Wildcard) {\n params.wildcard = \"/\" + decodeURIComponent(frag.value as string);\n }\n }\n\n return {\n path: \"/\" + matched.map((f) => f.value).join(\"/\"),\n pattern:\n \"/\" +\n fragments\n .map((f) => {\n if (f.type === FragTypes.Param) {\n return `{${f.name}}`;\n }\n\n if (f.type === FragTypes.NumericParam) {\n return `{#${f.name}}`;\n }\n\n return f.name;\n })\n .join(\"/\"),\n params,\n query: parseQueryParams(query),\n meta: route.meta,\n };\n }\n}\n\n/**\n * Sort routes descending by specificity. Guarantees that the most specific route matches first\n * no matter the order in which they were added.\n *\n * Routes without named params and routes with more fragments are weighted more heavily.\n */\nexport function sortRoutes<T>(routes: ParsedRoute<T>[]): ParsedRoute<T>[] {\n const withoutParams = [];\n const withNumericParams = [];\n const withParams = [];\n const wildcard = [];\n\n for (const route of routes) {\n const { fragments } = route;\n\n if (fragments.some((f) => f.type === FragTypes.Wildcard)) {\n wildcard.push(route);\n } else if (fragments.some((f) => f.type === FragTypes.NumericParam)) {\n withNumericParams.push(route);\n } else if (fragments.some((f) => f.type === FragTypes.Param)) {\n withParams.push(route);\n } else {\n withoutParams.push(route);\n }\n }\n\n const bySizeDesc = (a: ParsedRoute<T>, b: ParsedRoute<T>) => {\n if (a.fragments.length > b.fragments.length) {\n return -1;\n } else {\n return 1;\n }\n };\n\n withoutParams.sort(bySizeDesc);\n withNumericParams.sort(bySizeDesc);\n withParams.sort(bySizeDesc);\n wildcard.sort(bySizeDesc);\n\n return [...withoutParams, ...withNumericParams, ...withParams, ...wildcard];\n}\n\n/**\n * Converts a route pattern into a set of matchable fragments.\n *\n * @param route - A route string (e.g. \"/api/users/{id}\")\n */\nexport function patternToFragments(pattern: string): RouteFragment[] {\n const parts = splitPath(pattern);\n const fragments = [];\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n\n if (part === \"*\") {\n if (i !== parts.length - 1) {\n throw new Error(`Wildcard must be at the end of a pattern. Received: ${pattern}`);\n }\n fragments.push({\n type: FragTypes.Wildcard,\n name: \"*\",\n value: null,\n });\n } else if (part.at(0) === \"{\" && part.at(-1) === \"}\") {\n fragments.push({\n type: part[1] === \"#\" ? FragTypes.NumericParam : FragTypes.Param,\n name: part[1] === \"#\" ? part.slice(2, -1) : part.slice(1, -1),\n value: null,\n });\n } else {\n fragments.push({\n type: FragTypes.Literal,\n name: part,\n value: part,\n });\n }\n }\n\n return fragments;\n}\n\nconst safeExternalLink = /(noopener|noreferrer) (noopener|noreferrer)/;\nconst protocolLink = /^[\\w-_]+:/;\n\n/**\n * Intercepts links within the root node.\n *\n * This is adapted from https://github.com/choojs/nanohref/blob/master/index.js\n *\n * @param root - Element under which to intercept link clicks\n * @param callback - Function to call when a click event is intercepted\n * @param _window - (optional) Override for global window object\n */\nexport function catchLinks(root: Element, callback: (anchor: HTMLAnchorElement) => void, _window = window) {\n function traverse(node: HTMLElement | null): HTMLAnchorElement | null {\n if (!node || node === root) {\n return null;\n }\n\n if (node.localName !== \"a\" || (node as any).href === undefined) {\n return traverse(node.parentNode as HTMLElement | null);\n }\n\n return node as HTMLAnchorElement;\n }\n\n function handler(e: MouseEvent) {\n if ((e.button && e.button !== 0) || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey || e.defaultPrevented) {\n return;\n }\n\n const anchor = traverse(e.target as HTMLElement);\n\n if (!anchor) {\n return;\n }\n\n if (\n _window.location.protocol !== anchor.protocol ||\n _window.location.hostname !== anchor.hostname ||\n _window.location.port !== anchor.port ||\n anchor.hasAttribute(\"data-router-ignore\") ||\n anchor.hasAttribute(\"download\") ||\n (anchor.getAttribute(\"target\") === \"_blank\" && safeExternalLink.test(anchor.getAttribute(\"rel\")!)) ||\n protocolLink.test(anchor.getAttribute(\"href\")!)\n ) {\n return;\n }\n\n e.preventDefault();\n callback(anchor);\n }\n\n root.addEventListener(\"click\", handler as any);\n\n return function cancel() {\n root.removeEventListener(\"click\", handler as any);\n };\n}\n\n/**\n * Replace route pattern param placeholders with real matched values.\n */\nexport function replaceParams(path: string, params: Record<string, string | number>) {\n for (const key in params) {\n const value = params[key].toString();\n path = path.replace(`{${key}}`, value).replace(`{#${key}}`, value);\n }\n\n return path;\n}\n","import type { Dolla, Logger } from \"../core/dolla.js\";\nimport type { ViewElement, ViewFunction } from \"../core/nodes/view.js\";\nimport { $, peek, type UnsubscribeFunction } from \"../core/signals-api.js\";\nimport { IS_ROUTER } from \"../core/symbols.js\";\nimport { Passthrough } from \"../core/views/passthrough.js\";\nimport { assertObject, isArray, isFunction, isObject, isString } from \"../typeChecking.js\";\nimport type { Stringable } from \"../types.js\";\nimport { shallowEqual } from \"../utils.js\";\nimport {\n catchLinks,\n joinPath,\n matchRoutes,\n patternToFragments,\n replaceParams,\n resolvePath,\n sortRoutes,\n splitPath,\n type ParsedRoute,\n type RouteMatch,\n} from \"./router.utils.js\";\n\n// ----- Types ----- //\n\nexport interface RouteMatchContext {\n path: string;\n pattern: string;\n params: Record<string, string>;\n query: Record<string, string>;\n\n /**\n * Redirects the user to a different route instead of matching the current one.\n */\n redirect(path: string): void;\n\n /**\n * Triggers the next beforeMatch function, or mounts the route.\n */\n next(): void;\n}\n\nexport interface Route {\n /**\n * The path or path fragment to match.\n */\n path: string;\n\n /**\n * Path to redirect to when this route is matched, or a callback function that returns such path.\n */\n redirect?: string | ((ctx: RouteRedirectContext) => string) | ((ctx: RouteRedirectContext) => Promise<string>);\n\n /**\n * View to display when this route is matched.\n */\n view?: ViewFunction<any>;\n\n /**\n * Subroutes.\n */\n routes?: Route[];\n\n /**\n * Called after the match is identified but before it is acted on. Use this to set state, load data, etc.\n */\n beforeMatch?: (ctx: RouteMatchContext) => void | Promise<void>;\n}\n\nexport interface RouteMeta {\n redirect?: string | ((ctx: RouteRedirectContext) => string) | ((ctx: RouteRedirectContext) => Promise<string>);\n pattern?: string;\n layers?: RouteLayer[];\n beforeMatch?: ((ctx: RouteMatchContext) => void | Promise<void>)[];\n}\n\nexport interface RouteConfig {\n pattern: string;\n meta: RouteMeta;\n}\n\nexport interface RouteLayer {\n id: number;\n view: ViewFunction<{}>;\n}\n\n/**\n * An active route layer whose markup has been initialized into a view.\n */\ninterface ActiveLayer {\n id: number;\n view: ViewElement;\n}\n\n/**\n * Object passed to redirect callbacks. Contains information useful for determining how to redirect.\n */\nexport interface RouteRedirectContext {\n /**\n * The path as it appears in the URL bar.\n */\n path: string;\n\n /**\n * The pattern that this path was matched with.\n */\n pattern: string;\n\n /**\n * Named route params parsed from `path`.\n */\n params: Record<string, string>;\n\n /**\n * Query params parsed from `path`.\n */\n query: Record<string, string>;\n}\n\n/**\n * A log for a single step in the route resolution process.\n */\ninterface JourneyStep {\n kind: \"match\" | \"redirect\" | \"miss\";\n message: string;\n}\n\nexport interface NavigateOptions {\n /**\n * Replace the current item in the history stack instead of adding a new one.\n * The back button will send the user to the page they visited before this. Defaults to false.\n */\n replace?: boolean;\n\n /**\n * Preserve existing query params (if any) when navigating. Defaults to false.\n * If true, all existing query params are preserved and merged with new ones.\n * If an array of strings is passed only those keys will be preserved, then merged with any new ones.\n */\n preserveQuery?: boolean | string[];\n}\n\nexport interface RouterOptions {\n routes: Route[];\n\n /**\n * When true, the router will construct routes like \"https://www.example.com/#/sub/route\" which work without any backend intervention.\n */\n hash?: boolean;\n}\n\n// ----- Code ----- //\n\nexport function createRouter(options: RouterOptions): Router {\n return new Router(options);\n}\n\nconst ROUTER_MOUNT = Symbol.for(\"DollaRouterMountMethod\");\nconst ROUTER_UNMOUNT = Symbol.for(\"DollaRouterUnmountMethod\");\n\nexport function _isRouter(value: any): value is Router {\n return value?.[IS_ROUTER] === true;\n}\n\nexport async function _mountRouter(router: Router, dolla: Dolla) {\n return router[ROUTER_MOUNT](dolla);\n}\n\nexport async function _unmountRouter(router: Router) {\n return router[ROUTER_UNMOUNT]();\n}\n\nexport class Router {\n [IS_ROUTER] = true;\n\n #dolla?: Dolla;\n #logger?: Logger;\n\n #layerId = 0;\n #activeLayers: ActiveLayer[] = [];\n #routes: ParsedRoute<RouteMeta>[] = [];\n\n #isMounted = false;\n\n /**\n * Use hash routing when true. Configured in router options.\n */\n #hash = false;\n\n // Callbacks that need to be called on unmount.\n #unsubscribers: UnsubscribeFunction[] = [];\n\n /**\n * The current match object.\n */\n #match = $<RouteMatch>();\n\n /**\n * The currently matched route pattern, if any.\n */\n readonly pattern = $(() => this.#match()?.pattern);\n\n /**\n * The current URL path.\n */\n readonly path = $(() => this.#match()?.path ?? window.location.pathname);\n\n /**\n * The current named path params.\n */\n readonly params = $(() => this.#match()?.params ?? {}, { equals: shallowEqual });\n\n /**\n * The current query params. Changes to this object will be reflected in the URL.\n */\n readonly query = $(() => this.#match()?.query ?? {}, { equals: shallowEqual });\n\n constructor(options: RouterOptions) {\n assertObject(options, \"Options must be an object. Got: %t\");\n\n if (options.hash) {\n this.#hash = true;\n }\n\n // Add routes.\n this.#routes = sortRoutes(\n options.routes\n .flatMap((route) => this.#prepareRoute(route))\n .map((route) => ({\n pattern: route.pattern,\n meta: route.meta,\n fragments: patternToFragments(route.pattern),\n })),\n );\n\n console.log({ routes: options.routes, prepared: this.#routes });\n assertValidRedirects(this.#routes);\n }\n\n async [ROUTER_MOUNT](dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.router\");\n\n // Listen for popstate events and update route accordingly.\n const onPopState = () => {\n this.#updateRoute(undefined, {});\n };\n window.addEventListener(\"popstate\", onPopState);\n this.#unsubscribers.push(() => window.removeEventListener(\"popstate\", onPopState));\n\n const rootElement = dolla.getRootElement()!;\n\n // Listen for clicks on <a> tags within the app.\n this.#unsubscribers.push(\n catchLinks(rootElement, (anchor) => {\n let href = anchor.getAttribute(\"href\")!;\n this.#logger!.info(\"intercepted click on <a> tag\", anchor);\n\n const preserve = anchor.getAttribute(\"data-router-preserve-query\");\n\n this.go(href, {\n preserveQuery: parsePreserveQueryAttribute(preserve),\n });\n }),\n );\n this.#logger.info(\"will intercept clicks on <a> tags within root element\", rootElement);\n\n this.#isMounted = true;\n\n // Setup initial route content.\n await this.#updateRoute(undefined, {});\n }\n\n async [ROUTER_UNMOUNT]() {\n for (const callback of this.#unsubscribers) {\n callback();\n }\n this.#unsubscribers = [];\n }\n\n /**\n * Navigate backward. Pass a number of steps to hit the back button that many times.\n */\n back(steps = 1) {\n window.history.go(-steps);\n }\n\n /**\n * Navigate forward. Pass a number of steps to hit the forward button that many times.\n */\n forward(steps = 1) {\n window.history.go(steps);\n }\n\n /**\n * Navigates to another route.\n *\n * @example\n * router.go(\"/login\"); // navigate to `/login`\n * router.go[\"/users\", 215], { replace: true }); // replace current history entry with `/users/215`\n */\n go(path: Stringable | Stringable[], options: NavigateOptions = {}) {\n let joined: string;\n\n if (Array.isArray(path)) {\n joined = joinPath(path);\n } else {\n joined = path.toString();\n }\n\n joined = resolvePath(window.location.pathname, joined);\n\n if (options.replace) {\n this.#replace(joined, options);\n } else {\n this.#push(joined, options);\n }\n }\n\n /**\n * Updates query params, keeping existing ones and applying new ones. Removes the query param if value is set to `null`.\n */\n updateQuery(values: Record<string, Stringable | null>) {\n const match = peek(this.#match)!;\n const query = { ...this.query() };\n\n for (const key in values) {\n const value = values[key];\n if (value === null) {\n delete query[key];\n } else {\n query[key] = value.toString();\n }\n }\n\n let queryParts: string[] = [];\n\n for (const key in query) {\n queryParts.push(`${key}=${query[key]}`);\n }\n const queryString = queryParts.length > 0 ? \"?\" + queryParts.join(\"&\") : \"\";\n\n this.#match({ ...match, query });\n\n window.history.replaceState(null, \"\", this.#hash ? \"/#\" + match.path + queryString : match.path + queryString);\n }\n\n #push(href: string, options: NavigateOptions) {\n this.#logger?.info(\"(push)\", href);\n\n window.history.pushState(null, \"\", this.#hash ? \"/#\" + href : href);\n this.#updateRoute(href, options);\n }\n\n #replace(href: string, options: NavigateOptions) {\n this.#logger?.info(\"(replace)\", href);\n\n window.history.replaceState(null, \"\", this.#hash ? \"/#\" + href : href);\n this.#updateRoute(href, options);\n }\n\n #getCurrentURL(): URL {\n if (this.#hash) {\n return new URL(window.location.hash.slice(1), window.location.origin);\n } else {\n return new URL(window.location.pathname, window.location.origin);\n }\n }\n\n /**\n * Run when the location changes. Diffs and mounts new routes and updates\n * the $path, $route, $params and $query states accordingly.\n */\n async #updateRoute(href: string | undefined, options: NavigateOptions) {\n const logger = this.#logger;\n const rootView = this.#dolla?.getRootView();\n const url = href ? new URL(href, window.location.origin) : this.#getCurrentURL();\n\n const { match, journey } = await this.#resolveRoute(url);\n\n for (const step of journey) {\n switch (step.kind) {\n case \"match\":\n logger?.info(`📍 ${step.message}`);\n break;\n case \"redirect\":\n logger?.info(`↩️ ${step.message}`);\n break;\n case \"miss\":\n logger?.info(`💀 ${step.message}`);\n break;\n default:\n break;\n }\n }\n\n if (match) {\n const oldPattern = peek(this.pattern);\n\n // Merge query params.\n let query = match.query;\n let queryParts: string[] = [];\n\n if (options.preserveQuery === true) {\n query = Object.assign({}, this.query(), match.query);\n } else if (isArray(options.preserveQuery)) {\n const preserved: Record<string, any> = {};\n const current = this.query();\n for (const key in current) {\n if (options.preserveQuery.includes(key)) {\n preserved[key] = current[key];\n }\n }\n query = Object.assign({}, preserved, match.query);\n }\n\n for (const key in query) {\n queryParts.push(`${key}=${query[key]}`);\n }\n const queryString = queryParts.length > 0 ? \"?\" + queryParts.join(\"&\") : \"\";\n\n this.#match({ ...match, query });\n\n // Update the URL if matched path differs from navigator path.\n // This happens if route resolution involved redirects.\n if (rootView && (match.path !== location.pathname || location.search !== queryString)) {\n window.history.replaceState(null, \"\", this.#hash ? \"/#\" + match.path + queryString : match.path + queryString);\n }\n\n if (rootView && match.pattern !== oldPattern) {\n this.#mountRoute(rootView, match);\n }\n } else {\n // Only crash if routing has been configured.\n if (this.#isMounted) {\n logger!.crash(new NoRouteError(`Failed to match route '${url.pathname}'`));\n }\n }\n\n return { match, journey };\n }\n\n /**\n * Takes a matched route and mounts it.\n */\n #mountRoute(rootView: ViewElement, match: RouteMatch<RouteMeta>) {\n const layers = match.meta.layers!;\n\n // Diff and update route layers.\n for (let i = 0; i < layers.length; i++) {\n const matchedLayer = layers[i];\n const activeLayer = this.#activeLayers[i];\n\n if (activeLayer?.id !== matchedLayer.id) {\n // Discard all previously active layers starting at this depth.\n this.#activeLayers = this.#activeLayers.slice(0, i);\n activeLayer?.view.unmount();\n\n const parentLayer = this.#activeLayers.at(-1);\n const parent = parentLayer?.view ?? rootView;\n\n const view = parent.setRouteView(matchedLayer.view);\n this.#activeLayers.push({ id: matchedLayer.id, view });\n }\n }\n }\n\n /**\n * Takes a URL and finds a match, following redirects.\n */\n async #resolveRoute(\n url: URL,\n journey: JourneyStep[] = [],\n ): Promise<{\n match: RouteMatch<RouteMeta> | null;\n journey: JourneyStep[];\n }> {\n return new Promise((resolve, reject) => {\n const match = matchRoutes(this.#routes, url.pathname);\n\n if (!match) {\n return resolve({\n match: null,\n journey: [...journey, { kind: \"miss\", message: `no match for '${url.pathname}'` }],\n });\n }\n\n let redirect = match.meta.redirect;\n\n const finalize = async () => {\n if (redirect != null) {\n let path: string;\n\n if (isString(redirect)) {\n path = replaceParams(redirect, match.params);\n } else if (isFunction(redirect)) {\n const redirectContext: RouteRedirectContext = {\n path: match.path,\n pattern: match.pattern,\n params: match.params,\n query: match.query,\n };\n path = await redirect(redirectContext);\n if (!isString(path)) {\n return reject(new Error(`Redirect function must return a path to redirect to.`));\n }\n if (!path.startsWith(\"/\")) {\n // Not absolute. Resolve against matched path.\n path = resolvePath(match.path, path);\n }\n } else {\n return reject(new TypeError(`Redirect must either be a path string or a function.`));\n }\n\n resolve(\n this.#resolveRoute(new URL(path, window.location.origin), [\n ...journey,\n { kind: \"redirect\", message: `redirecting '${match.path}' -> '${path}'` },\n ]),\n );\n } else {\n resolve({ match, journey: [...journey, { kind: \"match\", message: `matched route '${match.path}'` }] });\n }\n };\n\n if (match.meta.beforeMatch?.length) {\n const callbacks = match.meta.beforeMatch;\n let i = -1;\n const next = () => {\n i++;\n if (i === callbacks.length) {\n // Mount route\n finalize();\n } else {\n // Next callback\n callbacks[i]({\n path: match.path,\n pattern: match.pattern,\n params: match.params,\n query: match.query,\n\n // TODO: Allow setting context variables from here? Would apply to the context of the matched view.\n redirect: (path) => {\n redirect = path;\n finalize();\n },\n\n next,\n });\n }\n };\n\n next();\n\n // TODO: Show warning after timeout if next hasn't been called?\n } else {\n finalize();\n }\n });\n }\n\n /**\n * Parses a route definition object into a set of matchable routes.\n *\n * @param route - Route config object.\n * @param layers - Array of parent layers. Passed when this function calls itself on nested routes.\n */\n #prepareRoute(route: Route, parents: Route[] = [], layers: RouteLayer[] = []) {\n if (!isObject(route) || !isString(route.path)) {\n throw new TypeError(`Route configs must be objects with a 'path' string property. Got: ${route}`);\n }\n\n if (route.redirect && route.routes) {\n throw new Error(`Route cannot have both a 'redirect' and nested 'routes'.`);\n } else if (route.redirect && route.view) {\n throw new Error(`Route cannot have both a 'redirect' and a 'view'.`);\n } else if (!route.view && !route.routes && !route.redirect) {\n throw new Error(`Route must have a 'view', a 'redirect', or a set of nested 'routes'.`);\n }\n\n let parts: string[] = [];\n\n for (const parent of parents) {\n parts.push(...splitPath(parent.path));\n }\n\n parts.push(...splitPath(route.path));\n\n // Remove trailing wildcard for joining with nested routes.\n if (parts[parts.length - 1] === \"*\") {\n parts.pop();\n }\n\n const routes: RouteConfig[] = [];\n\n if (route.redirect) {\n let redirect = route.redirect;\n\n if (isString(redirect)) {\n redirect = resolvePath(joinPath(parts), redirect);\n\n if (!redirect.startsWith(\"/\")) {\n redirect = \"/\" + redirect;\n }\n }\n\n routes.push({\n pattern: \"/\" + joinPath([...parts, ...splitPath(route.path)]),\n meta: {\n redirect,\n },\n });\n\n return routes;\n }\n\n let view: ViewFunction<any> = Passthrough;\n\n if (isFunction(route.view)) {\n view = route.view;\n } else if (route.view) {\n throw new TypeError(`Route '${route.path}' expected a view function or undefined. Got: ${route.view}`);\n }\n\n const layer: RouteLayer = { id: this.#layerId++, view };\n\n // Parse nested routes if they exist.\n if (route.routes) {\n for (const subroute of route.routes) {\n routes.push(...this.#prepareRoute(subroute, [...parents, route], [...layers, layer]));\n }\n } else {\n routes.push({\n pattern: parent ? joinPath([...parents.map((p) => p.path), route.path]) : route.path,\n meta: {\n pattern: route.path,\n layers: [...layers, layer],\n beforeMatch: parents\n .flatMap((parent) => parent.beforeMatch)\n .concat(route.beforeMatch)\n .filter((x) => x != null),\n },\n });\n }\n\n return routes;\n }\n}\n\nfunction assertValidRedirects(routes: ParsedRoute<RouteMeta>[]) {\n // Test redirects to make sure all possible redirect targets actually exist.\n for (const route of routes) {\n if (route.meta.redirect) {\n let redirectPath: string;\n\n if (isFunction(route.meta.redirect)) {\n // throw new Error(`Redirect functions are not yet supported.`);\n // Just allow, though it could fail later. Best not to call the function and cause potential side effects.\n } else if (isString(route.meta.redirect)) {\n redirectPath = route.meta.redirect;\n\n const match = matchRoutes(routes, redirectPath, {\n willMatch(r) {\n return r !== route;\n },\n });\n\n if (!match) {\n throw new Error(`Found a redirect to an undefined URL. From '${route.pattern}' to '${route.meta.redirect}'`);\n }\n } else {\n throw new TypeError(`Expected a string or redirect function. Got: ${route.meta.redirect}`);\n }\n }\n }\n}\n\n/**\n * Parses the data-router-preserve-query attribute from a link.\n */\nfunction parsePreserveQueryAttribute(value: null | string | boolean): boolean | string[] {\n if (value === null) {\n return false;\n } else if (value === true || value === false) {\n return value;\n } else if (typeof value === \"string\") {\n value = value.trim();\n if (value === \"\" || value === \"true\") {\n return true;\n } else if (value === \"false\") {\n return false;\n }\n\n return value\n .split(\",\")\n .map((k) => k.trim())\n .filter((k) => k.length > 0);\n } else {\n throw new Error(`Invalid type for data-router-preserve-query attribute: ${typeof value} (value: ${value})`);\n }\n}\n\nclass NoRouteError extends Error {}\n","import { isObject } from \"../typeChecking.js\";\n\n/**\n * A simple HTTP client with middleware support. Middleware applies to all requests made through this store,\n * so it's the perfect way to handle things like auth headers and permission checks for API calls.\n */\nexport class HTTP {\n #middleware: HTTPMiddleware[] = [];\n #fetch = getDefaultFetch();\n\n /**\n * Adds a new middleware that will apply to subsequent requests.\n * Returns a function to remove this middleware.\n *\n * @param middleware - A middleware function that will intercept requests.\n */\n use(fn: HTTPMiddleware) {\n this.#middleware.push(fn);\n\n // Call returned function to remove this middleware for subsequent requests.\n return () => {\n this.#middleware.splice(this.#middleware.indexOf(fn), 1);\n };\n }\n\n async get<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"get\", uri, options);\n }\n\n async put<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"put\", uri, options);\n }\n\n async patch<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"patch\", uri, options);\n }\n\n async post<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"post\", uri, options);\n }\n\n async delete<ResBody = unknown>(uri: string, options?: RequestOptions<never>) {\n return this.#request<ResBody, never>(\"delete\", uri, options);\n }\n\n async head<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"head\", uri, options);\n }\n\n async options<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"options\", uri, options);\n }\n\n async trace<ResBody = unknown, ReqBody = unknown>(uri: string, options?: RequestOptions<ReqBody>) {\n return this.#request<ResBody, ReqBody>(\"trace\", uri, options);\n }\n\n async #request<ResBody, ReqBody>(method: string, uri: string, options?: RequestOptions<any>) {\n const runner = new Runner<ResBody, ReqBody>({\n ...options,\n method,\n uri,\n middleware: this.#middleware,\n fetch: this.#fetch,\n });\n return runner.fetch();\n }\n}\n\nfunction getDefaultFetch(): typeof window.fetch {\n if (typeof window !== \"undefined\" && window.fetch) {\n return window.fetch.bind(window);\n }\n\n if (typeof global !== \"undefined\" && global.fetch) {\n return global.fetch.bind(global);\n }\n\n throw new Error(\"Running in neither browser nor node. Please run this app in one of the supported environments.\");\n}\n\n/*====================*\\\n|| Request ||\n\\*====================*/\n\nexport type HTTPMiddleware = (\n request: HTTPRequest<unknown>,\n next: () => Promise<HTTPResponse<unknown>>,\n) => void | Promise<void>;\n\nexport interface RequestOptions<ReqBody> {\n /**\n * Body to send with the request.\n */\n body?: ReqBody;\n\n /**\n * Headers to send with the request.\n */\n headers?: Record<string, any> | Headers;\n\n /**\n * Query params to interpolate into the URL.\n */\n query?: Record<string, any> | URLSearchParams;\n}\n\nexport interface HTTPRequest<Body> {\n method: string;\n url: URL;\n headers: Headers;\n body: Body;\n}\n\nexport interface HTTPResponse<Body> {\n method: string;\n url: URL;\n headers: Headers;\n status: number;\n statusText: string;\n body: Body;\n}\n\ninterface MakeRequestConfig<ReqBody> extends RequestOptions<ReqBody> {\n method: string;\n uri: string;\n middleware: HTTPMiddleware[];\n fetch: typeof window.fetch;\n}\n\nexport class HTTPResponseError extends Error {\n response;\n\n constructor(response: HTTPResponse<any>) {\n const { status, statusText, method, url } = response;\n const message = `${status} ${statusText}: Request failed (${method.toUpperCase()} ${url.toString()})`;\n\n super(message);\n\n this.response = response;\n }\n}\n\nclass Request<ReqBody> implements HTTPRequest<ReqBody> {\n method: string;\n url: URL;\n headers = new Headers();\n body!: ReqBody;\n\n get isSameOrigin() {\n return this.url.origin === window.location.origin;\n }\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this.method = config.method;\n this.body = config.body!;\n if (config.uri.startsWith(\"http\")) {\n this.url = new URL(config.uri);\n } else {\n this.url = new URL(config.uri, window.location.origin);\n }\n\n this._applyHeaders(config.headers);\n this._applyQueryParams(config.query);\n }\n\n private _applyHeaders(headers: any) {\n if (headers == null) return;\n\n if (headers instanceof Map || headers instanceof Headers) {\n headers.forEach((value, key) => {\n this.headers.set(key, value);\n });\n } else if (isObject(headers)) {\n for (const name in headers) {\n const value = headers[name];\n if (value instanceof Date) {\n this.headers.set(name, value.toISOString());\n } else if (value != null) {\n this.headers.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown headers type. Got: ${headers}`);\n }\n }\n\n private _applyQueryParams(query: any) {\n if (query == null) return;\n\n if (query instanceof Map || query instanceof URLSearchParams) {\n query.forEach((value, key) => {\n this.url.searchParams.set(key, value);\n });\n } else if (isObject(query)) {\n for (const name in query) {\n const value = query[name];\n if (value instanceof Date) {\n this.url.searchParams.set(name, value.toISOString());\n } else if (value != null) {\n this.url.searchParams.set(name, String(value));\n }\n }\n } else {\n throw new TypeError(`Unknown query params type. Got: ${query}`);\n }\n }\n}\n\nclass Runner<ResBody, ReqBody> {\n private _middleware;\n private _fetch;\n\n private _request: Request<ReqBody>;\n private _response?: HTTPResponse<ResBody>;\n\n constructor(config: MakeRequestConfig<ReqBody>) {\n this._middleware = config.middleware;\n this._fetch = config.fetch;\n\n this._request = new Request(config);\n }\n\n async fetch() {\n if (this._middleware.length > 0) {\n const mount = (index = 0) => {\n const current = this._middleware[index];\n const next = this._middleware[index + 1] ? mount(index + 1) : this._handler.bind(this);\n\n return async () =>\n current(this._request, async () => {\n await next();\n return this._response!;\n });\n };\n\n await mount()();\n } else {\n await this._handler();\n }\n\n if (this._response!.status < 200 || this._response!.status >= 400) {\n throw new HTTPResponseError(this._response!);\n }\n\n return this._response!;\n }\n\n // This is the function that performs the actual request after the final middleware.\n private async _handler() {\n let reqBody: BodyInit;\n\n const req = this._request;\n\n if (!req.headers.has(\"content-type\") && isObject(req.body)) {\n // Auto-detect JSON bodies and encode as a string with correct headers.\n req.headers.set(\"content-type\", \"application/json\");\n reqBody = JSON.stringify(req.body);\n } else {\n reqBody = req.body as BodyInit;\n }\n\n const fetched = await this._fetch(req.url.toString(), {\n method: req.method,\n headers: req.headers,\n body: reqBody,\n });\n\n // Auto-parse response body based on content-type header\n const contentType = fetched.headers.get(\"content-type\");\n\n let body: ResBody;\n\n if (contentType?.includes(\"application/json\")) {\n body = await fetched.json();\n } else if (contentType?.includes(\"application/x-www-form-urlencoded\")) {\n body = (await fetched.formData()) as ResBody;\n } else {\n body = (await fetched.text()) as ResBody;\n }\n\n this._response = {\n method: req.method,\n url: req.url,\n status: fetched.status,\n statusText: fetched.statusText,\n headers: fetched.headers,\n body,\n };\n }\n}\n","import type { Dolla, Logger } from \"../core/dolla.js\";\nimport { $, get, type MaybeSignal, type Signal } from \"../core/signals-api.js\";\nimport { isFunction, isObject, isString, typeOf } from \"../typeChecking.js\";\nimport { deepEqual } from \"../utils.js\";\n\n// ----- Types ----- //\n\n/**\n * A JSON object of translated strings. Values can be string templates or nested objects.\n */\ninterface LocalizedStrings extends Record<string, string | LocalizedStrings> {}\n\nenum SegmentType {\n Static,\n Variable,\n}\ntype StringTemplate = { segments: (StaticSegment | VariableSegment)[] };\n/**\n * A string segment with literal text to be appended without processing.\n */\ntype StaticSegment = {\n type: SegmentType.Static;\n text: string;\n};\n/**\n * A variable passed to the t() function. Needs to be formatted before it is appended.\n */\ntype VariableSegment = {\n type: SegmentType.Variable;\n name: string;\n formats: Format[];\n};\n/**\n * A formatter to be applied to a variable.\n */\ntype Format = {\n name: string;\n options: Record<string, any>;\n};\n\nexport interface TranslationConfig {\n /**\n * Name of the locale this translation is for (BCP 47 locale names recommended).\n */\n locale: string;\n\n /**\n * An object with translated strings for this language.\n */\n strings?: LocalizedStrings;\n\n /**\n * A callback function that returns a Promise that resolves to the translation object for this language.\n */\n fetch?: () => Promise<LocalizedStrings>;\n\n /**\n * Path to a JSON file with translated strings for this language.\n */\n path?: string;\n}\n\nexport type I18nSetupOptions = {\n /**\n * Default locale to load on startup\n */\n locale?: string | null;\n\n translations: TranslationConfig[];\n};\n\nexport type TOptions = {\n /**\n *\n */\n count?: MaybeSignal<number>;\n\n /**\n *\n */\n context?: MaybeSignal<string>;\n\n /**\n * Override formats specified in the template with the ones in the array for each named variable.\n *\n * @example\n * t(\"example_key\", {\n * count: 5,\n * formatOverrides: {\n * count: [ { name: \"datetime\", options: { style: \"currency\", currency: \"JPY\" } } ]\n * }\n * });\n */\n formatOverrides?: MaybeSignal<Record<string, Record<string, Format[]>>>;\n\n [value: string]: MaybeSignal<any>;\n};\n\nexport type Formatter = (locale: string, value: unknown, options: Record<string, any>) => string;\n\n// ----- Code ----- //\n\nclass Translation {\n dolla: Dolla;\n config: TranslationConfig;\n\n #isLoaded = false;\n\n #templates = new Map<string, StringTemplate>();\n\n constructor(config: TranslationConfig, dolla: Dolla) {\n this.config = config;\n this.dolla = dolla;\n }\n\n async load(): Promise<void> {\n let strings: LocalizedStrings | undefined;\n\n if (!this.#isLoaded) {\n if (isObject(this.config.strings)) {\n strings = this.config.strings;\n } else if (isFunction(this.config.fetch)) {\n strings = await this.config.fetch();\n if (!isObject(strings)) {\n throw new Error(`Fetch function did not return an object of language strings: ${strings}`);\n }\n } else if (isString(this.config.path)) {\n const res = await fetch(this.config.path);\n if (res.ok) {\n const body = await res.json();\n if (isObject(body)) {\n strings = body as LocalizedStrings;\n } else {\n throw new Error(\n `Language path '${this.config.path}' did not return an object of language strings: ${body}`,\n );\n }\n } else {\n throw new Error(`HTTP request failed.`);\n }\n }\n }\n\n if (strings) {\n const entries = this.#compile(strings);\n for (const entry of entries) {\n this.#templates.set(entry[0], entry[1]);\n }\n } else {\n throw new Error(`Language could not be loaded.`);\n }\n }\n\n getTemplate(selector: string): StringTemplate {\n return (\n this.#templates.get(selector) ?? {\n segments: [{ type: SegmentType.Static, text: `[MISSING: ${selector}]` }],\n }\n );\n }\n\n hasTemplate(selector: string): boolean {\n return this.#templates.has(selector);\n }\n\n #compile(strings: { [key: string]: any }, path: string[] = []): [string, StringTemplate][] {\n const entries: [string, StringTemplate][] = [];\n\n for (const key in strings) {\n switch (typeOf(strings[key])) {\n case \"string\":\n entries.push([[...path, key].join(\".\"), this.#parseTemplate(strings[key])]);\n break;\n case \"object\":\n entries.push(...this.#compile(strings[key], [...path, key]));\n break;\n default:\n throw new Error(\n `Expected to find a string or object at ${[...path, key].join(\".\")}. Got: ${typeOf(strings[key])}`,\n );\n }\n }\n\n return entries;\n }\n\n #parseTemplate(template: string): StringTemplate {\n // \"{{itemName}} costs {{amount | number(style: currency, currency: USD)}}.\"\n\n enum Loc {\n /**\n * Outside value braces.\n */\n Static,\n /**\n * Inside value braces; currently parsing the name of the value. e.g. `{{ [name] | number(style: currency, currency: USD) }}`\n */\n ValueName,\n /**\n * Inside value braces; currently parsing the name of a format function. e.g. `{{ name | [number](style: currency, currency: USD) }}`\n */\n FormatName,\n /**\n * Inside value braces; currently parsing the name of a format option. e.g. `{{ name | number([style]: currency, currency: USD) }}`\n */\n FormatOptionName,\n /**\n * Inside value braces; currently parsing the value of a format option. e.g. `{{ name | number(style: [currency], currency: USD ) }}`\n */\n FormatOptionValue,\n /**\n * Inside value braces; just reached the closing bracket of a format option. e.g. `{{ name | number(style: [currency], currency: USD) [] }}`\n */\n FormatOptionEnd,\n }\n\n const parsed: StringTemplate = {\n segments: [],\n };\n\n let buffer = \"\";\n let i = 0;\n let loc: Loc = Loc.Static;\n let segment!: VariableSegment;\n let format!: VariableSegment[\"formats\"][0];\n\n let formatOptionName!: string;\n\n const startSegment = () => {\n segment = {\n type: SegmentType.Variable,\n name: \"\",\n formats: [],\n };\n };\n\n const startFormat = () => {\n format = {\n name: \"\",\n options: {},\n };\n };\n\n while (i < template.length) {\n // Skip spaces (unless we're in static)\n if (loc !== Loc.Static && template[i] === \" \") {\n i++;\n continue;\n }\n\n switch (loc) {\n case Loc.Static:\n if (template[i] === \"{\" && template[i + 1] === \"{\") {\n loc = Loc.ValueName;\n i += 2;\n // close static segment\n if (buffer.length > 0) {\n parsed.segments.push({ type: SegmentType.Static, text: buffer });\n buffer = \"\";\n }\n startSegment();\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.ValueName:\n if (template[i] === \"|\") {\n loc = Loc.FormatName;\n i += 1;\n // add name to value segment\n segment.name = buffer;\n buffer = \"\";\n startFormat();\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // close value segment\n segment.name = buffer;\n buffer = \"\";\n parsed.segments.push(segment);\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatName:\n if (template[i] === \"(\") {\n loc = Loc.FormatOptionName;\n i += 1;\n // add name to format object\n format.name = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // close format and value segment\n segment.formats.push(format);\n parsed.segments.push(segment);\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionName:\n if (template[i] === \")\") {\n // TODO: error - no value provided for option\n } else if (template[i] === \":\") {\n loc = Loc.FormatOptionValue;\n i += 1;\n // add name to format option object\n formatOptionName = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n // TODO: error - format options parenthesis not closed\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionValue:\n if (template[i] === \")\") {\n loc = Loc.FormatOptionEnd;\n i += 1;\n // add value to format option object\n // add format option to format object; we're done with this format\n format.options[formatOptionName] = buffer;\n buffer = \"\";\n segment.formats.push(format);\n } else if (template[i] === \",\") {\n loc = Loc.FormatOptionName;\n i += 1;\n // add value to format option object\n // add format option to format object; we're adding another option\n format.options[formatOptionName] = buffer;\n buffer = \"\";\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n // TODO: error - format options parenthesis not closed\n } else {\n buffer += template[i];\n i++;\n }\n break;\n case Loc.FormatOptionEnd:\n if (template[i] === \"|\") {\n loc = Loc.FormatName;\n i += 1;\n startFormat();\n } else if (template[i] === \"}\" && template[i + 1] === \"}\") {\n loc = Loc.Static;\n i += 2;\n // add value segment\n parsed.segments.push(segment);\n } else {\n // TODO: error - no other valid characters\n }\n break;\n }\n }\n\n if (loc === Loc.Static && buffer.length > 0) {\n parsed.segments.push({ type: SegmentType.Static, text: buffer });\n }\n\n return parsed;\n }\n}\n\n/**\n * Dolla's I(nternationalizatio)n module. Manages language translations and locale-based formatting.\n */\nexport class I18n {\n #dolla: Dolla;\n #logger: Logger;\n #translations = new Map<string, Translation>();\n #cache: [key: string, values: Record<string, any> | undefined, output: string][] = [];\n #formats = new Map<string, Formatter>();\n\n #initialLocale = \"auto\";\n\n #locale = $<string>(\"en\");\n\n readonly locale = $(this.#locale);\n\n constructor(dolla: Dolla) {\n this.#dolla = dolla;\n this.#logger = dolla.createLogger(\"Dolla.i18n\");\n\n this.addFormat(\"number\", (_, value, options) => {\n return this.#formatNumber(Number(value), options);\n });\n this.addFormat(\"datetime\", (_, value, options) => {\n return this.#formatDateTime(value as any, options);\n });\n this.addFormat(\"list\", (_, value, options) => {\n return this.#formatList(value as any, options);\n });\n\n /**\n * Load language before the app mounts.\n */\n dolla.beforeMount(async () => {\n if (this.#translations.size > 0) {\n await this.setLocale(this.#initialLocale);\n }\n });\n }\n\n get locales() {\n return [...this.#translations.keys()];\n }\n\n setup(options: I18nSetupOptions) {\n // Convert languages into Language instances.\n options.translations.forEach((entry) => {\n this.#translations.set(entry.locale, new Translation(entry, this.#dolla));\n });\n\n // Check that initialLanguage is actually registered.\n if (options.locale && options.locale !== \"auto\") {\n const isRegistered = options.translations.some((entry) => entry.locale === options.locale);\n if (!isRegistered) {\n throw new Error(`Initial locale '${options.locale}' is not registered in the locales array.`);\n }\n this.#initialLocale = options.locale;\n }\n\n this.#logger.info(\n `${this.#translations.size} language${this.#translations.size === 1 ? \"\" : \"s\"} supported: '${[...this.#translations.keys()].join(\"', '\")}'`,\n );\n }\n\n async setLocale(name: string) {\n let realName!: string;\n\n if (name === \"auto\") {\n let names = [];\n\n if (typeof navigator !== \"undefined\") {\n const nav = navigator as any;\n\n if (nav.languages?.length > 0) {\n names.push(...nav.languages);\n } else if (nav.language) {\n names.push(nav.language);\n } else if (nav.browserLanguage) {\n names.push(nav.browserLanguage);\n } else if (nav.userLanguage) {\n names.push(nav.userLanguage);\n }\n }\n\n for (const name of names) {\n if (this.#translations.has(name)) {\n // Found a matching language.\n realName = name;\n }\n }\n } else {\n // Tag is the actual tag to set.\n if (this.#translations.has(name)) {\n realName = name;\n }\n }\n\n if (realName == null) {\n const firstLanguage = this.#translations.keys().next().value;\n if (firstLanguage) {\n realName = firstLanguage;\n }\n }\n\n if (!realName || !this.#translations.has(realName)) {\n throw new Error(`Locale '${name}' has no translation.`);\n }\n\n const translation = this.#translations.get(realName)!;\n\n try {\n await translation.load();\n\n this.#cache = [];\n this.#locale(realName);\n\n this.#logger.info(\"set language to \" + realName);\n } catch (error) {\n if (error instanceof Error) {\n this.#logger.crash(error);\n }\n }\n }\n\n /**\n * Returns a State containing the value at `key`.\n\n * @param selector - Key to the translated value.\n * @param options - A map of `{{placeholder}}` names and the values to replace them with.\n *\n * @example\n * const $value = t(\"your.key.here\", { count: 5 });\n */\n t(selector: string, options?: TOptions): Signal<string> {\n if (this === undefined) {\n throw new Error(\n `The 't' function cannot be destructured. If you need a standalone version you can import it like so: 'import { t } from \"@manyducks.co/dolla\"'`,\n );\n }\n\n return $(() => {\n const values: Record<string, any> = {};\n\n // Track all option values.\n for (const key in options) {\n values[key] = get(options[key]);\n }\n\n return this.#getValue(this.#locale(), selector, values);\n });\n }\n\n #getValue(locale: string, selector: string, options: Record<string, any>): string {\n const cached = this.#getCached(selector, options);\n if (cached) return cached;\n\n const translation = this.#translations.get(locale)!;\n\n // Handle count (pluralization) and context. Keys become \"key_context_pluralization\".\n\n if (options.context != null) {\n selector += \"_\" + options.context;\n }\n if (options.count != null) {\n if (options.ordinal) {\n // Try to match the exact number key if there is one (e.g. \"myExampleKey_ordinal_(=2)\" when count is 2).\n const exact = `${selector}_ordinal_(=${options.count})`;\n if (translation.hasTemplate(exact)) {\n selector = exact;\n } else {\n selector += \"_ordinal_\" + new Intl.PluralRules(locale, { type: \"ordinal\" }).select(options.count);\n }\n } else {\n // Try to match the exact number key if there is one (e.g. \"myExampleKey_(=2)\" when count is 2).\n const exact = `${selector}_(=${options.count})`;\n if (translation.hasTemplate(exact)) {\n selector = exact;\n } else {\n selector += \"_\" + new Intl.PluralRules(locale).select(options.count);\n }\n }\n }\n\n const template = translation.getTemplate(selector);\n let output = \"\";\n\n for (const segment of template.segments) {\n if (segment.type === SegmentType.Static) {\n output += segment.text;\n } else if (segment.type === SegmentType.Variable) {\n let value = resolve(options, segment.name);\n\n const formats = options.formatOverrides?.[segment.name] ?? [...segment.formats];\n\n if (segment.name === \"count\" && formats.length === 0) {\n formats.push({ name: \"number\", options: {} });\n }\n\n for (const format of formats) {\n const fn = this.#formats.get(format.name);\n if (fn == null) {\n const error = new Error(\n `Failed to load format '${format.name}' when processing '${selector}', template: ${template}`,\n );\n this.#logger.crash(error);\n throw error;\n }\n value = fn(locale, value, format.options);\n }\n\n output += value;\n }\n }\n\n return output;\n }\n\n /**\n * Add a custom format callback.\n *\n * @example\n * Dolla.i18n.addFormat(\"uppercase\", (locale, value, options) => {\n * return value.toUpperCase();\n * });\n *\n * {\n * \"greeting\": \"Hello, {{name|uppercase}}!\"\n * }\n *\n * t(\"greeting\", {name: \"world\"}); // State<\"Hello, WORLD!\">\n */\n addFormat(name: string, callback: (locale: string, value: unknown, options: Record<string, any>) => string) {\n this.#formats.set(name, callback);\n }\n\n /**\n * Creates an `Intl.Collator` configured for the current locale.\n * NOTE: The locale is tracked if called within a signal tracking context.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Collator/Collator#options\n */\n collator(options?: Intl.CollatorOptions) {\n return new Intl.Collator(this.#locale(), options);\n }\n\n /**\n * Formats a number for the current locale. Uses `Intl.NumberFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#options\n */\n number(count: MaybeSignal<number | bigint>, options?: Intl.NumberFormatOptions): Signal<string> {\n return $(() => this.#formatNumber(get(count), options));\n }\n\n #formatNumber(count: number | bigint, options?: Intl.NumberFormatOptions): string {\n // NOTE: Locale is tracked if called within a tracking context.\n return new Intl.NumberFormat(this.#locale(), options).format(count);\n }\n\n /**\n * Formats a date for the current locale. Uses `Intl.DateTimeFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options\n *\n * @example\n * const date = new Date();\n * const $formatted = Dolla.i18n.dateTime(date, { dateFormat: \"short\" });\n */\n dateTime(\n date?: MaybeSignal<string | number | Date | undefined>,\n options?: Intl.DateTimeFormatOptions,\n ): Signal<string> {\n return $(() => this.#formatDateTime(get(date), options));\n }\n\n #formatDateTime(date?: string | number | Date, options?: Intl.DateTimeFormatOptions): string {\n // NOTE: Locale is tracked if called within a tracking context.\n return new Intl.DateTimeFormat(this.#locale(), options).format(isString(date) ? new Date(date) : date);\n }\n\n /**\n * Formats a list for the current locale. Uses `Intl.ListFormat` under the hood.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat#options\n *\n * @example\n * const list = new Date();\n * const $formatted = Dolla.i18n.list(list, { });\n */\n list(list: MaybeSignal<Iterable<string>>, options?: Intl.ListFormatOptions): Signal<string> {\n return $(() => this.#formatList(get(list), options));\n }\n\n #formatList(list: Iterable<string>, options?: Intl.ListFormatOptions): string {\n // NOTE: Locale is tracked if called within a tracking context.\n return new Intl.ListFormat(this.#locale(), options).format(list);\n }\n\n // relativeTime(): State<string> {\n\n // }\n\n #getCached(key: string, values?: Record<string, any>): string | undefined {\n for (const entry of this.#cache) {\n if (entry[0] === key && deepEqual(entry[1], values)) {\n return entry[2];\n }\n }\n }\n}\n\nfunction resolve(object: any, key: string) {\n const parsed = String(key)\n .split(/[\\.\\[\\]]/)\n .filter((part) => part.trim() !== \"\");\n let value = object;\n\n while (parsed.length > 0) {\n const part = parsed.shift()!;\n\n if (value != null) {\n value = value[part];\n } else {\n value = undefined;\n }\n }\n\n return value;\n}\n","import { when, markup as m } from \"../markup.js\";\n\n/**\n * Props passed to the crash view when a crash occurs.\n */\nexport type CrashViewProps = {\n /**\n * JavaScript Error object.\n */\n error: Error;\n\n /**\n * A string to identify the logger that reported this error.\n */\n loggerName: string;\n\n /**\n * Unique identifier to pinpoint the specific view that reported the crash.\n */\n uid?: string;\n};\n\nexport function DefaultCrashView(props: CrashViewProps) {\n return m(\n \"div\",\n {\n style: {\n backgroundColor: \"#880000\",\n color: \"#fff\",\n padding: \"2rem\",\n position: \"fixed\",\n inset: 0,\n fontSize: \"20px\",\n },\n },\n m(\"h1\", { style: { marginBottom: \"0.5rem\" } }, \"The app has crashed\"),\n m(\n \"p\",\n { style: { marginBottom: \"0.25rem\" } },\n m(\"span\", { style: { fontFamily: \"monospace\" } }, props.loggerName),\n when(props.uid, m(\"span\", { style: { fontFamily: \"monospace\", opacity: 0.5 } }, ` [uid: ${props.uid}]`)),\n \" says:\",\n ),\n m(\n \"blockquote\",\n {\n style: {\n backgroundColor: \"#991111\",\n padding: \"0.25em\",\n borderRadius: \"6px\",\n fontFamily: \"monospace\",\n marginBottom: \"1rem\",\n },\n },\n m(\n \"span\",\n {\n style: {\n display: \"inline-block\",\n backgroundColor: \"red\",\n padding: \"0.1em 0.4em\",\n marginRight: \"0.5em\",\n borderRadius: \"4px\",\n fontSize: \"0.9em\",\n fontWeight: \"bold\",\n },\n },\n props.error.name,\n ),\n props.error.message,\n ),\n m(\"p\", {}, \"Please see the browser console for details.\"),\n );\n}\n","import { HTTP } from \"../http/index.js\";\nimport { _isRouter, _mountRouter, _unmountRouter, type Router } from \"../router/index.js\";\nimport { I18n } from \"../translate/index.js\";\nimport { assertInstanceOf, isFunction, isString } from \"../typeChecking.js\";\nimport { okhash, createMatcher, noOp } from \"../utils.js\";\nimport type { ElementContext, StoreConsumerContext, StoreProviderContext } from \"./context.js\";\nimport { constructMarkup, markup, groupElements, type Markup, type MarkupElement } from \"./markup.js\";\nimport { View, type ViewElement, type ViewFunction } from \"./nodes/view.js\";\nimport { Store, StoreError, StoreFunction } from \"./store.js\";\nimport { DefaultCrashView, type CrashViewProps } from \"./views/default-crash-view.js\";\nimport { Passthrough } from \"./views/passthrough.js\";\n\n// Affects which log messages will print and how much debugging info is included in the DOM.\nexport type Environment = \"development\" | \"production\";\n\n/**\n * Log type toggles. Each message category can be turned on or off or enabled only in a specific environment.\n */\nexport type Loggles = {\n info: boolean | Environment;\n log: boolean | Environment;\n warn: boolean | Environment;\n error: boolean | Environment;\n};\n\nexport interface Logger {\n info(...args: any[]): void;\n log(...args: any[]): void;\n warn(...args: any[]): void;\n error(...args: any[]): void;\n crash(error: Error): void;\n\n setName(name: string): Logger;\n}\n\nexport interface LoggerErrorContext {\n error: Error;\n loggerName: string;\n uid?: string;\n}\n\nexport type LoggerOptions = {\n /**\n * Console object to use for logging (mostly for testing). Uses window.console by default.\n */\n console?: any;\n\n /**\n * Unique ID to print with logs. Makes it easier to track down messages from specific view instances.\n */\n uid?: string;\n};\n\nexport class Dolla implements StoreProviderContext, StoreConsumerContext {\n // TODO: Take these off the global Dolla object.\n readonly http: HTTP;\n readonly i18n: I18n;\n\n #isMounted = false;\n #env: Environment = \"production\";\n #rootElement?: Element;\n #rootView?: ViewElement;\n #crashView: ViewFunction<CrashViewProps> = DefaultCrashView;\n\n #router?: Router;\n\n #beforeMountCallbacks: Array<() => void | Promise<void>> = [];\n #onMountCallbacks: Array<() => void> = [];\n #beforeUnmountCallbacks: Array<() => void | Promise<void>> = [];\n #onUnmountCallbacks: Array<() => void> = [];\n\n #rootElementContext: ElementContext = {\n root: this,\n stores: new Map(),\n viewName: \"Dolla\",\n };\n\n #loggles: Loggles = {\n info: \"development\",\n log: \"development\",\n warn: \"development\",\n error: true,\n };\n #match = createMatcher(\"*,-Dolla.*\");\n\n // Registration functions for modules.\n // All modules will be registered before mount.\n #modules: (() => Promise<any>)[] = [];\n\n constructor() {\n this.http = new HTTP();\n this.i18n = new I18n(this);\n }\n\n /**\n * True when the app is connected to a DOM node and displayed to the user.\n */\n get isMounted() {\n return this.#isMounted;\n }\n\n /**\n * Get the current environment that this app is running in.\n * Environment affects which log messages will print and how much debugging info is included in the DOM.\n */\n getEnv() {\n return this.#env;\n }\n\n /**\n * Sets the environment that this app is running in.\n * Environment affects which log messages will print and how much debugging info is included in the DOM.\n */\n setEnv(value: Environment) {\n this.#env = value;\n }\n\n /**\n * Sets the view that will be shown when the `crash` method is called on any logger.\n * When a crash is reported the app will be unmounted and replaced with this crash page.\n */\n setCrashView(view: ViewFunction<CrashViewProps>) {\n this.#crashView = view;\n }\n\n /**\n * Returns the HTMLElement Dolla is mounted to. This will return undefined until Dolla.mount() is called.\n */\n getRootElement() {\n return this.#rootElement;\n }\n\n /**\n * Returns the top level view Dolla is rendering inside the root element. This will return undefined until Dolla.mount() is called.\n */\n getRootView() {\n return this.#rootView;\n }\n\n /**\n * Attaches a new store to this context.\n */\n provide<Value>(store: StoreFunction<{}, Value>): Value;\n\n /**\n * Attaches a new store to this context.\n */\n provide<Value>(store: StoreFunction<undefined, Value>): Value;\n\n /**\n * Attaches a new store to this context.\n */\n provide<Options, Value>(store: StoreFunction<Options, Value>, options: Options): Value;\n\n provide<Options, Value>(store: StoreFunction<Options, Value>, options?: Options): Value {\n const instance = new Store(store, options!);\n const attached = instance.attach(this.#rootElementContext);\n if (!attached) {\n let name = store.name ? `'${store.name}'` : \"this store\";\n console.warn(`An instance of ${name} was already attached to this context.`);\n return this.get(store);\n } else {\n return instance.value;\n }\n }\n\n /**\n * Gets the nearest instance of a store. Throws an error if the store isn't provided higher in the tree.\n */\n get<Value>(store: StoreFunction<any, Value>): Value {\n if (isFunction(store)) {\n const instance = this.#rootElementContext.stores.get(store);\n if (instance == null) {\n throw new StoreError(`Store not found on this context.`);\n } else {\n return instance.value;\n }\n } else {\n throw new StoreError(`Invalid store.`);\n }\n }\n\n async mount(selector: string, router: Router): Promise<void>;\n async mount(selector: string, view: ViewFunction<any>): Promise<void>;\n async mount(element: Element, router: Router): Promise<void>;\n async mount(element: Element, view: ViewFunction<any>): Promise<void>;\n\n async mount(target: string | Element, root: ViewFunction<any> | Router) {\n if (this.#isMounted) {\n throw new Error(`Dolla is already mounted.`);\n }\n\n if (isString(target)) {\n const match = document.querySelector<Element>(target);\n assertInstanceOf(HTMLElement, match, `Selector '${target}' did not match any element.`);\n this.#rootElement = match!;\n } else {\n assertInstanceOf(HTMLElement, target, \"Expected an HTML element or a selector string. Got type: %t, value: %v\");\n this.#rootElement = target;\n }\n\n if (_isRouter(root)) {\n this.#router = root;\n }\n\n const view = _isRouter(root) ? Passthrough : root;\n\n // First, initialize the root view. The router store needs this to connect the initial route.\n const rootViewMarkup = markup(view);\n this.#rootView = this.constructView(rootViewMarkup.type as ViewFunction<any>, rootViewMarkup.props);\n\n // Register modules\n // TODO: Handle errors\n await Promise.all(this.#modules.map((register) => register()));\n\n // TODO: Run effects for stores\n\n // Run beforeMount\n // TODO: Handle errors\n await Promise.all(this.#beforeMountCallbacks.map((callback) => callback()));\n\n // Run onMount for stores.\n for (const store of this.#rootElementContext.stores.values()) {\n store.handleMount();\n }\n\n if (_isRouter(root)) {\n await _mountRouter(root, this);\n }\n\n this.#rootView.mount(this.#rootElement);\n this.#isMounted = true;\n\n // Run onMount\n // TODO: Handle errors\n for (const callback of this.#onMountCallbacks) {\n callback();\n }\n }\n\n async unmount() {\n if (!this.#isMounted) return;\n\n // Run beforeUnmount\n await Promise.all(this.#beforeUnmountCallbacks.map((callback) => callback()));\n\n this.#rootView?.unmount(false);\n\n if (this.#router) {\n await _unmountRouter(this.#router);\n }\n\n this.#isMounted = false;\n\n // Run onUnmount\n for (const callback of this.#onUnmountCallbacks) {\n callback();\n }\n }\n\n /**\n * Registers a `callback` to run after `Dolla.mount` is called, before the app is mounted. If `callback` returns a Promise,\n * it will be awaited before mounting finishes. Use this to perform initial setup before the app is displayed to the user.\n */\n beforeMount(callback: () => void | Promise<void>) {\n this.#beforeMountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after the app is mounted.\n */\n onMount(callback: () => void) {\n this.#onMountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after `Dolla.unmount` is called, before the app is unmounted. If `callback` returns a Promise,\n * it will be awaited before unmounting finishes. Use this to perform cleanup.\n */\n beforeUnmount(callback: () => void | Promise<void>) {\n this.#beforeUnmountCallbacks.push(callback);\n }\n\n /**\n * Registers a `callback` to run after the app is unmounted.\n */\n onUnmount(callback: () => void) {\n this.#onUnmountCallbacks.push(callback);\n }\n\n /**\n * Update log type toggles. Values that are not passed will remain unchanged.\n */\n setLoggles(options: Partial<Loggles>) {\n for (const key in options) {\n const value = options[key as keyof Loggles];\n if (value) {\n this.#loggles[key as keyof Loggles] = value;\n }\n }\n }\n\n setLogFilter(filter: string | RegExp) {\n this.#match = createMatcher(filter);\n }\n\n createLogger(name: string, options?: LoggerOptions): Logger {\n const _console = options?.console ?? getDefaultConsole();\n\n const self = this;\n const loggles = this.#loggles;\n\n const bind = (method: keyof Loggles) => {\n if (\n loggles[method] === false ||\n (isString(loggles[method]) && loggles[method] !== self.getEnv()) ||\n !this.#match(name)\n ) {\n return noOp;\n } else {\n let label = `%c${name}`;\n if (options?.uid) {\n label += ` %c[uid: %c${options.uid}%c]`;\n } else {\n label += `%c%c%c`;\n }\n return _console[method].bind(\n _console,\n label,\n `color:${okhash(label)};font-weight:bold`,\n `color:#777`,\n `color:#aaa`,\n `color:#777`,\n );\n }\n };\n\n return {\n setName(newName: string) {\n name = newName;\n return this;\n },\n get info() {\n return bind(\"info\");\n },\n get log() {\n return bind(\"log\");\n },\n get warn() {\n return bind(\"warn\");\n },\n get error() {\n return bind(\"error\");\n },\n crash(error: Error) {\n if (self.isMounted) {\n // Unmount the app.\n self.unmount();\n\n // Mount the crash page\n const crashPage = self.constructView(self.#crashView, {\n error,\n loggerName: name,\n uid: options?.uid,\n });\n crashPage.mount(self.#rootElement!);\n }\n\n // throw error;\n },\n };\n }\n\n /**\n *\n */\n constructView<P>(view: ViewFunction<P>, props: P, children: Markup[] = []): ViewElement {\n return new View(this.#rootElementContext, view, props, children);\n }\n\n /**\n *\n */\n constructMarkup(markup: Markup | Markup[]): MarkupElement {\n return groupElements(constructMarkup(this.#rootElementContext, markup));\n }\n}\n\nexport function getDefaultConsole() {\n if (typeof window !== \"undefined\" && window.console) {\n return window.console;\n }\n if (typeof global !== \"undefined\" && global.console) {\n return global.console;\n }\n}\n","// Signals\nexport { $, effect, get, peek } from \"./core/signals-api.js\";\nexport type { MaybeSignal, Signal, Source } from \"./core/signals-api.js\";\n\n// Equality checks\nexport { deepEqual, shallowEqual, strictEqual } from \"./utils.js\";\n\n// Store\nexport { type StoreContext, type StoreFunction } from \"./core/store.js\";\n\n// Router\nexport { createRouter, type Router, type RouterOptions } from \"./router/index.js\";\n\n// Markup\nexport { markup, portal, repeat, unless, when } from \"./core/markup.js\";\nexport type { Markup, MarkupElement } from \"./core/markup.js\";\n\nimport { Dolla } from \"./core/dolla.js\";\nconst dolla = new Dolla();\n\nexport default dolla;\n\nexport const t = dolla.i18n.t.bind(dolla.i18n);\nexport const i18n = dolla.i18n;\nexport const http = dolla.http;\n\nexport const createLogger = dolla.createLogger.bind(dolla);\n\n// Other types\nexport type { Dolla, Environment, Logger, LoggerErrorContext, LoggerOptions, Loggles } from \"./core/dolla.js\";\nexport type { ViewContext, ViewElement, ViewFunction } from \"./core/nodes/view.js\";\n// export type { HTTPRequest, HTTPResponse } from \"./modules/http.js\";\nexport type { CrashViewProps } from \"./core/views/default-crash-view.js\";\nexport type { InputType, Renderable } from \"./types.js\";\n\nimport type { IntrinsicElements as Elements } from \"./types\";\n\ndeclare global {\n namespace JSX {\n interface IntrinsicElements extends Elements {\n // Catch all for custom elements\n [tag: string]: any;\n }\n }\n}\n"],"names":["Passthrough","_","ctx","splitPath","path","assertString","f","joinPath","parts","assertArrayOf","part","isFunction","x","joined","_a","p","resolvePath","base","resolved","i","parseQueryParams","query","entries","entry","matchRoutes","routes","url","options","route","fragments","matched","frag","params","sortRoutes","withoutParams","withNumericParams","withParams","wildcard","bySizeDesc","a","b","patternToFragments","pattern","safeExternalLink","protocolLink","catchLinks","root","callback","_window","traverse","node","handler","e","anchor","replaceParams","key","value","createRouter","Router","ROUTER_MOUNT","ROUTER_UNMOUNT","_isRouter","IS_ROUTER","_mountRouter","router","dolla","_unmountRouter","__privateAdd","_Router_instances","__publicField","_dolla","_logger","_layerId","_activeLayers","_routes","_isMounted","_hash","_unsubscribers","_match","$","__privateGet","shallowEqual","assertObject","__privateSet","__privateMethod","prepareRoute_fn","assertValidRedirects","onPopState","updateRoute_fn","rootElement","href","preserve","parsePreserveQueryAttribute","steps","replace_fn","push_fn","values","match","peek","queryParts","queryString","getCurrentURL_fn","logger","rootView","journey","resolveRoute_fn","step","oldPattern","isArray","preserved","current","mountRoute_fn","NoRouteError","layers","matchedLayer","activeLayer","parentLayer","view","resolve","reject","redirect","finalize","isString","redirectContext","callbacks","next","parents","isObject","parent","layer","__privateWrapper","subroute","redirectPath","r","k","HTTP","_HTTP_instances","_middleware","_fetch","getDefaultFetch","fn","uri","request_fn","method","Runner","HTTPResponseError","response","status","statusText","message","Request","config","headers","name","mount","index","reqBody","req","fetched","contentType","body","Translation","_Translation_instances","_isLoaded","_templates","strings","res","compile_fn","selector","typeOf","parseTemplate_fn","template","Loc","Loc2","parsed","buffer","loc","segment","format","formatOptionName","startSegment","startFormat","I18n","_I18n_instances","_translations","_cache","_formats","_initialLocale","_locale","formatNumber_fn","formatDateTime_fn","formatList_fn","realName","names","nav","firstLanguage","translation","error","get","getValue_fn","count","date","list","locale","cached","getCached_fn","exact","output","formats","deepEqual","object","DefaultCrashView","props","m","when","Dolla","_env","_rootElement","_rootView","_crashView","_router","_beforeMountCallbacks","_onMountCallbacks","_beforeUnmountCallbacks","_onUnmountCallbacks","_rootElementContext","_loggles","createMatcher","_modules","store","instance","Store","StoreError","target","assertInstanceOf","rootViewMarkup","markup","register","filter","_console","getDefaultConsole","self","loggles","bind","noOp","label","okhash","newName","children","View","groupElements","constructMarkup","t","i18n","http","createLogger"],"mappings":"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"}
|