@tanstack/start-client-core 1.132.0-alpha.2 → 1.132.0-alpha.21
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/esm/constants.d.ts +5 -0
- package/dist/esm/constants.js +13 -0
- package/dist/esm/constants.js.map +1 -0
- package/dist/esm/createClientRpc.d.ts +6 -0
- package/dist/esm/createClientRpc.js +26 -0
- package/dist/esm/createClientRpc.js.map +1 -0
- package/dist/esm/createMiddleware.d.ts +42 -42
- package/dist/esm/createMiddleware.js.map +1 -1
- package/dist/esm/createServerFn.d.ts +57 -61
- package/dist/esm/createServerFn.js +40 -46
- package/dist/esm/createServerFn.js.map +1 -1
- package/dist/esm/envOnly.d.ts +2 -2
- package/dist/esm/envOnly.js +4 -4
- package/dist/esm/envOnly.js.map +1 -1
- package/dist/esm/getRouterInstance.d.ts +1 -0
- package/dist/esm/getRouterInstance.js +7 -0
- package/dist/esm/getRouterInstance.js.map +1 -0
- package/dist/esm/index.d.ts +6 -5
- package/dist/esm/index.js +13 -8
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/serializer/ServerFunctionSerializationAdapter.d.ts +5 -0
- package/dist/esm/serializer/ServerFunctionSerializationAdapter.js +17 -0
- package/dist/esm/serializer/ServerFunctionSerializationAdapter.js.map +1 -0
- package/dist/esm/serializer/getClientSerovalPlugins.d.ts +3 -0
- package/dist/esm/serializer/getClientSerovalPlugins.js +13 -0
- package/dist/esm/serializer/getClientSerovalPlugins.js.map +1 -0
- package/dist/esm/serializer/getDefaultSerovalPlugins.d.ts +1 -0
- package/dist/esm/serializer/getDefaultSerovalPlugins.js +16 -0
- package/dist/esm/serializer/getDefaultSerovalPlugins.js.map +1 -0
- package/dist/esm/serverFnFetcher.d.ts +1 -0
- package/dist/esm/serverFnFetcher.js +217 -0
- package/dist/esm/serverFnFetcher.js.map +1 -0
- package/package.json +5 -4
- package/src/constants.ts +8 -0
- package/src/createClientRpc.ts +26 -0
- package/src/createMiddleware.ts +113 -95
- package/src/createServerFn.ts +230 -208
- package/src/envOnly.ts +2 -2
- package/src/getRouterInstance.ts +7 -0
- package/src/index.tsx +11 -15
- package/src/serializer/ServerFunctionSerializationAdapter.ts +16 -0
- package/src/serializer/getClientSerovalPlugins.ts +10 -0
- package/src/serializer/getDefaultSerovalPlugins.ts +19 -0
- package/src/serverFnFetcher.ts +299 -0
- package/src/tests/createServerFn.test-d.ts +134 -108
- package/src/tests/createServerMiddleware.test-d.ts +16 -9
- package/src/tests/envOnly.test-d.ts +9 -9
- package/dist/esm/serializer.d.ts +0 -23
- package/dist/esm/serializer.js +0 -162
- package/dist/esm/serializer.js.map +0 -1
- package/dist/esm/tests/serializer.test.d.ts +0 -1
- package/src/serializer.ts +0 -219
- package/src/tests/serializer.test.tsx +0 -151
package/src/serializer.ts
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
import { isPlainObject } from '@tanstack/router-core'
|
|
2
|
-
|
|
3
|
-
export interface StartSerializer {
|
|
4
|
-
stringify: (obj: unknown) => string
|
|
5
|
-
parse: (str: string) => unknown
|
|
6
|
-
encode: <T>(value: T) => T
|
|
7
|
-
decode: <T>(value: T) => T
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export type SerializerStringifyBy<T, TSerializable> = T extends TSerializable
|
|
11
|
-
? T
|
|
12
|
-
: T extends (...args: Array<any>) => any
|
|
13
|
-
? 'Function is not serializable'
|
|
14
|
-
: { [K in keyof T]: SerializerStringifyBy<T[K], TSerializable> }
|
|
15
|
-
|
|
16
|
-
export type SerializerParseBy<T, TSerializable> = T extends TSerializable
|
|
17
|
-
? T
|
|
18
|
-
: unknown extends SerializerExtensions['ReadableStream']
|
|
19
|
-
? { [K in keyof T]: SerializerParseBy<T[K], TSerializable> }
|
|
20
|
-
: T extends SerializerExtensions['ReadableStream']
|
|
21
|
-
? ReadableStream
|
|
22
|
-
: { [K in keyof T]: SerializerParseBy<T[K], TSerializable> }
|
|
23
|
-
|
|
24
|
-
export interface DefaultSerializerExtensions {
|
|
25
|
-
ReadableStream: unknown
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface SerializerExtensions extends DefaultSerializerExtensions {}
|
|
29
|
-
|
|
30
|
-
export type Serializable = Date | undefined | Error | FormData | bigint
|
|
31
|
-
|
|
32
|
-
export type SerializerStringify<T> = SerializerStringifyBy<T, Serializable>
|
|
33
|
-
|
|
34
|
-
export type SerializerParse<T> = SerializerParseBy<T, Serializable>
|
|
35
|
-
export const startSerializer: StartSerializer = {
|
|
36
|
-
stringify: (value: any) =>
|
|
37
|
-
JSON.stringify(value, function replacer(key, val) {
|
|
38
|
-
const ogVal = this[key]
|
|
39
|
-
const serializer = serializers.find((t) => t.stringifyCondition(ogVal))
|
|
40
|
-
|
|
41
|
-
if (serializer) {
|
|
42
|
-
return serializer.stringify(ogVal)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return val
|
|
46
|
-
}),
|
|
47
|
-
parse: (value: string) =>
|
|
48
|
-
JSON.parse(value, function parser(key, val) {
|
|
49
|
-
const ogVal = this[key]
|
|
50
|
-
if (isPlainObject(ogVal)) {
|
|
51
|
-
const serializer = serializers.find((t) => t.parseCondition(ogVal))
|
|
52
|
-
|
|
53
|
-
if (serializer) {
|
|
54
|
-
return serializer.parse(ogVal)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return val
|
|
59
|
-
}),
|
|
60
|
-
encode: (value: any) => {
|
|
61
|
-
// When encoding, dive first
|
|
62
|
-
if (Array.isArray(value)) {
|
|
63
|
-
return value.map((v) => startSerializer.encode(v))
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (isPlainObject(value)) {
|
|
67
|
-
return Object.fromEntries(
|
|
68
|
-
Object.entries(value).map(([key, v]) => [
|
|
69
|
-
key,
|
|
70
|
-
startSerializer.encode(v),
|
|
71
|
-
]),
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const serializer = serializers.find((t) => t.stringifyCondition(value))
|
|
76
|
-
if (serializer) {
|
|
77
|
-
return serializer.stringify(value)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return value
|
|
81
|
-
},
|
|
82
|
-
decode: (value: any) => {
|
|
83
|
-
// Attempt transform first
|
|
84
|
-
if (isPlainObject(value)) {
|
|
85
|
-
const serializer = serializers.find((t) => t.parseCondition(value))
|
|
86
|
-
if (serializer) {
|
|
87
|
-
return serializer.parse(value)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (Array.isArray(value)) {
|
|
92
|
-
return value.map((v) => startSerializer.decode(v))
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (isPlainObject(value)) {
|
|
96
|
-
return Object.fromEntries(
|
|
97
|
-
Object.entries(value).map(([key, v]) => [
|
|
98
|
-
key,
|
|
99
|
-
startSerializer.decode(v),
|
|
100
|
-
]),
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return value
|
|
105
|
-
},
|
|
106
|
-
}
|
|
107
|
-
const createSerializer = <TKey extends string, TInput, TSerialized>(
|
|
108
|
-
key: TKey,
|
|
109
|
-
check: (value: any) => value is TInput,
|
|
110
|
-
toValue: (value: TInput) => TSerialized,
|
|
111
|
-
fromValue: (value: TSerialized) => TInput,
|
|
112
|
-
) => ({
|
|
113
|
-
key,
|
|
114
|
-
stringifyCondition: check,
|
|
115
|
-
stringify: (value: any) => ({ [`$${key}`]: toValue(value) }),
|
|
116
|
-
parseCondition: (value: any) => Object.hasOwn(value, `$${key}`),
|
|
117
|
-
parse: (value: any) => fromValue(value[`$${key}`]),
|
|
118
|
-
})
|
|
119
|
-
// Keep these ordered by predicted frequency
|
|
120
|
-
// Make sure to keep DefaultSerializable in sync with these serializers
|
|
121
|
-
// Also, make sure that they are unit tested in serializer.test.tsx
|
|
122
|
-
const serializers = [
|
|
123
|
-
createSerializer(
|
|
124
|
-
// Key
|
|
125
|
-
'undefined',
|
|
126
|
-
// Check
|
|
127
|
-
(v): v is undefined => v === undefined,
|
|
128
|
-
// To
|
|
129
|
-
() => 0,
|
|
130
|
-
// From
|
|
131
|
-
() => undefined,
|
|
132
|
-
),
|
|
133
|
-
createSerializer(
|
|
134
|
-
// Key
|
|
135
|
-
'date',
|
|
136
|
-
// Check
|
|
137
|
-
(v): v is Date => v instanceof Date,
|
|
138
|
-
// To
|
|
139
|
-
(v) => v.toISOString(),
|
|
140
|
-
// From
|
|
141
|
-
(v) => new Date(v),
|
|
142
|
-
),
|
|
143
|
-
createSerializer(
|
|
144
|
-
// Key
|
|
145
|
-
'error',
|
|
146
|
-
// Check
|
|
147
|
-
(v): v is Error => v instanceof Error,
|
|
148
|
-
// To
|
|
149
|
-
(v) => ({
|
|
150
|
-
...v,
|
|
151
|
-
message: v.message,
|
|
152
|
-
stack: process.env.NODE_ENV === 'development' ? v.stack : undefined,
|
|
153
|
-
cause: v.cause,
|
|
154
|
-
}),
|
|
155
|
-
// From
|
|
156
|
-
(v) => Object.assign(new Error(v.message), v),
|
|
157
|
-
),
|
|
158
|
-
createSerializer(
|
|
159
|
-
// Key
|
|
160
|
-
'formData',
|
|
161
|
-
// Check
|
|
162
|
-
(v): v is FormData => v instanceof FormData,
|
|
163
|
-
// To
|
|
164
|
-
(v) => {
|
|
165
|
-
const entries: Record<
|
|
166
|
-
string,
|
|
167
|
-
Array<FormDataEntryValue> | FormDataEntryValue
|
|
168
|
-
> = {}
|
|
169
|
-
v.forEach((value, key) => {
|
|
170
|
-
const entry = entries[key]
|
|
171
|
-
if (entry !== undefined) {
|
|
172
|
-
if (Array.isArray(entry)) {
|
|
173
|
-
entry.push(value)
|
|
174
|
-
} else {
|
|
175
|
-
entries[key] = [entry, value]
|
|
176
|
-
}
|
|
177
|
-
} else {
|
|
178
|
-
entries[key] = value
|
|
179
|
-
}
|
|
180
|
-
})
|
|
181
|
-
return entries
|
|
182
|
-
},
|
|
183
|
-
// From
|
|
184
|
-
(v) => {
|
|
185
|
-
const formData = new FormData()
|
|
186
|
-
Object.entries(v).forEach(([key, value]) => {
|
|
187
|
-
if (Array.isArray(value)) {
|
|
188
|
-
value.forEach((val) => formData.append(key, val))
|
|
189
|
-
} else {
|
|
190
|
-
formData.append(key, value)
|
|
191
|
-
}
|
|
192
|
-
})
|
|
193
|
-
return formData
|
|
194
|
-
},
|
|
195
|
-
),
|
|
196
|
-
createSerializer(
|
|
197
|
-
// Key
|
|
198
|
-
'bigint',
|
|
199
|
-
// Check
|
|
200
|
-
(v): v is bigint => typeof v === 'bigint',
|
|
201
|
-
// To
|
|
202
|
-
(v) => v.toString(),
|
|
203
|
-
// From
|
|
204
|
-
(v) => BigInt(v),
|
|
205
|
-
),
|
|
206
|
-
createSerializer(
|
|
207
|
-
// Key
|
|
208
|
-
'server-function',
|
|
209
|
-
// Check
|
|
210
|
-
(v): v is { functionId: string } =>
|
|
211
|
-
typeof v === 'function' &&
|
|
212
|
-
'functionId' in v &&
|
|
213
|
-
typeof v.functionId === 'string',
|
|
214
|
-
// To
|
|
215
|
-
({ functionId }) => ({ functionId, __serverFn: true }),
|
|
216
|
-
// From, dummy impl. the actual server function lookup is done on the server in packages/start-server-core/src/server-functions-handler.ts
|
|
217
|
-
(v) => v,
|
|
218
|
-
),
|
|
219
|
-
] as const
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { startSerializer as serializer } from '../serializer'
|
|
3
|
-
|
|
4
|
-
describe('transformer.stringify', () => {
|
|
5
|
-
it('should stringify dates', () => {
|
|
6
|
-
const date = new Date('2021-08-19T20:00:00.000Z')
|
|
7
|
-
expect(serializer.stringify(date)).toMatchInlineSnapshot(`
|
|
8
|
-
"{"$date":"2021-08-19T20:00:00.000Z"}"
|
|
9
|
-
`)
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
it('should stringify undefined', () => {
|
|
13
|
-
expect(serializer.stringify(undefined)).toMatchInlineSnapshot(
|
|
14
|
-
`"{"$undefined":0}"`,
|
|
15
|
-
)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('should stringify object foo="bar"', () => {
|
|
19
|
-
expect(serializer.stringify({ foo: 'bar' })).toMatchInlineSnapshot(`
|
|
20
|
-
"{"foo":"bar"}"
|
|
21
|
-
`)
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('should stringify object foo=undefined', () => {
|
|
25
|
-
expect(serializer.stringify({ foo: undefined })).toMatchInlineSnapshot(
|
|
26
|
-
`"{"foo":{"$undefined":0}}"`,
|
|
27
|
-
)
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('should stringify object foo=Date', () => {
|
|
31
|
-
const date = new Date('2021-08-19T20:00:00.000Z')
|
|
32
|
-
expect(serializer.stringify({ foo: date })).toMatchInlineSnapshot(`
|
|
33
|
-
"{"foo":{"$date":"2021-08-19T20:00:00.000Z"}}"
|
|
34
|
-
`)
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
it('should stringify empty FormData', () => {
|
|
38
|
-
const formData = new FormData()
|
|
39
|
-
expect(serializer.stringify(formData)).toMatchInlineSnapshot(
|
|
40
|
-
`"{"$formData":{}}"`,
|
|
41
|
-
)
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('should stringify FormData with key-value pairs of foo="bar",name="Sean"', () => {
|
|
45
|
-
const formData = new FormData()
|
|
46
|
-
formData.append('foo', 'bar')
|
|
47
|
-
formData.append('name', 'Sean')
|
|
48
|
-
expect(serializer.stringify(formData)).toMatchInlineSnapshot(
|
|
49
|
-
`"{"$formData":{"foo":"bar","name":"Sean"}}"`,
|
|
50
|
-
)
|
|
51
|
-
})
|
|
52
|
-
it('should stringify FormData with multiple values for the same key', () => {
|
|
53
|
-
const formData = new FormData()
|
|
54
|
-
formData.append('foo', 'bar')
|
|
55
|
-
formData.append('foo', 'baz')
|
|
56
|
-
expect(serializer.stringify(formData)).toMatchInlineSnapshot(
|
|
57
|
-
`"{"$formData":{"foo":["bar","baz"]}}"`,
|
|
58
|
-
)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('should stringify bigint', () => {
|
|
62
|
-
const bigint = BigInt('9007199254740992')
|
|
63
|
-
expect(serializer.stringify(bigint)).toMatchInlineSnapshot(
|
|
64
|
-
`"{"$bigint":"9007199254740992"}"`,
|
|
65
|
-
)
|
|
66
|
-
})
|
|
67
|
-
it('should stringify object foo=bigint', () => {
|
|
68
|
-
const bigint = BigInt('9007199254740992')
|
|
69
|
-
expect(serializer.stringify({ foo: bigint })).toMatchInlineSnapshot(
|
|
70
|
-
`"{"foo":{"$bigint":"9007199254740992"}}"`,
|
|
71
|
-
)
|
|
72
|
-
})
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
describe('transformer.parse', () => {
|
|
76
|
-
it('should parse dates', () => {
|
|
77
|
-
const date = new Date('2021-08-19T20:00:00.000Z')
|
|
78
|
-
const str = serializer.stringify(date)
|
|
79
|
-
expect(serializer.parse(str)).toEqual(date)
|
|
80
|
-
expect(serializer.parse(str) instanceof Date).toBe(true)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('should parse undefined', () => {
|
|
84
|
-
const str = serializer.stringify(undefined)
|
|
85
|
-
expect(serializer.parse(str)).toBeUndefined()
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('should parse object foo="bar"', () => {
|
|
89
|
-
const obj = { foo: 'bar' }
|
|
90
|
-
const str = serializer.stringify(obj)
|
|
91
|
-
expect(serializer.parse(str)).toEqual(obj)
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
it('should parse object foo=undefined', () => {
|
|
95
|
-
const obj = { foo: undefined }
|
|
96
|
-
const str = serializer.stringify(obj)
|
|
97
|
-
expect(serializer.parse(str)).toEqual(obj)
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
it('should parse object foo=Date', () => {
|
|
101
|
-
const date = new Date('2021-08-19T20:00:00.000Z')
|
|
102
|
-
const obj = { foo: date }
|
|
103
|
-
const str = serializer.stringify(obj)
|
|
104
|
-
expect(serializer.parse(str)).toEqual(obj)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
it('should parse empty FormData', () => {
|
|
108
|
-
const formData = new FormData()
|
|
109
|
-
const str = serializer.stringify(formData)
|
|
110
|
-
const parsed = serializer.parse(str) as FormData
|
|
111
|
-
expect(parsed).toBeInstanceOf(FormData)
|
|
112
|
-
expect([...parsed.entries()]).toEqual([])
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
it('should parse FormData with key-value pairs of foo="bar",name="Sean"', () => {
|
|
116
|
-
const formData = new FormData()
|
|
117
|
-
formData.append('foo', 'bar')
|
|
118
|
-
formData.append('name', 'Sean')
|
|
119
|
-
const str = serializer.stringify(formData)
|
|
120
|
-
const parsed = serializer.parse(str) as FormData
|
|
121
|
-
expect(parsed).toBeInstanceOf(FormData)
|
|
122
|
-
expect([...parsed.entries()]).toEqual([
|
|
123
|
-
['foo', 'bar'],
|
|
124
|
-
['name', 'Sean'],
|
|
125
|
-
])
|
|
126
|
-
})
|
|
127
|
-
it('should parse FormData with multiple values for the same key', () => {
|
|
128
|
-
const formData = new FormData()
|
|
129
|
-
formData.append('foo', 'bar')
|
|
130
|
-
formData.append('foo', 'baz')
|
|
131
|
-
const str = serializer.stringify(formData)
|
|
132
|
-
const parsed = serializer.parse(str) as FormData
|
|
133
|
-
expect(parsed).toBeInstanceOf(FormData)
|
|
134
|
-
expect([...parsed.entries()]).toEqual([
|
|
135
|
-
['foo', 'bar'],
|
|
136
|
-
['foo', 'baz'],
|
|
137
|
-
])
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
it('should parse bigint', () => {
|
|
141
|
-
const bigint = BigInt('9007199254740992')
|
|
142
|
-
const str = serializer.stringify(bigint)
|
|
143
|
-
expect(serializer.parse(str)).toEqual(bigint)
|
|
144
|
-
})
|
|
145
|
-
it('should parse object foo=bigint', () => {
|
|
146
|
-
const bigint = BigInt('9007199254740992')
|
|
147
|
-
const obj = { foo: bigint }
|
|
148
|
-
const str = serializer.stringify(obj)
|
|
149
|
-
expect(serializer.parse(str)).toEqual(obj)
|
|
150
|
-
})
|
|
151
|
-
})
|