@benjavicente/start-client-core 1.167.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.
Files changed (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +12 -0
  3. package/bin/intent.js +25 -0
  4. package/dist/esm/client/ServerFunctionSerializationAdapter.d.ts +7 -0
  5. package/dist/esm/client/ServerFunctionSerializationAdapter.js +18 -0
  6. package/dist/esm/client/ServerFunctionSerializationAdapter.js.map +1 -0
  7. package/dist/esm/client/hydrateStart.d.ts +2 -0
  8. package/dist/esm/client/hydrateStart.js +31 -0
  9. package/dist/esm/client/hydrateStart.js.map +1 -0
  10. package/dist/esm/client/index.d.ts +2 -0
  11. package/dist/esm/client/index.js +2 -0
  12. package/dist/esm/client-rpc/createClientRpc.d.ts +6 -0
  13. package/dist/esm/client-rpc/createClientRpc.js +21 -0
  14. package/dist/esm/client-rpc/createClientRpc.js.map +1 -0
  15. package/dist/esm/client-rpc/frame-decoder.d.ts +23 -0
  16. package/dist/esm/client-rpc/frame-decoder.js +231 -0
  17. package/dist/esm/client-rpc/frame-decoder.js.map +1 -0
  18. package/dist/esm/client-rpc/index.d.ts +1 -0
  19. package/dist/esm/client-rpc/index.js +2 -0
  20. package/dist/esm/client-rpc/serverFnFetcher.d.ts +1 -0
  21. package/dist/esm/client-rpc/serverFnFetcher.js +231 -0
  22. package/dist/esm/client-rpc/serverFnFetcher.js.map +1 -0
  23. package/dist/esm/constants.d.ts +53 -0
  24. package/dist/esm/constants.js +46 -0
  25. package/dist/esm/constants.js.map +1 -0
  26. package/dist/esm/createMiddleware.d.ts +195 -0
  27. package/dist/esm/createMiddleware.js +26 -0
  28. package/dist/esm/createMiddleware.js.map +1 -0
  29. package/dist/esm/createServerFn.d.ts +131 -0
  30. package/dist/esm/createServerFn.js +200 -0
  31. package/dist/esm/createServerFn.js.map +1 -0
  32. package/dist/esm/createStart.d.ts +50 -0
  33. package/dist/esm/createStart.js +29 -0
  34. package/dist/esm/createStart.js.map +1 -0
  35. package/dist/esm/fake-start-entry.d.ts +2 -0
  36. package/dist/esm/fake-start-entry.js +7 -0
  37. package/dist/esm/fake-start-entry.js.map +1 -0
  38. package/dist/esm/getDefaultSerovalPlugins.d.ts +1 -0
  39. package/dist/esm/getDefaultSerovalPlugins.js +10 -0
  40. package/dist/esm/getDefaultSerovalPlugins.js.map +1 -0
  41. package/dist/esm/getGlobalStartContext.d.ts +3 -0
  42. package/dist/esm/getGlobalStartContext.js +12 -0
  43. package/dist/esm/getGlobalStartContext.js.map +1 -0
  44. package/dist/esm/getRouterInstance.d.ts +2 -0
  45. package/dist/esm/getRouterInstance.js +8 -0
  46. package/dist/esm/getRouterInstance.js.map +1 -0
  47. package/dist/esm/getStartContextServerOnly.d.ts +2 -0
  48. package/dist/esm/getStartContextServerOnly.js +8 -0
  49. package/dist/esm/getStartContextServerOnly.js.map +1 -0
  50. package/dist/esm/getStartOptions.d.ts +2 -0
  51. package/dist/esm/getStartOptions.js +8 -0
  52. package/dist/esm/getStartOptions.js.map +1 -0
  53. package/dist/esm/global.d.ts +7 -0
  54. package/dist/esm/index.d.ts +20 -0
  55. package/dist/esm/index.js +12 -0
  56. package/dist/esm/safeObjectMerge.d.ts +10 -0
  57. package/dist/esm/safeObjectMerge.js +30 -0
  58. package/dist/esm/safeObjectMerge.js.map +1 -0
  59. package/dist/esm/serverRoute.d.ts +65 -0
  60. package/dist/esm/startEntry.d.ts +8 -0
  61. package/dist/esm/tests/createServerFn.test-d.d.ts +1 -0
  62. package/dist/esm/tests/createServerMiddleware.test-d.d.ts +1 -0
  63. package/package.json +98 -0
  64. package/skills/start-core/SKILL.md +210 -0
  65. package/skills/start-core/deployment/SKILL.md +306 -0
  66. package/skills/start-core/execution-model/SKILL.md +302 -0
  67. package/skills/start-core/middleware/SKILL.md +365 -0
  68. package/skills/start-core/server-functions/SKILL.md +335 -0
  69. package/skills/start-core/server-routes/SKILL.md +280 -0
  70. package/src/client/ServerFunctionSerializationAdapter.ts +16 -0
  71. package/src/client/hydrateStart.ts +43 -0
  72. package/src/client/index.ts +2 -0
  73. package/src/client-rpc/createClientRpc.ts +20 -0
  74. package/src/client-rpc/frame-decoder.ts +389 -0
  75. package/src/client-rpc/index.ts +1 -0
  76. package/src/client-rpc/serverFnFetcher.ts +416 -0
  77. package/src/constants.ts +90 -0
  78. package/src/createMiddleware.ts +824 -0
  79. package/src/createServerFn.ts +813 -0
  80. package/src/createStart.ts +166 -0
  81. package/src/fake-start-entry.ts +2 -0
  82. package/src/getDefaultSerovalPlugins.ts +17 -0
  83. package/src/getGlobalStartContext.ts +18 -0
  84. package/src/getRouterInstance.ts +8 -0
  85. package/src/getStartContextServerOnly.ts +4 -0
  86. package/src/getStartOptions.ts +8 -0
  87. package/src/global.ts +9 -0
  88. package/src/index.tsx +119 -0
  89. package/src/safeObjectMerge.ts +38 -0
  90. package/src/serverRoute.ts +509 -0
  91. package/src/start-entry.d.ts +11 -0
  92. package/src/startEntry.ts +10 -0
  93. package/src/tests/createServerFn.test-d.ts +866 -0
  94. package/src/tests/createServerMiddleware.test-d.ts +810 -0
@@ -0,0 +1,166 @@
1
+ import { createMiddleware } from './createMiddleware'
2
+ import type { TSS_SERVER_FUNCTION } from './constants'
3
+ import type {
4
+ AnyFunctionMiddleware,
5
+ AnyRequestMiddleware,
6
+ CreateMiddlewareFn,
7
+ } from './createMiddleware'
8
+ import type { CustomFetch } from './createServerFn'
9
+ import type {
10
+ AnySerializationAdapter,
11
+ Register,
12
+ SSROption,
13
+ } from '@benjavicente/router-core'
14
+
15
+ export interface StartInstanceOptions<
16
+ in out TSerializationAdapters,
17
+ in out TDefaultSsr,
18
+ in out TRequestMiddlewares,
19
+ in out TFunctionMiddlewares,
20
+ > {
21
+ '~types': StartInstanceTypes<
22
+ TSerializationAdapters,
23
+ TDefaultSsr,
24
+ TRequestMiddlewares,
25
+ TFunctionMiddlewares
26
+ >
27
+ serializationAdapters?: TSerializationAdapters
28
+ defaultSsr?: TDefaultSsr
29
+ requestMiddleware?: TRequestMiddlewares
30
+ functionMiddleware?: TFunctionMiddlewares
31
+ /**
32
+ * Configuration options for server functions.
33
+ */
34
+ serverFns?: {
35
+ /**
36
+ * A custom fetch implementation to use for all server function calls.
37
+ * This can be overridden by middleware or at the call site.
38
+ *
39
+ * Precedence (highest to lowest):
40
+ * 1. Call site: `serverFn({ fetch: customFetch })`
41
+ * 2. Later middleware: Last middleware in chain that provides `fetch`
42
+ * 3. Earlier middleware: First middleware in chain that provides `fetch`
43
+ * 4. createStart: `createStart({ serverFns: { fetch: customFetch } })`
44
+ * 5. Default: Global `fetch` function
45
+ *
46
+ * @note Only applies on the client side. During SSR, server functions are called directly.
47
+ */
48
+ fetch?: CustomFetch
49
+ }
50
+ }
51
+
52
+ export interface StartInstance<
53
+ in out TSerializationAdapters,
54
+ in out TDefaultSsr,
55
+ in out TRequestMiddlewares,
56
+ in out TFunctionMiddlewares,
57
+ > {
58
+ getOptions: () =>
59
+ | Promise<
60
+ StartInstanceOptions<
61
+ TSerializationAdapters,
62
+ TDefaultSsr,
63
+ TRequestMiddlewares,
64
+ TFunctionMiddlewares
65
+ >
66
+ >
67
+ | StartInstanceOptions<
68
+ TSerializationAdapters,
69
+ TDefaultSsr,
70
+ TRequestMiddlewares,
71
+ TFunctionMiddlewares
72
+ >
73
+ createMiddleware: CreateMiddlewareFn<Register>
74
+ }
75
+
76
+ export interface StartInstanceTypes<
77
+ in out TSerializationAdapters,
78
+ in out TDefaultSsr,
79
+ in out TRequestMiddlewares,
80
+ in out TFunctionMiddlewares,
81
+ > {
82
+ serializationAdapters: TSerializationAdapters
83
+ defaultSsr: TDefaultSsr
84
+ requestMiddleware: TRequestMiddlewares
85
+ functionMiddleware: TFunctionMiddlewares
86
+ }
87
+
88
+ function dedupeSerializationAdapters(
89
+ deduped: Set<AnySerializationAdapter>,
90
+ serializationAdapters: Array<AnySerializationAdapter>,
91
+ ): void {
92
+ for (let i = 0, len = serializationAdapters.length; i < len; i++) {
93
+ const current = serializationAdapters[i]!
94
+ if (!deduped.has(current)) {
95
+ deduped.add(current)
96
+ if (current.extends) {
97
+ dedupeSerializationAdapters(deduped, current.extends)
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ export const createStart = <
104
+ const TSerializationAdapters extends ReadonlyArray<AnySerializationAdapter> =
105
+ [],
106
+ TDefaultSsr extends SSROption = SSROption,
107
+ const TRequestMiddlewares extends ReadonlyArray<AnyRequestMiddleware> = [],
108
+ const TFunctionMiddlewares extends ReadonlyArray<AnyFunctionMiddleware> = [],
109
+ >(
110
+ getOptions: () =>
111
+ | Promise<
112
+ Omit<
113
+ StartInstanceOptions<
114
+ TSerializationAdapters,
115
+ TDefaultSsr,
116
+ TRequestMiddlewares,
117
+ TFunctionMiddlewares
118
+ >,
119
+ '~types'
120
+ >
121
+ >
122
+ | Omit<
123
+ StartInstanceOptions<
124
+ TSerializationAdapters,
125
+ TDefaultSsr,
126
+ TRequestMiddlewares,
127
+ TFunctionMiddlewares
128
+ >,
129
+ '~types'
130
+ >,
131
+ ): StartInstance<
132
+ TSerializationAdapters,
133
+ TDefaultSsr,
134
+ TRequestMiddlewares,
135
+ TFunctionMiddlewares
136
+ > => {
137
+ return {
138
+ getOptions: async () => {
139
+ const options = await getOptions()
140
+ if (options.serializationAdapters) {
141
+ const deduped = new Set<AnySerializationAdapter>()
142
+ dedupeSerializationAdapters(
143
+ deduped,
144
+ options.serializationAdapters as unknown as Array<AnySerializationAdapter>,
145
+ )
146
+ options.serializationAdapters = Array.from(deduped) as any
147
+ }
148
+ return options
149
+ },
150
+ createMiddleware: createMiddleware,
151
+ } as StartInstance<
152
+ TSerializationAdapters,
153
+ TDefaultSsr,
154
+ TRequestMiddlewares,
155
+ TFunctionMiddlewares
156
+ >
157
+ }
158
+
159
+ export type AnyStartInstance = StartInstance<any, any, any, any>
160
+ export type AnyStartInstanceOptions = StartInstanceOptions<any, any, any, any>
161
+
162
+ declare module '@benjavicente/router-core' {
163
+ interface SerializableExtensions {
164
+ serverFn: { [TSS_SERVER_FUNCTION]: true }
165
+ }
166
+ }
@@ -0,0 +1,2 @@
1
+ export const startInstance = undefined
2
+ export const getRouter = () => {}
@@ -0,0 +1,17 @@
1
+ import {
2
+ makeSerovalPlugin,
3
+ defaultSerovalPlugins as routerDefaultSerovalPlugins,
4
+ } from '@benjavicente/router-core'
5
+ import { getStartOptions } from './getStartOptions'
6
+ import type { AnySerializationAdapter } from '@benjavicente/router-core'
7
+
8
+ export function getDefaultSerovalPlugins() {
9
+ const start = getStartOptions()
10
+ const adapters = start?.serializationAdapters as
11
+ | Array<AnySerializationAdapter>
12
+ | undefined
13
+ return [
14
+ ...(adapters?.map(makeSerovalPlugin) ?? []),
15
+ ...routerDefaultSerovalPlugins,
16
+ ]
17
+ }
@@ -0,0 +1,18 @@
1
+ import { getStartContext } from '@benjavicente/start-storage-context'
2
+ import { createIsomorphicFn } from '@benjavicente/start-fn-stubs'
3
+ import type { AssignAllServerRequestContext } from './createMiddleware'
4
+ import type { Expand, Register } from '@benjavicente/router-core'
5
+
6
+ export const getGlobalStartContext: () =>
7
+ | Expand<AssignAllServerRequestContext<Register, []>>
8
+ | undefined = createIsomorphicFn()
9
+ .client(() => undefined)
10
+ .server(() => {
11
+ const context = getStartContext().contextAfterGlobalMiddlewares
12
+ if (!context) {
13
+ throw new Error(
14
+ `Global context not set yet, you are calling getGlobalStartContext() before the global middlewares are applied.`,
15
+ )
16
+ }
17
+ return context
18
+ })
@@ -0,0 +1,8 @@
1
+ import { getStartContext } from '@benjavicente/start-storage-context'
2
+ import { createIsomorphicFn } from '@benjavicente/start-fn-stubs'
3
+ import type { Awaitable, RegisteredRouter } from '@benjavicente/router-core'
4
+
5
+ export const getRouterInstance: () => Awaitable<RegisteredRouter> =
6
+ createIsomorphicFn()
7
+ .client(() => window.__TSR_ROUTER__!)
8
+ .server(() => getStartContext().getRouter())
@@ -0,0 +1,4 @@
1
+ import { getStartContext } from '@benjavicente/start-storage-context'
2
+ import { createServerOnlyFn } from '@benjavicente/start-fn-stubs'
3
+
4
+ export const getStartContextServerOnly = createServerOnlyFn(getStartContext)
@@ -0,0 +1,8 @@
1
+ import { getStartContext } from '@benjavicente/start-storage-context'
2
+ import { createIsomorphicFn } from '@benjavicente/start-fn-stubs'
3
+ import type { AnyStartInstanceOptions } from './createStart'
4
+
5
+ export const getStartOptions: () => AnyStartInstanceOptions | undefined =
6
+ createIsomorphicFn()
7
+ .client(() => window.__TSS_START_OPTIONS__)
8
+ .server(() => getStartContext().startOptions)
package/src/global.ts ADDED
@@ -0,0 +1,9 @@
1
+ import type { AnyStartInstanceOptions } from './createStart'
2
+
3
+ declare global {
4
+ interface Window {
5
+ __TSS_START_OPTIONS__?: AnyStartInstanceOptions
6
+ }
7
+ }
8
+
9
+ export {}
package/src/index.tsx ADDED
@@ -0,0 +1,119 @@
1
+ export type { JsonResponse } from '@benjavicente/router-core/ssr/client'
2
+
3
+ export { hydrate, json, mergeHeaders } from '@benjavicente/router-core/ssr/client'
4
+
5
+ export { RawStream } from '@benjavicente/router-core'
6
+ export type { OnRawStreamCallback } from '@benjavicente/router-core'
7
+
8
+ export {
9
+ createIsomorphicFn,
10
+ createServerOnlyFn,
11
+ createClientOnlyFn,
12
+ type IsomorphicFn,
13
+ type ServerOnlyFn,
14
+ type ClientOnlyFn,
15
+ type IsomorphicFnBase,
16
+ } from '@benjavicente/start-fn-stubs'
17
+ export { createServerFn } from './createServerFn'
18
+ export {
19
+ createMiddleware,
20
+ type IntersectAllValidatorInputs,
21
+ type IntersectAllValidatorOutputs,
22
+ type FunctionMiddlewareServerFn,
23
+ type AnyFunctionMiddleware,
24
+ type FunctionMiddlewareOptions,
25
+ type FunctionMiddlewareWithTypes,
26
+ type FunctionMiddlewareValidator,
27
+ type FunctionMiddlewareServer,
28
+ type FunctionMiddlewareAfterClient,
29
+ type FunctionMiddlewareAfterServer,
30
+ type FunctionMiddleware,
31
+ type FunctionMiddlewareAfterMiddleware,
32
+ type FunctionMiddlewareClientFnOptions,
33
+ type FunctionMiddlewareClientFnResult,
34
+ type FunctionMiddlewareClientNextFn,
35
+ type FunctionClientResultWithContext,
36
+ type AssignAllClientContextBeforeNext,
37
+ type AssignAllMiddleware,
38
+ type FunctionMiddlewareAfterValidator,
39
+ type FunctionMiddlewareClientFn,
40
+ type FunctionMiddlewareServerFnResult,
41
+ type FunctionMiddlewareClient,
42
+ type FunctionMiddlewareServerFnOptions,
43
+ type FunctionMiddlewareServerNextFn,
44
+ type FunctionServerResultWithContext,
45
+ type AnyRequestMiddleware,
46
+ type RequestMiddlewareOptions,
47
+ type RequestMiddlewareWithTypes,
48
+ type RequestMiddlewareServer,
49
+ type RequestMiddlewareAfterServer,
50
+ type RequestMiddleware,
51
+ type RequestMiddlewareAfterMiddleware,
52
+ type RequestServerFn,
53
+ type RequestMiddlewareServerFnResult,
54
+ type RequestServerOptions,
55
+ type RequestServerNextFn,
56
+ type RequestServerNextFnOptions,
57
+ type RequestServerResult,
58
+ } from './createMiddleware'
59
+ export type {
60
+ CompiledFetcherFnOptions,
61
+ CompiledFetcherFn,
62
+ CustomFetch,
63
+ Fetcher,
64
+ RscStream,
65
+ FetcherBaseOptions,
66
+ ServerFn,
67
+ ServerFnCtx,
68
+ MiddlewareFn,
69
+ ServerFnMiddlewareOptions,
70
+ ServerFnMiddlewareResult,
71
+ ServerFnBuilder,
72
+ ServerFnBaseOptions,
73
+ NextFn,
74
+ Method,
75
+ OptionalFetcher,
76
+ RequiredFetcher,
77
+ } from './createServerFn'
78
+ export {
79
+ execValidator,
80
+ flattenMiddlewares,
81
+ executeMiddleware,
82
+ } from './createServerFn'
83
+
84
+ export {
85
+ TSS_FORMDATA_CONTEXT,
86
+ TSS_SERVER_FUNCTION,
87
+ TSS_CONTENT_TYPE_FRAMED,
88
+ TSS_CONTENT_TYPE_FRAMED_VERSIONED,
89
+ TSS_FRAMED_PROTOCOL_VERSION,
90
+ FrameType,
91
+ FRAME_HEADER_SIZE,
92
+ X_TSS_SERIALIZED,
93
+ X_TSS_RAW_RESPONSE,
94
+ X_TSS_CONTEXT,
95
+ validateFramedProtocolVersion,
96
+ } from './constants'
97
+ export type {
98
+ FrameType as FrameTypeValue,
99
+ ClientFnMeta,
100
+ ServerFnMeta,
101
+ } from './constants'
102
+
103
+ export type * from './serverRoute'
104
+
105
+ export type * from './startEntry'
106
+
107
+ export { createStart } from './createStart'
108
+ export type {
109
+ AnyStartInstance,
110
+ AnyStartInstanceOptions,
111
+ StartInstance,
112
+ StartInstanceOptions,
113
+ } from './createStart'
114
+ export type { Register } from '@benjavicente/router-core'
115
+
116
+ export { getRouterInstance } from './getRouterInstance'
117
+ export { getDefaultSerovalPlugins } from './getDefaultSerovalPlugins'
118
+ export { getGlobalStartContext } from './getGlobalStartContext'
119
+ export { safeObjectMerge, createNullProtoObject } from './safeObjectMerge'
@@ -0,0 +1,38 @@
1
+ function isSafeKey(key: string): boolean {
2
+ return key !== '__proto__' && key !== 'constructor' && key !== 'prototype'
3
+ }
4
+
5
+ /**
6
+ * Merge target and source into a new null-proto object, filtering dangerous keys.
7
+ */
8
+ export function safeObjectMerge<T extends Record<string, unknown>>(
9
+ target: T | undefined,
10
+ source: Record<string, unknown> | null | undefined,
11
+ ): T {
12
+ const result = Object.create(null) as T
13
+ if (target) {
14
+ for (const key of Object.keys(target)) {
15
+ if (isSafeKey(key)) result[key as keyof T] = target[key] as T[keyof T]
16
+ }
17
+ }
18
+ if (source && typeof source === 'object') {
19
+ for (const key of Object.keys(source)) {
20
+ if (isSafeKey(key)) result[key as keyof T] = source[key] as T[keyof T]
21
+ }
22
+ }
23
+ return result
24
+ }
25
+
26
+ /**
27
+ * Create a null-prototype object, optionally copying from source.
28
+ */
29
+ export function createNullProtoObject<T extends object>(
30
+ source?: T,
31
+ ): { [K in keyof T]: T[K] } {
32
+ if (!source) return Object.create(null)
33
+ const obj = Object.create(null)
34
+ for (const key of Object.keys(source)) {
35
+ if (isSafeKey(key)) obj[key] = (source as Record<string, unknown>)[key]
36
+ }
37
+ return obj
38
+ }