@tanstack/start-client-core 1.132.0-alpha.1 → 1.132.0-alpha.10

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.
Files changed (53) hide show
  1. package/dist/esm/constants.d.ts +5 -0
  2. package/dist/esm/constants.js +13 -0
  3. package/dist/esm/constants.js.map +1 -0
  4. package/dist/esm/createClientRpc.d.ts +6 -0
  5. package/dist/esm/createClientRpc.js +26 -0
  6. package/dist/esm/createClientRpc.js.map +1 -0
  7. package/dist/esm/createMiddleware.d.ts +35 -40
  8. package/dist/esm/createMiddleware.js.map +1 -1
  9. package/dist/esm/createServerFn.d.ts +46 -58
  10. package/dist/esm/createServerFn.js +39 -45
  11. package/dist/esm/createServerFn.js.map +1 -1
  12. package/dist/esm/envOnly.d.ts +2 -2
  13. package/dist/esm/envOnly.js +4 -4
  14. package/dist/esm/envOnly.js.map +1 -1
  15. package/dist/esm/getRouterInstance.d.ts +1 -0
  16. package/dist/esm/getRouterInstance.js +7 -0
  17. package/dist/esm/getRouterInstance.js.map +1 -0
  18. package/dist/esm/index.d.ts +6 -5
  19. package/dist/esm/index.js +13 -8
  20. package/dist/esm/index.js.map +1 -1
  21. package/dist/esm/serializer/ServerFunctionSerializationAdapter.d.ts +5 -0
  22. package/dist/esm/serializer/ServerFunctionSerializationAdapter.js +17 -0
  23. package/dist/esm/serializer/ServerFunctionSerializationAdapter.js.map +1 -0
  24. package/dist/esm/serializer/getClientSerovalPlugins.d.ts +3 -0
  25. package/dist/esm/serializer/getClientSerovalPlugins.js +13 -0
  26. package/dist/esm/serializer/getClientSerovalPlugins.js.map +1 -0
  27. package/dist/esm/serializer/getDefaultSerovalPlugins.d.ts +1 -0
  28. package/dist/esm/serializer/getDefaultSerovalPlugins.js +16 -0
  29. package/dist/esm/serializer/getDefaultSerovalPlugins.js.map +1 -0
  30. package/dist/esm/serverFnFetcher.d.ts +1 -0
  31. package/dist/esm/serverFnFetcher.js +217 -0
  32. package/dist/esm/serverFnFetcher.js.map +1 -0
  33. package/package.json +5 -4
  34. package/src/constants.ts +8 -0
  35. package/src/createClientRpc.ts +26 -0
  36. package/src/createMiddleware.ts +93 -91
  37. package/src/createServerFn.ts +158 -206
  38. package/src/envOnly.ts +2 -2
  39. package/src/getRouterInstance.ts +7 -0
  40. package/src/index.tsx +11 -15
  41. package/src/serializer/ServerFunctionSerializationAdapter.ts +16 -0
  42. package/src/serializer/getClientSerovalPlugins.ts +10 -0
  43. package/src/serializer/getDefaultSerovalPlugins.ts +19 -0
  44. package/src/serverFnFetcher.ts +299 -0
  45. package/src/tests/createServerFn.test-d.ts +124 -105
  46. package/src/tests/createServerMiddleware.test-d.ts +11 -9
  47. package/src/tests/envOnly.test-d.ts +9 -9
  48. package/dist/esm/serializer.d.ts +0 -23
  49. package/dist/esm/serializer.js +0 -152
  50. package/dist/esm/serializer.js.map +0 -1
  51. package/dist/esm/tests/serializer.test.d.ts +0 -1
  52. package/src/serializer.ts +0 -206
  53. package/src/tests/serializer.test.tsx +0 -151
package/src/serializer.ts DELETED
@@ -1,206 +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
- ] 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
- })