orpc-fn 0.1.0 → 0.2.0
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 +48 -32
- package/dist/assemble-procedure.d.ts +13 -0
- package/dist/assemble-procedure.d.ts.map +1 -0
- package/dist/assemble-procedure.js +29 -0
- package/dist/assemble-procedure.js.map +1 -0
- package/dist/bound-call.d.ts +1 -1
- package/dist/bound-call.d.ts.map +1 -1
- package/dist/bound-call.js.map +1 -1
- package/dist/client.d.ts +4 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +4 -2
- package/dist/client.js.map +1 -1
- package/dist/compatibility.d.ts +16 -0
- package/dist/compatibility.d.ts.map +1 -0
- package/dist/compatibility.js +4 -0
- package/dist/compatibility.js.map +1 -0
- package/dist/create-fn.d.ts +30 -34
- package/dist/create-fn.d.ts.map +1 -1
- package/dist/create-fn.js +177 -121
- package/dist/create-fn.js.map +1 -1
- package/dist/expo.d.ts +11 -25
- package/dist/expo.d.ts.map +1 -1
- package/dist/expo.js +25 -30
- package/dist/expo.js.map +1 -1
- package/dist/hono.d.ts +12 -4
- package/dist/hono.d.ts.map +1 -1
- package/dist/hono.js +29 -12
- package/dist/hono.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/json-schema.d.ts +2 -0
- package/dist/json-schema.d.ts.map +1 -1
- package/dist/json-schema.js +11 -0
- package/dist/json-schema.js.map +1 -1
- package/dist/live/codec.d.ts +6 -1
- package/dist/live/codec.d.ts.map +1 -1
- package/dist/live/codec.js +14 -3
- package/dist/live/codec.js.map +1 -1
- package/dist/live/fn-live.d.ts +63 -22
- package/dist/live/fn-live.d.ts.map +1 -1
- package/dist/live/fn-live.js +98 -16
- package/dist/live/fn-live.js.map +1 -1
- package/dist/live/index.d.ts +1 -1
- package/dist/live/index.d.ts.map +1 -1
- package/dist/live/index.js.map +1 -1
- package/dist/live/ioredis.d.ts +4 -1
- package/dist/live/ioredis.d.ts.map +1 -1
- package/dist/live/ioredis.js +21 -2
- package/dist/live/ioredis.js.map +1 -1
- package/dist/live/lifecycle.d.ts +7 -0
- package/dist/live/lifecycle.d.ts.map +1 -0
- package/dist/live/lifecycle.js +36 -0
- package/dist/live/lifecycle.js.map +1 -0
- package/dist/live/memory.d.ts.map +1 -1
- package/dist/live/memory.js +4 -0
- package/dist/live/memory.js.map +1 -1
- package/dist/live/pub-sub.d.ts +76 -12
- package/dist/live/pub-sub.d.ts.map +1 -1
- package/dist/live/pub-sub.js +429 -125
- package/dist/live/pub-sub.js.map +1 -1
- package/dist/live/redis-bun.d.ts +1 -1
- package/dist/live/redis-bun.d.ts.map +1 -1
- package/dist/live/redis-bun.js +3 -5
- package/dist/live/redis-bun.js.map +1 -1
- package/dist/live/redis.d.ts +2 -2
- package/dist/live/redis.d.ts.map +1 -1
- package/dist/live/redis.js +36 -9
- package/dist/live/redis.js.map +1 -1
- package/dist/live/transport.d.ts +5 -1
- package/dist/live/transport.d.ts.map +1 -1
- package/dist/live/transport.js.map +1 -1
- package/dist/logger.d.ts +2 -0
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +21 -0
- package/dist/logger.js.map +1 -1
- package/dist/mastra.d.ts.map +1 -1
- package/dist/mastra.js +16 -7
- package/dist/mastra.js.map +1 -1
- package/dist/mcp/sdk.d.ts +20 -0
- package/dist/mcp/sdk.d.ts.map +1 -0
- package/dist/mcp/sdk.js +82 -0
- package/dist/mcp/sdk.js.map +1 -0
- package/dist/mcp.d.ts +3 -2
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +22 -7
- package/dist/mcp.js.map +1 -1
- package/dist/meta.d.ts +15 -7
- package/dist/meta.d.ts.map +1 -1
- package/dist/meta.js +9 -2
- package/dist/meta.js.map +1 -1
- package/dist/otel.d.ts.map +1 -1
- package/dist/otel.js +77 -6
- package/dist/otel.js.map +1 -1
- package/dist/route-options.d.ts +22 -0
- package/dist/route-options.d.ts.map +1 -0
- package/dist/route-options.js +67 -0
- package/dist/route-options.js.map +1 -0
- package/dist/router.d.ts +5 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +22 -0
- package/dist/router.js.map +1 -1
- package/dist/timing.d.ts +8 -0
- package/dist/timing.d.ts.map +1 -0
- package/dist/timing.js +4 -0
- package/dist/timing.js.map +1 -0
- package/dist/types.d.ts +86 -41
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -2
- package/dist/types.js.map +1 -1
- package/package.json +15 -3
- package/src/assemble-procedure.ts +42 -0
- package/src/bound-call.ts +4 -3
- package/src/client.ts +9 -2
- package/src/compatibility.ts +39 -0
- package/src/create-fn.ts +297 -183
- package/src/expo.ts +49 -44
- package/src/hono.ts +36 -17
- package/src/index.ts +6 -2
- package/src/json-schema.ts +16 -0
- package/src/live/codec.ts +22 -3
- package/src/live/fn-live.ts +244 -69
- package/src/live/index.ts +2 -0
- package/src/live/ioredis.ts +22 -2
- package/src/live/lifecycle.ts +44 -0
- package/src/live/memory.ts +4 -0
- package/src/live/pub-sub.ts +608 -166
- package/src/live/redis-bun.ts +7 -5
- package/src/live/redis.ts +37 -11
- package/src/live/transport.ts +4 -1
- package/src/logger.ts +20 -0
- package/src/mastra.ts +15 -7
- package/src/mcp/sdk.ts +118 -0
- package/src/mcp.ts +48 -20
- package/src/meta.ts +40 -24
- package/src/otel.ts +77 -10
- package/src/route-options.ts +100 -0
- package/src/router.ts +39 -1
- package/src/timing.ts +5 -0
- package/src/types.ts +204 -62
package/dist/create-fn.js
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
+
import { createProcedureAssembler } from './assemble-procedure.js';
|
|
2
|
+
import { isAsyncIteratorObject } from './stream.js';
|
|
3
|
+
import { normalizeRoute } from './route-options.js';
|
|
4
|
+
import { ORPCError, os } from '@orpc/server';
|
|
5
|
+
import { procedureDefinition } from './compatibility.js';
|
|
1
6
|
import { createBoundCall } from './bound-call.js';
|
|
2
7
|
import { isExpectedClientError } from './expected-client-error.js';
|
|
3
8
|
import { createFnLive } from './live/fn-live.js';
|
|
4
9
|
import { createLiveRuntime } from './live/pub-sub.js';
|
|
5
|
-
import { createDefaultLogger } from './logger.js';
|
|
6
|
-
import {
|
|
10
|
+
import { createDefaultLogger, protectLogger } from './logger.js';
|
|
11
|
+
import { readFnMeta } from './meta.js';
|
|
7
12
|
import { createTracing, errorMessageOf } from './otel.js';
|
|
13
|
+
import { RAW_INPUT, REQUEST_TIMING } from './timing.js';
|
|
8
14
|
import { createRouter } from './router.js';
|
|
9
|
-
import { RESERVED_OPTION_KEYS
|
|
15
|
+
import { RESERVED_OPTION_KEYS } from './types.js';
|
|
10
16
|
/**
|
|
11
17
|
* Builds the app's `fn` and friends once. Everything app-specific (auth,
|
|
12
18
|
* context, database, queues, i18n, permissions) is injected here.
|
|
@@ -14,19 +20,30 @@ import { RESERVED_OPTION_KEYS, ROUTE_OPTION_KEYS } from './types.js';
|
|
|
14
20
|
export function createFn(options) {
|
|
15
21
|
const runtime = options;
|
|
16
22
|
const tracing = createTracing(runtime.otel);
|
|
17
|
-
const defaultLogger = createDefaultLogger('fn');
|
|
18
|
-
const createLogger =
|
|
19
|
-
|
|
23
|
+
const defaultLogger = protectLogger(createDefaultLogger('fn'));
|
|
24
|
+
const createLogger = (scope, span) => {
|
|
25
|
+
try {
|
|
26
|
+
return protectLogger(runtime.logger?.(scope, span) ??
|
|
27
|
+
(scope === 'fn' ? defaultLogger : createDefaultLogger(scope)));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return defaultLogger;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
20
33
|
const isExpectedError = runtime.isExpectedError ?? isExpectedClientError;
|
|
21
34
|
const guards = runtime.guards ?? {};
|
|
22
35
|
const isGuard = (option) => Object.hasOwn(guards, option);
|
|
23
36
|
for (const guard of Object.keys(guards)) {
|
|
37
|
+
if (typeof guards[guard] !== 'function')
|
|
38
|
+
throw new TypeError(`orpc-fn: guard ${guard} must be a function`);
|
|
24
39
|
if (RESERVED_OPTION_KEYS.includes(guard)) {
|
|
25
40
|
throw new Error(`orpc-fn: guard "${guard}" reuses a route option name; rename it`);
|
|
26
41
|
}
|
|
27
42
|
}
|
|
43
|
+
if (runtime.default && !Object.hasOwn(runtime.procedures, runtime.default))
|
|
44
|
+
throw new TypeError(`orpc-fn: unknown default procedure ${runtime.default}`);
|
|
28
45
|
for (const [key, builder] of Object.entries(runtime.procedures)) {
|
|
29
|
-
const def = builder
|
|
46
|
+
const def = procedureDefinition(builder);
|
|
30
47
|
if (def?.inputSchema !== undefined || def?.outputSchema !== undefined) {
|
|
31
48
|
throw new Error(`orpc-fn: procedure "${key}" sets an input or output schema; set schemas on routes instead`);
|
|
32
49
|
}
|
|
@@ -38,138 +55,170 @@ export function createFn(options) {
|
|
|
38
55
|
}
|
|
39
56
|
return key;
|
|
40
57
|
};
|
|
41
|
-
const buildProcedure = (
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!builder)
|
|
45
|
-
throw new Error(`orpc-fn: unknown procedure "${key}"`);
|
|
46
|
-
const stored = {
|
|
47
|
-
name: route.name,
|
|
48
|
-
procedure: key,
|
|
49
|
-
meta: route.meta
|
|
50
|
-
};
|
|
51
|
-
builder = builder
|
|
52
|
-
.route({
|
|
53
|
-
operationId: route.name,
|
|
54
|
-
...Object.fromEntries(Object.entries(route.route).filter(([, value]) => value !== undefined))
|
|
55
|
-
})
|
|
56
|
-
.meta({ [FN_META_KEY]: stored });
|
|
57
|
-
if (route.input)
|
|
58
|
-
builder = builder.input(route.input);
|
|
59
|
-
if (route.output)
|
|
60
|
-
builder = builder.output(route.output);
|
|
61
|
-
return builder.handler(route.handler);
|
|
62
|
-
};
|
|
63
|
-
// biome-ignore lint/suspicious/noExplicitAny: the overloads in `Fn` carry the types
|
|
58
|
+
const buildProcedure = createProcedureAssembler(runtime.procedures, resolveKey);
|
|
59
|
+
const invocation = Symbol('orpc-fn.invocation');
|
|
60
|
+
// The overload-to-runtime boundary is adapted once at the returned factory.
|
|
64
61
|
const fn = (routeOptions) => {
|
|
65
|
-
const { handler, input, output, name, procedure,
|
|
62
|
+
const { handler, input, output, name, procedure, meta, stream, errors, guardResolvers, route, guardChecks } = normalizeRoute(routeOptions, isGuard);
|
|
66
63
|
const key = resolveKey(procedure, name);
|
|
67
|
-
const
|
|
68
|
-
const guardChecks = [];
|
|
69
|
-
const meta = {};
|
|
70
|
-
for (const [option, value] of Object.entries(rest)) {
|
|
71
|
-
if (value === undefined)
|
|
72
|
-
continue;
|
|
73
|
-
if (ROUTE_OPTION_KEYS.includes(option))
|
|
74
|
-
route[option] = value;
|
|
75
|
-
else if (isGuard(option))
|
|
76
|
-
guardChecks.push([option, value]);
|
|
77
|
-
else
|
|
78
|
-
meta[option] = value;
|
|
79
|
-
}
|
|
80
|
-
return buildProcedure({
|
|
64
|
+
const built = buildProcedure({
|
|
81
65
|
name,
|
|
82
66
|
procedure: key,
|
|
83
67
|
route,
|
|
84
68
|
meta,
|
|
85
69
|
input,
|
|
86
70
|
output,
|
|
87
|
-
|
|
71
|
+
stream,
|
|
72
|
+
...(errors ? { errors } : {}),
|
|
73
|
+
handler: async (params) => {
|
|
88
74
|
const { context, signal } = params;
|
|
89
|
-
const
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
span?.setAttribute('fn.procedure', key);
|
|
75
|
+
const state = context[invocation];
|
|
76
|
+
const { [invocation]: _invocation, ...observedContext } = context;
|
|
77
|
+
state.context = observedContext;
|
|
78
|
+
state.input = params.input;
|
|
79
|
+
state.handlerStarted = true;
|
|
80
|
+
try {
|
|
96
81
|
const attributes = runtime.spanAttributes?.({
|
|
97
82
|
context,
|
|
98
83
|
name,
|
|
99
84
|
procedure: key,
|
|
100
85
|
meta
|
|
101
86
|
});
|
|
102
|
-
for (const [attribute, value] of Object.entries(attributes ?? {}))
|
|
87
|
+
for (const [attribute, value] of Object.entries(attributes ?? {}))
|
|
103
88
|
if (value !== undefined)
|
|
104
|
-
span?.setAttribute(attribute, value);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
name,
|
|
122
|
-
procedure: key
|
|
123
|
-
});
|
|
124
|
-
return await handler({
|
|
125
|
-
...extras,
|
|
126
|
-
input: params.input,
|
|
127
|
-
context,
|
|
128
|
-
call: createBoundCall(context, signal, tracing),
|
|
129
|
-
signal,
|
|
130
|
-
span,
|
|
131
|
-
logger
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
finally {
|
|
135
|
-
// Server-Timing reports the time until the result (or stream) exists.
|
|
136
|
-
const timing = context.timing;
|
|
137
|
-
if (typeof timing === 'object' && timing !== null) {
|
|
138
|
-
;
|
|
139
|
-
timing.handler_ms = elapsedMs();
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
},
|
|
143
|
-
// After the result, or after a returned stream ends; before the span ends.
|
|
144
|
-
(span, ...error) => {
|
|
145
|
-
const durationMs = elapsedMs();
|
|
146
|
-
span?.setAttribute('fn.duration_ms', durationMs);
|
|
147
|
-
logCompleted(logger, {
|
|
89
|
+
state.span?.setAttribute(attribute, value);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
state.logger.warn('spanAttributes hook failed', {
|
|
93
|
+
error: errorMessageOf(error)
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const resolvedChecks = [...guardChecks];
|
|
97
|
+
for (const [guard, resolver] of Object.entries(guardResolvers)) {
|
|
98
|
+
const value = await resolver({ input: params.input, context, signal });
|
|
99
|
+
if (value !== undefined)
|
|
100
|
+
resolvedChecks.push([guard, value]);
|
|
101
|
+
}
|
|
102
|
+
for (const [guard, value] of resolvedChecks) {
|
|
103
|
+
const result = await guards[guard]?.(value, {
|
|
104
|
+
context,
|
|
105
|
+
input: params.input,
|
|
148
106
|
name,
|
|
149
107
|
procedure: key,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
error: error[0],
|
|
153
|
-
input: params.input,
|
|
154
|
-
context,
|
|
155
|
-
span,
|
|
156
|
-
meta
|
|
108
|
+
meta,
|
|
109
|
+
signal
|
|
157
110
|
});
|
|
111
|
+
if (result === false)
|
|
112
|
+
throw new ORPCError('FORBIDDEN', {
|
|
113
|
+
message: `Guard "${guard}" denied this call`
|
|
114
|
+
});
|
|
115
|
+
if (result !== undefined && result !== true)
|
|
116
|
+
throw new TypeError(`orpc-fn: guard "${guard}" must return void or boolean`);
|
|
117
|
+
}
|
|
118
|
+
const extraParams = {
|
|
119
|
+
context,
|
|
120
|
+
span: state.span,
|
|
121
|
+
signal,
|
|
122
|
+
name,
|
|
123
|
+
procedure: key
|
|
124
|
+
};
|
|
125
|
+
const shared = await runtime.extras?.(extraParams);
|
|
126
|
+
const scoped = await runtime.extrasByProcedure?.[key]?.(extraParams);
|
|
127
|
+
const extras = {
|
|
128
|
+
...shared,
|
|
129
|
+
...scoped
|
|
130
|
+
};
|
|
131
|
+
if (extras && typeof extras === 'object') {
|
|
132
|
+
for (const reserved of [
|
|
133
|
+
'input',
|
|
134
|
+
'context',
|
|
135
|
+
'call',
|
|
136
|
+
'signal',
|
|
137
|
+
'span',
|
|
138
|
+
'logger',
|
|
139
|
+
'errors',
|
|
140
|
+
'lastEventId'
|
|
141
|
+
]) {
|
|
142
|
+
if (Object.hasOwn(extras, reserved))
|
|
143
|
+
throw new TypeError(`orpc-fn: extra "${reserved}" shadows a handler parameter`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return handler({
|
|
147
|
+
...extras,
|
|
148
|
+
input: params.input,
|
|
149
|
+
context,
|
|
150
|
+
call: createBoundCall(context, signal, tracing),
|
|
151
|
+
signal,
|
|
152
|
+
span: state.span,
|
|
153
|
+
logger: state.logger,
|
|
154
|
+
errors: params.errors,
|
|
155
|
+
lastEventId: params.lastEventId,
|
|
156
|
+
[RAW_INPUT]: state.rawInput
|
|
158
157
|
});
|
|
159
158
|
}
|
|
160
159
|
});
|
|
160
|
+
// Prepending middleware shifts oRPC's validation indexes, covering auth,
|
|
161
|
+
// input validation, output validation, and the final stream lifetime.
|
|
162
|
+
return os
|
|
163
|
+
.use(async ({ context, next }, rawInput) => {
|
|
164
|
+
const started = performance.now();
|
|
165
|
+
const state = {
|
|
166
|
+
span: undefined,
|
|
167
|
+
logger: defaultLogger,
|
|
168
|
+
input: undefined,
|
|
169
|
+
context,
|
|
170
|
+
handlerStarted: false,
|
|
171
|
+
rawInput
|
|
172
|
+
};
|
|
173
|
+
const result = await tracing.inSpan(name, 'SERVER', async (span) => {
|
|
174
|
+
state.span = span;
|
|
175
|
+
state.logger = createLogger('fn', span);
|
|
176
|
+
span?.setAttribute('fn.operation', name);
|
|
177
|
+
span?.setAttribute('fn.procedure', key);
|
|
178
|
+
try {
|
|
179
|
+
const result = await next({ context: { [invocation]: state } });
|
|
180
|
+
if (isAsyncIteratorObject(result.output) !== stream) {
|
|
181
|
+
if (isAsyncIteratorObject(result.output)) {
|
|
182
|
+
try {
|
|
183
|
+
await result.output.return?.();
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
/* Release the unexpected stream. */
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
throw new TypeError(`orpc-fn: ${name} returned a result inconsistent with stream; declare stream: true for iterators`);
|
|
190
|
+
}
|
|
191
|
+
return result.output;
|
|
192
|
+
}
|
|
193
|
+
finally {
|
|
194
|
+
const timing = context[REQUEST_TIMING];
|
|
195
|
+
if (timing && !context[invocation]) {
|
|
196
|
+
timing.procedureMs += performance.now() - started;
|
|
197
|
+
timing.calls++;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}, (span, ...error) => {
|
|
201
|
+
const durationMs = Math.round((performance.now() - started) * 100) / 100;
|
|
202
|
+
span?.setAttribute('fn.duration_ms', durationMs);
|
|
203
|
+
logCompleted(state.logger, {
|
|
204
|
+
name,
|
|
205
|
+
procedure: key,
|
|
206
|
+
durationMs,
|
|
207
|
+
success: error.length === 0,
|
|
208
|
+
error: error[0],
|
|
209
|
+
input: state.input,
|
|
210
|
+
context: state.context,
|
|
211
|
+
span,
|
|
212
|
+
meta,
|
|
213
|
+
handlerStarted: state.handlerStarted
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
return { output: result, context };
|
|
217
|
+
})
|
|
218
|
+
.router({ route: built }).route;
|
|
161
219
|
};
|
|
162
220
|
const logCompleted = (logger, event) => {
|
|
163
221
|
const { error, success } = event;
|
|
164
|
-
const timing = event.context.timing;
|
|
165
|
-
const timingFields = {};
|
|
166
|
-
if (typeof timing === 'object' && timing !== null) {
|
|
167
|
-
for (const [field, value] of Object.entries(timing)) {
|
|
168
|
-
if (field !== 'handler_ms' && typeof value === 'number') {
|
|
169
|
-
timingFields[field] = value;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
222
|
let extra;
|
|
174
223
|
try {
|
|
175
224
|
extra = runtime.onCompleted?.(event);
|
|
@@ -179,25 +228,31 @@ export function createFn(options) {
|
|
|
179
228
|
error: errorMessageOf(hookError)
|
|
180
229
|
});
|
|
181
230
|
}
|
|
182
|
-
|
|
231
|
+
let expected = false;
|
|
232
|
+
try {
|
|
233
|
+
expected = isExpectedError(error);
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
expected = isExpectedClientError(error);
|
|
237
|
+
}
|
|
238
|
+
const level = success ? 'info' : expected ? 'warn' : 'error';
|
|
183
239
|
logger[level]('fn.completed', {
|
|
240
|
+
...extra,
|
|
184
241
|
event: 'fn.completed',
|
|
185
242
|
operation: event.name,
|
|
186
243
|
procedure: event.procedure,
|
|
187
244
|
duration_ms: event.durationMs,
|
|
188
245
|
status: success ? 'success' : 'failed',
|
|
189
|
-
...timingFields,
|
|
190
246
|
...(error === undefined
|
|
191
247
|
? {}
|
|
192
248
|
: {
|
|
193
249
|
error_type: error instanceof Error ? error.name : typeof error,
|
|
194
250
|
error_message: errorMessageOf(error)
|
|
195
|
-
})
|
|
196
|
-
...extra
|
|
251
|
+
})
|
|
197
252
|
});
|
|
198
253
|
};
|
|
199
254
|
const live = createLiveRuntime({
|
|
200
|
-
|
|
255
|
+
fn,
|
|
201
256
|
tracing,
|
|
202
257
|
createLogger,
|
|
203
258
|
pubsub: runtime.pubsub
|
|
@@ -205,7 +260,7 @@ export function createFn(options) {
|
|
|
205
260
|
// The runtimes are untyped; `Fn`, `FnLive`, `CreatePubSub` and
|
|
206
261
|
// `CreatePublisher` are their typed surface.
|
|
207
262
|
return {
|
|
208
|
-
fn
|
|
263
|
+
fn,
|
|
209
264
|
fnLive: createFnLive({
|
|
210
265
|
fn,
|
|
211
266
|
createChannel: live.createChannel,
|
|
@@ -215,8 +270,9 @@ export function createFn(options) {
|
|
|
215
270
|
createPubSub: live.createPubSub,
|
|
216
271
|
createPublisher: live.createPublisher,
|
|
217
272
|
createRouter,
|
|
218
|
-
readMeta:
|
|
273
|
+
readMeta: readFnMeta,
|
|
219
274
|
createCall: (context, signal) => createBoundCall(context, signal, tracing),
|
|
275
|
+
shutdown: live.shutdown,
|
|
220
276
|
drainPubSubSubscribers: live.drainPubSubSubscribers,
|
|
221
277
|
activePubSubSubscriberCount: live.activePubSubSubscriberCount
|
|
222
278
|
};
|
package/dist/create-fn.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-fn.js","sourceRoot":"","sources":["../src/create-fn.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AnySchema } from '@orpc/contract'\nimport type { AnyProcedure } from '@orpc/server'\nimport { type BoundCall, createBoundCall } from './bound-call.js'\nimport { isExpectedClientError } from './expected-client-error.js'\nimport { createFnLive, type FnLive } from './live/fn-live.js'\nimport {\n\ttype CreatePublisher,\n\ttype CreatePubSub,\n\tcreateLiveRuntime,\n\ttype PubSubRuntimeOptions\n} from './live/pub-sub.js'\nimport {\n\tcreateDefaultLogger,\n\ttype FnLogger,\n\ttype LogAttributes\n} from './logger.js'\nimport {\n\tFN_META_KEY,\n\ttype FnMeta,\n\treadFnMeta,\n\ttype StoredFnMeta\n} from './meta.js'\nimport {\n\ttype AttributeValue,\n\tcreateTracing,\n\terrorMessageOf,\n\ttype OtelApiLike,\n\ttype SpanLike,\n\ttype SpanOf\n} from './otel.js'\nimport { createRouter } from './router.js'\nimport {\n\ttype AnyFnContext,\n\ttype BuilderLike,\n\ttype BuildProcedure,\n\ttype FiniteExtras,\n\ttype Fn,\n\ttype FnCompletedEvent,\n\ttype FnDefinition,\n\ttype Guard,\n\ttype GuardParams,\n\ttype MaybePromise,\n\ttype RejectKeys,\n\tRESERVED_OPTION_KEYS,\n\tROUTE_OPTION_KEYS,\n\ttype ReservedOptionKey\n} from './types.js'\n\n/** Builder methods `createFn` calls; `BuilderLike` is the public constraint. */\ntype BuilderChain = {\n\troute(route: Record<string, unknown>): BuilderChain\n\tmeta(meta: Record<string, unknown>): BuilderChain\n\tinput(schema: AnySchema): BuilderChain\n\toutput(schema: AnySchema): BuilderChain\n\thandler(handler: Parameters<BuildProcedure>[0]['handler']): AnyProcedure\n}\n\n/** `CreateFnOptions` with the generics erased: what the implementation reads. */\ntype RuntimeOptions = {\n\tprocedures: Record<string, BuilderChain>\n\tdefault?: string\n\textras?: (params: Record<string, unknown>) => unknown\n\tguards?: Record<\n\t\tstring,\n\t\t(value: unknown, params: GuardParams<unknown, unknown>) => unknown\n\t>\n\totel?: OtelApiLike\n\tlogger?: (scope: string, span: SpanLike | undefined) => FnLogger\n\tspanAttributes?: (params: {\n\t\tcontext: unknown\n\t\tname: string\n\t\tprocedure: string\n\t\tmeta: Record<string, unknown>\n\t}) => Record<string, AttributeValue | undefined>\n\tonCompleted?: (event: FnCompletedEvent) => LogAttributes | undefined\n\tisExpectedError?: (error: unknown) => boolean\n\tpubsub?: PubSubRuntimeOptions\n}\n\ntype UnionContext<TProcedures extends Record<string, BuilderLike>> =\n\tAnyFnContext<{\n\t\tprocedures: TProcedures\n\t\tdefault: string\n\t\textras: object\n\t\tguards: object\n\t\tmeta: object\n\t\ttag: string\n\t\tspan: SpanLike\n\t\tlogger: FnLogger\n\t}>\n\nexport type CreateFnOptions<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTDefault extends keyof TProcedures & string,\n\tTExtras extends object,\n\tTGuards,\n\tTMeta extends object,\n\tTTag extends string,\n\tTOtel extends OtelApiLike | undefined,\n\tTLogger extends FnLogger\n> = {\n\t/** Named oRPC builders, e.g. `{ public: os.$context<Ctx>(), protected: authed }`. */\n\tprocedures: TProcedures\n\t/**\n\t * Builder used when a route omits `procedure`. Leave it out to make every\n\t * route name its procedure, so none gets one by accident.\n\t */\n\tdefault?: TDefault\n\t/** Per-call values merged into every handler's params; may be async. */\n\textras?: (params: {\n\t\tcontext: UnionContext<TProcedures>\n\t\tspan: SpanOf<TOtel> | undefined\n\t\tsignal: AbortSignal | undefined\n\t\tname: string\n\t\tprocedure: string\n\t}) => MaybePromise<TExtras>\n\t/**\n\t * Checks run before the handler; each key becomes a typed `fn()` option.\n\t * Keys must not reuse route options or meta keys.\n\t */\n\tguards?: TGuards &\n\t\tRecord<\n\t\t\tstring,\n\t\t\tGuard<never, GuardParams<UnionContext<TProcedures>, TMeta>>\n\t\t> &\n\t\tRejectKeys<\n\t\t\tNoInfer<TGuards>,\n\t\t\tReservedOptionKey | keyof NoInfer<TMeta>,\n\t\t\t'orpc-fn: this guard name is a route option or meta key'\n\t\t>\n\t/**\n\t * Typed route metadata: `meta: {} as { readOnly?: boolean }`. Keys become\n\t * `fn()` options and must not reuse route options.\n\t */\n\tmeta?: TMeta &\n\t\tRejectKeys<\n\t\t\tNoInfer<TMeta>,\n\t\t\tReservedOptionKey,\n\t\t\t'orpc-fn: this meta key is a route option'\n\t\t>\n\t/** Allowed route tags: `tags: ['internal', 'external']`. */\n\ttags?: readonly TTag[]\n\t/** `import * as otel from '@opentelemetry/api'`. Omit for no tracing. */\n\totel?: TOtel\n\tlogger?: (scope: string, span: SpanOf<TOtel> | undefined) => TLogger\n\t/** Extra span attributes per call; undefined values are skipped. */\n\tspanAttributes?: (params: {\n\t\tcontext: UnionContext<TProcedures>\n\t\tname: string\n\t\tprocedure: string\n\t\tmeta: Partial<TMeta>\n\t}) => Record<string, AttributeValue | undefined>\n\t/** Called after every handler; returned attributes join the `fn.completed` log. */\n\tonCompleted?: (\n\t\tevent: FnCompletedEvent<UnionContext<TProcedures>, SpanOf<TOtel>>\n\t\t// biome-ignore lint/suspicious/noConfusingVoidType: lets hooks that return nothing type-check\n\t) => LogAttributes | undefined | void\n\t/** Errors that are the caller's fault, logged at `warn`. Default: 4xx `ORPCError` or `AbortError`. */\n\tisExpectedError?: (error: unknown) => boolean\n\t/** Needed for `fnLive` and `createPubSub`. */\n\tpubsub?: PubSubRuntimeOptions\n}\n\ntype Definition<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTDefault extends string,\n\tTExtras extends object,\n\tTGuards,\n\tTMeta extends object,\n\tTTag extends string,\n\tTOtel,\n\tTLogger extends FnLogger\n> = {\n\tprocedures: TProcedures\n\tdefault: TDefault\n\textras: TExtras\n\tguards: TGuards\n\tmeta: TMeta\n\ttag: TTag\n\tspan: SpanOf<TOtel>\n\tlogger: TLogger\n}\n\nexport type FnFactory<TDef extends FnDefinition> = {\n\tfn: Fn<TDef>\n\tfnLive: FnLive<TDef>\n\tcreatePubSub: CreatePubSub<TDef>\n\tcreatePublisher: CreatePublisher\n\tcreateRouter: typeof createRouter\n\treadMeta: (procedure: AnyProcedure) => FnMeta<TDef['meta']>\n\t/**\n\t * A `call` outside any handler (seeders, scripts, tests), traced with this\n\t * instance's OpenTelemetry.\n\t */\n\tcreateCall: <TContext>(\n\t\tcontext: TContext,\n\t\tsignal?: AbortSignal\n\t) => BoundCall<TContext>\n\t/** End every open subscription of this instance; returns how many closed. */\n\tdrainPubSubSubscribers: () => number\n\tactivePubSubSubscriberCount: () => number\n}\n\n/**\n * Builds the app's `fn` and friends once. Everything app-specific (auth,\n * context, database, queues, i18n, permissions) is injected here.\n */\nexport function createFn<\n\tconst TProcedures extends Record<string, BuilderLike>,\n\tTDefault extends keyof TProcedures & string = never,\n\tTExtras extends object = Record<never, never>,\n\tTGuards extends object = Record<never, never>,\n\tTMeta extends object = Record<never, never>,\n\tconst TTag extends string = string,\n\tTOtel extends OtelApiLike | undefined = undefined,\n\tTLogger extends FnLogger = FnLogger\n>(\n\toptions: CreateFnOptions<\n\t\tTProcedures,\n\t\tTDefault,\n\t\tTExtras,\n\t\tTGuards,\n\t\tTMeta,\n\t\tTTag,\n\t\tTOtel,\n\t\tTLogger\n\t> &\n\t\tFiniteExtras<NoInfer<TExtras>>\n): FnFactory<\n\tDefinition<\n\t\tTProcedures,\n\t\tTDefault,\n\t\tTExtras,\n\t\tTGuards,\n\t\tTMeta,\n\t\tTTag,\n\t\tTOtel,\n\t\tTLogger\n\t>\n> {\n\tconst runtime = options as unknown as RuntimeOptions\n\tconst tracing = createTracing(runtime.otel)\n\tconst defaultLogger = createDefaultLogger('fn')\n\tconst createLogger =\n\t\truntime.logger ??\n\t\t((scope: string) =>\n\t\t\tscope === 'fn' ? defaultLogger : createDefaultLogger(scope))\n\tconst isExpectedError = runtime.isExpectedError ?? isExpectedClientError\n\tconst guards = runtime.guards ?? {}\n\tconst isGuard = (option: string) => Object.hasOwn(guards, option)\n\tfor (const guard of Object.keys(guards)) {\n\t\tif ((RESERVED_OPTION_KEYS as readonly string[]).includes(guard)) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: guard \"${guard}\" reuses a route option name; rename it`\n\t\t\t)\n\t\t}\n\t}\n\tfor (const [key, builder] of Object.entries(runtime.procedures)) {\n\t\tconst def = (builder as { '~orpc'?: Record<string, unknown> })['~orpc']\n\t\tif (def?.inputSchema !== undefined || def?.outputSchema !== undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: procedure \"${key}\" sets an input or output schema; set schemas on routes instead`\n\t\t\t)\n\t\t}\n\t}\n\n\tconst resolveKey = (procedure: string | undefined, name: string) => {\n\t\tconst key = procedure ?? runtime.default\n\t\tif (key === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: \"${name}\" needs a procedure; createFn has no default`\n\t\t\t)\n\t\t}\n\t\treturn key\n\t}\n\n\tconst buildProcedure: BuildProcedure = (route) => {\n\t\tconst key = resolveKey(route.procedure, route.name)\n\t\tlet builder = runtime.procedures[key]\n\t\tif (!builder) throw new Error(`orpc-fn: unknown procedure \"${key}\"`)\n\t\tconst stored: StoredFnMeta = {\n\t\t\tname: route.name,\n\t\t\tprocedure: key,\n\t\t\tmeta: route.meta\n\t\t}\n\t\tbuilder = builder\n\t\t\t.route({\n\t\t\t\toperationId: route.name,\n\t\t\t\t...Object.fromEntries(\n\t\t\t\t\tObject.entries(route.route).filter(([, value]) => value !== undefined)\n\t\t\t\t)\n\t\t\t})\n\t\t\t.meta({ [FN_META_KEY]: stored })\n\t\tif (route.input) builder = builder.input(route.input)\n\t\tif (route.output) builder = builder.output(route.output)\n\t\treturn builder.handler(route.handler)\n\t}\n\n\t// biome-ignore lint/suspicious/noExplicitAny: the overloads in `Fn` carry the types\n\tconst fn = (routeOptions: any): AnyProcedure => {\n\t\tconst { handler, input, output, name, procedure, ...rest } = routeOptions\n\t\tconst key = resolveKey(procedure, name)\n\t\tconst route: Record<string, unknown> = {}\n\t\tconst guardChecks: Array<[string, unknown]> = []\n\t\tconst meta: Record<string, unknown> = {}\n\t\tfor (const [option, value] of Object.entries(rest)) {\n\t\t\tif (value === undefined) continue\n\t\t\tif ((ROUTE_OPTION_KEYS as readonly string[]).includes(option))\n\t\t\t\troute[option] = value\n\t\t\telse if (isGuard(option)) guardChecks.push([option, value])\n\t\t\telse meta[option] = value\n\t\t}\n\n\t\treturn buildProcedure({\n\t\t\tname,\n\t\t\tprocedure: key,\n\t\t\troute,\n\t\t\tmeta,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\thandler: (params) => {\n\t\t\t\tconst { context, signal } = params\n\t\t\t\tconst startTime = performance.now()\n\t\t\t\tconst elapsedMs = () =>\n\t\t\t\t\tMath.round((performance.now() - startTime) * 100) / 100\n\t\t\t\tlet logger: FnLogger = defaultLogger\n\t\t\t\treturn tracing.inSpan(\n\t\t\t\t\tname,\n\t\t\t\t\t'SERVER',\n\t\t\t\t\tasync (span) => {\n\t\t\t\t\t\tlogger = createLogger('fn', span)\n\t\t\t\t\t\tspan?.setAttribute('fn.operation', name)\n\t\t\t\t\t\tspan?.setAttribute('fn.procedure', key)\n\t\t\t\t\t\tconst attributes = runtime.spanAttributes?.({\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\t\tmeta\n\t\t\t\t\t\t})\n\t\t\t\t\t\tfor (const [attribute, value] of Object.entries(attributes ?? {})) {\n\t\t\t\t\t\t\tif (value !== undefined) span?.setAttribute(attribute, value)\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tfor (const [guard, value] of guardChecks) {\n\t\t\t\t\t\t\t\tawait guards[guard]?.(value, {\n\t\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\t\tinput: params.input,\n\t\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\t\t\tsignal\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tconst extras = await runtime.extras?.({\n\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\t\tprocedure: key\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn await handler({\n\t\t\t\t\t\t\t\t...(extras as object | undefined),\n\t\t\t\t\t\t\t\tinput: params.input,\n\t\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\t\tcall: createBoundCall(context, signal, tracing),\n\t\t\t\t\t\t\t\tsignal,\n\t\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\t\tlogger\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t// Server-Timing reports the time until the result (or stream) exists.\n\t\t\t\t\t\t\tconst timing = context.timing\n\t\t\t\t\t\t\tif (typeof timing === 'object' && timing !== null) {\n\t\t\t\t\t\t\t\t;(timing as Record<string, unknown>).handler_ms = elapsedMs()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t// After the result, or after a returned stream ends; before the span ends.\n\t\t\t\t\t(span, ...error) => {\n\t\t\t\t\t\tconst durationMs = elapsedMs()\n\t\t\t\t\t\tspan?.setAttribute('fn.duration_ms', durationMs)\n\t\t\t\t\t\tlogCompleted(logger, {\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\t\tdurationMs,\n\t\t\t\t\t\t\tsuccess: error.length === 0,\n\t\t\t\t\t\t\terror: error[0],\n\t\t\t\t\t\t\tinput: params.input,\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\tmeta\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t}\n\n\tconst logCompleted = (logger: FnLogger, event: FnCompletedEvent) => {\n\t\tconst { error, success } = event\n\t\tconst timing = (event.context as { timing?: unknown }).timing\n\t\tconst timingFields: LogAttributes = {}\n\t\tif (typeof timing === 'object' && timing !== null) {\n\t\t\tfor (const [field, value] of Object.entries(timing)) {\n\t\t\t\tif (field !== 'handler_ms' && typeof value === 'number') {\n\t\t\t\t\ttimingFields[field] = value\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tlet extra: LogAttributes | undefined\n\t\ttry {\n\t\t\textra = runtime.onCompleted?.(event)\n\t\t} catch (hookError) {\n\t\t\tlogger.warn('onCompleted hook failed', {\n\t\t\t\terror: errorMessageOf(hookError)\n\t\t\t})\n\t\t}\n\t\tconst level = success ? 'info' : isExpectedError(error) ? 'warn' : 'error'\n\t\tlogger[level]('fn.completed', {\n\t\t\tevent: 'fn.completed',\n\t\t\toperation: event.name,\n\t\t\tprocedure: event.procedure,\n\t\t\tduration_ms: event.durationMs,\n\t\t\tstatus: success ? 'success' : 'failed',\n\t\t\t...timingFields,\n\t\t\t...(error === undefined\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\terror_type: error instanceof Error ? error.name : typeof error,\n\t\t\t\t\t\terror_message: errorMessageOf(error)\n\t\t\t\t\t}),\n\t\t\t...extra\n\t\t})\n\t}\n\n\tconst live = createLiveRuntime({\n\t\tbuildProcedure,\n\t\ttracing,\n\t\tcreateLogger,\n\t\tpubsub: runtime.pubsub\n\t})\n\n\t// The runtimes are untyped; `Fn`, `FnLive`, `CreatePubSub` and\n\t// `CreatePublisher` are their typed surface.\n\treturn {\n\t\tfn: fn as never,\n\t\tfnLive: createFnLive({\n\t\t\tfn,\n\t\t\tcreateChannel: live.createChannel,\n\t\t\tcreateLogger,\n\t\t\tisGuard\n\t\t}) as never,\n\t\tcreatePubSub: live.createPubSub as never,\n\t\tcreatePublisher: live.createPublisher as never,\n\t\tcreateRouter,\n\t\treadMeta: (procedure) => readFnMeta(procedure),\n\t\tcreateCall: (context, signal) => createBoundCall(context, signal, tracing),\n\t\tdrainPubSubSubscribers: live.drainPubSubSubscribers,\n\t\tactivePubSubSubscriberCount: live.activePubSubSubscriberCount\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create-fn.js","sourceRoot":"","sources":["../src/create-fn.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype BuilderChain,\n\tcreateProcedureAssembler\n} from './assemble-procedure.js'\nimport { isAsyncIteratorObject } from './stream.js'\nimport { normalizeRoute } from './route-options.js'\nimport { type AnyProcedure, ORPCError, os } from '@orpc/server'\nimport { procedureDefinition } from './compatibility.js'\nimport { type BoundCall, createBoundCall } from './bound-call.js'\nimport { isExpectedClientError } from './expected-client-error.js'\nimport { createFnLive, type FnLive } from './live/fn-live.js'\nimport {\n\ttype CreatePublisher,\n\ttype CreatePubSub,\n\tcreateLiveRuntime,\n\ttype PubSubRuntimeOptions\n} from './live/pub-sub.js'\nimport {\n\tcreateDefaultLogger,\n\tprotectLogger,\n\ttype FnLogger,\n\ttype LogAttributes\n} from './logger.js'\nimport { readFnMeta } from './meta.js'\nimport {\n\ttype AttributeValue,\n\tcreateTracing,\n\terrorMessageOf,\n\ttype OtelApiLike,\n\ttype SpanLike,\n\ttype SpanOf\n} from './otel.js'\nimport { RAW_INPUT, REQUEST_TIMING, type InvocationTiming } from './timing.js'\nimport { createRouter } from './router.js'\nimport {\n\ttype ProcedureHookParams,\n\ttype CompletedHookEvent,\n\ttype CurrentContextOf,\n\ttype BuilderLike,\n\ttype FiniteExtras,\n\ttype FiniteScopedExtras,\n\ttype Fn,\n\ttype FnCompletedEvent,\n\ttype FnDefinition,\n\ttype Guard,\n\ttype GuardParams,\n\ttype MaybePromise,\n\ttype RejectKeys,\n\tRESERVED_OPTION_KEYS,\n\ttype ReservedOptionKey\n} from './types.js'\n\n/** `CreateFnOptions` with the generics erased: what the implementation reads. */\ntype RuntimeOptions = {\n\tprocedures: Record<string, BuilderChain>\n\tdefault?: string\n\textras?: (params: Record<string, unknown>) => unknown\n\textrasByProcedure?: Record<\n\t\tstring,\n\t\t(params: Record<string, unknown>) => unknown\n\t>\n\tguards?: Record<\n\t\tstring,\n\t\t(value: unknown, params: GuardParams<unknown, unknown>) => unknown\n\t>\n\totel?: OtelApiLike\n\tlogger?: (scope: string, span: SpanLike | undefined) => FnLogger\n\tspanAttributes?: (params: {\n\t\tcontext: unknown\n\t\tname: string\n\t\tprocedure: string\n\t\tmeta: Record<string, unknown>\n\t}) => Record<string, AttributeValue | undefined>\n\tonCompleted?: (event: FnCompletedEvent) => LogAttributes | undefined\n\tisExpectedError?: (error: unknown) => boolean\n\tpubsub?: PubSubRuntimeOptions\n}\n\nexport type CreateFnOptions<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTDefault extends keyof TProcedures & string,\n\tTExtras extends object,\n\tTGuards,\n\tTMeta extends object,\n\tTTag extends string,\n\tTOtel extends OtelApiLike | undefined,\n\tTLogger extends FnLogger,\n\tTScoped extends Partial<Record<keyof TProcedures, object>> = Record<\n\t\tnever,\n\t\tnever\n\t>\n> = {\n\t/** Named oRPC builders, e.g. `{ public: os.$context<Ctx>(), protected: authed }`. */\n\tprocedures: TProcedures\n\t/**\n\t * Builder used when a route omits `procedure`. Leave it out to make every\n\t * route name its procedure, so none gets one by accident.\n\t */\n\tdefault?: TDefault\n\t/** Per-call values merged into every handler's params; may be async. */\n\textras?: (\n\t\tparams: ProcedureHookParams<\n\t\t\tTProcedures,\n\t\t\t{\n\t\t\t\tspan: SpanOf<TOtel> | undefined\n\t\t\t\tsignal: AbortSignal | undefined\n\t\t\t\tname: string\n\t\t\t}\n\t\t>\n\t) => MaybePromise<TExtras>\n\textrasByProcedure?: {\n\t\t[K in keyof TScoped & keyof TProcedures]: (params: {\n\t\t\tcontext: CurrentContextOf<TProcedures[K]>\n\t\t\tspan: SpanOf<TOtel> | undefined\n\t\t\tsignal: AbortSignal | undefined\n\t\t\tname: string\n\t\t\tprocedure: K\n\t\t}) => MaybePromise<TScoped[K]>\n\t}\n\t/**\n\t * Checks run before the handler; each key becomes a typed `fn()` option.\n\t * Keys must not reuse route options. False denies, true or void allows.\n\t */\n\tguards?: TGuards &\n\t\tRecord<\n\t\t\tstring,\n\t\t\tGuard<\n\t\t\t\tnever,\n\t\t\t\tProcedureHookParams<\n\t\t\t\t\tTProcedures,\n\t\t\t\t\tOmit<GuardParams<unknown, TMeta>, 'context' | 'procedure'>\n\t\t\t\t>\n\t\t\t>\n\t\t> &\n\t\tRejectKeys<\n\t\t\tNoInfer<TGuards>,\n\t\t\tReservedOptionKey,\n\t\t\t'orpc-fn: this guard name is a route option'\n\t\t>\n\t/**\n\t * Typed route metadata contract: `meta: defineMeta<AppMeta>()`.\n\t * Route declarations place values inside their own `meta` object.\n\t */\n\tmeta?: TMeta\n\t/** Allowed route tags: `tags: ['internal', 'external']`. */\n\ttags?: readonly TTag[]\n\t/** `import * as otel from '@opentelemetry/api'`. Omit for no tracing. */\n\totel?: TOtel\n\tlogger?: (scope: string, span: SpanOf<TOtel> | undefined) => TLogger\n\t/** Extra span attributes per call; undefined values are skipped. */\n\tspanAttributes?: (\n\t\tparams: ProcedureHookParams<\n\t\t\tTProcedures,\n\t\t\t{ name: string; meta: Partial<TMeta> }\n\t\t>\n\t) => Record<string, AttributeValue | undefined>\n\t/** Called after the procedure (or stream) settles; returned attributes join the `fn.completed` log. */\n\tonCompleted?: (\n\t\tevent: CompletedHookEvent<TProcedures, SpanOf<TOtel>>\n\t\t// biome-ignore lint/suspicious/noConfusingVoidType: lets hooks that return nothing type-check\n\t) => LogAttributes | undefined | void\n\t/** Errors that are the caller's fault, logged at `warn`. Default: 4xx `ORPCError` or `AbortError`. */\n\tisExpectedError?: (error: unknown) => boolean\n\t/** Needed for `fnLive` and `createPubSub`. */\n\tpubsub?: PubSubRuntimeOptions\n}\n\ntype Definition<\n\tTProcedures extends Record<string, BuilderLike>,\n\tTDefault extends string,\n\tTExtras extends object,\n\tTGuards,\n\tTMeta extends object,\n\tTTag extends string,\n\tTOtel,\n\tTLogger extends FnLogger,\n\tTScoped extends Partial<Record<keyof TProcedures, object>> = Record<\n\t\tnever,\n\t\tnever\n\t>\n> = {\n\tprocedures: TProcedures\n\tdefault: TDefault\n\textras: TExtras\n\textrasByProcedure: TScoped\n\tguards: TGuards\n\tmeta: TMeta\n\ttag: TTag\n\tspan: SpanOf<TOtel>\n\tlogger: TLogger\n}\n\nexport type FnFactory<TDef extends FnDefinition> = {\n\tfn: Fn<TDef>\n\tfnLive: FnLive<TDef>\n\tcreatePubSub: CreatePubSub<TDef>\n\tcreatePublisher: CreatePublisher\n\tcreateRouter: typeof createRouter\n\treadMeta: typeof readFnMeta\n\t/**\n\t * A `call` outside any handler (seeders, scripts, tests), traced with this\n\t * instance's OpenTelemetry.\n\t */\n\tcreateCall: <TContext>(\n\t\tcontext: TContext,\n\t\tsignal?: AbortSignal\n\t) => BoundCall<TContext>\n\t/** Terminal, idempotent shutdown: close streams and await owned resources. */\n\tshutdown: () => Promise<void>\n\tdrainPubSubSubscribers: () => number\n\tactivePubSubSubscriberCount: () => number\n}\n\n/**\n * Builds the app's `fn` and friends once. Everything app-specific (auth,\n * context, database, queues, i18n, permissions) is injected here.\n */\nexport function createFn<\n\tconst TProcedures extends Record<string, BuilderLike>,\n\tTDefault extends keyof TProcedures & string = never,\n\tTExtras extends object = Record<never, never>,\n\tTGuards extends object = Record<never, never>,\n\tTMeta extends object = Record<never, never>,\n\tconst TTag extends string = string,\n\tTOtel extends OtelApiLike | undefined = undefined,\n\tTLogger extends FnLogger = FnLogger,\n\tTScoped extends Partial<Record<keyof TProcedures, object>> = Record<\n\t\tnever,\n\t\tnever\n\t>\n>(\n\toptions: CreateFnOptions<\n\t\tTProcedures,\n\t\tTDefault,\n\t\tTExtras,\n\t\tTGuards,\n\t\tTMeta,\n\t\tTTag,\n\t\tTOtel,\n\t\tTLogger,\n\t\tTScoped\n\t> &\n\t\tFiniteExtras<NoInfer<TExtras>> &\n\t\tFiniteScopedExtras<NoInfer<TScoped>>\n): FnFactory<\n\tDefinition<\n\t\tTProcedures,\n\t\tTDefault,\n\t\tTExtras,\n\t\tTGuards,\n\t\tTMeta,\n\t\tTTag,\n\t\tTOtel,\n\t\tTLogger,\n\t\tTScoped\n\t>\n> {\n\tconst runtime = options as unknown as RuntimeOptions\n\tconst tracing = createTracing(runtime.otel)\n\tconst defaultLogger = protectLogger(createDefaultLogger('fn'))\n\tconst createLogger = (\n\t\tscope: string,\n\t\tspan: SpanLike | undefined\n\t): FnLogger => {\n\t\ttry {\n\t\t\treturn protectLogger(\n\t\t\t\truntime.logger?.(scope, span) ??\n\t\t\t\t\t(scope === 'fn' ? defaultLogger : createDefaultLogger(scope))\n\t\t\t)\n\t\t} catch {\n\t\t\treturn defaultLogger\n\t\t}\n\t}\n\tconst isExpectedError = runtime.isExpectedError ?? isExpectedClientError\n\tconst guards = runtime.guards ?? {}\n\tconst isGuard = (option: string) => Object.hasOwn(guards, option)\n\tfor (const guard of Object.keys(guards)) {\n\t\tif (typeof guards[guard] !== 'function')\n\t\t\tthrow new TypeError(`orpc-fn: guard ${guard} must be a function`)\n\t\tif ((RESERVED_OPTION_KEYS as readonly string[]).includes(guard)) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: guard \"${guard}\" reuses a route option name; rename it`\n\t\t\t)\n\t\t}\n\t}\n\tif (runtime.default && !Object.hasOwn(runtime.procedures, runtime.default))\n\t\tthrow new TypeError(`orpc-fn: unknown default procedure ${runtime.default}`)\n\tfor (const [key, builder] of Object.entries(runtime.procedures)) {\n\t\tconst def = procedureDefinition(builder)\n\t\tif (def?.inputSchema !== undefined || def?.outputSchema !== undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: procedure \"${key}\" sets an input or output schema; set schemas on routes instead`\n\t\t\t)\n\t\t}\n\t}\n\n\tconst resolveKey = (procedure: string | undefined, name: string) => {\n\t\tconst key = procedure ?? runtime.default\n\t\tif (key === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`orpc-fn: \"${name}\" needs a procedure; createFn has no default`\n\t\t\t)\n\t\t}\n\t\treturn key\n\t}\n\n\tconst buildProcedure = createProcedureAssembler(\n\t\truntime.procedures,\n\t\tresolveKey\n\t)\n\n\tconst invocation = Symbol('orpc-fn.invocation')\n\ttype Invocation = {\n\t\tspan: SpanLike | undefined\n\t\tlogger: FnLogger\n\t\tinput: unknown\n\t\tcontext: unknown\n\t\thandlerStarted: boolean\n\t\trawInput: unknown\n\t}\n\t// The overload-to-runtime boundary is adapted once at the returned factory.\n\tconst fn = (routeOptions: Record<string, unknown>): AnyProcedure => {\n\t\tconst {\n\t\t\thandler,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tname,\n\t\t\tprocedure,\n\t\t\tmeta,\n\t\t\tstream,\n\t\t\terrors,\n\t\t\tguardResolvers,\n\t\t\troute,\n\t\t\tguardChecks\n\t\t} = normalizeRoute(routeOptions, isGuard)\n\t\tconst key = resolveKey(procedure, name)\n\t\tconst built = buildProcedure({\n\t\t\tname,\n\t\t\tprocedure: key,\n\t\t\troute,\n\t\t\tmeta,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tstream,\n\t\t\t...(errors ? { errors } : {}),\n\t\t\thandler: async (params) => {\n\t\t\t\tconst { context, signal } = params\n\t\t\t\tconst state = context[invocation] as Invocation\n\t\t\t\tconst { [invocation]: _invocation, ...observedContext } = context\n\t\t\t\tstate.context = observedContext\n\t\t\t\tstate.input = params.input\n\t\t\t\tstate.handlerStarted = true\n\t\t\t\ttry {\n\t\t\t\t\tconst attributes = runtime.spanAttributes?.({\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\tmeta\n\t\t\t\t\t})\n\t\t\t\t\tfor (const [attribute, value] of Object.entries(attributes ?? {}))\n\t\t\t\t\t\tif (value !== undefined) state.span?.setAttribute(attribute, value)\n\t\t\t\t} catch (error) {\n\t\t\t\t\tstate.logger.warn('spanAttributes hook failed', {\n\t\t\t\t\t\terror: errorMessageOf(error)\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t\tconst resolvedChecks = [...guardChecks]\n\t\t\t\tfor (const [guard, resolver] of Object.entries(guardResolvers)) {\n\t\t\t\t\tconst value = await resolver({ input: params.input, context, signal })\n\t\t\t\t\tif (value !== undefined) resolvedChecks.push([guard, value])\n\t\t\t\t}\n\t\t\t\tfor (const [guard, value] of resolvedChecks) {\n\t\t\t\t\tconst result = await guards[guard]?.(value, {\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tinput: params.input,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\tmeta,\n\t\t\t\t\t\tsignal\n\t\t\t\t\t})\n\t\t\t\t\tif (result === false)\n\t\t\t\t\t\tthrow new ORPCError('FORBIDDEN', {\n\t\t\t\t\t\t\tmessage: `Guard \"${guard}\" denied this call`\n\t\t\t\t\t\t})\n\t\t\t\t\tif (result !== undefined && result !== true)\n\t\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t\t`orpc-fn: guard \"${guard}\" must return void or boolean`\n\t\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tconst extraParams = {\n\t\t\t\t\tcontext,\n\t\t\t\t\tspan: state.span,\n\t\t\t\t\tsignal,\n\t\t\t\t\tname,\n\t\t\t\t\tprocedure: key\n\t\t\t\t}\n\t\t\t\tconst shared = await runtime.extras?.(extraParams)\n\t\t\t\tconst scoped = await runtime.extrasByProcedure?.[key]?.(extraParams)\n\t\t\t\tconst extras = {\n\t\t\t\t\t...(shared as object | undefined),\n\t\t\t\t\t...(scoped as object | undefined)\n\t\t\t\t}\n\t\t\t\tif (extras && typeof extras === 'object') {\n\t\t\t\t\tfor (const reserved of [\n\t\t\t\t\t\t'input',\n\t\t\t\t\t\t'context',\n\t\t\t\t\t\t'call',\n\t\t\t\t\t\t'signal',\n\t\t\t\t\t\t'span',\n\t\t\t\t\t\t'logger',\n\t\t\t\t\t\t'errors',\n\t\t\t\t\t\t'lastEventId'\n\t\t\t\t\t]) {\n\t\t\t\t\t\tif (Object.hasOwn(extras, reserved))\n\t\t\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t\t\t`orpc-fn: extra \"${reserved}\" shadows a handler parameter`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn handler({\n\t\t\t\t\t...(extras as object | undefined),\n\t\t\t\t\tinput: params.input,\n\t\t\t\t\tcontext,\n\t\t\t\t\tcall: createBoundCall(context, signal, tracing),\n\t\t\t\t\tsignal,\n\t\t\t\t\tspan: state.span,\n\t\t\t\t\tlogger: state.logger,\n\t\t\t\t\terrors: params.errors,\n\t\t\t\t\tlastEventId: params.lastEventId,\n\t\t\t\t\t[RAW_INPUT]: state.rawInput\n\t\t\t\t})\n\t\t\t}\n\t\t})\n\t\t// Prepending middleware shifts oRPC's validation indexes, covering auth,\n\t\t// input validation, output validation, and the final stream lifetime.\n\t\treturn os\n\t\t\t.use(async ({ context, next }, rawInput) => {\n\t\t\t\tconst started = performance.now()\n\t\t\t\tconst state: Invocation = {\n\t\t\t\t\tspan: undefined,\n\t\t\t\t\tlogger: defaultLogger,\n\t\t\t\t\tinput: undefined,\n\t\t\t\t\tcontext,\n\t\t\t\t\thandlerStarted: false,\n\t\t\t\t\trawInput\n\t\t\t\t}\n\t\t\t\tconst result = await tracing.inSpan(\n\t\t\t\t\tname,\n\t\t\t\t\t'SERVER',\n\t\t\t\t\tasync (span) => {\n\t\t\t\t\t\tstate.span = span\n\t\t\t\t\t\tstate.logger = createLogger('fn', span)\n\t\t\t\t\t\tspan?.setAttribute('fn.operation', name)\n\t\t\t\t\t\tspan?.setAttribute('fn.procedure', key)\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst result = await next({ context: { [invocation]: state } })\n\t\t\t\t\t\t\tif (isAsyncIteratorObject(result.output) !== stream) {\n\t\t\t\t\t\t\t\tif (isAsyncIteratorObject(result.output)) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tawait result.output.return?.()\n\t\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\t\t/* Release the unexpected stream. */\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t\t\t\t`orpc-fn: ${name} returned a result inconsistent with stream; declare stream: true for iterators`\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn result.output\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tconst timing = (context as Record<symbol, unknown>)[\n\t\t\t\t\t\t\t\tREQUEST_TIMING\n\t\t\t\t\t\t\t] as InvocationTiming | undefined\n\t\t\t\t\t\t\tif (timing && !(context as Record<symbol, unknown>)[invocation]) {\n\t\t\t\t\t\t\t\ttiming.procedureMs += performance.now() - started\n\t\t\t\t\t\t\t\ttiming.calls++\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t(span, ...error) => {\n\t\t\t\t\t\tconst durationMs =\n\t\t\t\t\t\t\tMath.round((performance.now() - started) * 100) / 100\n\t\t\t\t\t\tspan?.setAttribute('fn.duration_ms', durationMs)\n\t\t\t\t\t\tlogCompleted(state.logger, {\n\t\t\t\t\t\t\tname,\n\t\t\t\t\t\t\tprocedure: key,\n\t\t\t\t\t\t\tdurationMs,\n\t\t\t\t\t\t\tsuccess: error.length === 0,\n\t\t\t\t\t\t\terror: error[0],\n\t\t\t\t\t\t\tinput: state.input,\n\t\t\t\t\t\t\tcontext: state.context,\n\t\t\t\t\t\t\tspan,\n\t\t\t\t\t\t\tmeta,\n\t\t\t\t\t\t\thandlerStarted: state.handlerStarted\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t\treturn { output: result, context }\n\t\t\t})\n\t\t\t.router({ route: built }).route\n\t}\n\n\tconst logCompleted = (logger: FnLogger, event: FnCompletedEvent) => {\n\t\tconst { error, success } = event\n\t\tlet extra: LogAttributes | undefined\n\t\ttry {\n\t\t\textra = runtime.onCompleted?.(event)\n\t\t} catch (hookError) {\n\t\t\tlogger.warn('onCompleted hook failed', {\n\t\t\t\terror: errorMessageOf(hookError)\n\t\t\t})\n\t\t}\n\t\tlet expected = false\n\t\ttry {\n\t\t\texpected = isExpectedError(error)\n\t\t} catch {\n\t\t\texpected = isExpectedClientError(error)\n\t\t}\n\t\tconst level = success ? 'info' : expected ? 'warn' : 'error'\n\t\tlogger[level]('fn.completed', {\n\t\t\t...extra,\n\t\t\tevent: 'fn.completed',\n\t\t\toperation: event.name,\n\t\t\tprocedure: event.procedure,\n\t\t\tduration_ms: event.durationMs,\n\t\t\tstatus: success ? 'success' : 'failed',\n\t\t\t...(error === undefined\n\t\t\t\t? {}\n\t\t\t\t: {\n\t\t\t\t\t\terror_type: error instanceof Error ? error.name : typeof error,\n\t\t\t\t\t\terror_message: errorMessageOf(error)\n\t\t\t\t\t})\n\t\t})\n\t}\n\n\tconst live = createLiveRuntime({\n\t\tfn,\n\t\ttracing,\n\t\tcreateLogger,\n\t\tpubsub: runtime.pubsub\n\t})\n\n\t// The runtimes are untyped; `Fn`, `FnLive`, `CreatePubSub` and\n\t// `CreatePublisher` are their typed surface.\n\treturn {\n\t\tfn,\n\t\tfnLive: createFnLive({\n\t\t\tfn,\n\t\t\tcreateChannel: live.createChannel,\n\t\t\tcreateLogger,\n\t\t\tisGuard\n\t\t}),\n\t\tcreatePubSub: live.createPubSub,\n\t\tcreatePublisher: live.createPublisher,\n\t\tcreateRouter,\n\t\treadMeta: readFnMeta,\n\t\tcreateCall: <TContext>(context: TContext, signal?: AbortSignal) =>\n\t\t\tcreateBoundCall(context, signal, tracing),\n\t\tshutdown: live.shutdown,\n\t\tdrainPubSubSubscribers: live.drainPubSubSubscribers,\n\t\tactivePubSubSubscriberCount: live.activePubSubSubscriberCount\n\t} as unknown as FnFactory<\n\t\tDefinition<\n\t\t\tTProcedures,\n\t\t\tTDefault,\n\t\t\tTExtras,\n\t\t\tTGuards,\n\t\t\tTMeta,\n\t\t\tTTag,\n\t\t\tTOtel,\n\t\t\tTLogger,\n\t\t\tTScoped\n\t\t>\n\t>\n}\n"]}
|
package/dist/expo.d.ts
CHANGED
|
@@ -31,36 +31,22 @@ export declare function createExpoFetch(options: {
|
|
|
31
31
|
fetch: ExpoFetch;
|
|
32
32
|
/** `Platform.OS !== 'web'`. */
|
|
33
33
|
native: boolean;
|
|
34
|
+
webFetch?: (request: Request, init?: RequestInit) => Promise<Response>;
|
|
34
35
|
}): (request: Request, init?: {
|
|
35
36
|
redirect?: NonNullable<RequestInit['redirect']>;
|
|
36
37
|
}) => Promise<Response>;
|
|
37
|
-
export type CreateExpoLinkOptions<T extends ClientContext> = Omit<CreateRpcLinkOptions<T>, 'fetch'
|
|
38
|
+
export type CreateExpoLinkOptions<T extends ClientContext> = Omit<CreateRpcLinkOptions<T>, 'fetch'> & {
|
|
38
39
|
fetch: ExpoFetch;
|
|
39
40
|
native: boolean;
|
|
40
|
-
/**
|
|
41
|
-
|
|
42
|
-
/** `expo-origin` header; the server copies it to `origin` (`normalizeExpoOrigin`). */
|
|
43
|
-
getExpoOrigin?: () => string | null | undefined;
|
|
44
|
-
/** Extra headers on every request. */
|
|
45
|
-
headers?: () => Record<string, string>;
|
|
41
|
+
/** Explicit browser fetch override; native always uses expo/fetch. */
|
|
42
|
+
webFetch?: (request: Request, init?: RequestInit) => Promise<Response>;
|
|
46
43
|
};
|
|
47
|
-
/**
|
|
48
|
-
* `createRpcLink` for Expo: batching, the `expo/fetch` bridge and the headers
|
|
49
|
-
* a Better Auth Expo client sends, so the API sees the same session and
|
|
50
|
-
* origin as `/api/auth` requests.
|
|
51
|
-
*
|
|
52
|
-
* ```ts
|
|
53
|
-
* import { fetch } from 'expo/fetch'
|
|
54
|
-
* import { Platform } from 'react-native'
|
|
55
|
-
*
|
|
56
|
-
* const link = createExpoLink({
|
|
57
|
-
* url: `${baseUrl}/api/rpc`,
|
|
58
|
-
* fetch,
|
|
59
|
-
* native: Platform.OS !== 'web',
|
|
60
|
-
* getCookie: () => authClient.getCookie(),
|
|
61
|
-
* getExpoOrigin
|
|
62
|
-
* })
|
|
63
|
-
* ```
|
|
64
|
-
*/
|
|
44
|
+
/** Generic streaming bridge with upstream async/context-aware headers. */
|
|
65
45
|
export declare function createExpoLink<T extends ClientContext = ClientContext>(options: CreateExpoLinkOptions<T>): RPCLink<T>;
|
|
46
|
+
export type CreateBetterAuthExpoLinkOptions<T extends ClientContext> = CreateExpoLinkOptions<T> & {
|
|
47
|
+
getCookie?: () => string | null | undefined | Promise<string | null | undefined>;
|
|
48
|
+
getExpoOrigin?: () => string | null | undefined | Promise<string | null | undefined>;
|
|
49
|
+
};
|
|
50
|
+
/** Better Auth's native cookie/origin headers, kept behind an explicit preset. */
|
|
51
|
+
export declare function createBetterAuthExpoLink<T extends ClientContext = ClientContext>(options: CreateBetterAuthExpoLinkOptions<T>): RPCLink<T>;
|
|
66
52
|
//# sourceMappingURL=expo.d.ts.map
|
package/dist/expo.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expo.d.ts","sourceRoot":"","sources":["../src/expo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,KAAK,oBAAoB,EAAiB,MAAM,aAAa,CAAA;AAEtE,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,MAAM,EAAE,WAAW,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAA;CAC/C,CAAA;AAED,gFAAgF;AAChF,MAAM,MAAM,YAAY,GAAG,IAAI,CAC9B,QAAQ,EACR,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAC5D,CAAA;AAED,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,CACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,aAAa,KACf,OAAO,CAAC,YAAY,CAAC,CAAA;AAE1B;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACxC,KAAK,EAAE,SAAS,CAAA;IAChB,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"expo.d.ts","sourceRoot":"","sources":["../src/expo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,KAAK,oBAAoB,EAAiB,MAAM,aAAa,CAAA;AAEtE,+DAA+D;AAC/D,MAAM,MAAM,aAAa,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,MAAM,EAAE,WAAW,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAA;CAC/C,CAAA;AAED,gFAAgF;AAChF,MAAM,MAAM,YAAY,GAAG,IAAI,CAC9B,QAAQ,EACR,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,UAAU,CAC5D,CAAA;AAED,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,CACvB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,aAAa,KACf,OAAO,CAAC,YAAY,CAAC,CAAA;AAE1B;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACxC,KAAK,EAAE,SAAS,CAAA;IAChB,+BAA+B;IAC/B,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtE,aAEU,OAAO,SACT;IAAE,QAAQ,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAA;CAAE,KACxD,OAAO,CAAC,QAAQ,CAAC,CAqBpB;AAED,MAAM,MAAM,qBAAqB,CAAC,CAAC,SAAS,aAAa,IAAI,IAAI,CAChE,oBAAoB,CAAC,CAAC,CAAC,EACvB,OAAO,CACP,GAAG;IACH,KAAK,EAAE,SAAS,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,sEAAsE;IACtE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtE,CAAA;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,EACrE,OAAO,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC,CAMZ;AAED,MAAM,MAAM,+BAA+B,CAAC,CAAC,SAAS,aAAa,IAClE,qBAAqB,CAAC,CAAC,CAAC,GAAG;IAC1B,SAAS,CAAC,EAAE,MACT,MAAM,GACN,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;IACrC,aAAa,CAAC,EAAE,MACb,MAAM,GACN,IAAI,GACJ,SAAS,GACT,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;CACrC,CAAA;AAEF,kFAAkF;AAClF,wBAAgB,wBAAwB,CACvC,CAAC,SAAS,aAAa,GAAG,aAAa,EACtC,OAAO,EAAE,+BAA+B,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAsBzD"}
|
package/dist/expo.js
CHANGED
|
@@ -15,7 +15,10 @@ import { createRpcLink } from './client.js';
|
|
|
15
15
|
export function createExpoFetch(options) {
|
|
16
16
|
return async (request, init) => {
|
|
17
17
|
if (!options.native) {
|
|
18
|
-
return globalThis.fetch(request, {
|
|
18
|
+
return (options.webFetch ?? globalThis.fetch)(request, {
|
|
19
|
+
...init,
|
|
20
|
+
credentials: 'include'
|
|
21
|
+
});
|
|
19
22
|
}
|
|
20
23
|
const hasBody = request.method !== 'GET' && request.method !== 'HEAD';
|
|
21
24
|
const body = hasBody ? await request.arrayBuffer() : undefined;
|
|
@@ -32,40 +35,32 @@ export function createExpoFetch(options) {
|
|
|
32
35
|
return response;
|
|
33
36
|
};
|
|
34
37
|
}
|
|
35
|
-
/**
|
|
36
|
-
* `createRpcLink` for Expo: batching, the `expo/fetch` bridge and the headers
|
|
37
|
-
* a Better Auth Expo client sends, so the API sees the same session and
|
|
38
|
-
* origin as `/api/auth` requests.
|
|
39
|
-
*
|
|
40
|
-
* ```ts
|
|
41
|
-
* import { fetch } from 'expo/fetch'
|
|
42
|
-
* import { Platform } from 'react-native'
|
|
43
|
-
*
|
|
44
|
-
* const link = createExpoLink({
|
|
45
|
-
* url: `${baseUrl}/api/rpc`,
|
|
46
|
-
* fetch,
|
|
47
|
-
* native: Platform.OS !== 'web',
|
|
48
|
-
* getCookie: () => authClient.getCookie(),
|
|
49
|
-
* getExpoOrigin
|
|
50
|
-
* })
|
|
51
|
-
* ```
|
|
52
|
-
*/
|
|
38
|
+
/** Generic streaming bridge with upstream async/context-aware headers. */
|
|
53
39
|
export function createExpoLink(options) {
|
|
54
|
-
const { fetch, native,
|
|
40
|
+
const { fetch, native, webFetch, ...rest } = options;
|
|
55
41
|
return createRpcLink({
|
|
56
42
|
...rest,
|
|
57
|
-
fetch: createExpoFetch({ fetch, native })
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
43
|
+
fetch: createExpoFetch({ fetch, native, ...(webFetch ? { webFetch } : {}) })
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** Better Auth's native cookie/origin headers, kept behind an explicit preset. */
|
|
47
|
+
export function createBetterAuthExpoLink(options) {
|
|
48
|
+
const { getCookie, getExpoOrigin, headers: extraHeaders, ...rest } = options;
|
|
49
|
+
return createExpoLink({
|
|
50
|
+
...rest,
|
|
51
|
+
headers: async (...args) => {
|
|
52
|
+
const supplied = typeof extraHeaders === 'function'
|
|
53
|
+
? await extraHeaders(...args)
|
|
54
|
+
: await extraHeaders;
|
|
55
|
+
const headers = new Headers(supplied);
|
|
56
|
+
const cookie = await getCookie?.();
|
|
61
57
|
if (cookie)
|
|
62
|
-
headers.Cookie
|
|
63
|
-
if (native) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const origin = getExpoOrigin?.();
|
|
58
|
+
headers.set('Cookie', cookie);
|
|
59
|
+
if (options.native) {
|
|
60
|
+
headers.set('x-skip-oauth-proxy', 'true');
|
|
61
|
+
const origin = await getExpoOrigin?.();
|
|
67
62
|
if (origin)
|
|
68
|
-
headers
|
|
63
|
+
headers.set('expo-origin', origin);
|
|
69
64
|
}
|
|
70
65
|
return headers;
|
|
71
66
|
}
|