osra 0.2.13 → 0.3.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.
Files changed (40) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +319 -304
  3. package/build/connections/bidirectional.d.ts +53 -0
  4. package/build/connections/index.d.ts +20 -0
  5. package/build/connections/utils.d.ts +31 -0
  6. package/build/index.d.ts +16 -630
  7. package/build/index.js +918 -634
  8. package/build/index.js.map +1 -1
  9. package/build/revivables/abort-signal.d.ts +20 -0
  10. package/build/revivables/array-buffer.d.ts +12 -0
  11. package/build/revivables/bigint.d.ts +14 -0
  12. package/build/revivables/date.d.ts +9 -0
  13. package/build/revivables/error.d.ts +10 -0
  14. package/build/revivables/event-target.d.ts +29 -0
  15. package/build/revivables/function.d.ts +29 -0
  16. package/build/revivables/headers.d.ts +9 -0
  17. package/build/revivables/identity.d.ts +39 -0
  18. package/build/revivables/index.d.ts +39 -0
  19. package/build/revivables/map.d.ts +11 -0
  20. package/build/revivables/message-port.d.ts +83 -0
  21. package/build/revivables/promise.d.ts +34 -0
  22. package/build/revivables/readable-stream.d.ts +18 -0
  23. package/build/revivables/request.d.ts +23 -0
  24. package/build/revivables/response.d.ts +18 -0
  25. package/build/revivables/set.d.ts +11 -0
  26. package/build/revivables/transfer.d.ts +37 -0
  27. package/build/revivables/typed-array.d.ts +15 -0
  28. package/build/revivables/utils.d.ts +59 -0
  29. package/build/types.d.ts +45 -0
  30. package/build/utils/capable-check.d.ts +44 -0
  31. package/build/utils/event-channel.d.ts +27 -0
  32. package/build/utils/index.d.ts +11 -0
  33. package/build/utils/replace.d.ts +25 -0
  34. package/build/utils/transferable.d.ts +20 -0
  35. package/build/utils/transport.d.ts +56 -0
  36. package/build/utils/type-guards.d.ts +58 -0
  37. package/build/utils/type.d.ts +2 -0
  38. package/build/utils/typed-event-target.d.ts +16 -0
  39. package/build/utils/typed-message-channel.d.ts +19 -0
  40. package/package.json +60 -67
