@derivation/rpc 0.1.6 → 0.1.8
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/dist/client-handler.d.ts +12 -11
- package/dist/client-handler.js +19 -13
- package/dist/client.d.ts +4 -3
- package/dist/client.js +8 -8
- package/dist/index.d.ts +7 -7
- package/dist/index.js +6 -6
- package/dist/iso.d.ts +1 -1
- package/dist/iso.js +1 -1
- package/dist/messageport-transport.d.ts +13 -0
- package/dist/messageport-transport.js +28 -0
- package/dist/node-web-socket-transport.d.ts +16 -0
- package/dist/node-web-socket-transport.js +33 -0
- package/dist/queue.d.ts +9 -0
- package/dist/queue.js +32 -0
- package/dist/rate-limiter.d.ts +1 -1
- package/dist/rate-limiter.js +13 -8
- package/dist/reactive-map-adapter.d.ts +4 -3
- package/dist/reactive-map-adapter.js +3 -2
- package/dist/reactive-set-adapter.d.ts +4 -3
- package/dist/reactive-set-adapter.js +3 -2
- package/dist/shared-worker-client-handler.d.ts +27 -0
- package/dist/shared-worker-client-handler.js +149 -0
- package/dist/shared-worker-client.d.ts +22 -0
- package/dist/shared-worker-client.js +25 -0
- package/dist/shared-worker-server.d.ts +28 -0
- package/dist/shared-worker-server.js +62 -0
- package/dist/stream-adapter.d.ts +2 -2
- package/dist/stream-adapter.js +2 -1
- package/dist/stream-types.d.ts +4 -4
- package/dist/transport.d.ts +27 -0
- package/dist/transport.js +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/web-socket-server.d.ts +11 -0
- package/dist/web-socket-server.js +59 -0
- package/dist/web-socket-transport.d.ts +13 -0
- package/dist/web-socket-transport.js +25 -0
- package/dist/websocket-server.d.ts +8 -2
- package/dist/websocket-server.js +29 -5
- package/dist/websocket-transport.d.ts +28 -0
- package/dist/websocket-transport.js +58 -0
- package/package.json +23 -2
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Graph } from "derivation";
|
|
2
|
+
import { Client } from "./client.js";
|
|
3
|
+
import { StreamSinks, RPCDefinition } from "./stream-types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Create a client connected to a SharedWorker.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // main.ts
|
|
10
|
+
* const graph = new Graph();
|
|
11
|
+
* const worker = new SharedWorker('/worker.js');
|
|
12
|
+
*
|
|
13
|
+
* const client = createSharedWorkerClient(worker.port, {
|
|
14
|
+
* streams: {
|
|
15
|
+
* todos: setSink(graph, todoIso),
|
|
16
|
+
* },
|
|
17
|
+
* }, graph);
|
|
18
|
+
*
|
|
19
|
+
* const todos = await client.run('todos', { filter: 'active' });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function createSharedWorkerClient<Defs extends RPCDefinition>(port: MessagePort, sinks: StreamSinks<Defs["streams"]>, graph: Graph): Client<Defs>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Client } from "./client.js";
|
|
2
|
+
import { MessagePortTransport } from "./messageport-transport.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a client connected to a SharedWorker.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* // main.ts
|
|
9
|
+
* const graph = new Graph();
|
|
10
|
+
* const worker = new SharedWorker('/worker.js');
|
|
11
|
+
*
|
|
12
|
+
* const client = createSharedWorkerClient(worker.port, {
|
|
13
|
+
* streams: {
|
|
14
|
+
* todos: setSink(graph, todoIso),
|
|
15
|
+
* },
|
|
16
|
+
* }, graph);
|
|
17
|
+
*
|
|
18
|
+
* const todos = await client.run('todos', { filter: 'active' });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function createSharedWorkerClient(port, sinks, graph) {
|
|
22
|
+
const transport = new MessagePortTransport(port);
|
|
23
|
+
port.start();
|
|
24
|
+
return new Client(transport, sinks, graph);
|
|
25
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Graph } from "derivation";
|
|
2
|
+
import { StreamEndpoints, MutationEndpoints, RPCDefinition } from "./stream-types.js";
|
|
3
|
+
import { PresenceHandler } from "./presence-manager.js";
|
|
4
|
+
export type SharedWorkerServerOptions<Defs extends RPCDefinition, Ctx = void> = {
|
|
5
|
+
streams: StreamEndpoints<Defs["streams"], Ctx>;
|
|
6
|
+
mutations: MutationEndpoints<Defs["mutations"], Ctx>;
|
|
7
|
+
createContext: (port: MessagePort) => Ctx | Promise<Ctx>;
|
|
8
|
+
presenceHandler?: PresenceHandler;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Set up a SharedWorker server for RPC communication.
|
|
12
|
+
* This creates a shared Graph that all connected tabs can interact with.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* // worker.ts
|
|
17
|
+
* const { graph } = setupSharedWorker({
|
|
18
|
+
* streams: {
|
|
19
|
+
* todos: async (args, ctx) => new ReactiveSetSourceAdapter(source),
|
|
20
|
+
* },
|
|
21
|
+
* mutations: {
|
|
22
|
+
* addTodo: async (args, ctx) => ({ success: true, value: newTodo }),
|
|
23
|
+
* },
|
|
24
|
+
* createContext: (port) => ({ portId: crypto.randomUUID() }),
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function setupSharedWorker<Defs extends RPCDefinition, Ctx = void>(options: SharedWorkerServerOptions<Defs, Ctx>, graph: Graph): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { SharedWorkerClientHandler } from "./shared-worker-client-handler.js";
|
|
2
|
+
import WeakList from "./weak-list.js";
|
|
3
|
+
import { MessagePortTransport } from "./messageport-transport.js";
|
|
4
|
+
/**
|
|
5
|
+
* Set up a SharedWorker server for RPC communication.
|
|
6
|
+
* This creates a shared Graph that all connected tabs can interact with.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // worker.ts
|
|
11
|
+
* const { graph } = setupSharedWorker({
|
|
12
|
+
* streams: {
|
|
13
|
+
* todos: async (args, ctx) => new ReactiveSetSourceAdapter(source),
|
|
14
|
+
* },
|
|
15
|
+
* mutations: {
|
|
16
|
+
* addTodo: async (args, ctx) => ({ success: true, value: newTodo }),
|
|
17
|
+
* },
|
|
18
|
+
* createContext: (port) => ({ portId: crypto.randomUUID() }),
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function setupSharedWorker(options, graph) {
|
|
23
|
+
const { streams, mutations, createContext, presenceHandler } = options;
|
|
24
|
+
const clients = new WeakList();
|
|
25
|
+
// After each graph step, broadcast deltas to all connected clients
|
|
26
|
+
graph.afterStep(() => {
|
|
27
|
+
for (const client of clients) {
|
|
28
|
+
client.handleStep();
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
// Handle SharedWorker connections
|
|
32
|
+
const globalScope = self;
|
|
33
|
+
globalScope.onconnect = (event) => {
|
|
34
|
+
const port = event.ports[0];
|
|
35
|
+
const messageBuffer = [];
|
|
36
|
+
let client = null;
|
|
37
|
+
// Set up temporary message handler to buffer messages
|
|
38
|
+
const tempMessageHandler = (e) => {
|
|
39
|
+
messageBuffer.push(e.data);
|
|
40
|
+
};
|
|
41
|
+
port.onmessage = tempMessageHandler;
|
|
42
|
+
// Create context (handle both sync and async)
|
|
43
|
+
Promise.resolve(createContext(port))
|
|
44
|
+
.then((context) => {
|
|
45
|
+
// Create transport and client handler
|
|
46
|
+
const transport = new MessagePortTransport(port);
|
|
47
|
+
client = new SharedWorkerClientHandler(transport, context, streams, mutations, presenceHandler);
|
|
48
|
+
clients.add(client);
|
|
49
|
+
// Process buffered messages
|
|
50
|
+
for (const msg of messageBuffer) {
|
|
51
|
+
client.handleMessage(msg);
|
|
52
|
+
}
|
|
53
|
+
messageBuffer.length = 0;
|
|
54
|
+
// Start the port
|
|
55
|
+
port.start();
|
|
56
|
+
})
|
|
57
|
+
.catch((err) => {
|
|
58
|
+
console.error("Error creating context:", err);
|
|
59
|
+
port.close();
|
|
60
|
+
});
|
|
61
|
+
};
|
|
62
|
+
}
|
package/dist/stream-adapter.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Graph, ReactiveValue, Input } from "derivation";
|
|
2
|
-
import { Source, Sink } from "./stream-types";
|
|
3
|
-
import { Iso } from "./iso";
|
|
2
|
+
import { Source, Sink } from "./stream-types.js";
|
|
3
|
+
import { Iso } from "./iso.js";
|
|
4
4
|
export declare class StreamSourceAdapter<T extends object> implements Source<ReactiveValue<T>> {
|
|
5
5
|
private readonly stream;
|
|
6
6
|
private readonly iso;
|
package/dist/stream-adapter.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { inputValue } from "derivation";
|
|
1
2
|
export class StreamSourceAdapter {
|
|
2
3
|
constructor(stream, iso) {
|
|
3
4
|
this.stream = stream;
|
|
@@ -23,7 +24,7 @@ export class StreamSinkAdapter {
|
|
|
23
24
|
input.push(this.iso.from(change));
|
|
24
25
|
}
|
|
25
26
|
build() {
|
|
26
|
-
const stream = this.graph
|
|
27
|
+
const stream = inputValue(this.graph, this.initialValue);
|
|
27
28
|
return { stream, input: stream };
|
|
28
29
|
}
|
|
29
30
|
}
|
package/dist/stream-types.d.ts
CHANGED
|
@@ -17,8 +17,8 @@ export type StreamDefinition<Args extends object, ReturnType extends object, Sin
|
|
|
17
17
|
inputType: InputType;
|
|
18
18
|
};
|
|
19
19
|
export type StreamDefinitions = Record<string, StreamDefinition<object, object, object, object>>;
|
|
20
|
-
export type StreamEndpoints<Definitions extends StreamDefinitions> = {
|
|
21
|
-
[K in keyof Definitions]: (args: Definitions[K]["args"]) => Source<Definitions[K]["returnType"]
|
|
20
|
+
export type StreamEndpoints<Definitions extends StreamDefinitions, Ctx = void> = {
|
|
21
|
+
[K in keyof Definitions]: (args: Definitions[K]["args"], ctx: Ctx) => Promise<Source<Definitions[K]["returnType"]>>;
|
|
22
22
|
};
|
|
23
23
|
export type StreamSinks<Definitions extends StreamDefinitions> = {
|
|
24
24
|
[K in keyof Definitions]: (snapshot: object) => Sink<Definitions[K]["sinkType"], Definitions[K]["inputType"]>;
|
|
@@ -35,8 +35,8 @@ export type MutationDefinition<Args, Result> = {
|
|
|
35
35
|
result: Result;
|
|
36
36
|
};
|
|
37
37
|
export type MutationDefinitions = Record<string, MutationDefinition<unknown, unknown>>;
|
|
38
|
-
export type MutationEndpoints<Definitions extends MutationDefinitions> = {
|
|
39
|
-
[K in keyof Definitions]: (args: Definitions[K]["args"]) => Promise<MutationResult<Definitions[K]["result"]>>;
|
|
38
|
+
export type MutationEndpoints<Definitions extends MutationDefinitions, Ctx = void> = {
|
|
39
|
+
[K in keyof Definitions]: (args: Definitions[K]["args"], ctx: Ctx) => Promise<MutationResult<Definitions[K]["result"]>>;
|
|
40
40
|
};
|
|
41
41
|
export type RPCDefinition = {
|
|
42
42
|
streams: StreamDefinitions;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport abstraction for RPC communication.
|
|
3
|
+
* Allows the same RPC system to work over WebSocket or MessagePort.
|
|
4
|
+
*/
|
|
5
|
+
export interface Transport {
|
|
6
|
+
/**
|
|
7
|
+
* Send a string message through the transport.
|
|
8
|
+
*/
|
|
9
|
+
send(data: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Register a handler for incoming messages.
|
|
12
|
+
*/
|
|
13
|
+
onMessage(handler: (data: string) => void): void;
|
|
14
|
+
/**
|
|
15
|
+
* Register a handler for transport closure/disconnection.
|
|
16
|
+
*/
|
|
17
|
+
onClose(handler: () => void): void;
|
|
18
|
+
/**
|
|
19
|
+
* Close the transport connection.
|
|
20
|
+
*/
|
|
21
|
+
close(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Number of bytes buffered to be sent (optional, used for flow control).
|
|
24
|
+
* MessagePort doesn't provide this, so it's optional.
|
|
25
|
+
*/
|
|
26
|
+
readonly bufferedAmount?: number;
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|