@decocms/tanstack 7.77.7 → 7.77.9
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/package.json +4 -4
- package/src/sdk/router.test.ts +34 -0
- package/src/sdk/router.ts +13 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decocms/tanstack",
|
|
3
|
-
"version": "7.77.
|
|
3
|
+
"version": "7.77.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Deco framework binding for TanStack Start + Cloudflare Workers",
|
|
6
6
|
"repository": {
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"lint:unused": "knip"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@decocms/blocks": "7.77.
|
|
31
|
-
"@decocms/blocks-admin": "7.77.
|
|
32
|
-
"@decocms/blocks-cli": "7.77.
|
|
30
|
+
"@decocms/blocks": "7.77.9",
|
|
31
|
+
"@decocms/blocks-admin": "7.77.9",
|
|
32
|
+
"@decocms/blocks-cli": "7.77.9",
|
|
33
33
|
"@deco-cx/warp-node": "^0.3.16",
|
|
34
34
|
"fast-json-patch": "^3.1.0",
|
|
35
35
|
"ws": "^8.18.0"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { decoParseSearch, decoStringifySearch } from "./router";
|
|
3
|
+
|
|
4
|
+
describe("decoStringifySearch ∘ decoParseSearch is a fixed point", () => {
|
|
5
|
+
// TanStack Router redirects (307) on the server when
|
|
6
|
+
// stringifySearch(parseSearch(search)) differs from the request's search —
|
|
7
|
+
// every query string that round-trips unchanged is a request that never
|
|
8
|
+
// redirects.
|
|
9
|
+
it.each([
|
|
10
|
+
"?q=camisa&sort=",
|
|
11
|
+
"?utm_source=",
|
|
12
|
+
"?a=&b=",
|
|
13
|
+
"?q=camisa",
|
|
14
|
+
"?filter.brand=Nike&filter.brand=Adidas",
|
|
15
|
+
// (`%20` is re-encoded as `+` by URLSearchParams — a pre-existing
|
|
16
|
+
// normalization, out of this fix's scope.)
|
|
17
|
+
"?q=a+b&page=2",
|
|
18
|
+
])("round-trips %s unchanged", (search) => {
|
|
19
|
+
expect(decoStringifySearch(decoParseSearch(search))).toBe(search);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("parses a value-less param to an empty string", () => {
|
|
23
|
+
expect(decoParseSearch("?q=camisa&sort=")).toEqual({ q: "camisa", sort: "" });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("still drops undefined and null (how navigate() removes a param)", () => {
|
|
27
|
+
expect(decoStringifySearch({ q: "camisa", sort: undefined, page: null })).toBe("?q=camisa");
|
|
28
|
+
expect(decoStringifySearch({ q: undefined })).toBe("");
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("keeps an explicit empty string as key= and arrays as repeated keys", () => {
|
|
32
|
+
expect(decoStringifySearch({ sort: "", f: ["a", "b"] })).toBe("?sort=&f=a&f=b");
|
|
33
|
+
});
|
|
34
|
+
});
|
package/src/sdk/router.ts
CHANGED
|
@@ -30,10 +30,22 @@ export const decoParseSearch: SearchParser = (searchStr) => {
|
|
|
30
30
|
return result;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Serializes the router's search object back to a query string.
|
|
35
|
+
*
|
|
36
|
+
* Must be a fixed point of {@link decoParseSearch}: on the server, TanStack
|
|
37
|
+
* Router compares the request's href with `stringifySearch(parseSearch(...))`
|
|
38
|
+
* (`router.beforeLoad`) and answers a 307 to the normalized URL when they
|
|
39
|
+
* differ. A value-less parameter (`?sort=`, `?utm_source=`) parses to `""`,
|
|
40
|
+
* so dropping `""` here turned every such request into a redirect that
|
|
41
|
+
* Fresh — and TanStack's own default serializer, which only drops
|
|
42
|
+
* `undefined` — never issued. `undefined`/`null` still remove a param, which
|
|
43
|
+
* is how `navigate({ search: { q: undefined } })` clears one.
|
|
44
|
+
*/
|
|
33
45
|
export const decoStringifySearch: SearchSerializer = (search) => {
|
|
34
46
|
const params = new URLSearchParams();
|
|
35
47
|
for (const [key, value] of Object.entries(search)) {
|
|
36
|
-
if (value === undefined || value === null
|
|
48
|
+
if (value === undefined || value === null) continue;
|
|
37
49
|
if (Array.isArray(value)) {
|
|
38
50
|
for (const v of value) params.append(key, String(v));
|
|
39
51
|
} else {
|