@@ -0,0 +1,20 @@
1
+ import type { Capable } from '../types';
2
+ import type { RevivableContext, BoxBase as BoxBaseType } from './utils';
3
+ import type { UnderlyingType } from '../utils/type';
4
+ import type { BoxedMessagePort } from './message-port';
5
+ export declare const type: 'abortSignal';
6
+ type AbortMessage = {
7
+ type: 'abort';
8
+ reason?: Capable;
9
+ };
10
+ export type BoxedAbortSignal<T extends AbortSignal = AbortSignal> = BoxBaseType<typeof type> & {
11
+ aborted: boolean;
12
+ reason?: Capable;
13
+ port: BoxedMessagePort<AbortMessage>;
14
+ } & {
15
+ [UnderlyingType]: T;
16
+ };
17
+ export declare const isType: (value: unknown) => value is AbortSignal;
18
+ export declare const box: <T extends AbortSignal, T2 extends RevivableContext>(value: T, context: T2) => BoxedAbortSignal<T>;
19
+ export declare const revive: <T extends BoxedAbortSignal, T2 extends RevivableContext>(value: T, context: T2) => AbortSignal;
20
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { RevivableContext, UnderlyingType, BoxedBuffer } from './utils';
2
+ import { BoxBase } from './utils';
3
+ export declare const type: 'arrayBuffer';
4
+ type BoxedArrayBuffer<T extends ArrayBuffer, T2 extends RevivableContext> = typeof BoxBase & {
5
+ type: typeof type;
6
+ } & BoxedBuffer<T2> & {
7
+ [UnderlyingType]: T;
8
+ };
9
+ export declare const isType: (value: unknown) => value is ArrayBuffer;
10
+ export declare const box: <T extends ArrayBuffer, T2 extends RevivableContext>(value: T, context: T2) => BoxedArrayBuffer<T, T2>;
11
+ export declare const revive: <T extends BoxedArrayBuffer<ArrayBuffer, RevivableContext>>(value: T, _context: RevivableContext) => T[UnderlyingType];
12
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { RevivableContext, UnderlyingType } from './utils';
2
+ import { BoxBase } from './utils';
3
+ export declare const type: 'bigint';
4
+ type BoxedBigInt<T extends bigint> = typeof BoxBase & {
5
+ type: typeof type;
6
+ } & {
7
+ value: string;
8
+ } & {
9
+ [UnderlyingType]: T;
10
+ };
11
+ export declare const isType: (value: unknown) => value is bigint;
12
+ export declare const box: <T extends bigint, T2 extends RevivableContext>(value: T, _context: T2) => BoxedBigInt<T>;
13
+ export declare const revive: <T extends BoxedBigInt<bigint>>(value: T, _context: RevivableContext) => T[UnderlyingType];
14
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { RevivableContext } from './utils';
2
+ export declare const type: 'date';
3
+ export declare const isType: (value: unknown) => value is Date;
4
+ export declare const box: <T extends Date, T2 extends RevivableContext>(value: T, _context: T2) => {
5
+ __OSRA_BOX__: 'revivable';
6
+ type: "date";
7
+ ISOString: string;
8
+ };
9
+ export declare const revive: <T extends ReturnType<typeof box>, T2 extends RevivableContext>(value: T, _context: T2) => Date;
@@ -0,0 +1,10 @@
1
+ import type { RevivableContext } from './utils';
2
+ export declare const type: 'error';
3
+ export declare const isType: (value: unknown) => value is Error;
4
+ export declare const box: <T extends Error, T2 extends RevivableContext>(value: T, _context: T2) => {
5
+ __OSRA_BOX__: 'revivable';
6
+ type: "error";
7
+ message: string;
8
+ stack: string;
9
+ };
10
+ export declare const revive: <T extends ReturnType<typeof box>, T2 extends RevivableContext>(value: T, _context: T2) => Error;
@@ -0,0 +1,29 @@
1
+ import type { Capable } from '../types';
2
+ import type { RevivableContext, BoxBase as BoxBaseType, UnderlyingType } from './utils';
3
+ import type { BoxedMessagePort } from './message-port';
4
+ export declare const type: 'eventTarget';
5
+ type EventTargetMessage = {
6
+ kind: 'subscribe';
7
+ eventType: string;
8
+ } | {
9
+ kind: 'unsubscribe';
10
+ eventType: string;
11
+ } | {
12
+ kind: 'close';
13
+ } | {
14
+ kind: 'event';
15
+ eventType: string;
16
+ bubbles: boolean;
17
+ cancelable: boolean;
18
+ composed: boolean;
19
+ detail?: Capable;
20
+ };
21
+ export type BoxedEventTarget<T extends EventTarget = EventTarget> = BoxBaseType<typeof type> & {
22
+ port: BoxedMessagePort<EventTargetMessage>;
23
+ } & {
24
+ [UnderlyingType]: T;
25
+ };
26
+ export declare const isType: (value: unknown) => value is EventTarget;
27
+ export declare const box: <T extends EventTarget, T2 extends RevivableContext>(value: T, context: T2) => BoxedEventTarget<T>;
28
+ export declare const revive: <T extends BoxedEventTarget, T2 extends RevivableContext>(value: T, context: T2) => T[UnderlyingType];
29
+ export {};
@@ -0,0 +1,29 @@
1
+ import type { Capable } from '../types';
2
+ import type { UnderlyingType, RevivableContext, BoxBase as BoxBaseType } from './utils';
3
+ import type { AnyPort } from './message-port';
4
+ import { BoxedMessagePort } from './message-port';
5
+ export declare const type: 'function';
6
+ type ResultMessage = {
7
+ __osra_ok__: true;
8
+ value: Capable;
9
+ } | {
10
+ __osra_err__: true;
11
+ error: string;
12
+ };
13
+ type CallMessage = CallContext | {
14
+ __osra_close__: true;
15
+ };
16
+ /** Call-site payload as received by the callee, after box-side revival: the
17
+ * return port is now a live AnyPort<ResultMessage> (ProtocolPort on clone,
18
+ * EventPort on JSON); args are revived. */
19
+ export type CallContext = [AnyPort<ResultMessage>, Capable[]];
20
+ export type BoxedFunction<T extends (...args: any[]) => any = (...args: any[]) => any> = BoxBaseType<typeof type> & {
21
+ port: BoxedMessagePort<CallMessage>;
22
+ } & {
23
+ [UnderlyingType]: (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>>;
24
+ };
25
+ type CapableFunction<T> = T extends (...args: infer P) => infer R ? P extends Capable[] ? R extends Capable ? T : never : never : never;
26
+ export declare const isType: (value: unknown) => value is (...args: any[]) => any;
27
+ export declare const box: <T extends (...args: any[]) => any, T2 extends RevivableContext>(value: T & CapableFunction<T>, context: T2) => BoxedFunction<T>;
28
+ export declare const revive: <T extends BoxedFunction, T2 extends RevivableContext>(value: T, context: T2) => T[UnderlyingType];
29
+ export {};
@@ -0,0 +1,9 @@
1
+ import type { RevivableContext } from './utils';
2
+ export declare const type: 'headers';
3
+ export declare const isType: (value: unknown) => value is Headers;
4
+ export declare const box: <T extends Headers, T2 extends RevivableContext>(value: T, _context: T2) => {
5
+ __OSRA_BOX__: 'revivable';
6
+ type: "headers";
7
+ entries: [string, string][];
8
+ };
9
+ export declare const revive: <T extends ReturnType<typeof box>, T2 extends RevivableContext>(value: T, _context: T2) => Headers;
@@ -0,0 +1,39 @@
1
+ import type { Capable, Uuid } from '../types';
2
+ import type { RevivableContext, BoxBase as BoxBaseType } from './utils';
3
+ import type { UnderlyingType } from '../utils/type';
4
+ export declare const type: 'identity';
5
+ export type Messages = {
6
+ type: 'identity-dispose';
7
+ remoteUuid: Uuid;
8
+ /** id of the identity-wrapped value that was collected */
9
+ id: string;
10
+ };
11
+ export declare const Messages: Messages;
12
+ declare const IDENTITY_MARKER: unique symbol;
13
+ type IdentityWrapper<T = unknown> = {
14
+ readonly [IDENTITY_MARKER]: true;
15
+ readonly value: T;
16
+ };
17
+ export type BoxedIdentity<T extends Capable = Capable> = BoxBaseType<typeof type> & {
18
+ id: string;
19
+ inner?: Capable;
20
+ [UnderlyingType]: T;
21
+ };
22
+ /**
23
+ * Wrap a value so that osra preserves its reference identity across the
24
+ * RPC boundary, per connection. Calling identity(X) twice on the same
25
+ * value produces the same wrapper, and both wrapper sends resolve to the
26
+ * same revived reference on the remote side.
27
+ *
28
+ * - Primitives pass through unchanged (there is no identity to preserve).
29
+ * - Already-wrapped values pass through unchanged (idempotent).
30
+ *
31
+ * NOTE: This lies at the type level — the runtime value for object/function
32
+ * inputs is an IdentityWrapper<T>, typed as T so the user's surrounding
33
+ * code stays unchanged. The box-site unwraps it.
34
+ */
35
+ export declare const identity: <T>(value: T) => T;
36
+ export declare const isType: (value: unknown) => value is IdentityWrapper;
37
+ export declare const box: <T extends Capable, TContext extends RevivableContext>(wrapper: IdentityWrapper<T>, context: TContext) => BoxedIdentity<T>;
38
+ export declare const revive: <T extends BoxedIdentity, TContext extends RevivableContext>(value: T, context: TContext) => T[UnderlyingType];
39
+ export {};
@@ -0,0 +1,39 @@
1
+ import type { BoxBase, RevivableContext } from './utils';
2
+ import type { DeepReplaceWithBox, DeepReplaceWithRevive, ReplaceWithBox, ReplaceWithRevive } from '../utils/replace';
3
+ import type { MessageFields, Capable } from '../types';
4
+ import * as arrayBuffer from './array-buffer';
5
+ import * as date from './date';
6
+ import * as headers from './headers';
7
+ import * as error from './error';
8
+ import * as typedArray from './typed-array';
9
+ import * as promise from './promise';
10
+ import * as func from './function';
11
+ import * as messagePort from './message-port';
12
+ import * as readableStream from './readable-stream';
13
+ import * as abortSignal from './abort-signal';
14
+ import * as response from './response';
15
+ import * as request from './request';
16
+ import * as identity from './identity';
17
+ import * as transfer from './transfer';
18
+ import * as map from './map';
19
+ import * as set from './set';
20
+ import * as bigInt from './bigint';
21
+ import * as eventTarget from './event-target';
22
+ export { identity } from './identity';
23
+ export { transfer } from './transfer';
24
+ export * from './utils';
25
+ export type RevivableModule<T extends string = string, T2 = any, T3 extends BoxBase<T> = any, T4 extends MessageFields = MessageFields> = {
26
+ readonly type: T;
27
+ readonly isType: (value: unknown) => value is T2;
28
+ readonly box: ((value: T2, context: RevivableContext<any>) => T3) | ((...args: any[]) => any);
29
+ readonly revive: (value: T3, context: RevivableContext<any>) => T2;
30
+ readonly init?: (context: RevivableContext<any>) => void;
31
+ readonly Messages?: T4;
32
+ };
33
+ export declare const defaultRevivableModules: readonly [typeof transfer, typeof identity, typeof arrayBuffer, typeof date, typeof headers, typeof error, typeof typedArray, typeof promise, typeof func, typeof messagePort, typeof readableStream, typeof abortSignal, typeof response, typeof request, typeof map, typeof set, typeof bigInt, typeof eventTarget];
34
+ export type DefaultRevivableModules = typeof defaultRevivableModules;
35
+ export type DefaultRevivableModule = DefaultRevivableModules[number];
36
+ export declare const box: <T extends Capable, TModules extends readonly RevivableModule[]>(value: T, context: RevivableContext<TModules>) => ReplaceWithBox<T, TModules[number]>;
37
+ export declare const recursiveBox: <T extends Capable, TModules extends readonly RevivableModule[]>(value: T, context: RevivableContext<TModules>) => DeepReplaceWithBox<T, TModules[number]>;
38
+ export declare const revive: <T extends ReturnType<typeof box>, TModules extends readonly RevivableModule[]>(value: T, context: RevivableContext<TModules>) => ReplaceWithRevive<T, TModules[number]>;
39
+ export declare const recursiveRevive: <T extends Capable, TModules extends readonly RevivableModule[]>(value: T, context: RevivableContext<TModules>) => DeepReplaceWithRevive<T, TModules[number]>;
@@ -0,0 +1,11 @@
1
+ import type { Capable } from '../types';
2
+ import type { RevivableContext, UnderlyingType, BoxBase as BoxBaseType } from './utils';
3
+ export declare const type: 'map';
4
+ export type BoxedMap<T extends Map<Capable, Capable> = Map<Capable, Capable>> = BoxBaseType<typeof type> & {
5
+ entries: Array<[Capable, Capable]>;
6
+ } & {
7
+ [UnderlyingType]: T;
8
+ };
9
+ export declare const isType: (value: unknown) => value is Map<unknown, unknown>;
10
+ export declare const box: <T extends Map<Capable, Capable>, T2 extends RevivableContext>(value: T, context: T2) => BoxedMap<T>;
11
+ export declare const revive: <T extends BoxedMap, T2 extends RevivableContext>(value: T, context: T2) => T[UnderlyingType];
@@ -0,0 +1,83 @@
1
+ import type { Capable, StructurableTransferable, Uuid } from '../types';
2
+ import type { TypedMessagePort } from '../utils/typed-message-channel';
3
+ import type { RevivableContext, BoxBase as BoxBaseType } from './utils';
4
+ import type { UnderlyingType } from '../utils/type';
5
+ import type { BadFieldValue, BadFieldPath, BadFieldParent, ErrorMessage, BadValue, Path, ParentObject } from '../utils/capable-check';
6
+ import { EventPort } from '../utils/event-channel';
7
+ export declare const type: 'messagePort';
8
+ export type Messages = {
9
+ type: 'message';
10
+ remoteUuid: Uuid;
11
+ data: Capable;
12
+ /** uuid of the messagePort that the message was sent through */
13
+ portId: Uuid;
14
+ } | {
15
+ type: 'message-port-close';
16
+ remoteUuid: Uuid;
17
+ /** uuid of the messagePort that closed */
18
+ portId: Uuid;
19
+ };
20
+ export declare const Messages: Messages;
21
+ /** Any port-shape the message-port revivable is happy to accept. Real
22
+ * MessagePorts (from `new MessageChannel()`) and synthetic EventPorts
23
+ * (from `new EventChannel()`) both flow through here. Messages can be any
24
+ * Capable value — message-port boxes/revives as they cross the transport,
25
+ * and the in-realm side uses pass-by-reference via EventChannel. */
26
+ export type AnyPort<T = Capable> = TypedMessagePort<T> | EventPort<T>;
27
+ export type BoxedMessagePort<T = Capable> = BoxBaseType<typeof type> & (
28
+ /** The origin was a synthetic EventPort — revive must reproduce an
29
+ * EventPort on the other side so live (non-clonable) Promises/Functions
30
+ * etc. can flow through by reference. */
31
+ {
32
+ portId: Uuid;
33
+ synthetic: true;
34
+ }
35
+ /** The origin was a real MessagePort but the transport can't carry
36
+ * ports (JSON-only) — revive produces a real MessagePort proxy so the
37
+ * receiver sees it as if it had been transferred. Payloads must be
38
+ * structured-clonable; live (non-clonable) values nested in a
39
+ * user-level MessagePort aren't supported in this mode. */
40
+ | {
41
+ portId: Uuid;
42
+ synthetic: false;
43
+ }
44
+ /** The origin was a real MessagePort and the transport supports
45
+ * structured clone — the port is transferred on the wire. When
46
+ * `autoBox` is true, the revive side wraps it in a `ProtocolPort`
47
+ * that auto-boxes outgoing / auto-revives incoming payloads so
48
+ * live values (Promises/Functions) flow through unchanged. When
49
+ * `autoBox` is absent/false, the receiver gets the raw MessagePort
50
+ * with structured-clone semantics (used for user-owned ports). */
51
+ | {
52
+ port: AnyPort<T>;
53
+ autoBox?: boolean;
54
+ }) & {
55
+ [UnderlyingType]: TypedMessagePort<T>;
56
+ };
57
+ type StructurableTransferablePort<T> = [T] extends [Capable] ? AnyPort<T> : AnyPort<T> & {
58
+ [ErrorMessage]: 'Message type must extend Capable';
59
+ [BadValue]: BadFieldValue<T, Capable>;
60
+ [Path]: BadFieldPath<T, Capable>;
61
+ [ParentObject]: BadFieldParent<T, Capable>;
62
+ };
63
+ export declare const init: (context: RevivableContext) => void;
64
+ export declare const isType: (value: unknown) => value is MessagePort | EventPort<StructurableTransferable>;
65
+ export declare const box: <T, T2 extends RevivableContext = RevivableContext>(value: StructurableTransferablePort<T>, context: T2, options?: {
66
+ autoBox?: boolean;
67
+ }) => BoxedMessagePort<T>;
68
+ export declare const revive: <T extends Capable, T2 extends RevivableContext>(value: BoxedMessagePort<T>, context: T2) => TypedMessagePort<T>;
69
+ /**
70
+ * Factory for revivable-internal channels. Returns a local port used by the
71
+ * revivable and a pre-boxed remote port ready to embed in the revivable's
72
+ * Boxed* structure. The local port auto-boxes/revives on clone transports
73
+ * (via ProtocolPort over a MessageChannel) and passes by reference on JSON
74
+ * transports (via EventChannel → portId routing).
75
+ *
76
+ * Revivables can post live values (Promises/Functions/…) on `localPort`
77
+ * without caring about the transport mode.
78
+ */
79
+ export declare const createRevivableChannel: <T extends Capable>(context: RevivableContext) => {
80
+ localPort: AnyPort<T>;
81
+ boxedRemote: BoxedMessagePort<T>;
82
+ };
83
+ export {};
@@ -0,0 +1,34 @@
1
+ import type { Capable } from '../types';
2
+ import type { RevivableContext, BoxBase as BoxBaseType } from './utils';
3
+ import type { UnderlyingType } from '.';
4
+ import type { BadFieldValue, BadFieldPath, BadFieldParent, ErrorMessage, BadValue, Path, ParentObject } from '../utils/capable-check';
5
+ import { BoxedMessagePort } from './message-port';
6
+ export declare const type: 'promise';
7
+ export type Context = {
8
+ type: 'resolve';
9
+ data: Capable;
10
+ } | {
11
+ type: 'reject';
12
+ error: string;
13
+ };
14
+ type CapablePromise<T> = T extends Promise<infer U> ? U extends Capable ? T : T & {
15
+ [ErrorMessage]: 'Value type must extend a Promise that resolves to a Capable';
16
+ [BadValue]: BadFieldValue<U, Capable>;
17
+ [Path]: BadFieldPath<U, Capable>;
18
+ [ParentObject]: BadFieldParent<U, Capable>;
19
+ } : T & {
20
+ [ErrorMessage]: 'Value type must extend a Promise that resolves to a Capable';
21
+ [BadValue]: T;
22
+ [Path]: '';
23
+ [ParentObject]: T;
24
+ };
25
+ type ExtractCapable<T> = T extends Promise<infer U> ? U extends Capable ? U : never : never;
26
+ export type BoxedPromise<T extends Capable = Capable> = BoxBaseType<typeof type> & {
27
+ port: BoxedMessagePort<Context>;
28
+ } & {
29
+ [UnderlyingType]: T;
30
+ };
31
+ export declare const isType: (value: unknown) => value is Promise<any>;
32
+ export declare const box: <T, T2 extends RevivableContext>(value: CapablePromise<T>, context: T2) => BoxedPromise<ExtractCapable<T>>;
33
+ export declare const revive: <T extends BoxedPromise, T2 extends RevivableContext>(value: T, context: T2) => Promise<T[typeof UnderlyingType]>;
34
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { RevivableContext, BoxBase as BoxBaseType } from './utils';
2
+ import type { UnderlyingType } from '.';
3
+ import { BoxedMessagePort } from './message-port';
4
+ export declare const type: 'readableStream';
5
+ export type PullContext = {
6
+ type: 'pull' | 'cancel';
7
+ };
8
+ type ChunkMessage<T = unknown> = Promise<ReadableStreamReadResult<T>>;
9
+ type Msg = PullContext | ChunkMessage;
10
+ export type BoxedReadableStream<T extends ReadableStream = ReadableStream> = BoxBaseType<typeof type> & {
11
+ port: BoxedMessagePort<Msg>;
12
+ } & {
13
+ [UnderlyingType]: T;
14
+ };
15
+ export declare const isType: (value: unknown) => value is ReadableStream;
16
+ export declare const box: <T extends ReadableStream, T2 extends RevivableContext>(value: T, context: T2) => BoxedReadableStream<T>;
17
+ export declare const revive: <T extends BoxedReadableStream, T2 extends RevivableContext>(value: T, context: T2) => T[UnderlyingType];
18
+ export {};
@@ -0,0 +1,23 @@
1
+ import type { RevivableContext } from './utils';
2
+ export declare const type: 'request';
3
+ export declare const isType: (value: unknown) => value is Request;
4
+ export declare const box: <T extends Request, T2 extends RevivableContext>(value: T, context: T2) => {
5
+ __OSRA_BOX__: 'revivable';
6
+ type: "request";
7
+ method: string;
8
+ url: string;
9
+ headers: {
10
+ __OSRA_BOX__: 'revivable';
11
+ type: "headers";
12
+ entries: [string, string][];
13
+ };
14
+ body: import("./readable-stream").BoxedReadableStream<ReadableStream<Uint8Array<ArrayBuffer>>> | null;
15
+ credentials: RequestCredentials;
16
+ cache: RequestCache;
17
+ redirect: RequestRedirect;
18
+ referrer: string;
19
+ referrerPolicy: ReferrerPolicy;
20
+ integrity: string;
21
+ keepalive: boolean;
22
+ };
23
+ export declare const revive: <T extends ReturnType<typeof box>, T2 extends RevivableContext>(value: T, context: T2) => Request;
@@ -0,0 +1,18 @@
1
+ import type { RevivableContext } from './utils';
2
+ export declare const type: 'response';
3
+ export declare const isType: (value: unknown) => value is Response;
4
+ export declare const box: <T extends Response, T2 extends RevivableContext>(value: T, context: T2) => {
5
+ __OSRA_BOX__: 'revivable';
6
+ type: "response";
7
+ status: number;
8
+ statusText: string;
9
+ headers: {
10
+ __OSRA_BOX__: 'revivable';
11
+ type: "headers";
12
+ entries: [string, string][];
13
+ };
14
+ body: import("./readable-stream").BoxedReadableStream<ReadableStream<Uint8Array<ArrayBuffer>>> | null;
15
+ url: string;
16
+ redirected: boolean;
17
+ };
18
+ export declare const revive: <T extends ReturnType<typeof box>, T2 extends RevivableContext>(value: T, context: T2) => Response;
@@ -0,0 +1,11 @@
1
+ import type { Capable } from '../types';
2
+ import type { RevivableContext, UnderlyingType, BoxBase as BoxBaseType } from './utils';
3
+ export declare const type: 'set';
4
+ export type BoxedSet<T extends Set<Capable> = Set<Capable>> = BoxBaseType<typeof type> & {
5
+ values: Array<Capable>;
6
+ } & {
7
+ [UnderlyingType]: T;
8
+ };
9
+ export declare const isType: (value: unknown) => value is Set<unknown>;
10
+ export declare const box: <T extends Set<Capable>, T2 extends RevivableContext>(value: T, context: T2) => BoxedSet<T>;
11
+ export declare const revive: <T extends BoxedSet, T2 extends RevivableContext>(value: T, context: T2) => T[UnderlyingType];
@@ -0,0 +1,37 @@
1
+ import type { Capable } from '../types';
2
+ import type { BoxBase as BoxBaseType, RevivableContext, UnderlyingType } from './utils';
3
+ export declare const type: 'transfer';
4
+ declare const TRANSFER_MARKER: unique symbol;
5
+ type TransferWrapper<T = unknown> = {
6
+ readonly [TRANSFER_MARKER]: true;
7
+ readonly value: T;
8
+ };
9
+ export type BoxedTransfer<T extends Capable = Capable> = BoxBaseType<typeof type> & {
10
+ inner: Capable;
11
+ degraded: boolean;
12
+ [UnderlyingType]: T;
13
+ };
14
+ /**
15
+ * Opt into transfer semantics for a transferable value. Without this wrapper
16
+ * osra sends transferables as structured clones (copies) — the sender-side
17
+ * reference stays usable after the RPC. Wrapping hands the underlying storage
18
+ * off to the receiver and neuters the sender-side reference, matching what
19
+ * you'd get by listing it in the transfer list of `postMessage(msg, [buf])`.
20
+ *
21
+ * - Primitives, null, undefined, plain objects, Promises, Dates, etc. are
22
+ * returned unchanged.
23
+ * - Typed array views (`Uint8Array`, `DataView`, …) are accepted as a
24
+ * convenience — their underlying `.buffer` is what actually gets moved.
25
+ * - `transfer(transfer(x))` returns the same wrapper as `transfer(x)`.
26
+ * - If the current platform cannot transfer the given type, the wrapper
27
+ * silently degrades to a copy — nothing throws.
28
+ *
29
+ * NOTE: This lies at the type level — the runtime value for transferable
30
+ * inputs is a TransferWrapper<T>, typed as T so the user's surrounding
31
+ * code stays unchanged. The box-site unwraps it.
32
+ */
33
+ export declare const transfer: <T>(value: T) => T;
34
+ export declare const isType: (value: unknown) => value is TransferWrapper;
35
+ export declare const box: <T extends Capable, TContext extends RevivableContext>(wrapper: TransferWrapper<T>, context: TContext) => BoxedTransfer<T>;
36
+ export declare const revive: <T extends BoxedTransfer, TContext extends RevivableContext>(value: T, context: TContext) => T[UnderlyingType];
37
+ export {};
@@ -0,0 +1,15 @@
1
+ import type { RevivableContext, UnderlyingType, BoxedBuffer } from './utils';
2
+ import type { TypedArray, TypedArrayType } from '../utils/type-guards';
3
+ import { BoxBase } from './utils';
4
+ export declare const type: 'typedArray';
5
+ type BoxedTypedArray<T extends TypedArray, T2 extends RevivableContext> = typeof BoxBase & {
6
+ type: typeof type;
7
+ } & {
8
+ typedArrayType: TypedArrayType;
9
+ } & BoxedBuffer<T2> & {
10
+ [UnderlyingType]: T;
11
+ };
12
+ export declare const isType: (value: unknown) => value is TypedArray;
13
+ export declare const box: <T extends TypedArray, T2 extends RevivableContext>(value: T, context: T2) => BoxedTypedArray<T, T2>;
14
+ export declare const revive: <T extends BoxedTypedArray<TypedArray, RevivableContext>>(value: T, _context: RevivableContext) => T[UnderlyingType];
15
+ export {};
@@ -0,0 +1,59 @@
1
+ import type { DefaultRevivableModules, RevivableModule } from '.';
2
+ import type { MessageEventTarget, MessageFields, Uuid } from '../types';
3
+ import type { Transport } from '../utils/transport';
4
+ import type { IsJsonOnlyTransport } from '../utils/type-guards';
5
+ export type { UnderlyingType } from '../utils/type';
6
+ export declare const BoxBase: {
7
+ readonly __OSRA_BOX__: 'revivable';
8
+ };
9
+ export type BoxBase<T extends string = string> = typeof BoxBase & {
10
+ type: T;
11
+ };
12
+ export type RevivableContext<TModules extends readonly RevivableModule[] = DefaultRevivableModules> = {
13
+ transport: Transport;
14
+ remoteUuid: Uuid;
15
+ unregisterSignal?: AbortSignal;
16
+ /** Typed as a broad dispatcher so revivables can post their own message
17
+ * variants without triggering contravariant function-parameter mismatches
18
+ * across modules. The shape is enforced structurally via `MessageFields`. */
19
+ sendMessage: (message: MessageFields & Record<string, unknown>) => void;
20
+ revivableModules: TModules;
21
+ eventTarget: MessageEventTarget<TModules>;
22
+ };
23
+ export type ExtractType<T> = T extends {
24
+ isType: (value: unknown) => value is infer S;
25
+ } ? S : never;
26
+ export type ExtractBox<T> = T extends {
27
+ box: (...args: any[]) => infer B;
28
+ } ? B : never;
29
+ export type ExtractMessages<T> = T extends {
30
+ Messages?: infer B;
31
+ } ? B extends {
32
+ type: string;
33
+ } ? string extends B['type'] ? never : B : never : never;
34
+ export type InferMessages<TModules extends readonly unknown[]> = ExtractMessages<TModules[number]>;
35
+ export type InferRevivables<TModules extends readonly unknown[]> = ExtractType<TModules[number]>;
36
+ export type InferRevivableBox<TModules extends readonly unknown[]> = ExtractBox<TModules[number]>;
37
+ export declare const isRevivableBox: (value: unknown) => value is BoxBase;
38
+ /** Stable string form for an unknown rejection value. Errors keep their stack;
39
+ * everything else gets coerced via `String()`. Used wherever a Promise/Function
40
+ * rejection has to cross the wire as a serialisable string. */
41
+ export declare const serializeError: (error: unknown) => string;
42
+ /** Wire shape for an ArrayBuffer carried by a JSON or clone transport. JSON
43
+ * paths emit a base64 string (so the buffer survives JSON.stringify); clone
44
+ * paths pass the buffer through structured-clone unchanged. */
45
+ export type BoxedBuffer<TCtx extends RevivableContext = RevivableContext> = IsJsonOnlyTransport<TCtx['transport']> extends true ? {
46
+ base64Buffer: string;
47
+ } : IsJsonOnlyTransport<TCtx['transport']> extends false ? {
48
+ arrayBuffer: ArrayBuffer;
49
+ } : {
50
+ base64Buffer: string;
51
+ } | {
52
+ arrayBuffer: ArrayBuffer;
53
+ };
54
+ export declare const boxBuffer: <TCtx extends RevivableContext>(buffer: ArrayBuffer, context: TCtx) => BoxedBuffer<TCtx>;
55
+ export declare const reviveBuffer: (boxed: {
56
+ arrayBuffer: ArrayBuffer;
57
+ } | {
58
+ base64Buffer: string;
59
+ }) => ArrayBuffer;
@@ -0,0 +1,45 @@
1
+ import type { ConnectionMessage } from './connections';
2
+ import type { TypedEventTarget } from './utils';
3
+ import type { DefaultRevivableModules, RevivableModule, InferMessages, InferRevivables } from './revivables';
4
+ export declare const OSRA_KEY: '__OSRA_KEY__';
5
+ export declare const OSRA_DEFAULT_KEY: '__OSRA_DEFAULT_KEY__';
6
+ export declare const OSRA_BOX: '__OSRA_BOX__';
7
+ export type Uuid = `${string}-${string}-${string}-${string}-${string}`;
8
+ export type Jsonable = boolean | null | number | string | {
9
+ [key: string]: Jsonable;
10
+ } | Array<Jsonable>;
11
+ export type Structurable = Jsonable
12
+ /** not really structureable but here for convenience */
13
+ | void | undefined | bigint | Date | RegExp | Blob | File | FileList | ArrayBuffer | ArrayBufferView | ImageBitmap | ImageData | {
14
+ [key: string]: Structurable;
15
+ } | Array<Structurable> | Map<Structurable, Structurable> | Set<Structurable>;
16
+ export type StructurableTransferable = Structurable | Transferable | {
17
+ [key: string]: StructurableTransferable;
18
+ } | Array<StructurableTransferable> | Map<StructurableTransferable, StructurableTransferable> | Set<StructurableTransferable>;
19
+ export type Capable<TModules extends readonly RevivableModule[] = DefaultRevivableModules> = StructurableTransferable | InferRevivables<TModules> | {
20
+ [key: string]: Capable<TModules>;
21
+ } | Array<Capable<TModules>> | Map<Capable<TModules>, Capable<TModules>> | Set<Capable<TModules>>;
22
+ export type MessageFields = {
23
+ type: string;
24
+ remoteUuid: Uuid;
25
+ };
26
+ export type MessageBase = {
27
+ [OSRA_KEY]: string;
28
+ /** UUID of the client that sent the message */
29
+ uuid: Uuid;
30
+ name?: string;
31
+ };
32
+ export type ProtocolMessage = {
33
+ type: 'announce';
34
+ /** Only set when acknowledging a remote announcement */
35
+ remoteUuid?: Uuid;
36
+ } | {
37
+ type: 'close';
38
+ remoteUuid: Uuid;
39
+ };
40
+ export type MessageVariant<TModules extends readonly RevivableModule[] = DefaultRevivableModules> = ProtocolMessage | ConnectionMessage<TModules> | InferMessages<TModules>;
41
+ export type Message<TModules extends readonly RevivableModule[] = DefaultRevivableModules> = MessageBase & MessageVariant<TModules>;
42
+ export type MessageEventMap<TModules extends readonly RevivableModule[] = DefaultRevivableModules> = {
43
+ message: CustomEvent<Message<TModules>>;
44
+ };
45
+ export type MessageEventTarget<TModules extends readonly RevivableModule[] = DefaultRevivableModules> = TypedEventTarget<MessageEventMap<TModules>>;
@@ -0,0 +1,44 @@
1
+ export declare const ErrorMessage: unique symbol;
2
+ export declare const BadValue: unique symbol;
3
+ export declare const Path: unique symbol;
4
+ export declare const ParentObject: unique symbol;
5
+ type IsPlainObject<T> = T extends object ? T extends readonly unknown[] ? false : T extends (...args: any[]) => any ? false : T extends Date | RegExp | Blob | File | FileList | ArrayBuffer | ArrayBufferView | ImageBitmap | ImageData | Map<any, any> | Set<any> | Promise<any> ? false : true : false;
6
+ type FindBadField<T, TConstraint, TPath extends string = '', TParent = T> = T extends TConstraint ? never : T extends readonly unknown[] ? {
7
+ [K in Extract<keyof T, `${number}`>]: T[K] extends TConstraint ? never : FindBadField<T[K], TConstraint, `${TPath}[${K}]`, T>;
8
+ }[Extract<keyof T, `${number}`>] extends infer R ? [R] extends [never] ? {
9
+ value: T;
10
+ path: TPath;
11
+ parent: TParent;
12
+ } : R : never : IsPlainObject<T> extends true ? {
13
+ [K in Extract<keyof T, string>]: T[K] extends TConstraint ? never : FindBadField<T[K], TConstraint, TPath extends '' ? K : `${TPath}.${K}`, T>;
14
+ }[Extract<keyof T, string>] extends infer R ? [R] extends [never] ? {
15
+ value: T;
16
+ path: TPath;
17
+ parent: TParent;
18
+ } : R : never : {
19
+ value: T;
20
+ path: TPath;
21
+ parent: TParent;
22
+ };
23
+ /**
24
+ * The first non-conforming value found by deep traversal of `T` against
25
+ * `TConstraint`. Falls back to `T` if no traversal is applicable.
26
+ */
27
+ export type BadFieldValue<T, TConstraint> = FindBadField<T, TConstraint> extends {
28
+ value: infer V;
29
+ } ? V : T;
30
+ /**
31
+ * Dotted/bracketed path to the first non-conforming value (e.g. `"a.b[2]"`).
32
+ * Empty string if the root itself fails the check.
33
+ */
34
+ export type BadFieldPath<T, TConstraint> = FindBadField<T, TConstraint> extends {
35
+ path: infer P extends string;
36
+ } ? P : '';
37
+ /**
38
+ * The immediate parent object/array containing the first non-conforming
39
+ * value. Equals `T` when the root itself fails.
40
+ */
41
+ export type BadFieldParent<T, TConstraint> = FindBadField<T, TConstraint> extends {
42
+ parent: infer P;
43
+ } ? P : T;
44
+ export {};