@hybridly/core 0.10.0-beta.16 → 0.10.0-beta.18
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 +13 -10
- package/dist/index.mjs +25 -48
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -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. */
|
|
@@ -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
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
|
});
|
|
@@ -610,6 +585,9 @@ function createPromiseWithResolvers() {
|
|
|
610
585
|
reject
|
|
611
586
|
};
|
|
612
587
|
}
|
|
588
|
+
function evaluateConditionalOption(options, option) {
|
|
589
|
+
return typeof option === "function" ? option(options) : option;
|
|
590
|
+
}
|
|
613
591
|
//#endregion
|
|
614
592
|
//#region src/router/request/request.ts
|
|
615
593
|
function createPendingHybridRequest(options) {
|
|
@@ -699,8 +677,8 @@ async function transformOptions(options) {
|
|
|
699
677
|
debug.router("Converted data to FormData.", options.data);
|
|
700
678
|
}
|
|
701
679
|
if (!(options.data instanceof FormData) && options.method === "GET" && Object.keys(options.data ?? {}).length) {
|
|
702
|
-
debug.router("Transforming data to query parameters.", options.data);
|
|
703
680
|
options.url = makeUrl(options.url ?? context.url, { query: options.data });
|
|
681
|
+
debug.router("Transforming data to query parameters.", options.data, options.url);
|
|
704
682
|
options.data = {};
|
|
705
683
|
}
|
|
706
684
|
if ([
|
|
@@ -734,13 +712,10 @@ async function navigate(options) {
|
|
|
734
712
|
options.payload ??= payloadFromContext();
|
|
735
713
|
options.payload.view ??= payloadFromContext().view;
|
|
736
714
|
options.payload.view.properties = options.properties ?? options.payload.view.properties;
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
const
|
|
741
|
-
const shouldPreserveScroll = evaluateConditionalOption(options.preserveScroll);
|
|
742
|
-
const shouldReplaceHistory = evaluateConditionalOption(options.replace);
|
|
743
|
-
const shouldReplaceUrl = evaluateConditionalOption(options.preserveUrl);
|
|
715
|
+
const shouldPreserveState = evaluateConditionalOption(options, options.preserveState);
|
|
716
|
+
const shouldPreserveScroll = evaluateConditionalOption(options, options.preserveScroll);
|
|
717
|
+
const shouldReplaceHistory = evaluateConditionalOption(options, options.replace);
|
|
718
|
+
const shouldReplaceUrl = evaluateConditionalOption(options, options.preserveUrl);
|
|
744
719
|
const shouldPreserveView = !options.payload.view.component;
|
|
745
720
|
if (shouldPreserveState && getHistoryMemo() && options.payload.view.component === context.view.component) {
|
|
746
721
|
debug.history("Setting the memo from this history entry into the current context.");
|
|
@@ -913,7 +888,7 @@ async function handleHybridRequestResponse({ request, response }) {
|
|
|
913
888
|
if (options.mode !== "async" || context.view.component === request.view.component) {
|
|
914
889
|
const properties = (() => {
|
|
915
890
|
if (!payload.view && !isPartial(options)) return;
|
|
916
|
-
if (!payload.view.component || payload.view.component === context.view.component) return resolveProperties(context.view.properties, payload.view);
|
|
891
|
+
if (!payload.view.component || payload.view.component === context.view.component) return resolveProperties(context.view.properties, payload.view, { mergeWithOriginal: evaluateConditionalOption(options, options.preserveState) !== false });
|
|
917
892
|
})();
|
|
918
893
|
if (properties) debug.router("Merged properties:", properties);
|
|
919
894
|
await navigate({
|
|
@@ -944,13 +919,15 @@ function isHybridResponse(response) {
|
|
|
944
919
|
return response.headers.has(HYBRIDLY_HEADER);
|
|
945
920
|
}
|
|
946
921
|
function isPartial(options) {
|
|
947
|
-
return options.only !== void 0 || options.except !== void 0;
|
|
922
|
+
return options.only !== void 0 || options.except !== void 0 || options.reset !== void 0;
|
|
948
923
|
}
|
|
949
|
-
function resolveProperties(original, payload) {
|
|
950
|
-
const
|
|
951
|
-
|
|
924
|
+
function resolveProperties(original, payload, options) {
|
|
925
|
+
const mergeable = payload.mergeable ?? [];
|
|
926
|
+
const mergedPayloadProperties = options.mergeWithOriginal ? merge(original, payload.properties) : payload.properties;
|
|
927
|
+
mergeable.forEach(([mergeableProperty, prepends, uniqueBy]) => {
|
|
952
928
|
const originalValue = get(original, mergeableProperty);
|
|
953
929
|
const newValue = get(payload.properties, mergeableProperty);
|
|
930
|
+
if (!options.mergeWithOriginal && newValue === void 0) return;
|
|
954
931
|
const mergeArrays = (current, incoming) => {
|
|
955
932
|
const merged = prepends === true ? [...incoming, ...current] : [...current, ...incoming];
|
|
956
933
|
if (typeof uniqueBy !== "string") return merged;
|
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.18",
|
|
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.18",
|
|
44
|
+
"neoqs": "^6.13.0",
|
|
45
45
|
"superjson": "^2.2.2",
|
|
46
46
|
"es-toolkit": "^1.45.1"
|
|
47
47
|
},
|