@tanstack/react-router 1.92.1 → 1.92.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.
@@ -1,6 +1,8 @@
1
1
  export interface RouterTransformer {
2
2
  stringify: (obj: unknown) => string;
3
3
  parse: (str: string) => unknown;
4
+ encode: <T>(value: T) => T;
5
+ decode: <T>(value: T) => T;
4
6
  }
5
7
  export declare const defaultTransformer: RouterTransformer;
6
8
  export type TransformerStringify<T, TSerializable> = T extends TSerializable ? T : T extends (...args: Array<any>) => any ? 'Function is not serializable' : {
@@ -1,37 +1,100 @@
1
1
  import { isPlainObject } from "./utils.js";
2
2
  const defaultTransformer = {
3
- stringify: (value) => JSON.stringify(value, function replacer(key, value2) {
4
- const keyVal = this[key];
5
- const transformer = transformers.find((t) => t.stringifyCondition(keyVal));
3
+ stringify: (value) => JSON.stringify(value, function replacer(key, val) {
4
+ const ogVal = this[key];
5
+ const transformer = transformers.find((t) => t.stringifyCondition(ogVal));
6
6
  if (transformer) {
7
- return transformer.stringify(keyVal);
7
+ return transformer.stringify(ogVal);
8
8
  }
9
- return value2;
9
+ return val;
10
10
  }),
11
- parse: (value) => JSON.parse(value, function parser(key, value2) {
12
- const keyVal = this[key];
13
- const transformer = transformers.find((t) => t.parseCondition(keyVal));
11
+ parse: (value) => JSON.parse(value, function parser(key, val) {
12
+ const ogVal = this[key];
13
+ if (isPlainObject(ogVal)) {
14
+ const transformer = transformers.find((t) => t.parseCondition(ogVal));
15
+ if (transformer) {
16
+ return transformer.parse(ogVal);
17
+ }
18
+ }
19
+ return val;
20
+ }),
21
+ encode: (value) => {
22
+ if (Array.isArray(value)) {
23
+ return value.map((v) => defaultTransformer.encode(v));
24
+ }
25
+ if (isPlainObject(value)) {
26
+ return Object.fromEntries(
27
+ Object.entries(value).map(([key, v]) => [
28
+ key,
29
+ defaultTransformer.encode(v)
30
+ ])
31
+ );
32
+ }
33
+ const transformer = transformers.find((t) => t.stringifyCondition(value));
14
34
  if (transformer) {
15
- return transformer.parse(keyVal);
35
+ return transformer.stringify(value);
16
36
  }
17
- return value2;
18
- })
19
- };
20
- const transformers = [
21
- {
22
- // Dates
23
- stringifyCondition: (value) => value instanceof Date,
24
- stringify: (value) => ({ $date: value.toISOString() }),
25
- parseCondition: (value) => isPlainObject(value) && value.$date,
26
- parse: (value) => new Date(value.$date)
37
+ return value;
27
38
  },
28
- {
29
- // undefined
30
- stringifyCondition: (value) => value === void 0,
31
- stringify: () => ({ $undefined: "" }),
32
- parseCondition: (value) => isPlainObject(value) && value.$undefined === "",
33
- parse: () => void 0
39
+ decode: (value) => {
40
+ if (isPlainObject(value)) {
41
+ const transformer = transformers.find((t) => t.parseCondition(value));
42
+ if (transformer) {
43
+ return transformer.parse(value);
44
+ }
45
+ }
46
+ if (Array.isArray(value)) {
47
+ return value.map((v) => defaultTransformer.decode(v));
48
+ }
49
+ if (isPlainObject(value)) {
50
+ return Object.fromEntries(
51
+ Object.entries(value).map(([key, v]) => [
52
+ key,
53
+ defaultTransformer.decode(v)
54
+ ])
55
+ );
56
+ }
57
+ return value;
34
58
  }
59
+ };
60
+ const createTransformer = (key, check, toValue = (v) => v, fromValue = (v) => v) => ({
61
+ key,
62
+ stringifyCondition: check,
63
+ stringify: (value) => ({ [`$${key}`]: toValue(value) }),
64
+ parseCondition: (value) => Object.hasOwn(value, `$${key}`),
65
+ parse: (value) => fromValue(value[`$${key}`])
66
+ });
67
+ const transformers = [
68
+ createTransformer(
69
+ // Key
70
+ "undefined",
71
+ // Check
72
+ (v) => v === void 0,
73
+ // To
74
+ () => 0,
75
+ // From
76
+ () => void 0
77
+ ),
78
+ createTransformer(
79
+ // Key
80
+ "date",
81
+ // Check
82
+ (v) => v instanceof Date,
83
+ // To
84
+ (v) => v.toISOString(),
85
+ // From
86
+ (v) => new Date(v)
87
+ ),
88
+ createTransformer(
89
+ // Key
90
+ "error",
91
+ // Check
92
+ (v) => v instanceof Error,
93
+ // To
94
+ (v) => ({ ...v, message: v.message, stack: v.stack, cause: v.cause }),
95
+ // From
96
+ (v) => Object.assign(new Error(v.message), v)
97
+ )
35
98
  ];
36
99
  export {
37
100
  defaultTransformer
@@ -1 +1 @@
1
- {"version":3,"file":"transformer.js","sources":["../../src/transformer.ts"],"sourcesContent":["import { isPlainObject } from './utils'\n\nexport interface RouterTransformer {\n stringify: (obj: unknown) => string\n parse: (str: string) => unknown\n}\n\nexport const defaultTransformer: RouterTransformer = {\n stringify: (value: any) =>\n JSON.stringify(value, function replacer(key, value) {\n const keyVal = this[key]\n const transformer = transformers.find((t) => t.stringifyCondition(keyVal))\n\n if (transformer) {\n return transformer.stringify(keyVal)\n }\n\n return value\n }),\n parse: (value: string) =>\n JSON.parse(value, function parser(key, value) {\n const keyVal = this[key]\n const transformer = transformers.find((t) => t.parseCondition(keyVal))\n\n if (transformer) {\n return transformer.parse(keyVal)\n }\n\n return value\n }),\n}\n\nconst transformers = [\n {\n // Dates\n stringifyCondition: (value: any) => value instanceof Date,\n stringify: (value: any) => ({ $date: value.toISOString() }),\n parseCondition: (value: any) => isPlainObject(value) && value.$date,\n parse: (value: any) => new Date(value.$date),\n },\n {\n // undefined\n stringifyCondition: (value: any) => value === undefined,\n stringify: () => ({ $undefined: '' }),\n parseCondition: (value: any) =>\n isPlainObject(value) && value.$undefined === '',\n parse: () => undefined,\n },\n] as const\n\nexport type TransformerStringify<T, TSerializable> = T extends TSerializable\n ? T\n : T extends (...args: Array<any>) => any\n ? 'Function is not serializable'\n : { [K in keyof T]: TransformerStringify<T[K], TSerializable> }\n\nexport type TransformerParse<T, TSerializable> = T extends TSerializable\n ? T\n : T extends React.JSX.Element\n ? ReadableStream\n : { [K in keyof T]: TransformerParse<T[K], TSerializable> }\n\nexport type DefaultTransformerStringify<T> = TransformerStringify<\n T,\n Date | undefined\n>\n\nexport type DefaultTransformerParse<T> = TransformerParse<T, Date | undefined>\n"],"names":["value"],"mappings":";AAOO,MAAM,qBAAwC;AAAA,EACnD,WAAW,CAAC,UACV,KAAK,UAAU,OAAO,SAAS,SAAS,KAAKA,QAAO;AAC5C,UAAA,SAAS,KAAK,GAAG;AACjB,UAAA,cAAc,aAAa,KAAK,CAAC,MAAM,EAAE,mBAAmB,MAAM,CAAC;AAEzE,QAAI,aAAa;AACR,aAAA,YAAY,UAAU,MAAM;AAAA,IAAA;AAG9BA,WAAAA;AAAAA,EAAA,CACR;AAAA,EACH,OAAO,CAAC,UACN,KAAK,MAAM,OAAO,SAAS,OAAO,KAAKA,QAAO;AACtC,UAAA,SAAS,KAAK,GAAG;AACjB,UAAA,cAAc,aAAa,KAAK,CAAC,MAAM,EAAE,eAAe,MAAM,CAAC;AAErE,QAAI,aAAa;AACR,aAAA,YAAY,MAAM,MAAM;AAAA,IAAA;AAG1BA,WAAAA;AAAAA,EACR,CAAA;AACL;AAEA,MAAM,eAAe;AAAA,EACnB;AAAA;AAAA,IAEE,oBAAoB,CAAC,UAAe,iBAAiB;AAAA,IACrD,WAAW,CAAC,WAAgB,EAAE,OAAO,MAAM;IAC3C,gBAAgB,CAAC,UAAe,cAAc,KAAK,KAAK,MAAM;AAAA,IAC9D,OAAO,CAAC,UAAe,IAAI,KAAK,MAAM,KAAK;AAAA,EAC7C;AAAA,EACA;AAAA;AAAA,IAEE,oBAAoB,CAAC,UAAe,UAAU;AAAA,IAC9C,WAAW,OAAO,EAAE,YAAY;IAChC,gBAAgB,CAAC,UACf,cAAc,KAAK,KAAK,MAAM,eAAe;AAAA,IAC/C,OAAO,MAAM;AAAA,EAAA;AAEjB;"}
1
+ {"version":3,"file":"transformer.js","sources":["../../src/transformer.ts"],"sourcesContent":["import { isPlainObject } from './utils'\n\nexport interface RouterTransformer {\n stringify: (obj: unknown) => string\n parse: (str: string) => unknown\n encode: <T>(value: T) => T\n decode: <T>(value: T) => T\n}\n\nexport const defaultTransformer: RouterTransformer = {\n stringify: (value: any) =>\n JSON.stringify(value, function replacer(key, val) {\n const ogVal = this[key]\n const transformer = transformers.find((t) => t.stringifyCondition(ogVal))\n\n if (transformer) {\n return transformer.stringify(ogVal)\n }\n\n return val\n }),\n parse: (value: string) =>\n JSON.parse(value, function parser(key, val) {\n const ogVal = this[key]\n if (isPlainObject(ogVal)) {\n const transformer = transformers.find((t) => t.parseCondition(ogVal))\n\n if (transformer) {\n return transformer.parse(ogVal)\n }\n }\n\n return val\n }),\n encode: (value: any) => {\n // When encodign, dive first\n if (Array.isArray(value)) {\n return value.map((v) => defaultTransformer.encode(v))\n }\n\n if (isPlainObject(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, v]) => [\n key,\n defaultTransformer.encode(v),\n ]),\n )\n }\n\n const transformer = transformers.find((t) => t.stringifyCondition(value))\n if (transformer) {\n return transformer.stringify(value)\n }\n\n return value\n },\n decode: (value: any) => {\n // Attempt transform first\n if (isPlainObject(value)) {\n const transformer = transformers.find((t) => t.parseCondition(value))\n if (transformer) {\n return transformer.parse(value)\n }\n }\n\n if (Array.isArray(value)) {\n return value.map((v) => defaultTransformer.decode(v))\n }\n\n if (isPlainObject(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, v]) => [\n key,\n defaultTransformer.decode(v),\n ]),\n )\n }\n\n return value\n },\n}\n\nconst createTransformer = <T extends string>(\n key: T,\n check: (value: any) => boolean,\n toValue: (value: any) => any = (v) => v,\n fromValue: (value: any) => any = (v) => v,\n) => ({\n key,\n stringifyCondition: check,\n stringify: (value: any) => ({ [`$${key}`]: toValue(value) }),\n parseCondition: (value: any) => Object.hasOwn(value, `$${key}`),\n parse: (value: any) => fromValue(value[`$${key}`]),\n})\n\n// Keep these ordered by predicted frequency\nconst transformers = [\n createTransformer(\n // Key\n 'undefined',\n // Check\n (v) => v === undefined,\n // To\n () => 0,\n // From\n () => undefined,\n ),\n createTransformer(\n // Key\n 'date',\n // Check\n (v) => v instanceof Date,\n // To\n (v) => v.toISOString(),\n // From\n (v) => new Date(v),\n ),\n createTransformer(\n // Key\n 'error',\n // Check\n (v) => v instanceof Error,\n // To\n (v) => ({ ...v, message: v.message, stack: v.stack, cause: v.cause }),\n // From\n (v) => Object.assign(new Error(v.message), v),\n ),\n] as const\n\nexport type TransformerStringify<T, TSerializable> = T extends TSerializable\n ? T\n : T extends (...args: Array<any>) => any\n ? 'Function is not serializable'\n : { [K in keyof T]: TransformerStringify<T[K], TSerializable> }\n\nexport type TransformerParse<T, TSerializable> = T extends TSerializable\n ? T\n : T extends React.JSX.Element\n ? ReadableStream\n : { [K in keyof T]: TransformerParse<T[K], TSerializable> }\n\nexport type DefaultTransformerStringify<T> = TransformerStringify<\n T,\n Date | undefined\n>\n\nexport type DefaultTransformerParse<T> = TransformerParse<T, Date | undefined>\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-router",
3
- "version": "1.92.1",
3
+ "version": "1.92.6",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -49,7 +49,7 @@
49
49
  "node": ">=12"
50
50
  },
51
51
  "dependencies": {
52
- "@tanstack/react-store": "^0.6.1",
52
+ "@tanstack/react-store": "^0.7.0",
53
53
  "jsesc": "^3.0.2",
54
54
  "tiny-invariant": "^1.3.3",
55
55
  "tiny-warning": "^1.0.3",
package/src/router.ts CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  createMemoryHistory,
4
4
  parseHref,
5
5
  } from '@tanstack/history'
6
- import { Store } from '@tanstack/react-store'
6
+ import { Store, batch } from '@tanstack/react-store'
7
7
  import invariant from 'tiny-invariant'
8
8
  import warning from 'tiny-warning'
9
9
  import { rootRouteId } from './root'
@@ -1959,7 +1959,7 @@ export class Router<
1959
1959
 
1960
1960
  let pendingMatches!: Array<AnyRouteMatch>
1961
1961
 
1962
- this.__store.batch(() => {
1962
+ batch(() => {
1963
1963
  // this call breaks a route context of destination route after a redirect
1964
1964
  // we should be fine not eagerly calling this since we call it later
1965
1965
  // this.clearExpiredCache()
@@ -2014,7 +2014,7 @@ export class Router<
2014
2014
  let enteringMatches!: Array<AnyRouteMatch>
2015
2015
  let stayingMatches!: Array<AnyRouteMatch>
2016
2016
 
2017
- this.__store.batch(() => {
2017
+ batch(() => {
2018
2018
  this.__store.setState((s) => {
2019
2019
  const previousMatches = s.matches
2020
2020
  const newMatches = s.pendingMatches || s.matches
@@ -2877,7 +2877,7 @@ export class Router<
2877
2877
  ])
2878
2878
 
2879
2879
  // If the matches are already loaded, we need to add them to the cachedMatches
2880
- this.__store.batch(() => {
2880
+ batch(() => {
2881
2881
  matches.forEach((match) => {
2882
2882
  if (!loadedMatchIds.has(match.id)) {
2883
2883
  this.__store.setState((s) => ({
@@ -3,49 +3,128 @@ import { isPlainObject } from './utils'
3
3
  export interface RouterTransformer {
4
4
  stringify: (obj: unknown) => string
5
5
  parse: (str: string) => unknown
6
+ encode: <T>(value: T) => T
7
+ decode: <T>(value: T) => T
6
8
  }
7
9
 
8
10
  export const defaultTransformer: RouterTransformer = {
9
11
  stringify: (value: any) =>
10
- JSON.stringify(value, function replacer(key, value) {
11
- const keyVal = this[key]
12
- const transformer = transformers.find((t) => t.stringifyCondition(keyVal))
12
+ JSON.stringify(value, function replacer(key, val) {
13
+ const ogVal = this[key]
14
+ const transformer = transformers.find((t) => t.stringifyCondition(ogVal))
13
15
 
14
16
  if (transformer) {
15
- return transformer.stringify(keyVal)
17
+ return transformer.stringify(ogVal)
16
18
  }
17
19
 
18
- return value
20
+ return val
19
21
  }),
20
22
  parse: (value: string) =>
21
- JSON.parse(value, function parser(key, value) {
22
- const keyVal = this[key]
23
- const transformer = transformers.find((t) => t.parseCondition(keyVal))
23
+ JSON.parse(value, function parser(key, val) {
24
+ const ogVal = this[key]
25
+ if (isPlainObject(ogVal)) {
26
+ const transformer = transformers.find((t) => t.parseCondition(ogVal))
24
27
 
25
- if (transformer) {
26
- return transformer.parse(keyVal)
28
+ if (transformer) {
29
+ return transformer.parse(ogVal)
30
+ }
27
31
  }
28
32
 
29
- return value
33
+ return val
30
34
  }),
31
- }
35
+ encode: (value: any) => {
36
+ // When encodign, dive first
37
+ if (Array.isArray(value)) {
38
+ return value.map((v) => defaultTransformer.encode(v))
39
+ }
32
40
 
33
- const transformers = [
34
- {
35
- // Dates
36
- stringifyCondition: (value: any) => value instanceof Date,
37
- stringify: (value: any) => ({ $date: value.toISOString() }),
38
- parseCondition: (value: any) => isPlainObject(value) && value.$date,
39
- parse: (value: any) => new Date(value.$date),
41
+ if (isPlainObject(value)) {
42
+ return Object.fromEntries(
43
+ Object.entries(value).map(([key, v]) => [
44
+ key,
45
+ defaultTransformer.encode(v),
46
+ ]),
47
+ )
48
+ }
49
+
50
+ const transformer = transformers.find((t) => t.stringifyCondition(value))
51
+ if (transformer) {
52
+ return transformer.stringify(value)
53
+ }
54
+
55
+ return value
40
56
  },
41
- {
42
- // undefined
43
- stringifyCondition: (value: any) => value === undefined,
44
- stringify: () => ({ $undefined: '' }),
45
- parseCondition: (value: any) =>
46
- isPlainObject(value) && value.$undefined === '',
47
- parse: () => undefined,
57
+ decode: (value: any) => {
58
+ // Attempt transform first
59
+ if (isPlainObject(value)) {
60
+ const transformer = transformers.find((t) => t.parseCondition(value))
61
+ if (transformer) {
62
+ return transformer.parse(value)
63
+ }
64
+ }
65
+
66
+ if (Array.isArray(value)) {
67
+ return value.map((v) => defaultTransformer.decode(v))
68
+ }
69
+
70
+ if (isPlainObject(value)) {
71
+ return Object.fromEntries(
72
+ Object.entries(value).map(([key, v]) => [
73
+ key,
74
+ defaultTransformer.decode(v),
75
+ ]),
76
+ )
77
+ }
78
+
79
+ return value
48
80
  },
81
+ }
82
+
83
+ const createTransformer = <T extends string>(
84
+ key: T,
85
+ check: (value: any) => boolean,
86
+ toValue: (value: any) => any = (v) => v,
87
+ fromValue: (value: any) => any = (v) => v,
88
+ ) => ({
89
+ key,
90
+ stringifyCondition: check,
91
+ stringify: (value: any) => ({ [`$${key}`]: toValue(value) }),
92
+ parseCondition: (value: any) => Object.hasOwn(value, `$${key}`),
93
+ parse: (value: any) => fromValue(value[`$${key}`]),
94
+ })
95
+
96
+ // Keep these ordered by predicted frequency
97
+ const transformers = [
98
+ createTransformer(
99
+ // Key
100
+ 'undefined',
101
+ // Check
102
+ (v) => v === undefined,
103
+ // To
104
+ () => 0,
105
+ // From
106
+ () => undefined,
107
+ ),
108
+ createTransformer(
109
+ // Key
110
+ 'date',
111
+ // Check
112
+ (v) => v instanceof Date,
113
+ // To
114
+ (v) => v.toISOString(),
115
+ // From
116
+ (v) => new Date(v),
117
+ ),
118
+ createTransformer(
119
+ // Key
120
+ 'error',
121
+ // Check
122
+ (v) => v instanceof Error,
123
+ // To
124
+ (v) => ({ ...v, message: v.message, stack: v.stack, cause: v.cause }),
125
+ // From
126
+ (v) => Object.assign(new Error(v.message), v),
127
+ ),
49
128
  ] as const
50
129
 
51
130
  export type TransformerStringify<T, TSerializable> = T extends TSerializable