@hybridly/core 0.10.0-beta.15 → 0.10.0-beta.17
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.d.mts +17 -14
- package/dist/index.mjs +23 -45
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -109,7 +109,7 @@ interface RequestHooks {
|
|
|
109
109
|
*/
|
|
110
110
|
fail: (error: Error, request: PendingHybridRequest, context: InternalRouterContext) => MaybePromise<any>;
|
|
111
111
|
/**
|
|
112
|
-
* Called after a
|
|
112
|
+
* Called after a response has been received, even if it didn't succeed in a navigation.
|
|
113
113
|
*/
|
|
114
114
|
after: (request: PendingHybridRequest, context: InternalRouterContext) => MaybePromise<any>;
|
|
115
115
|
}
|
|
@@ -271,11 +271,23 @@ interface CloseDialogOptions extends HybridRequestOptions {
|
|
|
271
271
|
local?: boolean;
|
|
272
272
|
}
|
|
273
273
|
//#endregion
|
|
274
|
+
//#region src/query.d.ts
|
|
275
|
+
type QueryArrayFormat = 'indices' | 'brackets';
|
|
276
|
+
type QueryValue = string | number | boolean | null | undefined | QueryValue[] | Set<QueryValue> | {
|
|
277
|
+
[key: string]: QueryValue;
|
|
278
|
+
};
|
|
279
|
+
interface StringifyQueryOptions {
|
|
280
|
+
arrayFormat?: QueryArrayFormat;
|
|
281
|
+
addQueryPrefix?: boolean;
|
|
282
|
+
}
|
|
283
|
+
declare function parseQueryString(query: string): Record<string, any>;
|
|
284
|
+
declare function stringifyQueryString(value: QueryValue, options?: StringifyQueryOptions): string;
|
|
285
|
+
//#endregion
|
|
274
286
|
//#region src/url.d.ts
|
|
275
287
|
type UrlResolvable = string | URL | Location;
|
|
276
288
|
type UrlTransformable = BaseUrlTransformable | ((string: URL) => BaseUrlTransformable);
|
|
277
289
|
type BaseUrlTransformable = Partial<Omit<URL, 'searchParams' | 'toJSON' | 'toString'>> & {
|
|
278
|
-
query?:
|
|
290
|
+
query?: Record<string, QueryValue>;
|
|
279
291
|
trailingSlash?: boolean;
|
|
280
292
|
};
|
|
281
293
|
/** Normalizes the given input to an URL. */
|
|
@@ -553,7 +565,7 @@ type Validation = Record<string, Errors>;
|
|
|
553
565
|
declare const router: {
|
|
554
566
|
abort: () => void;
|
|
555
567
|
navigate: (options: HybridRequestOptions) => Promise<NavigationResponse>;
|
|
556
|
-
reload: (options
|
|
568
|
+
reload: (options?: HybridRequestOptions | undefined) => Promise<NavigationResponse>;
|
|
557
569
|
get: (url: UrlResolvable, options?: Omit<HybridRequestOptions, "method" | "url"> | undefined) => Promise<NavigationResponse>;
|
|
558
570
|
post: (url: UrlResolvable, options?: Omit<HybridRequestOptions, "method" | "url"> | undefined) => Promise<NavigationResponse>;
|
|
559
571
|
put: (url: UrlResolvable, options?: Omit<HybridRequestOptions, "method" | "url"> | undefined) => Promise<NavigationResponse>;
|
|
@@ -561,8 +573,8 @@ declare const router: {
|
|
|
561
573
|
delete: (url: UrlResolvable, options?: Omit<HybridRequestOptions, "method" | "url"> | undefined) => Promise<NavigationResponse>;
|
|
562
574
|
local: (url: UrlResolvable, options?: ComponentNavigationOptions) => Promise<void>;
|
|
563
575
|
external: (url: UrlResolvable, data?: _hybridly_utils0.RequestData) => void;
|
|
564
|
-
to: <T extends RouteName>(name: T, parameters
|
|
565
|
-
matches: <T extends RouteName>(name: T, parameters
|
|
576
|
+
to: <T extends RouteName>(name: T, parameters?: Record<string, any> | undefined, options?: Omit<HybridRequestOptions, "url"> | undefined) => Promise<NavigationResponse>;
|
|
577
|
+
matches: <T extends RouteName>(name: T, parameters?: Record<string, any> | undefined) => boolean;
|
|
566
578
|
current: () => string | undefined;
|
|
567
579
|
dialog: {
|
|
568
580
|
close: (options?: CloseDialogOptions | undefined) => Promise<void | NavigationResponse>;
|
|
@@ -575,15 +587,6 @@ declare const router: {
|
|
|
575
587
|
/** Creates the hybridly router. */
|
|
576
588
|
declare function createRouter(options: RouterContextOptions): Promise<InternalRouterContext>;
|
|
577
589
|
//#endregion
|
|
578
|
-
//#region src/query.d.ts
|
|
579
|
-
type QueryArrayFormat = 'indices' | 'brackets';
|
|
580
|
-
interface StringifyQueryOptions {
|
|
581
|
-
arrayFormat?: QueryArrayFormat;
|
|
582
|
-
addQueryPrefix?: boolean;
|
|
583
|
-
}
|
|
584
|
-
declare function parseQueryString(query: string): Record<string, any>;
|
|
585
|
-
declare function stringifyQueryString(value: unknown, options?: StringifyQueryOptions): string;
|
|
586
|
-
//#endregion
|
|
587
590
|
//#region src/authorization.d.ts
|
|
588
591
|
interface Authorizable<Authorizations extends Record<string, boolean>> {
|
|
589
592
|
authorization: Authorizations;
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { t as __exportAll } from "./_chunks/chunk.mjs";
|
|
2
|
-
import { debug,
|
|
2
|
+
import { debug, hasFiles, merge, mergeObject, objectToFormData, random, showResponseErrorModal, wrap } from "@hybridly/utils";
|
|
3
3
|
import { trimEnd } from "es-toolkit/string";
|
|
4
|
-
import {
|
|
4
|
+
import { isPlainObject } from "es-toolkit/predicate";
|
|
5
|
+
import { parse, stringify } from "neoqs";
|
|
5
6
|
import { debounce } from "es-toolkit/function";
|
|
6
7
|
import { parse as parse$1, stringify as stringify$1 } from "superjson";
|
|
7
8
|
import { get, set, uniqBy } from "es-toolkit/compat";
|
|
@@ -9,35 +10,15 @@ import { get, set, uniqBy } from "es-toolkit/compat";
|
|
|
9
10
|
function parseQueryString(query) {
|
|
10
11
|
const source = query.startsWith("?") ? query.slice(1) : query;
|
|
11
12
|
if (!source) return {};
|
|
12
|
-
return parse(source
|
|
13
|
-
nesting: true,
|
|
14
|
-
nestingSyntax: "index",
|
|
15
|
-
arrayRepeat: true,
|
|
16
|
-
arrayRepeatSyntax: "bracket"
|
|
17
|
-
});
|
|
13
|
+
return parse(source);
|
|
18
14
|
}
|
|
19
15
|
function stringifyQueryString(value, options = {}) {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
if (!normalizedQuery) return "";
|
|
27
|
-
return options.addQueryPrefix ? `?${normalizedQuery}` : normalizedQuery;
|
|
28
|
-
}
|
|
29
|
-
function unescapeBracketSyntaxInKeys(query) {
|
|
30
|
-
if (!query) return query;
|
|
31
|
-
return query.split("&").map((entry) => {
|
|
32
|
-
const separator = entry.indexOf("=");
|
|
33
|
-
if (separator < 0) return decodeBracketSyntax(entry);
|
|
34
|
-
const key = entry.slice(0, separator);
|
|
35
|
-
const value = entry.slice(separator);
|
|
36
|
-
return `${decodeBracketSyntax(key)}${value}`;
|
|
37
|
-
}).join("&");
|
|
38
|
-
}
|
|
39
|
-
function decodeBracketSyntax(value) {
|
|
40
|
-
return value.replace(/%5B/gi, "[").replace(/%5D/gi, "]");
|
|
16
|
+
const query = stringify(normalizeQueryValue(value), {
|
|
17
|
+
arrayFormat: options.arrayFormat ?? "brackets",
|
|
18
|
+
encodeValuesOnly: true
|
|
19
|
+
});
|
|
20
|
+
if (!query) return "";
|
|
21
|
+
return options.addQueryPrefix ? `?${query}` : query;
|
|
41
22
|
}
|
|
42
23
|
function normalizeQueryValue(value) {
|
|
43
24
|
if (value instanceof Set) return [...value].map((entry) => normalizeQueryValue(entry));
|
|
@@ -48,11 +29,6 @@ function normalizeQueryValue(value) {
|
|
|
48
29
|
}), {});
|
|
49
30
|
return value;
|
|
50
31
|
}
|
|
51
|
-
function isPlainObject(value) {
|
|
52
|
-
if (typeof value !== "object" || value === null) return false;
|
|
53
|
-
const prototype = Object.getPrototypeOf(value);
|
|
54
|
-
return prototype === null || prototype === Object.prototype;
|
|
55
|
-
}
|
|
56
32
|
//#endregion
|
|
57
33
|
//#region src/url.ts
|
|
58
34
|
/** Normalizes the given input to an URL. */
|
|
@@ -69,9 +45,8 @@ function makeUrl(href, transformations = {}) {
|
|
|
69
45
|
transformations = typeof transformations === "function" ? transformations(url) ?? {} : transformations ?? {};
|
|
70
46
|
Object.entries(transformations).forEach(([key, value]) => {
|
|
71
47
|
if (key === "query") {
|
|
72
|
-
const currentQueryParameters = merge(parseQueryString(url.search), value, { mergePlainObjects: true });
|
|
73
48
|
key = "search";
|
|
74
|
-
value = stringifyQueryString(
|
|
49
|
+
value = stringifyQueryString(merge(parseQueryString(url.search), value, { mergePlainObjects: true }), { arrayFormat: "brackets" });
|
|
75
50
|
}
|
|
76
51
|
Reflect.set(url, key, value);
|
|
77
52
|
});
|
|
@@ -699,8 +674,8 @@ async function transformOptions(options) {
|
|
|
699
674
|
debug.router("Converted data to FormData.", options.data);
|
|
700
675
|
}
|
|
701
676
|
if (!(options.data instanceof FormData) && options.method === "GET" && Object.keys(options.data ?? {}).length) {
|
|
702
|
-
debug.router("Transforming data to query parameters.", options.data);
|
|
703
677
|
options.url = makeUrl(options.url ?? context.url, { query: options.data });
|
|
678
|
+
debug.router("Transforming data to query parameters.", options.data, options.url);
|
|
704
679
|
options.data = {};
|
|
705
680
|
}
|
|
706
681
|
if ([
|
|
@@ -949,8 +924,8 @@ function isPartial(options) {
|
|
|
949
924
|
function resolveProperties(original, payload) {
|
|
950
925
|
const mergedPayloadProperties = merge(original, payload.properties);
|
|
951
926
|
(payload.mergeable ?? []).forEach(([mergeableProperty, prepends, uniqueBy]) => {
|
|
952
|
-
const originalValue =
|
|
953
|
-
const newValue =
|
|
927
|
+
const originalValue = get(original, mergeableProperty);
|
|
928
|
+
const newValue = get(payload.properties, mergeableProperty);
|
|
954
929
|
const mergeArrays = (current, incoming) => {
|
|
955
930
|
const merged = prepends === true ? [...incoming, ...current] : [...current, ...incoming];
|
|
956
931
|
if (typeof uniqueBy !== "string") return merged;
|
|
@@ -1014,7 +989,12 @@ async function processNextResponse() {
|
|
|
1014
989
|
return;
|
|
1015
990
|
}
|
|
1016
991
|
debug.queue("Processing response", response);
|
|
1017
|
-
|
|
992
|
+
try {
|
|
993
|
+
response.request.resolve(await handleHybridRequestResponse(response));
|
|
994
|
+
} finally {
|
|
995
|
+
debug.router("Ended navigation.", response.request);
|
|
996
|
+
await runHooks("after", response.request.options.hooks, response.request, getInternalRouterContext());
|
|
997
|
+
}
|
|
1018
998
|
return await processNextResponse();
|
|
1019
999
|
}
|
|
1020
1000
|
//#endregion
|
|
@@ -1071,8 +1051,6 @@ async function processRequest(request, onFinally) {
|
|
|
1071
1051
|
await handleTransportError(request, error);
|
|
1072
1052
|
} finally {
|
|
1073
1053
|
request.completed = true;
|
|
1074
|
-
debug.router("Ended navigation.", request);
|
|
1075
|
-
await runHooks("after", request.options.hooks, request, getRouterContext());
|
|
1076
1054
|
onFinally();
|
|
1077
1055
|
}
|
|
1078
1056
|
}
|
|
@@ -1535,7 +1513,7 @@ async function closeDialog(options) {
|
|
|
1535
1513
|
const router = {
|
|
1536
1514
|
abort: () => cancelNavigationRequest(),
|
|
1537
1515
|
navigate: async (options) => await performHybridNavigation(options),
|
|
1538
|
-
reload: async (options) => await performHybridNavigation({
|
|
1516
|
+
reload: async (options = {}) => await performHybridNavigation({
|
|
1539
1517
|
preserveScroll: true,
|
|
1540
1518
|
preserveState: true,
|
|
1541
1519
|
replace: true,
|
|
@@ -1573,7 +1551,7 @@ const router = {
|
|
|
1573
1551
|
}),
|
|
1574
1552
|
local: async (url, options = {}) => await performLocalNavigation(url, options),
|
|
1575
1553
|
external: (url, data = {}) => navigateToExternalUrl(url, data),
|
|
1576
|
-
to: async (name, parameters, options) => {
|
|
1554
|
+
to: async (name, parameters = void 0, options = {}) => {
|
|
1577
1555
|
const url = generateRouteFromName(name, parameters);
|
|
1578
1556
|
const method = getRouteDefinition(name).method.at(0);
|
|
1579
1557
|
return await performHybridNavigation({
|
|
@@ -1582,7 +1560,7 @@ const router = {
|
|
|
1582
1560
|
method
|
|
1583
1561
|
});
|
|
1584
1562
|
},
|
|
1585
|
-
matches: (name, parameters) => currentRouteMatches(name, parameters),
|
|
1563
|
+
matches: (name, parameters = void 0) => currentRouteMatches(name, parameters),
|
|
1586
1564
|
current: () => getCurrentRouteName(),
|
|
1587
1565
|
dialog: { close: (options = {}) => closeDialog(options) },
|
|
1588
1566
|
history: {
|
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.17",
|
|
5
5
|
"description": "Core functionality of Hybridly",
|
|
6
6
|
"author": "Enzo Innocenzi <enzo@innocenzi.dev>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"build:stub": "obuild --stub"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@hybridly/utils": "0.10.0-beta.
|
|
44
|
-
"
|
|
43
|
+
"@hybridly/utils": "0.10.0-beta.17",
|
|
44
|
+
"neoqs": "^6.13.0",
|
|
45
45
|
"superjson": "^2.2.2",
|
|
46
46
|
"es-toolkit": "^1.45.1"
|
|
47
47
|
},
|