@swimmesberger/elarion-jsonrpc-client-generator 0.2.11 → 0.2.12
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/README.md +11 -3
- package/dist/start-adapter-source.d.ts +4 -2
- package/dist/start-adapter-source.js +42 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -125,14 +125,22 @@ The core client stays framework-neutral, but you can opt into a framework adapte
|
|
|
125
125
|
npx elarion-jsonrpc-client-generator --schema rpc-schema.json --out src/generated --framework tanstack-start
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
It exports `createStartRpcApi` — a `createRpcApi` with request-scoped
|
|
129
|
-
`
|
|
130
|
-
consumers that don't opt in stay
|
|
128
|
+
It exports `createStartRpcApi` — a `createRpcApi` with request-scoped header forwarding pre-wired for SSR (the
|
|
129
|
+
`cookie` by default) — plus the isomorphic headers functions on their own: `forwardRequestHeaders(names)` and
|
|
130
|
+
`forwardRequestCookie`. The core client never imports the adapter, so consumers that don't opt in stay
|
|
131
|
+
framework-neutral and their output is byte-identical.
|
|
131
132
|
|
|
132
133
|
```ts
|
|
133
134
|
import { createStartRpcApi } from './generated/start-adapter'
|
|
134
135
|
|
|
135
136
|
export const rpc = createStartRpcApi({ url: '/rpc' })
|
|
137
|
+
|
|
138
|
+
// Behind an authenticating reverse proxy, forward its identity header too. The list replaces the default,
|
|
139
|
+
// so keep 'cookie' in it when the session cookie should still travel.
|
|
140
|
+
export const proxiedRpc = createStartRpcApi({
|
|
141
|
+
url: '/rpc',
|
|
142
|
+
forwardHeaders: ['cookie', 'cf-access-jwt-assertion'], // e.g. Cloudflare Access
|
|
143
|
+
})
|
|
136
144
|
```
|
|
137
145
|
|
|
138
146
|
## Client-side tracing
|
|
@@ -6,7 +6,9 @@ export interface GenerateStartAdapterSourceOptions {
|
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
8
8
|
* Emits the opt-in TanStack Start adapter (`start-adapter.ts`), produced only with `--framework tanstack-start`.
|
|
9
|
-
* It
|
|
10
|
-
*
|
|
9
|
+
* It forwards incoming request headers (the `cookie` by default, or the configured `forwardHeaders`) to API calls
|
|
10
|
+
* made during SSR. It imports the framework-specific pieces (`@tanstack/react-start`) so the core generated client
|
|
11
|
+
* never does — a non-Start consumer neither installs nor imports this file, keeping the client's framework-neutral
|
|
12
|
+
* boundary.
|
|
11
13
|
*/
|
|
12
14
|
export declare function generateStartAdapterSource(options: GenerateStartAdapterSourceOptions): string;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { moduleSpecifier } from './rpc-client-source.js';
|
|
2
2
|
/**
|
|
3
3
|
* Emits the opt-in TanStack Start adapter (`start-adapter.ts`), produced only with `--framework tanstack-start`.
|
|
4
|
-
* It
|
|
5
|
-
*
|
|
4
|
+
* It forwards incoming request headers (the `cookie` by default, or the configured `forwardHeaders`) to API calls
|
|
5
|
+
* made during SSR. It imports the framework-specific pieces (`@tanstack/react-start`) so the core generated client
|
|
6
|
+
* never does — a non-Start consumer neither installs nor imports this file, keeping the client's framework-neutral
|
|
7
|
+
* boundary.
|
|
6
8
|
*/
|
|
7
9
|
export function generateStartAdapterSource(options) {
|
|
8
10
|
const clientImport = moduleSpecifier(options.clientFileName);
|
|
@@ -17,29 +19,49 @@ export function generateStartAdapterSource(options) {
|
|
|
17
19
|
"import { getRequestHeader } from '@tanstack/react-start/server'",
|
|
18
20
|
`import { createRpcApi, type RpcApi, type RpcClientOptions, type RpcHeadersInit } from '${clientImport}'`,
|
|
19
21
|
'',
|
|
20
|
-
"// Forwards the incoming request
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
'export const
|
|
26
|
-
' .server((): RpcHeadersInit => {',
|
|
27
|
-
|
|
28
|
-
'
|
|
22
|
+
"// Forwards the named headers of the incoming request during SSR (names are matched case-insensitively and",
|
|
23
|
+
"// emitted lower-case; a header the request does not carry is skipped), and returns nothing in the browser.",
|
|
24
|
+
"// The read is isolated inside `createIsomorphicFn().server(...)` so the TanStack Start compiler strips both",
|
|
25
|
+
"// the read and the `@tanstack/react-start/server` import from the client bundle — a plain import (even one",
|
|
26
|
+
"// behind a `typeof window` guard) would fail `vite build` with `[import-protection] Import denied`.",
|
|
27
|
+
'export const forwardRequestHeaders = createIsomorphicFn()',
|
|
28
|
+
' .server((names: readonly string[]): RpcHeadersInit => {',
|
|
29
|
+
' const forwarded: Record<string, string> = {}',
|
|
30
|
+
' for (const name of names) {',
|
|
31
|
+
' const value = getRequestHeader(name)',
|
|
32
|
+
' if (value) {',
|
|
33
|
+
' forwarded[name.toLowerCase()] = value',
|
|
34
|
+
' }',
|
|
35
|
+
' }',
|
|
36
|
+
' return forwarded',
|
|
29
37
|
' })',
|
|
30
|
-
' .client((): RpcHeadersInit => ({}))',
|
|
38
|
+
' .client((_names: readonly string[]): RpcHeadersInit => ({}))',
|
|
39
|
+
'',
|
|
40
|
+
"// Forwards the incoming request's `cookie` during SSR so the RPC call runs as the signed-in user.",
|
|
41
|
+
"export const forwardRequestCookie = (): RpcHeadersInit => forwardRequestHeaders(['cookie'])",
|
|
42
|
+
'',
|
|
43
|
+
'/** Options for {@link createStartRpcApi}: the core client options plus the request headers forwarded during SSR. */',
|
|
44
|
+
'export interface StartRpcClientOptions extends RpcClientOptions {',
|
|
45
|
+
' /**',
|
|
46
|
+
" * Incoming request headers to forward on every call made during SSR (default `['cookie']`). The list",
|
|
47
|
+
" * replaces the default, so include `'cookie'` when you still want the session cookie forwarded; an empty",
|
|
48
|
+
' * list forwards nothing. Forward identity or correlation headers only — never hop-by-hop or',
|
|
49
|
+
' * framing headers such as `host`, `connection`, or `content-length`.',
|
|
50
|
+
' */',
|
|
51
|
+
' readonly forwardHeaders?: readonly string[]',
|
|
52
|
+
'}',
|
|
31
53
|
'',
|
|
32
|
-
'// Turnkey `createRpcApi` for a TanStack Start app: request-scoped
|
|
33
|
-
'// `headers` you pass are layered on top (yours win on a conflict).
|
|
34
|
-
'// (url, fetch, idempotency, instrumentation, …) passes through unchanged.',
|
|
35
|
-
'export function createStartRpcApi(options:
|
|
36
|
-
|
|
54
|
+
'// Turnkey `createRpcApi` for a TanStack Start app: request-scoped header forwarding (the `cookie` by',
|
|
55
|
+
'// default) is pre-wired, and any `headers` you pass are layered on top (yours win on a conflict).',
|
|
56
|
+
'// Everything else in RpcClientOptions (url, fetch, idempotency, instrumentation, …) passes through unchanged.',
|
|
57
|
+
'export function createStartRpcApi(options: StartRpcClientOptions): RpcApi {',
|
|
58
|
+
" const { forwardHeaders = ['cookie'], headers: provided, ...rest } = options",
|
|
37
59
|
' return createRpcApi({',
|
|
38
|
-
' ...
|
|
60
|
+
' ...rest,',
|
|
39
61
|
' headers: async (context) => {',
|
|
40
|
-
' const
|
|
62
|
+
' const forwarded = await forwardRequestHeaders(forwardHeaders)',
|
|
41
63
|
" const extra = typeof provided === 'function' ? await provided(context) : provided",
|
|
42
|
-
' return { ...toHeaderRecord(
|
|
64
|
+
' return { ...toHeaderRecord(forwarded), ...toHeaderRecord(extra) }',
|
|
43
65
|
' },',
|
|
44
66
|
' })',
|
|
45
67
|
'}',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swimmesberger/elarion-jsonrpc-client-generator",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
4
4
|
"description": "Generate TypeScript RPC contracts, Zod schemas, and a fetch client from Elarion JSON-RPC schema exports.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|