@manyducks.co/dolla 0.69.2 → 0.69.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -50
- package/lib/classes/EventEmitter.d.ts +44 -0
- package/lib/index.js +274 -272
- package/lib/index.js.map +4 -4
- package/lib/nodes/text.d.ts +1 -1
- package/lib/routing.d.ts +79 -0
- package/lib/routing.test.d.ts +1 -0
- package/lib/state.d.ts +1 -1
- package/lib/store.d.ts +1 -1
- package/lib/typeChecking.d.ts +191 -0
- package/lib/types.d.ts +1 -1
- package/notes/views.md +3 -9
- package/package.json +8 -9
- package/tests/state.test.js +52 -52
- package/notes/state.md +0 -71
package/lib/index.js
CHANGED
|
@@ -29,7 +29,7 @@ var require_lib = __commonJS({
|
|
|
29
29
|
"node_modules/simple-color-hash/lib/index.js"(exports, module) {
|
|
30
30
|
"use strict";
|
|
31
31
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
-
var _slicedToArray = function() {
|
|
32
|
+
var _slicedToArray = /* @__PURE__ */ function() {
|
|
33
33
|
function a(a2, b) {
|
|
34
34
|
var c = [], d = true, e = false, f = void 0;
|
|
35
35
|
try {
|
|
@@ -88,7 +88,55 @@ var require_lib = __commonJS({
|
|
|
88
88
|
}
|
|
89
89
|
});
|
|
90
90
|
|
|
91
|
-
//
|
|
91
|
+
// src/classes/CrashCollector.ts
|
|
92
|
+
var CrashCollector = class {
|
|
93
|
+
#errors = [];
|
|
94
|
+
#errorCallbacks = [];
|
|
95
|
+
/**
|
|
96
|
+
* Registers a callback to receive all errors that pass through the CrashCollector.
|
|
97
|
+
* Returns a function that cancels this listener when called.
|
|
98
|
+
*/
|
|
99
|
+
onError(callback) {
|
|
100
|
+
this.#errorCallbacks.push(callback);
|
|
101
|
+
return () => {
|
|
102
|
+
this.#errorCallbacks.splice(this.#errorCallbacks.indexOf(callback), 1);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Reports an unrecoverable error that requires crashing the whole app.
|
|
107
|
+
*/
|
|
108
|
+
crash({ error, componentName }) {
|
|
109
|
+
const ctx = {
|
|
110
|
+
error,
|
|
111
|
+
severity: "crash",
|
|
112
|
+
componentName: componentName ?? "anonymous component"
|
|
113
|
+
};
|
|
114
|
+
this.#errors.push(ctx);
|
|
115
|
+
for (const callback of this.#errorCallbacks) {
|
|
116
|
+
callback(ctx);
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Reports a recoverable error.
|
|
122
|
+
*/
|
|
123
|
+
error({ error, componentName }) {
|
|
124
|
+
const ctx = {
|
|
125
|
+
error,
|
|
126
|
+
severity: "error",
|
|
127
|
+
componentName: componentName ?? "anonymous component"
|
|
128
|
+
};
|
|
129
|
+
this.#errors.push(ctx);
|
|
130
|
+
for (const callback of this.#errorCallbacks) {
|
|
131
|
+
callback(ctx);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// src/classes/DebugHub.ts
|
|
137
|
+
var import_simple_color_hash = __toESM(require_lib(), 1);
|
|
138
|
+
|
|
139
|
+
// src/typeChecking.ts
|
|
92
140
|
function typeOf(value) {
|
|
93
141
|
if (value === void 0) {
|
|
94
142
|
return "undefined";
|
|
@@ -209,274 +257,7 @@ function formatError(value, message) {
|
|
|
209
257
|
return message.replaceAll("%t", typeName).replaceAll("%v", valueString);
|
|
210
258
|
}
|
|
211
259
|
|
|
212
|
-
// node_modules/@borf/bedrock/lib/routing.js
|
|
213
|
-
var FragTypes;
|
|
214
|
-
(function(FragTypes2) {
|
|
215
|
-
FragTypes2[FragTypes2["Literal"] = 1] = "Literal";
|
|
216
|
-
FragTypes2[FragTypes2["Param"] = 2] = "Param";
|
|
217
|
-
FragTypes2[FragTypes2["Wildcard"] = 3] = "Wildcard";
|
|
218
|
-
FragTypes2[FragTypes2["NumericParam"] = 4] = "NumericParam";
|
|
219
|
-
})(FragTypes || (FragTypes = {}));
|
|
220
|
-
function splitPath(path) {
|
|
221
|
-
assertString(path, "Expected `path` to be a string. Got type: %t, value: %v");
|
|
222
|
-
return path.split("/").map((f) => f.trim()).filter((f) => f !== "");
|
|
223
|
-
}
|
|
224
|
-
function joinPath(parts) {
|
|
225
|
-
assertArrayOf((part) => isFunction(part?.toString), parts, "Expected `parts` to be an array of objects with a .toString() method. Got type: %t, value: %v");
|
|
226
|
-
parts = parts.filter((x) => x).flatMap(String);
|
|
227
|
-
let joined = parts.shift()?.toString();
|
|
228
|
-
if (joined) {
|
|
229
|
-
for (const part of parts.map((p) => p.toString())) {
|
|
230
|
-
if (part.startsWith(".")) {
|
|
231
|
-
joined = resolvePath(joined, part);
|
|
232
|
-
} else if (joined[joined.length - 1] !== "/") {
|
|
233
|
-
if (part[0] !== "/") {
|
|
234
|
-
joined += "/" + part;
|
|
235
|
-
} else {
|
|
236
|
-
joined += part;
|
|
237
|
-
}
|
|
238
|
-
} else {
|
|
239
|
-
if (part[0] === "/") {
|
|
240
|
-
joined += part.slice(1);
|
|
241
|
-
} else {
|
|
242
|
-
joined += part;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
if (joined && joined !== "/" && joined.endsWith("/")) {
|
|
247
|
-
joined = joined.slice(0, joined.length - 1);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
return joined ?? "";
|
|
251
|
-
}
|
|
252
|
-
function resolvePath(base, part) {
|
|
253
|
-
assertString(base, "Expected `base` to be a string. Got type: %t, value: %v");
|
|
254
|
-
if (part == null) {
|
|
255
|
-
part = base;
|
|
256
|
-
base = "";
|
|
257
|
-
}
|
|
258
|
-
if (part.startsWith("/")) {
|
|
259
|
-
return part;
|
|
260
|
-
}
|
|
261
|
-
let resolved = base;
|
|
262
|
-
while (true) {
|
|
263
|
-
if (part.startsWith("..")) {
|
|
264
|
-
for (let i = resolved.length; i > 0; --i) {
|
|
265
|
-
if (resolved[i] === "/" || i === 0) {
|
|
266
|
-
resolved = resolved.slice(0, i);
|
|
267
|
-
part = part.replace(/^\.\.\/?/, "");
|
|
268
|
-
break;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
} else if (part.startsWith(".")) {
|
|
272
|
-
part = part.replace(/^\.\/?/, "");
|
|
273
|
-
} else {
|
|
274
|
-
break;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return joinPath([resolved, part]);
|
|
278
|
-
}
|
|
279
|
-
function parseQueryParams(query) {
|
|
280
|
-
if (!query)
|
|
281
|
-
return {};
|
|
282
|
-
const entries = query.split("&").filter((x) => x.trim() !== "").map((entry) => {
|
|
283
|
-
const [key, value] = entry.split("=").map((x) => x.trim());
|
|
284
|
-
if (value.toLowerCase() === "true") {
|
|
285
|
-
return [key, true];
|
|
286
|
-
}
|
|
287
|
-
if (value.toLowerCase() === "false") {
|
|
288
|
-
return [key, false];
|
|
289
|
-
}
|
|
290
|
-
if (!isNaN(Number(value))) {
|
|
291
|
-
return [key, Number(value)];
|
|
292
|
-
}
|
|
293
|
-
return [key, value];
|
|
294
|
-
});
|
|
295
|
-
return Object.fromEntries(entries);
|
|
296
|
-
}
|
|
297
|
-
function matchRoutes(routes, url, options = {}) {
|
|
298
|
-
const [path, query] = url.split("?");
|
|
299
|
-
const parts = splitPath(path);
|
|
300
|
-
routes:
|
|
301
|
-
for (const route of routes) {
|
|
302
|
-
const { fragments } = route;
|
|
303
|
-
const hasWildcard = fragments[fragments.length - 1]?.type === FragTypes.Wildcard;
|
|
304
|
-
if (!hasWildcard && fragments.length !== parts.length) {
|
|
305
|
-
continue routes;
|
|
306
|
-
}
|
|
307
|
-
if (options.willMatch && !options.willMatch(route)) {
|
|
308
|
-
continue routes;
|
|
309
|
-
}
|
|
310
|
-
const matched = [];
|
|
311
|
-
fragments:
|
|
312
|
-
for (let i = 0; i < fragments.length; i++) {
|
|
313
|
-
const part = parts[i];
|
|
314
|
-
const frag = fragments[i];
|
|
315
|
-
if (part == null && frag.type !== FragTypes.Wildcard) {
|
|
316
|
-
continue routes;
|
|
317
|
-
}
|
|
318
|
-
switch (frag.type) {
|
|
319
|
-
case FragTypes.Literal:
|
|
320
|
-
if (frag.name.toLowerCase() === part.toLowerCase()) {
|
|
321
|
-
matched.push(frag);
|
|
322
|
-
break;
|
|
323
|
-
} else {
|
|
324
|
-
continue routes;
|
|
325
|
-
}
|
|
326
|
-
case FragTypes.Param:
|
|
327
|
-
matched.push({ ...frag, value: part });
|
|
328
|
-
break;
|
|
329
|
-
case FragTypes.Wildcard:
|
|
330
|
-
matched.push({ ...frag, value: parts.slice(i).join("/") });
|
|
331
|
-
break fragments;
|
|
332
|
-
case FragTypes.NumericParam:
|
|
333
|
-
if (!isNaN(Number(part))) {
|
|
334
|
-
matched.push({ ...frag, value: Number(part) });
|
|
335
|
-
break;
|
|
336
|
-
} else {
|
|
337
|
-
continue routes;
|
|
338
|
-
}
|
|
339
|
-
default:
|
|
340
|
-
throw new Error(`Unknown fragment type: ${frag.type}`);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
const params = /* @__PURE__ */ Object.create(null);
|
|
344
|
-
for (const frag of matched) {
|
|
345
|
-
if (frag.type === FragTypes.Param) {
|
|
346
|
-
params[frag.name] = decodeURIComponent(frag.value);
|
|
347
|
-
}
|
|
348
|
-
if (frag.type === FragTypes.NumericParam) {
|
|
349
|
-
params[frag.name] = frag.value;
|
|
350
|
-
}
|
|
351
|
-
if (frag.type === FragTypes.Wildcard) {
|
|
352
|
-
params.wildcard = "/" + decodeURIComponent(frag.value);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
return {
|
|
356
|
-
path: "/" + matched.map((f) => f.value).join("/"),
|
|
357
|
-
pattern: "/" + fragments.map((f) => {
|
|
358
|
-
if (f.type === FragTypes.Param) {
|
|
359
|
-
return `{${f.name}}`;
|
|
360
|
-
}
|
|
361
|
-
if (f.type === FragTypes.NumericParam) {
|
|
362
|
-
return `{#${f.name}}`;
|
|
363
|
-
}
|
|
364
|
-
return f.name;
|
|
365
|
-
}).join("/"),
|
|
366
|
-
params,
|
|
367
|
-
query: parseQueryParams(query),
|
|
368
|
-
meta: route.meta
|
|
369
|
-
};
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
function sortRoutes(routes) {
|
|
373
|
-
const withoutParams = [];
|
|
374
|
-
const withNumericParams = [];
|
|
375
|
-
const withParams = [];
|
|
376
|
-
const wildcard = [];
|
|
377
|
-
for (const route of routes) {
|
|
378
|
-
const { fragments } = route;
|
|
379
|
-
if (fragments.some((f) => f.type === FragTypes.Wildcard)) {
|
|
380
|
-
wildcard.push(route);
|
|
381
|
-
} else if (fragments.some((f) => f.type === FragTypes.NumericParam)) {
|
|
382
|
-
withNumericParams.push(route);
|
|
383
|
-
} else if (fragments.some((f) => f.type === FragTypes.Param)) {
|
|
384
|
-
withParams.push(route);
|
|
385
|
-
} else {
|
|
386
|
-
withoutParams.push(route);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
const bySizeDesc = (a, b) => {
|
|
390
|
-
if (a.fragments.length > b.fragments.length) {
|
|
391
|
-
return -1;
|
|
392
|
-
} else {
|
|
393
|
-
return 1;
|
|
394
|
-
}
|
|
395
|
-
};
|
|
396
|
-
withoutParams.sort(bySizeDesc);
|
|
397
|
-
withNumericParams.sort(bySizeDesc);
|
|
398
|
-
withParams.sort(bySizeDesc);
|
|
399
|
-
wildcard.sort(bySizeDesc);
|
|
400
|
-
return [...withoutParams, ...withNumericParams, ...withParams, ...wildcard];
|
|
401
|
-
}
|
|
402
|
-
function patternToFragments(pattern) {
|
|
403
|
-
const parts = splitPath(pattern);
|
|
404
|
-
const fragments = [];
|
|
405
|
-
for (let i = 0; i < parts.length; i++) {
|
|
406
|
-
const part = parts[i];
|
|
407
|
-
if (part === "*") {
|
|
408
|
-
if (i !== parts.length - 1) {
|
|
409
|
-
throw new Error(`Wildcard must be at the end of a pattern. Received: ${pattern}`);
|
|
410
|
-
}
|
|
411
|
-
fragments.push({
|
|
412
|
-
type: FragTypes.Wildcard,
|
|
413
|
-
name: "*",
|
|
414
|
-
value: null
|
|
415
|
-
});
|
|
416
|
-
} else if (part.at(0) === "{" && part.at(-1) === "}") {
|
|
417
|
-
fragments.push({
|
|
418
|
-
type: part[1] === "#" ? FragTypes.NumericParam : FragTypes.Param,
|
|
419
|
-
name: part[1] === "#" ? part.slice(2, -1) : part.slice(1, -1),
|
|
420
|
-
value: null
|
|
421
|
-
});
|
|
422
|
-
} else {
|
|
423
|
-
fragments.push({
|
|
424
|
-
type: FragTypes.Literal,
|
|
425
|
-
name: part,
|
|
426
|
-
value: part
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return fragments;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// src/classes/CrashCollector.ts
|
|
434
|
-
var CrashCollector = class {
|
|
435
|
-
#errors = [];
|
|
436
|
-
#errorCallbacks = [];
|
|
437
|
-
/**
|
|
438
|
-
* Registers a callback to receive all errors that pass through the CrashCollector.
|
|
439
|
-
* Returns a function that cancels this listener when called.
|
|
440
|
-
*/
|
|
441
|
-
onError(callback) {
|
|
442
|
-
this.#errorCallbacks.push(callback);
|
|
443
|
-
return () => {
|
|
444
|
-
this.#errorCallbacks.splice(this.#errorCallbacks.indexOf(callback), 1);
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Reports an unrecoverable error that requires crashing the whole app.
|
|
449
|
-
*/
|
|
450
|
-
crash({ error, componentName }) {
|
|
451
|
-
const ctx = {
|
|
452
|
-
error,
|
|
453
|
-
severity: "crash",
|
|
454
|
-
componentName: componentName ?? "anonymous component"
|
|
455
|
-
};
|
|
456
|
-
this.#errors.push(ctx);
|
|
457
|
-
for (const callback of this.#errorCallbacks) {
|
|
458
|
-
callback(ctx);
|
|
459
|
-
}
|
|
460
|
-
throw error;
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* Reports a recoverable error.
|
|
464
|
-
*/
|
|
465
|
-
error({ error, componentName }) {
|
|
466
|
-
const ctx = {
|
|
467
|
-
error,
|
|
468
|
-
severity: "error",
|
|
469
|
-
componentName: componentName ?? "anonymous component"
|
|
470
|
-
};
|
|
471
|
-
this.#errors.push(ctx);
|
|
472
|
-
for (const callback of this.#errorCallbacks) {
|
|
473
|
-
callback(ctx);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
};
|
|
477
|
-
|
|
478
260
|
// src/classes/DebugHub.ts
|
|
479
|
-
var import_simple_color_hash = __toESM(require_lib(), 1);
|
|
480
261
|
var DebugHub = class {
|
|
481
262
|
#filter = "*,-dolla/*";
|
|
482
263
|
#matcher;
|
|
@@ -686,7 +467,9 @@ function $$(initialValue, config) {
|
|
|
686
467
|
}
|
|
687
468
|
function $(...args) {
|
|
688
469
|
if (args.length > 1) {
|
|
689
|
-
|
|
470
|
+
const callback = args.pop();
|
|
471
|
+
const readables = args.flat().map(readable);
|
|
472
|
+
return computed(...readables, callback);
|
|
690
473
|
} else {
|
|
691
474
|
return readable(args[0]);
|
|
692
475
|
}
|
|
@@ -715,7 +498,6 @@ function computed(...args) {
|
|
|
715
498
|
if (typeof compute !== "function") {
|
|
716
499
|
throw new TypeError(`Final argument must be a function. Got ${typeOf(compute)}: ${compute}`);
|
|
717
500
|
}
|
|
718
|
-
args = args.flat().map(readable);
|
|
719
501
|
if (args.length < 1) {
|
|
720
502
|
throw new Error(`Must pass at least one value before the callback function.`);
|
|
721
503
|
}
|
|
@@ -881,7 +663,7 @@ function proxy(source, config) {
|
|
|
881
663
|
}
|
|
882
664
|
function observe(...args) {
|
|
883
665
|
const callback = args.pop();
|
|
884
|
-
const readables = args.flat();
|
|
666
|
+
const readables = args.flat().map(readable);
|
|
885
667
|
if (readables.length === 0) {
|
|
886
668
|
throw new TypeError(`Expected at least one readable.`);
|
|
887
669
|
}
|
|
@@ -3146,6 +2928,226 @@ function parsePath(path) {
|
|
|
3146
2928
|
return parsedPath;
|
|
3147
2929
|
}
|
|
3148
2930
|
|
|
2931
|
+
// src/routing.ts
|
|
2932
|
+
function splitPath(path) {
|
|
2933
|
+
assertString(path, "Expected `path` to be a string. Got type: %t, value: %v");
|
|
2934
|
+
return path.split("/").map((f) => f.trim()).filter((f) => f !== "");
|
|
2935
|
+
}
|
|
2936
|
+
function joinPath(parts) {
|
|
2937
|
+
assertArrayOf(
|
|
2938
|
+
(part) => isFunction(part?.toString),
|
|
2939
|
+
parts,
|
|
2940
|
+
"Expected `parts` to be an array of objects with a .toString() method. Got type: %t, value: %v"
|
|
2941
|
+
);
|
|
2942
|
+
parts = parts.filter((x) => x).flatMap(String);
|
|
2943
|
+
let joined = parts.shift()?.toString();
|
|
2944
|
+
if (joined) {
|
|
2945
|
+
for (const part of parts.map((p) => p.toString())) {
|
|
2946
|
+
if (part.startsWith(".")) {
|
|
2947
|
+
joined = resolvePath(joined, part);
|
|
2948
|
+
} else if (joined[joined.length - 1] !== "/") {
|
|
2949
|
+
if (part[0] !== "/") {
|
|
2950
|
+
joined += "/" + part;
|
|
2951
|
+
} else {
|
|
2952
|
+
joined += part;
|
|
2953
|
+
}
|
|
2954
|
+
} else {
|
|
2955
|
+
if (part[0] === "/") {
|
|
2956
|
+
joined += part.slice(1);
|
|
2957
|
+
} else {
|
|
2958
|
+
joined += part;
|
|
2959
|
+
}
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
if (joined && joined !== "/" && joined.endsWith("/")) {
|
|
2963
|
+
joined = joined.slice(0, joined.length - 1);
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
return joined ?? "";
|
|
2967
|
+
}
|
|
2968
|
+
function resolvePath(base, part) {
|
|
2969
|
+
assertString(base, "Expected `base` to be a string. Got type: %t, value: %v");
|
|
2970
|
+
if (part == null) {
|
|
2971
|
+
part = base;
|
|
2972
|
+
base = "";
|
|
2973
|
+
}
|
|
2974
|
+
if (part.startsWith("/")) {
|
|
2975
|
+
return part;
|
|
2976
|
+
}
|
|
2977
|
+
let resolved = base;
|
|
2978
|
+
while (true) {
|
|
2979
|
+
if (part.startsWith("..")) {
|
|
2980
|
+
for (let i = resolved.length; i > 0; --i) {
|
|
2981
|
+
if (resolved[i] === "/" || i === 0) {
|
|
2982
|
+
resolved = resolved.slice(0, i);
|
|
2983
|
+
part = part.replace(/^\.\.\/?/, "");
|
|
2984
|
+
break;
|
|
2985
|
+
}
|
|
2986
|
+
}
|
|
2987
|
+
} else if (part.startsWith(".")) {
|
|
2988
|
+
part = part.replace(/^\.\/?/, "");
|
|
2989
|
+
} else {
|
|
2990
|
+
break;
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
return joinPath([resolved, part]);
|
|
2994
|
+
}
|
|
2995
|
+
function parseQueryParams(query) {
|
|
2996
|
+
if (!query)
|
|
2997
|
+
return {};
|
|
2998
|
+
const entries = query.split("&").filter((x) => x.trim() !== "").map((entry) => {
|
|
2999
|
+
const [key, value] = entry.split("=").map((x) => x.trim());
|
|
3000
|
+
if (value.toLowerCase() === "true") {
|
|
3001
|
+
return [key, true];
|
|
3002
|
+
}
|
|
3003
|
+
if (value.toLowerCase() === "false") {
|
|
3004
|
+
return [key, false];
|
|
3005
|
+
}
|
|
3006
|
+
if (!isNaN(Number(value))) {
|
|
3007
|
+
return [key, Number(value)];
|
|
3008
|
+
}
|
|
3009
|
+
return [key, value];
|
|
3010
|
+
});
|
|
3011
|
+
return Object.fromEntries(entries);
|
|
3012
|
+
}
|
|
3013
|
+
function matchRoutes(routes, url, options = {}) {
|
|
3014
|
+
const [path, query] = url.split("?");
|
|
3015
|
+
const parts = splitPath(path);
|
|
3016
|
+
routes:
|
|
3017
|
+
for (const route of routes) {
|
|
3018
|
+
const { fragments } = route;
|
|
3019
|
+
const hasWildcard = fragments[fragments.length - 1]?.type === 3 /* Wildcard */;
|
|
3020
|
+
if (!hasWildcard && fragments.length !== parts.length) {
|
|
3021
|
+
continue routes;
|
|
3022
|
+
}
|
|
3023
|
+
if (options.willMatch && !options.willMatch(route)) {
|
|
3024
|
+
continue routes;
|
|
3025
|
+
}
|
|
3026
|
+
const matched = [];
|
|
3027
|
+
fragments:
|
|
3028
|
+
for (let i = 0; i < fragments.length; i++) {
|
|
3029
|
+
const part = parts[i];
|
|
3030
|
+
const frag = fragments[i];
|
|
3031
|
+
if (part == null && frag.type !== 3 /* Wildcard */) {
|
|
3032
|
+
continue routes;
|
|
3033
|
+
}
|
|
3034
|
+
switch (frag.type) {
|
|
3035
|
+
case 1 /* Literal */:
|
|
3036
|
+
if (frag.name.toLowerCase() === part.toLowerCase()) {
|
|
3037
|
+
matched.push(frag);
|
|
3038
|
+
break;
|
|
3039
|
+
} else {
|
|
3040
|
+
continue routes;
|
|
3041
|
+
}
|
|
3042
|
+
case 2 /* Param */:
|
|
3043
|
+
matched.push({ ...frag, value: part });
|
|
3044
|
+
break;
|
|
3045
|
+
case 3 /* Wildcard */:
|
|
3046
|
+
matched.push({ ...frag, value: parts.slice(i).join("/") });
|
|
3047
|
+
break fragments;
|
|
3048
|
+
case 4 /* NumericParam */:
|
|
3049
|
+
if (!isNaN(Number(part))) {
|
|
3050
|
+
matched.push({ ...frag, value: Number(part) });
|
|
3051
|
+
break;
|
|
3052
|
+
} else {
|
|
3053
|
+
continue routes;
|
|
3054
|
+
}
|
|
3055
|
+
default:
|
|
3056
|
+
throw new Error(`Unknown fragment type: ${frag.type}`);
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
const params = /* @__PURE__ */ Object.create(null);
|
|
3060
|
+
for (const frag of matched) {
|
|
3061
|
+
if (frag.type === 2 /* Param */) {
|
|
3062
|
+
params[frag.name] = decodeURIComponent(frag.value);
|
|
3063
|
+
}
|
|
3064
|
+
if (frag.type === 4 /* NumericParam */) {
|
|
3065
|
+
params[frag.name] = frag.value;
|
|
3066
|
+
}
|
|
3067
|
+
if (frag.type === 3 /* Wildcard */) {
|
|
3068
|
+
params.wildcard = "/" + decodeURIComponent(frag.value);
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
return {
|
|
3072
|
+
path: "/" + matched.map((f) => f.value).join("/"),
|
|
3073
|
+
pattern: "/" + fragments.map((f) => {
|
|
3074
|
+
if (f.type === 2 /* Param */) {
|
|
3075
|
+
return `{${f.name}}`;
|
|
3076
|
+
}
|
|
3077
|
+
if (f.type === 4 /* NumericParam */) {
|
|
3078
|
+
return `{#${f.name}}`;
|
|
3079
|
+
}
|
|
3080
|
+
return f.name;
|
|
3081
|
+
}).join("/"),
|
|
3082
|
+
params,
|
|
3083
|
+
query: parseQueryParams(query),
|
|
3084
|
+
meta: route.meta
|
|
3085
|
+
};
|
|
3086
|
+
}
|
|
3087
|
+
}
|
|
3088
|
+
function sortRoutes(routes) {
|
|
3089
|
+
const withoutParams = [];
|
|
3090
|
+
const withNumericParams = [];
|
|
3091
|
+
const withParams = [];
|
|
3092
|
+
const wildcard = [];
|
|
3093
|
+
for (const route of routes) {
|
|
3094
|
+
const { fragments } = route;
|
|
3095
|
+
if (fragments.some((f) => f.type === 3 /* Wildcard */)) {
|
|
3096
|
+
wildcard.push(route);
|
|
3097
|
+
} else if (fragments.some((f) => f.type === 4 /* NumericParam */)) {
|
|
3098
|
+
withNumericParams.push(route);
|
|
3099
|
+
} else if (fragments.some((f) => f.type === 2 /* Param */)) {
|
|
3100
|
+
withParams.push(route);
|
|
3101
|
+
} else {
|
|
3102
|
+
withoutParams.push(route);
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
const bySizeDesc = (a, b) => {
|
|
3106
|
+
if (a.fragments.length > b.fragments.length) {
|
|
3107
|
+
return -1;
|
|
3108
|
+
} else {
|
|
3109
|
+
return 1;
|
|
3110
|
+
}
|
|
3111
|
+
};
|
|
3112
|
+
withoutParams.sort(bySizeDesc);
|
|
3113
|
+
withNumericParams.sort(bySizeDesc);
|
|
3114
|
+
withParams.sort(bySizeDesc);
|
|
3115
|
+
wildcard.sort(bySizeDesc);
|
|
3116
|
+
return [...withoutParams, ...withNumericParams, ...withParams, ...wildcard];
|
|
3117
|
+
}
|
|
3118
|
+
function patternToFragments(pattern) {
|
|
3119
|
+
const parts = splitPath(pattern);
|
|
3120
|
+
const fragments = [];
|
|
3121
|
+
for (let i = 0; i < parts.length; i++) {
|
|
3122
|
+
const part = parts[i];
|
|
3123
|
+
if (part === "*") {
|
|
3124
|
+
if (i !== parts.length - 1) {
|
|
3125
|
+
throw new Error(
|
|
3126
|
+
`Wildcard must be at the end of a pattern. Received: ${pattern}`
|
|
3127
|
+
);
|
|
3128
|
+
}
|
|
3129
|
+
fragments.push({
|
|
3130
|
+
type: 3 /* Wildcard */,
|
|
3131
|
+
name: "*",
|
|
3132
|
+
value: null
|
|
3133
|
+
});
|
|
3134
|
+
} else if (part.at(0) === "{" && part.at(-1) === "}") {
|
|
3135
|
+
fragments.push({
|
|
3136
|
+
type: part[1] === "#" ? 4 /* NumericParam */ : 2 /* Param */,
|
|
3137
|
+
name: part[1] === "#" ? part.slice(2, -1) : part.slice(1, -1),
|
|
3138
|
+
value: null
|
|
3139
|
+
});
|
|
3140
|
+
} else {
|
|
3141
|
+
fragments.push({
|
|
3142
|
+
type: 1 /* Literal */,
|
|
3143
|
+
name: part,
|
|
3144
|
+
value: part
|
|
3145
|
+
});
|
|
3146
|
+
}
|
|
3147
|
+
}
|
|
3148
|
+
return fragments;
|
|
3149
|
+
}
|
|
3150
|
+
|
|
3149
3151
|
// src/stores/router.ts
|
|
3150
3152
|
var DefaultView = (_, ctx) => ctx.outlet();
|
|
3151
3153
|
function RouterStore(ctx) {
|