capnweb 0.0.0-c2bb17b → 0.0.0-cfa1b95
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 +1 -1
- package/dist/index-workers.cjs +183 -8
- package/dist/index-workers.cjs.map +1 -1
- package/dist/index-workers.js +183 -8
- package/dist/index-workers.js.map +1 -1
- package/dist/index.cjs +183 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +88 -16
- package/dist/index.d.ts +88 -16
- package/dist/index.js +183 -8
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.d.cts
CHANGED
|
@@ -12,18 +12,26 @@ import { IncomingMessage, ServerResponse, OutgoingHttpHeaders, OutgoingHttpHeade
|
|
|
12
12
|
// accept `WorkerEntrypoint` from `cloudflare:workers`, not any other class with the same shape)
|
|
13
13
|
declare const __RPC_STUB_BRAND: '__RPC_STUB_BRAND';
|
|
14
14
|
declare const __RPC_TARGET_BRAND: '__RPC_TARGET_BRAND';
|
|
15
|
+
// Distinguishes mapper placeholders from regular values so param unwrapping can accept them.
|
|
16
|
+
declare const __RPC_MAP_VALUE_BRAND: unique symbol;
|
|
15
17
|
interface RpcTargetBranded {
|
|
16
18
|
[__RPC_TARGET_BRAND]: never;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
// Types that can be used through `Stub`s
|
|
20
|
-
|
|
22
|
+
// `never[]` preserves compatibility with strongly-typed function signatures without introducing
|
|
23
|
+
// `any` into inference.
|
|
24
|
+
type Stubable = RpcTargetBranded | ((...args: never[]) => unknown);
|
|
25
|
+
|
|
26
|
+
type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false;
|
|
21
27
|
|
|
22
28
|
// Types that can be passed over RPC
|
|
23
29
|
// The reason for using a generic type here is to build a serializable subset of structured
|
|
24
30
|
// cloneable composite types. This allows types defined with the "interface" keyword to pass the
|
|
25
31
|
// serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
|
|
26
32
|
type RpcCompatible<T> =
|
|
33
|
+
// Allow `unknown` as a leaf so records/interfaces with `unknown` fields remain compatible.
|
|
34
|
+
| (IsUnknown<T> extends true ? unknown : never)
|
|
27
35
|
// Structured cloneables
|
|
28
36
|
| BaseType
|
|
29
37
|
// Structured cloneable composites
|
|
@@ -45,7 +53,7 @@ type RpcCompatible<T> =
|
|
|
45
53
|
|
|
46
54
|
// Base type for all RPC stubs, including common memory management methods.
|
|
47
55
|
// `T` is used as a marker type for unwrapping `Stub`s later.
|
|
48
|
-
interface StubBase<T
|
|
56
|
+
interface StubBase<T = unknown> extends Disposable {
|
|
49
57
|
[__RPC_STUB_BRAND]: T;
|
|
50
58
|
dup(): this;
|
|
51
59
|
onRpcBroken(callback: (error: any) => void): void;
|
|
@@ -102,7 +110,7 @@ type Stubify<T> =
|
|
|
102
110
|
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Stubify<V>>
|
|
103
111
|
: T extends BaseType ? T
|
|
104
112
|
// When using "unknown" instead of "any", interfaces are not stubified.
|
|
105
|
-
: T extends { [key: string | number]: any } ? { [K in keyof T]: Stubify<T[K]> }
|
|
113
|
+
: T extends { [key: string | number]: any } ? { [K in keyof T as K extends string | number ? K : never]: Stubify<T[K]> }
|
|
106
114
|
: T;
|
|
107
115
|
|
|
108
116
|
// Recursively rewrite all `Stub<T>`s with the corresponding `T`s.
|
|
@@ -110,7 +118,10 @@ type Stubify<T> =
|
|
|
110
118
|
// `Stub` depends on `Provider`, which depends on `Unstubify`, which would depend on `Stub`.
|
|
111
119
|
// prettier-ignore
|
|
112
120
|
type UnstubifyInner<T> =
|
|
113
|
-
|
|
121
|
+
// Preserve local RpcTarget acceptance, but avoid needless `Stub | Value` unions when the stub
|
|
122
|
+
// is already assignable to the value type (important for callback contextual typing).
|
|
123
|
+
T extends StubBase<infer V> ? (T extends V ? UnstubifyInner<V> : (T | UnstubifyInner<V>))
|
|
124
|
+
: T extends Promise<infer U> ? UnstubifyInner<U>
|
|
114
125
|
: T extends Map<infer K, infer V> ? Map<Unstubify<K>, Unstubify<V>>
|
|
115
126
|
: T extends Set<infer V> ? Set<Unstubify<V>>
|
|
116
127
|
: T extends [] ? []
|
|
@@ -120,14 +131,30 @@ type UnstubifyInner<T> =
|
|
|
120
131
|
: T extends Array<infer V> ? Array<Unstubify<V>>
|
|
121
132
|
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Unstubify<V>>
|
|
122
133
|
: T extends BaseType ? T
|
|
123
|
-
: T extends { [key: string | number]: unknown } ? { [K in keyof T]: Unstubify<T[K]> }
|
|
134
|
+
: T extends { [key: string | number]: unknown } ? { [K in keyof T as K extends string | number ? K : never]: Unstubify<T[K]> }
|
|
124
135
|
: T;
|
|
125
136
|
|
|
126
137
|
// You can put promises anywhere in the params and they'll be resolved before delivery.
|
|
127
138
|
// (This also covers RpcPromise, because it's defined as being a Promise.)
|
|
128
|
-
|
|
139
|
+
// Map placeholders are also allowed so primitive map callback inputs can be forwarded directly
|
|
140
|
+
// into RPC params.
|
|
141
|
+
//
|
|
142
|
+
// Keep raw non-stub members so generic assignability still works when UnstubifyInner<T> is deferred.
|
|
143
|
+
// Remove stub members from mixed unions so callback params don’t get both stub and unstubbed signatures.
|
|
144
|
+
// Marker carried by map() callback inputs. This lets primitive placeholders flow through params.
|
|
145
|
+
type Unstubify<T> =
|
|
146
|
+
| NonStubMembers<T>
|
|
147
|
+
| UnstubifyInner<T>
|
|
148
|
+
| Promise<UnstubifyInner<T>>
|
|
149
|
+
| MapValuePlaceholder<UnstubifyInner<T>>;
|
|
150
|
+
|
|
151
|
+
type UnstubifyAll<A extends readonly unknown[]> = { [I in keyof A]: Unstubify<A[I]> };
|
|
129
152
|
|
|
130
|
-
|
|
153
|
+
interface MapValuePlaceholder<T> {
|
|
154
|
+
[__RPC_MAP_VALUE_BRAND]: T;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
type NonStubMembers<T> = Exclude<T, StubBase<any>>;
|
|
131
158
|
|
|
132
159
|
// Utility type for adding `Disposable`s to `object` types only.
|
|
133
160
|
// Note `unknown & T` is equivalent to `T`.
|
|
@@ -142,17 +169,22 @@ type MaybeDisposable<T> = T extends object ? Disposable : unknown;
|
|
|
142
169
|
// Intersecting with `(Maybe)Provider` allows pipelining.
|
|
143
170
|
// prettier-ignore
|
|
144
171
|
type Result<R> =
|
|
145
|
-
R extends
|
|
172
|
+
IsAny<R> extends true ? UnknownResult
|
|
173
|
+
: IsUnknown<R> extends true ? UnknownResult
|
|
174
|
+
: R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
|
|
146
175
|
: R extends RpcCompatible<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
|
|
147
176
|
: never;
|
|
148
177
|
|
|
178
|
+
type IsAny<T> = 0 extends (1 & T) ? true : false;
|
|
179
|
+
type UnknownResult = Promise<unknown> & Provider<unknown> & StubBase<unknown>;
|
|
180
|
+
|
|
149
181
|
// Type for method or property on an RPC interface.
|
|
150
182
|
// For methods, unwrap `Stub`s in parameters, and rewrite returns to be `Result`s.
|
|
151
183
|
// Unwrapping `Stub`s allows calling with `Stubable` arguments.
|
|
152
184
|
// For properties, rewrite types to be `Result`s.
|
|
153
185
|
// In each case, unwrap `Promise`s.
|
|
154
186
|
type MethodOrProperty<V> = V extends (...args: infer P) => infer R
|
|
155
|
-
? (...args: UnstubifyAll<P>) => Result<Awaited<R>>
|
|
187
|
+
? (...args: UnstubifyAll<P>) => IsAny<R> extends true ? UnknownResult : Result<Awaited<R>>
|
|
156
188
|
: Result<Awaited<V>>;
|
|
157
189
|
|
|
158
190
|
// Type for the callable part of an `Provider` if `T` is callable.
|
|
@@ -161,22 +193,62 @@ type MaybeCallableProvider<T> = T extends (...args: any[]) => any
|
|
|
161
193
|
? MethodOrProperty<T>
|
|
162
194
|
: unknown;
|
|
163
195
|
|
|
196
|
+
type TupleIndexKeys<T extends ReadonlyArray<unknown>> = Extract<keyof T, `${number}`>;
|
|
197
|
+
type MapCallbackValue<T> =
|
|
198
|
+
// `Omit` removes call signatures, so re-intersect callable provider behavior.
|
|
199
|
+
T extends unknown
|
|
200
|
+
? Omit<Result<T>, keyof Promise<unknown>> &
|
|
201
|
+
MaybeCallableProvider<T> &
|
|
202
|
+
MapValuePlaceholder<T>
|
|
203
|
+
: never;
|
|
204
|
+
type InvalidNativePromiseInMapResult<T, Seen = never> =
|
|
205
|
+
T extends unknown ? InvalidNativePromiseInMapResultImpl<T, Seen> : never;
|
|
206
|
+
type InvalidNativePromiseInMapResultImpl<T, Seen> =
|
|
207
|
+
[T] extends [Seen] ? never
|
|
208
|
+
// RpcPromise is modeled as Promise & StubBase, so allow promise-like stub values.
|
|
209
|
+
: T extends StubBase<any> ? never
|
|
210
|
+
// Native thenables cannot be represented in map recordings, even when typed as PromiseLike.
|
|
211
|
+
: T extends PromiseLike<unknown> ? T
|
|
212
|
+
: T extends Map<infer K, infer V>
|
|
213
|
+
? InvalidNativePromiseInMapResult<K, Seen | T> |
|
|
214
|
+
InvalidNativePromiseInMapResult<V, Seen | T>
|
|
215
|
+
: T extends Set<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
|
|
216
|
+
: T extends readonly [] ? never
|
|
217
|
+
: T extends readonly [infer Head, ...infer Tail]
|
|
218
|
+
? InvalidNativePromiseInMapResult<Head, Seen | T> |
|
|
219
|
+
InvalidNativePromiseInMapResult<Tail[number], Seen | T>
|
|
220
|
+
: T extends ReadonlyArray<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
|
|
221
|
+
: T extends { [key: string | number]: unknown }
|
|
222
|
+
? InvalidNativePromiseInMapResult<
|
|
223
|
+
T[Extract<keyof T, string | number>],
|
|
224
|
+
Seen | T
|
|
225
|
+
>
|
|
226
|
+
: never;
|
|
227
|
+
type MapCallbackReturn<T> =
|
|
228
|
+
InvalidNativePromiseInMapResult<T> extends never ? T : never;
|
|
229
|
+
type ArrayProvider<E> = {
|
|
230
|
+
[K in number]: MethodOrProperty<E>;
|
|
231
|
+
} & {
|
|
232
|
+
map<V>(callback: (elem: MapCallbackValue<E>) => MapCallbackReturn<V>): Result<Array<V>>;
|
|
233
|
+
};
|
|
234
|
+
type TupleProvider<T extends ReadonlyArray<unknown>> = {
|
|
235
|
+
[K in TupleIndexKeys<T>]: MethodOrProperty<T[K]>;
|
|
236
|
+
} & ArrayProvider<T[number]>;
|
|
237
|
+
|
|
164
238
|
// Base type for all other types providing RPC-like interfaces.
|
|
165
239
|
// Rewrites all methods/properties to be `MethodOrProperty`s, while preserving callable types.
|
|
166
240
|
type Provider<T> = MaybeCallableProvider<T> &
|
|
167
|
-
(T extends
|
|
168
|
-
?
|
|
169
|
-
[key: number]: MethodOrProperty<U>;
|
|
170
|
-
} & {
|
|
171
|
-
map<V>(callback: (elem: U) => V): Result<Array<V>>;
|
|
172
|
-
}
|
|
241
|
+
(T extends ReadonlyArray<unknown>
|
|
242
|
+
? number extends T["length"] ? ArrayProvider<T[number]> : TupleProvider<T>
|
|
173
243
|
: {
|
|
174
244
|
[K in Exclude<
|
|
175
245
|
keyof T,
|
|
176
246
|
symbol | keyof StubBase<never>
|
|
177
247
|
>]: MethodOrProperty<T[K]>;
|
|
178
248
|
} & {
|
|
179
|
-
map<V>(
|
|
249
|
+
map<V>(
|
|
250
|
+
callback: (value: MapCallbackValue<NonNullable<T>>) => MapCallbackReturn<V>
|
|
251
|
+
): Result<Array<V>>;
|
|
180
252
|
});
|
|
181
253
|
|
|
182
254
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -12,18 +12,26 @@ import { IncomingMessage, ServerResponse, OutgoingHttpHeaders, OutgoingHttpHeade
|
|
|
12
12
|
// accept `WorkerEntrypoint` from `cloudflare:workers`, not any other class with the same shape)
|
|
13
13
|
declare const __RPC_STUB_BRAND: '__RPC_STUB_BRAND';
|
|
14
14
|
declare const __RPC_TARGET_BRAND: '__RPC_TARGET_BRAND';
|
|
15
|
+
// Distinguishes mapper placeholders from regular values so param unwrapping can accept them.
|
|
16
|
+
declare const __RPC_MAP_VALUE_BRAND: unique symbol;
|
|
15
17
|
interface RpcTargetBranded {
|
|
16
18
|
[__RPC_TARGET_BRAND]: never;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
// Types that can be used through `Stub`s
|
|
20
|
-
|
|
22
|
+
// `never[]` preserves compatibility with strongly-typed function signatures without introducing
|
|
23
|
+
// `any` into inference.
|
|
24
|
+
type Stubable = RpcTargetBranded | ((...args: never[]) => unknown);
|
|
25
|
+
|
|
26
|
+
type IsUnknown<T> = unknown extends T ? ([T] extends [unknown] ? true : false) : false;
|
|
21
27
|
|
|
22
28
|
// Types that can be passed over RPC
|
|
23
29
|
// The reason for using a generic type here is to build a serializable subset of structured
|
|
24
30
|
// cloneable composite types. This allows types defined with the "interface" keyword to pass the
|
|
25
31
|
// serializable check as well. Otherwise, only types defined with the "type" keyword would pass.
|
|
26
32
|
type RpcCompatible<T> =
|
|
33
|
+
// Allow `unknown` as a leaf so records/interfaces with `unknown` fields remain compatible.
|
|
34
|
+
| (IsUnknown<T> extends true ? unknown : never)
|
|
27
35
|
// Structured cloneables
|
|
28
36
|
| BaseType
|
|
29
37
|
// Structured cloneable composites
|
|
@@ -45,7 +53,7 @@ type RpcCompatible<T> =
|
|
|
45
53
|
|
|
46
54
|
// Base type for all RPC stubs, including common memory management methods.
|
|
47
55
|
// `T` is used as a marker type for unwrapping `Stub`s later.
|
|
48
|
-
interface StubBase<T
|
|
56
|
+
interface StubBase<T = unknown> extends Disposable {
|
|
49
57
|
[__RPC_STUB_BRAND]: T;
|
|
50
58
|
dup(): this;
|
|
51
59
|
onRpcBroken(callback: (error: any) => void): void;
|
|
@@ -102,7 +110,7 @@ type Stubify<T> =
|
|
|
102
110
|
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Stubify<V>>
|
|
103
111
|
: T extends BaseType ? T
|
|
104
112
|
// When using "unknown" instead of "any", interfaces are not stubified.
|
|
105
|
-
: T extends { [key: string | number]: any } ? { [K in keyof T]: Stubify<T[K]> }
|
|
113
|
+
: T extends { [key: string | number]: any } ? { [K in keyof T as K extends string | number ? K : never]: Stubify<T[K]> }
|
|
106
114
|
: T;
|
|
107
115
|
|
|
108
116
|
// Recursively rewrite all `Stub<T>`s with the corresponding `T`s.
|
|
@@ -110,7 +118,10 @@ type Stubify<T> =
|
|
|
110
118
|
// `Stub` depends on `Provider`, which depends on `Unstubify`, which would depend on `Stub`.
|
|
111
119
|
// prettier-ignore
|
|
112
120
|
type UnstubifyInner<T> =
|
|
113
|
-
|
|
121
|
+
// Preserve local RpcTarget acceptance, but avoid needless `Stub | Value` unions when the stub
|
|
122
|
+
// is already assignable to the value type (important for callback contextual typing).
|
|
123
|
+
T extends StubBase<infer V> ? (T extends V ? UnstubifyInner<V> : (T | UnstubifyInner<V>))
|
|
124
|
+
: T extends Promise<infer U> ? UnstubifyInner<U>
|
|
114
125
|
: T extends Map<infer K, infer V> ? Map<Unstubify<K>, Unstubify<V>>
|
|
115
126
|
: T extends Set<infer V> ? Set<Unstubify<V>>
|
|
116
127
|
: T extends [] ? []
|
|
@@ -120,14 +131,30 @@ type UnstubifyInner<T> =
|
|
|
120
131
|
: T extends Array<infer V> ? Array<Unstubify<V>>
|
|
121
132
|
: T extends ReadonlyArray<infer V> ? ReadonlyArray<Unstubify<V>>
|
|
122
133
|
: T extends BaseType ? T
|
|
123
|
-
: T extends { [key: string | number]: unknown } ? { [K in keyof T]: Unstubify<T[K]> }
|
|
134
|
+
: T extends { [key: string | number]: unknown } ? { [K in keyof T as K extends string | number ? K : never]: Unstubify<T[K]> }
|
|
124
135
|
: T;
|
|
125
136
|
|
|
126
137
|
// You can put promises anywhere in the params and they'll be resolved before delivery.
|
|
127
138
|
// (This also covers RpcPromise, because it's defined as being a Promise.)
|
|
128
|
-
|
|
139
|
+
// Map placeholders are also allowed so primitive map callback inputs can be forwarded directly
|
|
140
|
+
// into RPC params.
|
|
141
|
+
//
|
|
142
|
+
// Keep raw non-stub members so generic assignability still works when UnstubifyInner<T> is deferred.
|
|
143
|
+
// Remove stub members from mixed unions so callback params don’t get both stub and unstubbed signatures.
|
|
144
|
+
// Marker carried by map() callback inputs. This lets primitive placeholders flow through params.
|
|
145
|
+
type Unstubify<T> =
|
|
146
|
+
| NonStubMembers<T>
|
|
147
|
+
| UnstubifyInner<T>
|
|
148
|
+
| Promise<UnstubifyInner<T>>
|
|
149
|
+
| MapValuePlaceholder<UnstubifyInner<T>>;
|
|
150
|
+
|
|
151
|
+
type UnstubifyAll<A extends readonly unknown[]> = { [I in keyof A]: Unstubify<A[I]> };
|
|
129
152
|
|
|
130
|
-
|
|
153
|
+
interface MapValuePlaceholder<T> {
|
|
154
|
+
[__RPC_MAP_VALUE_BRAND]: T;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
type NonStubMembers<T> = Exclude<T, StubBase<any>>;
|
|
131
158
|
|
|
132
159
|
// Utility type for adding `Disposable`s to `object` types only.
|
|
133
160
|
// Note `unknown & T` is equivalent to `T`.
|
|
@@ -142,17 +169,22 @@ type MaybeDisposable<T> = T extends object ? Disposable : unknown;
|
|
|
142
169
|
// Intersecting with `(Maybe)Provider` allows pipelining.
|
|
143
170
|
// prettier-ignore
|
|
144
171
|
type Result<R> =
|
|
145
|
-
R extends
|
|
172
|
+
IsAny<R> extends true ? UnknownResult
|
|
173
|
+
: IsUnknown<R> extends true ? UnknownResult
|
|
174
|
+
: R extends Stubable ? Promise<Stub<R>> & Provider<R> & StubBase<R>
|
|
146
175
|
: R extends RpcCompatible<R> ? Promise<Stubify<R> & MaybeDisposable<R>> & Provider<R> & StubBase<R>
|
|
147
176
|
: never;
|
|
148
177
|
|
|
178
|
+
type IsAny<T> = 0 extends (1 & T) ? true : false;
|
|
179
|
+
type UnknownResult = Promise<unknown> & Provider<unknown> & StubBase<unknown>;
|
|
180
|
+
|
|
149
181
|
// Type for method or property on an RPC interface.
|
|
150
182
|
// For methods, unwrap `Stub`s in parameters, and rewrite returns to be `Result`s.
|
|
151
183
|
// Unwrapping `Stub`s allows calling with `Stubable` arguments.
|
|
152
184
|
// For properties, rewrite types to be `Result`s.
|
|
153
185
|
// In each case, unwrap `Promise`s.
|
|
154
186
|
type MethodOrProperty<V> = V extends (...args: infer P) => infer R
|
|
155
|
-
? (...args: UnstubifyAll<P>) => Result<Awaited<R>>
|
|
187
|
+
? (...args: UnstubifyAll<P>) => IsAny<R> extends true ? UnknownResult : Result<Awaited<R>>
|
|
156
188
|
: Result<Awaited<V>>;
|
|
157
189
|
|
|
158
190
|
// Type for the callable part of an `Provider` if `T` is callable.
|
|
@@ -161,22 +193,62 @@ type MaybeCallableProvider<T> = T extends (...args: any[]) => any
|
|
|
161
193
|
? MethodOrProperty<T>
|
|
162
194
|
: unknown;
|
|
163
195
|
|
|
196
|
+
type TupleIndexKeys<T extends ReadonlyArray<unknown>> = Extract<keyof T, `${number}`>;
|
|
197
|
+
type MapCallbackValue<T> =
|
|
198
|
+
// `Omit` removes call signatures, so re-intersect callable provider behavior.
|
|
199
|
+
T extends unknown
|
|
200
|
+
? Omit<Result<T>, keyof Promise<unknown>> &
|
|
201
|
+
MaybeCallableProvider<T> &
|
|
202
|
+
MapValuePlaceholder<T>
|
|
203
|
+
: never;
|
|
204
|
+
type InvalidNativePromiseInMapResult<T, Seen = never> =
|
|
205
|
+
T extends unknown ? InvalidNativePromiseInMapResultImpl<T, Seen> : never;
|
|
206
|
+
type InvalidNativePromiseInMapResultImpl<T, Seen> =
|
|
207
|
+
[T] extends [Seen] ? never
|
|
208
|
+
// RpcPromise is modeled as Promise & StubBase, so allow promise-like stub values.
|
|
209
|
+
: T extends StubBase<any> ? never
|
|
210
|
+
// Native thenables cannot be represented in map recordings, even when typed as PromiseLike.
|
|
211
|
+
: T extends PromiseLike<unknown> ? T
|
|
212
|
+
: T extends Map<infer K, infer V>
|
|
213
|
+
? InvalidNativePromiseInMapResult<K, Seen | T> |
|
|
214
|
+
InvalidNativePromiseInMapResult<V, Seen | T>
|
|
215
|
+
: T extends Set<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
|
|
216
|
+
: T extends readonly [] ? never
|
|
217
|
+
: T extends readonly [infer Head, ...infer Tail]
|
|
218
|
+
? InvalidNativePromiseInMapResult<Head, Seen | T> |
|
|
219
|
+
InvalidNativePromiseInMapResult<Tail[number], Seen | T>
|
|
220
|
+
: T extends ReadonlyArray<infer V> ? InvalidNativePromiseInMapResult<V, Seen | T>
|
|
221
|
+
: T extends { [key: string | number]: unknown }
|
|
222
|
+
? InvalidNativePromiseInMapResult<
|
|
223
|
+
T[Extract<keyof T, string | number>],
|
|
224
|
+
Seen | T
|
|
225
|
+
>
|
|
226
|
+
: never;
|
|
227
|
+
type MapCallbackReturn<T> =
|
|
228
|
+
InvalidNativePromiseInMapResult<T> extends never ? T : never;
|
|
229
|
+
type ArrayProvider<E> = {
|
|
230
|
+
[K in number]: MethodOrProperty<E>;
|
|
231
|
+
} & {
|
|
232
|
+
map<V>(callback: (elem: MapCallbackValue<E>) => MapCallbackReturn<V>): Result<Array<V>>;
|
|
233
|
+
};
|
|
234
|
+
type TupleProvider<T extends ReadonlyArray<unknown>> = {
|
|
235
|
+
[K in TupleIndexKeys<T>]: MethodOrProperty<T[K]>;
|
|
236
|
+
} & ArrayProvider<T[number]>;
|
|
237
|
+
|
|
164
238
|
// Base type for all other types providing RPC-like interfaces.
|
|
165
239
|
// Rewrites all methods/properties to be `MethodOrProperty`s, while preserving callable types.
|
|
166
240
|
type Provider<T> = MaybeCallableProvider<T> &
|
|
167
|
-
(T extends
|
|
168
|
-
?
|
|
169
|
-
[key: number]: MethodOrProperty<U>;
|
|
170
|
-
} & {
|
|
171
|
-
map<V>(callback: (elem: U) => V): Result<Array<V>>;
|
|
172
|
-
}
|
|
241
|
+
(T extends ReadonlyArray<unknown>
|
|
242
|
+
? number extends T["length"] ? ArrayProvider<T[number]> : TupleProvider<T>
|
|
173
243
|
: {
|
|
174
244
|
[K in Exclude<
|
|
175
245
|
keyof T,
|
|
176
246
|
symbol | keyof StubBase<never>
|
|
177
247
|
>]: MethodOrProperty<T[K]>;
|
|
178
248
|
} & {
|
|
179
|
-
map<V>(
|
|
249
|
+
map<V>(
|
|
250
|
+
callback: (value: MapCallbackValue<NonNullable<T>>) => MapCallbackReturn<V>
|
|
251
|
+
): Result<Array<V>>;
|
|
180
252
|
});
|
|
181
253
|
|
|
182
254
|
/**
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ var RpcTarget = workersModule ? workersModule.RpcTarget : class {
|
|
|
24
24
|
};
|
|
25
25
|
var AsyncFunction = (async function() {
|
|
26
26
|
}).constructor;
|
|
27
|
+
var BUFFER_PROTOTYPE = typeof Buffer !== "undefined" ? Buffer.prototype : void 0;
|
|
27
28
|
function typeForRpc(value) {
|
|
28
29
|
switch (typeof value) {
|
|
29
30
|
case "boolean":
|
|
@@ -55,11 +56,18 @@ function typeForRpc(value) {
|
|
|
55
56
|
case Date.prototype:
|
|
56
57
|
return "date";
|
|
57
58
|
case Uint8Array.prototype:
|
|
59
|
+
case BUFFER_PROTOTYPE:
|
|
58
60
|
return "bytes";
|
|
59
61
|
case WritableStream.prototype:
|
|
60
62
|
return "writable";
|
|
61
63
|
case ReadableStream.prototype:
|
|
62
64
|
return "readable";
|
|
65
|
+
case Headers.prototype:
|
|
66
|
+
return "headers";
|
|
67
|
+
case Request.prototype:
|
|
68
|
+
return "request";
|
|
69
|
+
case Response.prototype:
|
|
70
|
+
return "response";
|
|
63
71
|
// TODO: All other structured clone types.
|
|
64
72
|
case RpcStub.prototype:
|
|
65
73
|
return "stub";
|
|
@@ -613,6 +621,22 @@ var RpcPayload = class _RpcPayload {
|
|
|
613
621
|
this.hooks.push(hook);
|
|
614
622
|
return stream;
|
|
615
623
|
}
|
|
624
|
+
case "headers":
|
|
625
|
+
return new Headers(value);
|
|
626
|
+
case "request": {
|
|
627
|
+
let req = value;
|
|
628
|
+
if (req.body) {
|
|
629
|
+
this.deepCopy(req.body, req, "body", req, dupStubs, owner);
|
|
630
|
+
}
|
|
631
|
+
return new Request(req);
|
|
632
|
+
}
|
|
633
|
+
case "response": {
|
|
634
|
+
let resp = value;
|
|
635
|
+
if (resp.body) {
|
|
636
|
+
this.deepCopy(resp.body, resp, "body", resp, dupStubs, owner);
|
|
637
|
+
}
|
|
638
|
+
return new Response(resp.body, resp);
|
|
639
|
+
}
|
|
616
640
|
default:
|
|
617
641
|
throw new Error("unreachable");
|
|
618
642
|
}
|
|
@@ -792,6 +816,18 @@ var RpcPayload = class _RpcPayload {
|
|
|
792
816
|
}
|
|
793
817
|
case "rpc-thenable":
|
|
794
818
|
return;
|
|
819
|
+
case "headers":
|
|
820
|
+
return;
|
|
821
|
+
case "request": {
|
|
822
|
+
let req = value;
|
|
823
|
+
if (req.body) this.disposeImpl(req.body, req);
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
826
|
+
case "response": {
|
|
827
|
+
let resp = value;
|
|
828
|
+
if (resp.body) this.disposeImpl(resp.body, resp);
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
795
831
|
case "writable": {
|
|
796
832
|
let stream = value;
|
|
797
833
|
let hook = this.rpcTargets?.get(stream);
|
|
@@ -847,6 +883,9 @@ var RpcPayload = class _RpcPayload {
|
|
|
847
883
|
case "rpc-target":
|
|
848
884
|
case "writable":
|
|
849
885
|
case "readable":
|
|
886
|
+
case "headers":
|
|
887
|
+
case "request":
|
|
888
|
+
case "response":
|
|
850
889
|
return;
|
|
851
890
|
case "array": {
|
|
852
891
|
let array = value;
|
|
@@ -930,6 +969,9 @@ function followPath(value, parent, path, owner) {
|
|
|
930
969
|
case "bytes":
|
|
931
970
|
case "date":
|
|
932
971
|
case "error":
|
|
972
|
+
case "headers":
|
|
973
|
+
case "request":
|
|
974
|
+
case "response":
|
|
933
975
|
value = void 0;
|
|
934
976
|
break;
|
|
935
977
|
case "undefined":
|
|
@@ -1344,12 +1386,86 @@ var Devaluator = class _Devaluator {
|
|
|
1344
1386
|
let bytes = value;
|
|
1345
1387
|
if (bytes.toBase64) {
|
|
1346
1388
|
return ["bytes", bytes.toBase64({ omitPadding: true })];
|
|
1347
|
-
} else {
|
|
1348
|
-
return [
|
|
1349
|
-
"bytes",
|
|
1350
|
-
btoa(String.fromCharCode.apply(null, bytes).replace(/=*$/, ""))
|
|
1351
|
-
];
|
|
1352
1389
|
}
|
|
1390
|
+
let b64;
|
|
1391
|
+
if (typeof Buffer !== "undefined") {
|
|
1392
|
+
let buf = bytes instanceof Buffer ? bytes : Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
1393
|
+
b64 = buf.toString("base64");
|
|
1394
|
+
} else {
|
|
1395
|
+
let binary = "";
|
|
1396
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
1397
|
+
binary += String.fromCharCode(bytes[i]);
|
|
1398
|
+
}
|
|
1399
|
+
b64 = btoa(binary);
|
|
1400
|
+
}
|
|
1401
|
+
return ["bytes", b64.replace(/=+$/, "")];
|
|
1402
|
+
}
|
|
1403
|
+
case "headers":
|
|
1404
|
+
return ["headers", [...value]];
|
|
1405
|
+
case "request": {
|
|
1406
|
+
let req = value;
|
|
1407
|
+
let init = {};
|
|
1408
|
+
if (req.method !== "GET") init.method = req.method;
|
|
1409
|
+
let headers = [...req.headers];
|
|
1410
|
+
if (headers.length > 0) {
|
|
1411
|
+
init.headers = headers;
|
|
1412
|
+
}
|
|
1413
|
+
if (req.body) {
|
|
1414
|
+
init.body = this.devaluateImpl(req.body, req, depth + 1);
|
|
1415
|
+
init.duplex = req.duplex || "half";
|
|
1416
|
+
} else if (req.body === void 0 && !["GET", "HEAD", "OPTIONS", "TRACE", "DELETE"].includes(req.method)) {
|
|
1417
|
+
let bodyPromise = req.arrayBuffer();
|
|
1418
|
+
let readable = new ReadableStream({
|
|
1419
|
+
async start(controller) {
|
|
1420
|
+
try {
|
|
1421
|
+
controller.enqueue(new Uint8Array(await bodyPromise));
|
|
1422
|
+
controller.close();
|
|
1423
|
+
} catch (err) {
|
|
1424
|
+
controller.error(err);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
});
|
|
1428
|
+
let hook = streamImpl.createReadableStreamHook(readable);
|
|
1429
|
+
let importId = this.exporter.createPipe(readable, hook);
|
|
1430
|
+
init.body = ["readable", importId];
|
|
1431
|
+
init.duplex = req.duplex || "half";
|
|
1432
|
+
}
|
|
1433
|
+
if (req.cache && req.cache !== "default") init.cache = req.cache;
|
|
1434
|
+
if (req.redirect !== "follow") init.redirect = req.redirect;
|
|
1435
|
+
if (req.integrity) init.integrity = req.integrity;
|
|
1436
|
+
if (req.mode && req.mode !== "cors") init.mode = req.mode;
|
|
1437
|
+
if (req.credentials && req.credentials !== "same-origin") {
|
|
1438
|
+
init.credentials = req.credentials;
|
|
1439
|
+
}
|
|
1440
|
+
if (req.referrer && req.referrer !== "about:client") init.referrer = req.referrer;
|
|
1441
|
+
if (req.referrerPolicy) init.referrerPolicy = req.referrerPolicy;
|
|
1442
|
+
if (req.keepalive) init.keepalive = req.keepalive;
|
|
1443
|
+
let cfReq = req;
|
|
1444
|
+
if (cfReq.cf) init.cf = cfReq.cf;
|
|
1445
|
+
if (cfReq.encodeResponseBody && cfReq.encodeResponseBody !== "automatic") {
|
|
1446
|
+
init.encodeResponseBody = cfReq.encodeResponseBody;
|
|
1447
|
+
}
|
|
1448
|
+
return ["request", req.url, init];
|
|
1449
|
+
}
|
|
1450
|
+
case "response": {
|
|
1451
|
+
let resp = value;
|
|
1452
|
+
let body = this.devaluateImpl(resp.body, resp, depth + 1);
|
|
1453
|
+
let init = {};
|
|
1454
|
+
if (resp.status !== 200) init.status = resp.status;
|
|
1455
|
+
if (resp.statusText) init.statusText = resp.statusText;
|
|
1456
|
+
let headers = [...resp.headers];
|
|
1457
|
+
if (headers.length > 0) {
|
|
1458
|
+
init.headers = headers;
|
|
1459
|
+
}
|
|
1460
|
+
let cfResp = resp;
|
|
1461
|
+
if (cfResp.cf) init.cf = cfResp.cf;
|
|
1462
|
+
if (cfResp.encodeBody && cfResp.encodeBody !== "automatic") {
|
|
1463
|
+
init.encodeBody = cfResp.encodeBody;
|
|
1464
|
+
}
|
|
1465
|
+
if (cfResp.webSocket) {
|
|
1466
|
+
throw new TypeError("Can't serialize a Response containing a webSocket.");
|
|
1467
|
+
}
|
|
1468
|
+
return ["response", body, init];
|
|
1353
1469
|
}
|
|
1354
1470
|
case "error": {
|
|
1355
1471
|
let e = value;
|
|
@@ -1450,6 +1566,14 @@ var NullImporter = class {
|
|
|
1450
1566
|
}
|
|
1451
1567
|
};
|
|
1452
1568
|
var NULL_IMPORTER = new NullImporter();
|
|
1569
|
+
function fixBrokenRequestBody(request, body) {
|
|
1570
|
+
let promise = new Response(body).arrayBuffer().then((arrayBuffer) => {
|
|
1571
|
+
let bytes = new Uint8Array(arrayBuffer);
|
|
1572
|
+
let result = new Request(request, { body: bytes });
|
|
1573
|
+
return new PayloadStubHook(RpcPayload.fromAppReturn(result));
|
|
1574
|
+
});
|
|
1575
|
+
return new RpcPromise(new PromiseStubHook(promise), []);
|
|
1576
|
+
}
|
|
1453
1577
|
var Evaluator = class _Evaluator {
|
|
1454
1578
|
constructor(importer) {
|
|
1455
1579
|
this.importer = importer;
|
|
@@ -1490,10 +1614,11 @@ var Evaluator = class _Evaluator {
|
|
|
1490
1614
|
}
|
|
1491
1615
|
break;
|
|
1492
1616
|
case "bytes": {
|
|
1493
|
-
let b64 = Uint8Array;
|
|
1494
1617
|
if (typeof value[1] == "string") {
|
|
1495
|
-
if (
|
|
1496
|
-
return
|
|
1618
|
+
if (typeof Buffer !== "undefined") {
|
|
1619
|
+
return Buffer.from(value[1], "base64");
|
|
1620
|
+
} else if (Uint8Array.fromBase64) {
|
|
1621
|
+
return Uint8Array.fromBase64(value[1]);
|
|
1497
1622
|
} else {
|
|
1498
1623
|
let bs = atob(value[1]);
|
|
1499
1624
|
let len = bs.length;
|
|
@@ -1527,6 +1652,56 @@ var Evaluator = class _Evaluator {
|
|
|
1527
1652
|
return -Infinity;
|
|
1528
1653
|
case "nan":
|
|
1529
1654
|
return NaN;
|
|
1655
|
+
case "headers":
|
|
1656
|
+
if (value.length === 2 && value[1] instanceof Array) {
|
|
1657
|
+
return new Headers(value[1]);
|
|
1658
|
+
}
|
|
1659
|
+
break;
|
|
1660
|
+
case "request": {
|
|
1661
|
+
if (value.length !== 3 || typeof value[1] !== "string") break;
|
|
1662
|
+
let url = value[1];
|
|
1663
|
+
let init = value[2];
|
|
1664
|
+
if (typeof init !== "object" || init === null) break;
|
|
1665
|
+
if (init.body) {
|
|
1666
|
+
init.body = this.evaluateImpl(init.body, init, "body");
|
|
1667
|
+
if (init.body === null || typeof init.body === "string" || init.body instanceof Uint8Array || init.body instanceof ReadableStream) ; else {
|
|
1668
|
+
throw new TypeError("Request body must be of type ReadableStream.");
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
if (init.signal) {
|
|
1672
|
+
init.signal = this.evaluateImpl(init.signal, init, "signal");
|
|
1673
|
+
if (!(init.signal instanceof AbortSignal)) {
|
|
1674
|
+
throw new TypeError("Request siganl must be of type AbortSignal.");
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
if (init.headers && !(init.headers instanceof Array)) {
|
|
1678
|
+
throw new TypeError("Request headers must be serialized as an array of pairs.");
|
|
1679
|
+
}
|
|
1680
|
+
let result = new Request(url, init);
|
|
1681
|
+
if (init.body instanceof ReadableStream && result.body === void 0) {
|
|
1682
|
+
let promise = fixBrokenRequestBody(result, init.body);
|
|
1683
|
+
this.promises.push({ promise, parent, property });
|
|
1684
|
+
return promise;
|
|
1685
|
+
} else {
|
|
1686
|
+
return result;
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
case "response": {
|
|
1690
|
+
if (value.length !== 3) break;
|
|
1691
|
+
let body = this.evaluateImpl(value[1], parent, property);
|
|
1692
|
+
if (body === null || typeof body === "string" || body instanceof Uint8Array || body instanceof ReadableStream) ; else {
|
|
1693
|
+
throw new TypeError("Response body must be of type ReadableStream.");
|
|
1694
|
+
}
|
|
1695
|
+
let init = value[2];
|
|
1696
|
+
if (typeof init !== "object" || init === null) break;
|
|
1697
|
+
if (init.webSocket) {
|
|
1698
|
+
throw new TypeError("Can't deserialize a Response containing a webSocket.");
|
|
1699
|
+
}
|
|
1700
|
+
if (init.headers && !(init.headers instanceof Array)) {
|
|
1701
|
+
throw new TypeError("Request headers must be serialized as an array of pairs.");
|
|
1702
|
+
}
|
|
1703
|
+
return new Response(body, init);
|
|
1704
|
+
}
|
|
1530
1705
|
case "import":
|
|
1531
1706
|
case "pipeline": {
|
|
1532
1707
|
if (value.length < 2 || value.length > 4) {
|