@hybridly/core 0.10.0-beta.4 → 0.10.0-beta.6
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/_chunks/chunk.mjs +7 -15
- package/dist/index.mjs +1 -183
- package/package.json +2 -2
package/dist/_chunks/chunk.mjs
CHANGED
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import "node:module";
|
|
2
|
-
|
|
3
|
-
//#region rolldown:runtime
|
|
4
2
|
var __defProp = Object.defineProperty;
|
|
5
|
-
var __exportAll = (all,
|
|
3
|
+
var __exportAll = (all, no_symbols) => {
|
|
6
4
|
let target = {};
|
|
7
|
-
for (var name in all) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
if (symbols) {
|
|
14
|
-
__defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
15
|
-
}
|
|
5
|
+
for (var name in all) __defProp(target, name, {
|
|
6
|
+
get: all[name],
|
|
7
|
+
enumerable: true
|
|
8
|
+
});
|
|
9
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
16
10
|
return target;
|
|
17
11
|
};
|
|
18
|
-
|
|
19
|
-
//#endregion
|
|
20
|
-
export { __exportAll as t };
|
|
12
|
+
export { __exportAll as t };
|
package/dist/index.mjs
CHANGED
|
@@ -3,8 +3,6 @@ import { debounce, debug, hasFiles, match, merge, objectToFormData, random, remo
|
|
|
3
3
|
import axios from "axios";
|
|
4
4
|
import { parse, stringify } from "superjson";
|
|
5
5
|
import qs from "qs";
|
|
6
|
-
|
|
7
|
-
//#region src/constants.ts
|
|
8
6
|
var constants_exports = /* @__PURE__ */ __exportAll({
|
|
9
7
|
DIALOG_KEY_HEADER: () => DIALOG_KEY_HEADER,
|
|
10
8
|
DIALOG_REDIRECT_HEADER: () => DIALOG_REDIRECT_HEADER,
|
|
@@ -31,9 +29,6 @@ const EXCEPT_DATA_HEADER = `${HYBRIDLY_HEADER}-except-data`;
|
|
|
31
29
|
const VERSION_HEADER = `${HYBRIDLY_HEADER}-version`;
|
|
32
30
|
const ERROR_BAG_HEADER = `${HYBRIDLY_HEADER}-error-bag`;
|
|
33
31
|
const SCROLL_REGION_ATTRIBUTE = "scroll-region";
|
|
34
|
-
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/errors.ts
|
|
37
32
|
var NotAHybridResponseError = class extends Error {
|
|
38
33
|
constructor(response) {
|
|
39
34
|
super();
|
|
@@ -56,9 +51,6 @@ var MissingRouteParameter = class extends Error {
|
|
|
56
51
|
super(`Parameter [${parameter}] is required for route [${routeName}].`);
|
|
57
52
|
}
|
|
58
53
|
};
|
|
59
|
-
|
|
60
|
-
//#endregion
|
|
61
|
-
//#region src/plugins/plugin.ts
|
|
62
54
|
function definePlugin(plugin) {
|
|
63
55
|
return plugin;
|
|
64
56
|
}
|
|
@@ -95,12 +87,6 @@ async function runHooks(hook, requestHooks, ...args) {
|
|
|
95
87
|
debug.hook(`Called all hooks for [${hook}],`, result);
|
|
96
88
|
return !result.includes(false);
|
|
97
89
|
}
|
|
98
|
-
|
|
99
|
-
//#endregion
|
|
100
|
-
//#region src/plugins/hooks.ts
|
|
101
|
-
/**
|
|
102
|
-
* Registers a global hook.
|
|
103
|
-
*/
|
|
104
90
|
function appendCallbackToHooks(hook, fn) {
|
|
105
91
|
const hooks = getRouterContext().hooks;
|
|
106
92
|
hooks[hook] = [...hooks[hook] ?? [], fn];
|
|
@@ -109,9 +95,6 @@ function appendCallbackToHooks(hook, fn) {
|
|
|
109
95
|
if (index !== -1) hooks[hook]?.splice(index, 1);
|
|
110
96
|
};
|
|
111
97
|
}
|
|
112
|
-
/**
|
|
113
|
-
* Registers a global hook.
|
|
114
|
-
*/
|
|
115
98
|
function registerHook(hook, fn, options) {
|
|
116
99
|
if (options?.once) {
|
|
117
100
|
const unregister = appendCallbackToHooks(hook, async (...args) => {
|
|
@@ -122,10 +105,6 @@ function registerHook(hook, fn, options) {
|
|
|
122
105
|
}
|
|
123
106
|
return appendCallbackToHooks(hook, fn);
|
|
124
107
|
}
|
|
125
|
-
|
|
126
|
-
//#endregion
|
|
127
|
-
//#region src/scroll.ts
|
|
128
|
-
/** Saves the current view's scrollbar positions into the history state. */
|
|
129
108
|
function saveScrollPositions() {
|
|
130
109
|
const regions = getScrollRegions();
|
|
131
110
|
debug.scroll("Saving scroll positions of:", regions.map((el) => ({
|
|
@@ -141,14 +120,9 @@ function saveScrollPositions() {
|
|
|
141
120
|
})) });
|
|
142
121
|
setHistoryState({ replace: true });
|
|
143
122
|
}
|
|
144
|
-
/** Gets DOM elements which scroll positions should be saved. */
|
|
145
123
|
function getScrollRegions() {
|
|
146
124
|
return Array.from(document?.querySelectorAll(`[${SCROLL_REGION_ATTRIBUTE}]`) ?? []).concat(document.documentElement, document.body);
|
|
147
125
|
}
|
|
148
|
-
/**
|
|
149
|
-
* Resets the current view's scrollbars positions to the top, and save them
|
|
150
|
-
* in the history state.
|
|
151
|
-
*/
|
|
152
126
|
function resetScrollPositions() {
|
|
153
127
|
debug.scroll("Resetting scroll positions.");
|
|
154
128
|
getScrollRegions().forEach((element) => element.scrollTo({
|
|
@@ -161,7 +135,6 @@ function resetScrollPositions() {
|
|
|
161
135
|
document.getElementById(window.location.hash.slice(1))?.scrollIntoView();
|
|
162
136
|
}
|
|
163
137
|
}
|
|
164
|
-
/** Restores the scroll positions stored in the context. */
|
|
165
138
|
async function restoreScrollPositions() {
|
|
166
139
|
const context = getRouterContext();
|
|
167
140
|
const regions = getScrollRegions();
|
|
@@ -177,16 +150,9 @@ async function restoreScrollPositions() {
|
|
|
177
150
|
}));
|
|
178
151
|
});
|
|
179
152
|
}
|
|
180
|
-
|
|
181
|
-
//#endregion
|
|
182
|
-
//#region src/url.ts
|
|
183
|
-
/** Normalizes the given input to an URL. */
|
|
184
153
|
function normalizeUrl(href, trailingSlash) {
|
|
185
154
|
return makeUrl(href, { trailingSlash }).toString();
|
|
186
155
|
}
|
|
187
|
-
/**
|
|
188
|
-
* Converts an input to an URL, optionally changing its properties after initialization.
|
|
189
|
-
*/
|
|
190
156
|
function makeUrl(href, transformations = {}) {
|
|
191
157
|
try {
|
|
192
158
|
const base = document?.location?.href === "//" ? void 0 : document.location.href;
|
|
@@ -213,9 +179,6 @@ function makeUrl(href, transformations = {}) {
|
|
|
213
179
|
throw new TypeError(`${href} is not resolvable to a valid URL.`);
|
|
214
180
|
}
|
|
215
181
|
}
|
|
216
|
-
/**
|
|
217
|
-
* Checks if the given URLs have the same origin and path.
|
|
218
|
-
*/
|
|
219
182
|
function sameUrls(...hrefs) {
|
|
220
183
|
if (hrefs.length < 2) return true;
|
|
221
184
|
try {
|
|
@@ -225,9 +188,6 @@ function sameUrls(...hrefs) {
|
|
|
225
188
|
} catch {}
|
|
226
189
|
return false;
|
|
227
190
|
}
|
|
228
|
-
/**
|
|
229
|
-
* Checks if the given URLs have the same origin, path, and hash.
|
|
230
|
-
*/
|
|
231
191
|
function sameHashes(...hrefs) {
|
|
232
192
|
if (hrefs.length < 2) return true;
|
|
233
193
|
try {
|
|
@@ -237,21 +197,12 @@ function sameHashes(...hrefs) {
|
|
|
237
197
|
} catch {}
|
|
238
198
|
return false;
|
|
239
199
|
}
|
|
240
|
-
/**
|
|
241
|
-
* If the back-end did not specify a hash, if the navigation specified one,
|
|
242
|
-
* and both URLs lead to the same endpoint, we update the target URL
|
|
243
|
-
* to use the hash of the initially-requested URL.
|
|
244
|
-
*/
|
|
245
200
|
function fillHash(currentUrl, targetUrl) {
|
|
246
201
|
currentUrl = makeUrl(currentUrl);
|
|
247
202
|
targetUrl = makeUrl(targetUrl);
|
|
248
203
|
if (currentUrl.hash && !targetUrl.hash && sameUrls(targetUrl, currentUrl)) targetUrl.hash = currentUrl.hash;
|
|
249
204
|
return targetUrl.toString();
|
|
250
205
|
}
|
|
251
|
-
|
|
252
|
-
//#endregion
|
|
253
|
-
//#region src/router/history.ts
|
|
254
|
-
/** Puts the given context into the history state. */
|
|
255
206
|
function setHistoryState(options = {}) {
|
|
256
207
|
if (!window?.history) throw new Error("The history API is not available, so Hybridly cannot operate.");
|
|
257
208
|
const context = getRouterContext();
|
|
@@ -268,16 +219,13 @@ function setHistoryState(options = {}) {
|
|
|
268
219
|
throw error;
|
|
269
220
|
}
|
|
270
221
|
}
|
|
271
|
-
/** Gets the current history data if it exists. */
|
|
272
222
|
function getHistoryState() {
|
|
273
223
|
return getRouterContext().serializer.unserialize(window.history.state);
|
|
274
224
|
}
|
|
275
|
-
/** Gets the current history state if it exists. */
|
|
276
225
|
function getHistoryMemo(key) {
|
|
277
226
|
const state = getHistoryState();
|
|
278
227
|
return key ? state?.memo?.[key] : state?.memo;
|
|
279
228
|
}
|
|
280
|
-
/** Register history-related event listeneners. */
|
|
281
229
|
async function registerEventListeners() {
|
|
282
230
|
const context = getRouterContext();
|
|
283
231
|
debug.history("Registering [popstate] and [scroll] event listeners.");
|
|
@@ -314,12 +262,10 @@ async function registerEventListeners() {
|
|
|
314
262
|
if ((event?.target)?.hasAttribute?.(SCROLL_REGION_ATTRIBUTE)) saveScrollPositions();
|
|
315
263
|
}), true);
|
|
316
264
|
}
|
|
317
|
-
/** Checks if the current navigation was made by going back or forward. */
|
|
318
265
|
function isBackForwardNavigation() {
|
|
319
266
|
if (!window.history.state) return false;
|
|
320
267
|
return (window.performance?.getEntriesByType("navigation").at(0))?.type === "back_forward";
|
|
321
268
|
}
|
|
322
|
-
/** Handles a navigation which was going back or forward. */
|
|
323
269
|
async function handleBackForwardNavigation() {
|
|
324
270
|
debug.router("Handling a back/forward navigation from an external URL.");
|
|
325
271
|
const context = getRouterContext();
|
|
@@ -336,7 +282,6 @@ async function handleBackForwardNavigation() {
|
|
|
336
282
|
updateHistoryState: false
|
|
337
283
|
});
|
|
338
284
|
}
|
|
339
|
-
/** Saves a value into the current history state. */
|
|
340
285
|
function remember(key, value) {
|
|
341
286
|
debug.history(`Remembering key "${key}" with value`, value);
|
|
342
287
|
setContext({ memo: {
|
|
@@ -345,7 +290,6 @@ function remember(key, value) {
|
|
|
345
290
|
} }, { propagate: false });
|
|
346
291
|
setHistoryState({ replace: true });
|
|
347
292
|
}
|
|
348
|
-
/** Serializes the context so it can be written to the history state. */
|
|
349
293
|
function serializeContext(context) {
|
|
350
294
|
return context.serializer.serialize({
|
|
351
295
|
url: context.url,
|
|
@@ -372,9 +316,6 @@ function createSerializer(options) {
|
|
|
372
316
|
}
|
|
373
317
|
};
|
|
374
318
|
}
|
|
375
|
-
|
|
376
|
-
//#endregion
|
|
377
|
-
//#region src/routing/route.ts
|
|
378
319
|
function getUrlRegexForRoute(name) {
|
|
379
320
|
const routing = getRouting();
|
|
380
321
|
const definition = getRouteDefinition(name);
|
|
@@ -392,12 +333,6 @@ function getUrlRegexForRoute(name) {
|
|
|
392
333
|
});
|
|
393
334
|
return RegExp(urlRegexPattern);
|
|
394
335
|
}
|
|
395
|
-
/**
|
|
396
|
-
* Check if a given URL matches a route based on its name.
|
|
397
|
-
* Additionally you can pass an object of parameters to check if the URL matches the route with the given parameters.
|
|
398
|
-
* Otherwise it will accept and thus return true for any values for the parameters defined by the route.
|
|
399
|
-
* Note: passing additional parameters that are not defined by the route or included in the current URL will cause this to return false.
|
|
400
|
-
*/
|
|
401
336
|
function urlMatchesRoute(fullUrl, name, routeParameters) {
|
|
402
337
|
const url = makeUrl(fullUrl, { hash: "" }).toString();
|
|
403
338
|
const parameters = routeParameters || {};
|
|
@@ -434,9 +369,6 @@ function getUrlFromName(name, parameters, shouldThrow) {
|
|
|
434
369
|
...transforms
|
|
435
370
|
}));
|
|
436
371
|
}
|
|
437
|
-
/**
|
|
438
|
-
* Resolved the value of a route parameter from either the passed parameters or the default parameters.
|
|
439
|
-
*/
|
|
440
372
|
function getRouteParameterValue(routeName, parameterName, routeParameters) {
|
|
441
373
|
const routing = getRouting();
|
|
442
374
|
const definition = getRouteDefinition(routeName);
|
|
@@ -454,9 +386,6 @@ function getRouteParameterValue(routeName, parameterName, routeParameters) {
|
|
|
454
386
|
}
|
|
455
387
|
if (routing.defaults?.[parameterName]) return routing.defaults?.[parameterName];
|
|
456
388
|
}
|
|
457
|
-
/**
|
|
458
|
-
* Gets the `UrlTransformable` object for the given route and parameters.
|
|
459
|
-
*/
|
|
460
389
|
function getRouteTransformable(routeName, routeParameters, shouldThrow) {
|
|
461
390
|
const definition = getRouteDefinition(routeName);
|
|
462
391
|
const parameters = routeParameters || {};
|
|
@@ -486,45 +415,23 @@ function getRouteTransformable(routeName, routeParameters, shouldThrow) {
|
|
|
486
415
|
})
|
|
487
416
|
};
|
|
488
417
|
}
|
|
489
|
-
/**
|
|
490
|
-
* Gets the route definition.
|
|
491
|
-
*/
|
|
492
418
|
function getRouteDefinition(name) {
|
|
493
419
|
const definition = getRouting().routes[name];
|
|
494
420
|
if (!definition) throw new RouteNotFound(name);
|
|
495
421
|
return definition;
|
|
496
422
|
}
|
|
497
|
-
/**
|
|
498
|
-
* Gets the routing configuration from the current context.
|
|
499
|
-
*/
|
|
500
423
|
function getRouting() {
|
|
501
424
|
const { routing } = getInternalRouterContext();
|
|
502
425
|
if (!routing) throw new RoutingNotInitialized();
|
|
503
426
|
return routing;
|
|
504
427
|
}
|
|
505
|
-
/**
|
|
506
|
-
* Generates a route from the given route name.
|
|
507
|
-
*/
|
|
508
428
|
function route(name, parameters, absolute) {
|
|
509
429
|
return generateRouteFromName(name, parameters, absolute ?? getRouting().absolute ?? true);
|
|
510
430
|
}
|
|
511
|
-
|
|
512
|
-
//#endregion
|
|
513
|
-
//#region src/routing/current.ts
|
|
514
431
|
function getCurrentUrl() {
|
|
515
432
|
if (typeof window === "undefined") return getInternalRouterContext().url;
|
|
516
433
|
return window.location.toString();
|
|
517
434
|
}
|
|
518
|
-
/**
|
|
519
|
-
* Determines whether the current route matches the given name and parameters.
|
|
520
|
-
* If multiple routes match, the first one will be returned.
|
|
521
|
-
*
|
|
522
|
-
* @example
|
|
523
|
-
* ```ts
|
|
524
|
-
* currentRouteMatches('tenant.*') // matches all routes starting with 'tenant.'
|
|
525
|
-
* currentRouteMatches('tenant.*.admin') // matches all routes starting with 'tenant.' and ending with '.admin'
|
|
526
|
-
* ```
|
|
527
|
-
*/
|
|
528
435
|
function currentRouteMatches(name, parameters) {
|
|
529
436
|
const namePattern = `^${name.replaceAll(".", "\\.").replaceAll("*", ".*")}$`;
|
|
530
437
|
const possibleRoutes = Object.values(getRouting().routes).filter((x) => x.method.includes("GET") && RegExp(namePattern).test(x.name)).map((x) => x.name);
|
|
@@ -536,21 +443,13 @@ function currentRouteMatches(name, parameters) {
|
|
|
536
443
|
function getCurrentRouteName() {
|
|
537
444
|
return getNameFromUrl(getCurrentUrl());
|
|
538
445
|
}
|
|
539
|
-
|
|
540
|
-
//#endregion
|
|
541
|
-
//#region src/routing/index.ts
|
|
542
446
|
function updateRoutingConfiguration(routing) {
|
|
543
447
|
if (!routing) return;
|
|
544
448
|
setContext({ routing });
|
|
545
449
|
}
|
|
546
|
-
|
|
547
|
-
//#endregion
|
|
548
|
-
//#region src/download.ts
|
|
549
|
-
/** Checks if the response wants to redirect to an external URL. */
|
|
550
450
|
function isDownloadResponse(response) {
|
|
551
451
|
return response.status === 200 && !!response.headers["content-disposition"];
|
|
552
452
|
}
|
|
553
|
-
/** Handles a download. */
|
|
554
453
|
async function handleDownloadResponse(response) {
|
|
555
454
|
const blob = new Blob([response.data], { type: response.headers["content-type"] });
|
|
556
455
|
const urlObject = window.webkitURL || window.URL;
|
|
@@ -567,23 +466,17 @@ async function handleDownloadResponse(response) {
|
|
|
567
466
|
function getFileNameFromContentDispositionHeader(header) {
|
|
568
467
|
return (header.split(";")[1]?.trim().split("=")[1])?.replace(/^"(.*)"$/, "$1") ?? "";
|
|
569
468
|
}
|
|
570
|
-
|
|
571
|
-
//#endregion
|
|
572
|
-
//#region src/context/context.ts
|
|
573
469
|
const state = {
|
|
574
470
|
initialized: false,
|
|
575
471
|
context: {}
|
|
576
472
|
};
|
|
577
|
-
/** Gets the current context. */
|
|
578
473
|
function getRouterContext() {
|
|
579
474
|
return getInternalRouterContext();
|
|
580
475
|
}
|
|
581
|
-
/** Gets the current context, but not in read-only. */
|
|
582
476
|
function getInternalRouterContext() {
|
|
583
477
|
if (!state.initialized) throw new Error("Hybridly is not initialized.");
|
|
584
478
|
return state.context;
|
|
585
479
|
}
|
|
586
|
-
/** Initializes the context. */
|
|
587
480
|
async function initializeContext(options) {
|
|
588
481
|
state.initialized = true;
|
|
589
482
|
state.context = {
|
|
@@ -606,10 +499,6 @@ async function initializeContext(options) {
|
|
|
606
499
|
await runHooks("initialized", {}, state.context);
|
|
607
500
|
return getInternalRouterContext();
|
|
608
501
|
}
|
|
609
|
-
/**
|
|
610
|
-
* Registers an interceptor that assumes `arraybuffer`
|
|
611
|
-
* responses and converts responses to JSON or text.
|
|
612
|
-
*/
|
|
613
502
|
function registerAxios(axios) {
|
|
614
503
|
axios.interceptors.response.use((response) => {
|
|
615
504
|
if (!isDownloadResponse(response)) {
|
|
@@ -624,9 +513,6 @@ function registerAxios(axios) {
|
|
|
624
513
|
}, (error) => Promise.reject(error));
|
|
625
514
|
return axios;
|
|
626
515
|
}
|
|
627
|
-
/**
|
|
628
|
-
* Mutates properties at the top-level of the context.
|
|
629
|
-
*/
|
|
630
516
|
function setContext(merge = {}, options = {}) {
|
|
631
517
|
Object.keys(merge).forEach((key) => {
|
|
632
518
|
Reflect.set(state.context, key, merge[key]);
|
|
@@ -637,7 +523,6 @@ function setContext(merge = {}, options = {}) {
|
|
|
637
523
|
added: merge
|
|
638
524
|
});
|
|
639
525
|
}
|
|
640
|
-
/** Gets a payload from the current context. */
|
|
641
526
|
function payloadFromContext() {
|
|
642
527
|
return {
|
|
643
528
|
url: getRouterContext().url,
|
|
@@ -646,14 +531,6 @@ function payloadFromContext() {
|
|
|
646
531
|
dialog: getRouterContext().dialog
|
|
647
532
|
};
|
|
648
533
|
}
|
|
649
|
-
|
|
650
|
-
//#endregion
|
|
651
|
-
//#region src/external.ts
|
|
652
|
-
/**
|
|
653
|
-
* Performs an external navigation by saving options to the storage and
|
|
654
|
-
* making a full page reload. Upon loading, the navigation options
|
|
655
|
-
* will be pulled and a hybrid navigation will be made.
|
|
656
|
-
*/
|
|
657
534
|
async function performExternalNavigation(options) {
|
|
658
535
|
debug.external("Navigating to an external URL:", options);
|
|
659
536
|
if (options.target === "new-tab") {
|
|
@@ -672,21 +549,15 @@ async function performExternalNavigation(options) {
|
|
|
672
549
|
window.location.reload();
|
|
673
550
|
}
|
|
674
551
|
}
|
|
675
|
-
/** Navigates to the given URL without the hybrid protocol. */
|
|
676
552
|
function navigateToExternalUrl(url, data) {
|
|
677
553
|
document.location.href = makeUrl(url, { search: qs.stringify(data, {
|
|
678
554
|
encodeValuesOnly: true,
|
|
679
555
|
arrayFormat: "brackets"
|
|
680
556
|
}) }).toString();
|
|
681
557
|
}
|
|
682
|
-
/** Checks if the response wants to redirect to an external URL. */
|
|
683
558
|
function isExternalResponse(response) {
|
|
684
559
|
return response?.status === 409 && !!response?.headers?.[EXTERNAL_NAVIGATION_HEADER];
|
|
685
560
|
}
|
|
686
|
-
/**
|
|
687
|
-
* Performs the internal navigation when an external navigation to a hybrid view has been made.
|
|
688
|
-
* This method is meant to be called on router creation.
|
|
689
|
-
*/
|
|
690
561
|
async function handleExternalNavigation() {
|
|
691
562
|
debug.external("Handling an external navigation.");
|
|
692
563
|
const options = JSON.parse(window.sessionStorage.getItem(STORAGE_EXTERNAL_KEY) || "{}");
|
|
@@ -699,19 +570,12 @@ async function handleExternalNavigation() {
|
|
|
699
570
|
preserveScroll: options.preserveScroll
|
|
700
571
|
});
|
|
701
572
|
}
|
|
702
|
-
/** Checks if the navigation being initialized points to an external location. */
|
|
703
573
|
function isExternalNavigation() {
|
|
704
574
|
try {
|
|
705
575
|
return window.sessionStorage.getItem(STORAGE_EXTERNAL_KEY) !== null;
|
|
706
576
|
} catch {}
|
|
707
577
|
return false;
|
|
708
578
|
}
|
|
709
|
-
|
|
710
|
-
//#endregion
|
|
711
|
-
//#region src/dialog/index.ts
|
|
712
|
-
/**
|
|
713
|
-
* Closes the dialog.
|
|
714
|
-
*/
|
|
715
579
|
async function closeDialog(options) {
|
|
716
580
|
const context = getInternalRouterContext();
|
|
717
581
|
const url = context.dialog?.redirectUrl ?? context.dialog?.baseUrl;
|
|
@@ -732,34 +596,18 @@ async function closeDialog(options) {
|
|
|
732
596
|
...options
|
|
733
597
|
});
|
|
734
598
|
}
|
|
735
|
-
|
|
736
|
-
//#endregion
|
|
737
|
-
//#region src/router/preload.ts
|
|
738
|
-
/**
|
|
739
|
-
* Checks if there is a preloaded request for the given URL.
|
|
740
|
-
*/
|
|
741
599
|
function isPreloaded(targetUrl) {
|
|
742
600
|
return getInternalRouterContext().preloadCache.has(targetUrl.toString()) ?? false;
|
|
743
601
|
}
|
|
744
|
-
/**
|
|
745
|
-
* Gets the response of a preloaded request.
|
|
746
|
-
*/
|
|
747
602
|
function getPreloadedRequest(targetUrl) {
|
|
748
603
|
return getInternalRouterContext().preloadCache.get(targetUrl.toString());
|
|
749
604
|
}
|
|
750
|
-
/**
|
|
751
|
-
* Stores the response of a preloaded request.
|
|
752
|
-
*/
|
|
753
605
|
function storePreloadRequest(targetUrl, response) {
|
|
754
606
|
getInternalRouterContext().preloadCache.set(targetUrl.toString(), response);
|
|
755
607
|
}
|
|
756
|
-
/**
|
|
757
|
-
* Discards a preloaded request.
|
|
758
|
-
*/
|
|
759
608
|
function discardPreloadedRequest(targetUrl) {
|
|
760
609
|
return getInternalRouterContext().preloadCache.delete(targetUrl.toString());
|
|
761
610
|
}
|
|
762
|
-
/** Preloads a hybrid request. */
|
|
763
611
|
async function performPreloadRequest(options) {
|
|
764
612
|
const context = getRouterContext();
|
|
765
613
|
const url = makeUrl(options.url ?? context.url);
|
|
@@ -789,18 +637,6 @@ async function performPreloadRequest(options) {
|
|
|
789
637
|
return false;
|
|
790
638
|
}
|
|
791
639
|
}
|
|
792
|
-
|
|
793
|
-
//#endregion
|
|
794
|
-
//#region src/router/router.ts
|
|
795
|
-
/**
|
|
796
|
-
* The hybridly router.
|
|
797
|
-
* This is the core function that you can use to navigate in
|
|
798
|
-
* your application. Make sure the routes you call return a
|
|
799
|
-
* hybrid response, otherwise you need to call `external`.
|
|
800
|
-
*
|
|
801
|
-
* @example
|
|
802
|
-
* router.get('/posts/edit', { post })
|
|
803
|
-
*/
|
|
804
640
|
const router = {
|
|
805
641
|
abort: async () => getRouterContext().pendingNavigation?.controller.abort(),
|
|
806
642
|
active: () => !!getRouterContext().pendingNavigation,
|
|
@@ -864,12 +700,10 @@ const router = {
|
|
|
864
700
|
remember: (key, value) => remember(key, value)
|
|
865
701
|
}
|
|
866
702
|
};
|
|
867
|
-
/** Creates the hybridly router. */
|
|
868
703
|
async function createRouter(options) {
|
|
869
704
|
await initializeContext(options);
|
|
870
705
|
return await initializeRouter();
|
|
871
706
|
}
|
|
872
|
-
/** Performs every action necessary to make a hybrid navigation. */
|
|
873
707
|
async function performHybridNavigation(options) {
|
|
874
708
|
const navigationId = random();
|
|
875
709
|
const context = getRouterContext();
|
|
@@ -1020,14 +854,9 @@ async function performHybridNavigation(options) {
|
|
|
1020
854
|
if (context.pendingNavigation?.id === navigationId) setContext({ pendingNavigation: void 0 });
|
|
1021
855
|
}
|
|
1022
856
|
}
|
|
1023
|
-
/** Checks if the response contains a hybrid header. */
|
|
1024
857
|
function isHybridResponse(response) {
|
|
1025
858
|
return !!response?.headers[HYBRIDLY_HEADER];
|
|
1026
859
|
}
|
|
1027
|
-
/**
|
|
1028
|
-
* Makes an internal navigation that swaps the view and updates the context.
|
|
1029
|
-
* @internal
|
|
1030
|
-
*/
|
|
1031
860
|
async function navigate(options) {
|
|
1032
861
|
const context = getRouterContext();
|
|
1033
862
|
options.hasDialog ??= !!options.payload?.dialog;
|
|
@@ -1137,7 +966,6 @@ async function performHybridRequest(targetUrl, options, abortController) {
|
|
|
1137
966
|
}
|
|
1138
967
|
});
|
|
1139
968
|
}
|
|
1140
|
-
/** Initializes the router by reading the context and registering events if necessary. */
|
|
1141
969
|
async function initializeRouter() {
|
|
1142
970
|
const context = getRouterContext();
|
|
1143
971
|
if (isBackForwardNavigation()) handleBackForwardNavigation();
|
|
@@ -1155,7 +983,6 @@ async function initializeRouter() {
|
|
|
1155
983
|
await runHooks("ready", {}, context);
|
|
1156
984
|
return context;
|
|
1157
985
|
}
|
|
1158
|
-
/** Performs a local navigation to the given component without a round-trip. */
|
|
1159
986
|
async function performLocalNavigation(targetUrl, options) {
|
|
1160
987
|
const context = getRouterContext();
|
|
1161
988
|
const url = normalizeUrl(targetUrl);
|
|
@@ -1174,16 +1001,7 @@ async function performLocalNavigation(targetUrl, options) {
|
|
|
1174
1001
|
}
|
|
1175
1002
|
});
|
|
1176
1003
|
}
|
|
1177
|
-
|
|
1178
|
-
//#endregion
|
|
1179
|
-
//#region src/authorization.ts
|
|
1180
|
-
/**
|
|
1181
|
-
* Checks whether the given data has the authorization for the given action.
|
|
1182
|
-
* If the data object has no authorization definition corresponding to the given action, this method will return `false`.
|
|
1183
|
-
*/
|
|
1184
1004
|
function can(resource, action) {
|
|
1185
1005
|
return resource.authorization?.[action] ?? false;
|
|
1186
1006
|
}
|
|
1187
|
-
|
|
1188
|
-
//#endregion
|
|
1189
|
-
export { can, constants_exports as constants, createRouter, definePlugin, getRouterContext, makeUrl, registerHook, route, router, sameUrls };
|
|
1007
|
+
export { can, constants_exports as constants, createRouter, definePlugin, getRouterContext, makeUrl, registerHook, route, router, sameUrls };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridly/core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.10.0-beta.
|
|
4
|
+
"version": "0.10.0-beta.6",
|
|
5
5
|
"description": "Core functionality of Hybridly",
|
|
6
6
|
"author": "Enzo Innocenzi <enzo@innocenzi.dev>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"axios": "^1.7.2"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@hybridly/utils": "0.10.0-beta.
|
|
46
|
+
"@hybridly/utils": "0.10.0-beta.6",
|
|
47
47
|
"qs": "^6.14.0",
|
|
48
48
|
"superjson": "^2.2.2"
|
|
49
49
|
},
|