awesomerpc 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/LICENSE.txt ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2026 Sam Vervaeck
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
package/README.md CHANGED
@@ -10,6 +10,7 @@ First, you need to define a _contract_ for your API. A contract is kind of like
10
10
  a TypeScript interface: it defines what methods (and events) are allowed.
11
11
 
12
12
  ```ts
13
+ import t from "reflect-types";
13
14
  import { contract } from "awesomerpc";
14
15
 
15
16
  // A client API that connects to the server in the browser via web sockets
@@ -30,7 +31,7 @@ Next, you need to implement this contract, like so:
30
31
  ```ts
31
32
  import { implement } from "awesomerpc";
32
33
 
33
- const petStoreClientImpl = implement(petStoreClient)
34
+ const petStoreClientImpl = implement(petStoreClientContract, petStoreServerContract)
34
35
  .method('refresh', (_ctx) => {
35
36
  window.location.reload();
36
37
  })
@@ -57,3 +58,70 @@ console.log(`Available products: ${await rpc.callMethod('getProducts', [])}`);
57
58
 
58
59
  For more information, read the full example in the `example/` directory.
59
60
 
61
+ ## API
62
+
63
+ ### Transports
64
+
65
+ #### `new WebSocketTransport(url)`
66
+
67
+ Create a new transport that uses WebSocket to send and receive messages.
68
+
69
+ ### `Transport.open()`
70
+
71
+ Connect to whatever was specified as the destination address during the
72
+ construction of the transport.
73
+
74
+ This method returns a promise object that may be awaited in order to ensure the
75
+ connection is ready for use.
76
+
77
+ ### Top-level Functions
78
+
79
+ #### `connect(impl, state, logger?)`
80
+
81
+ ```ts
82
+ import pino from "pino";
83
+
84
+ import { connect } from "awesomerpc";
85
+
86
+ connect(petStoreClientImpl, {});
87
+ ```
88
+
89
+ ## FAQ
90
+
91
+ ### How do I enable logging?
92
+
93
+ To enable logging, you need to create and object that satisfies the `Logger`
94
+ interface. [Pino][pino] is one such logger that is compatible with this
95
+ interface. You can install it using:
96
+
97
+ ```sh
98
+ $ npm install pino
99
+ ```
100
+
101
+ Next, you need to define the logger object. In this example, the log level is
102
+ read from the environment variable `MYAPP_LOG_LEVEL` and defaults to `info`.
103
+
104
+ **src/logging.ts**
105
+ ```ts
106
+ import pino from "pino";
107
+
108
+ export const logger = pino({
109
+ level: process.env.MYAPP_LOG_LEVEL || 'info',
110
+ });
111
+ ```
112
+
113
+ Pass this object in while creating a connection, like so:
114
+
115
+ ```ts
116
+ import { connect } from "awesomerpc";
117
+
118
+ import { logger } from "./logging";
119
+
120
+ connect(petStoreClientImpl, {}, logger);
121
+ ```
122
+
123
+ If no logger is specified, AwesomeRPC will simply not log anything.
124
+
125
+ ## License
126
+
127
+ This project is licensed under the MIT license. See `LICENSE.txt` for more information.
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { type Transport, WebSocketTransport, DummyTransport, RawTransport, createDuplex, } from "./transport.js";
2
- export { implement, contract } from "./types.js";
3
- export { RPC, type AnyMethods, type AnyEvents } from "./rpc.js";
1
+ export { type Transport, WebSocketTransport, DummyTransport, RawTransport, createDuplex, TransportError } from "./transport.js";
2
+ export { implement, contract, emptyContract, anyContract } from "./types.js";
3
+ export { RPC, type AnyMethods, type AnyEvents, connect } from "./rpc.js";
4
4
  export { createProxy } from "./proxy.js";
5
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,GAAI,MAAM,gBAAgB,CAAA;AACjH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,GAAG,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAE,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/H,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAAE,GAAG,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
- export { WebSocketTransport, DummyTransport, RawTransport, createDuplex, } from "./transport.js";
2
- export { implement, contract } from "./types.js";
3
- export { RPC } from "./rpc.js";
1
+ export { WebSocketTransport, DummyTransport, RawTransport, createDuplex, TransportError } from "./transport.js";
2
+ export { implement, contract, emptyContract, anyContract } from "./types.js";
3
+ export { RPC, connect } from "./rpc.js";
4
4
  export { createProxy } from "./proxy.js";
5
5
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,GAAI,MAAM,gBAAgB,CAAA;AACjH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,GAAG,EAAmC,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,kBAAkB,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC/H,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC5E,OAAO,EAAE,GAAG,EAAmC,OAAO,EAAE,MAAM,UAAU,CAAA;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA"}
@@ -1,10 +1,10 @@
1
1
  import { test, expect } from "bun:test";
2
- import { types as t } from "reflect-types";
2
+ import t from "reflect-types";
3
3
  import { contract, implement } from "./types.js";
4
4
  import { createDuplex } from "./transport.js";
5
5
  import { connect } from "./rpc.js";
6
6
  import { FailedValidationError } from "./error.js";
7
- const local = contract({
7
+ const leftContract = contract({
8
8
  methods: {
9
9
  getState: t.callable([], t.number()),
10
10
  setState: t.callable([t.number()], t.undefined()),
@@ -14,46 +14,49 @@ const local = contract({
14
14
  someevent: t.string(),
15
15
  }
16
16
  });
17
- const remote = contract({
17
+ const rightContract = contract({
18
18
  methods: {
19
19
  getState: t.callable([], t.number()),
20
20
  setState: t.callable([t.number()], t.undefined()),
21
21
  getLength: t.callable([t.string()], t.number()),
22
22
  }
23
23
  });
24
- const leftImpl = implement(local)
24
+ const leftImpl = implement(leftContract, rightContract)
25
25
  .state()
26
+ // .methods(stateHandlers())
26
27
  .methods({
27
- getState(ctx) {
28
- return ctx.foo;
28
+ getState({ state: { foo } }) {
29
+ return foo;
29
30
  },
30
- setState(ctx, state) {
31
- ctx.foo = state;
31
+ setState({ state, args: [newFoo] }) {
32
+ state.foo = newFoo;
32
33
  },
34
+ })
35
+ .methods({
33
36
  // @ts-expect-error Wrong function return type on purpose
34
37
  returnInvalid() {
35
38
  return "a string";
36
39
  }
37
40
  })
38
41
  .finish();
39
- const rightImpl = implement(remote)
42
+ const rightImpl = implement(rightContract, leftContract)
40
43
  .state()
41
44
  .methods({
42
- getState(ctx) {
43
- return ctx.foo;
45
+ getState({ state }) {
46
+ return state.foo;
44
47
  },
45
- setState(ctx, state) {
46
- ctx.foo = state;
48
+ setState({ state, args: [newState] }) {
49
+ state.foo = newState;
47
50
  },
48
- getLength(_ctx, s) {
51
+ getLength({ args: [s] }) {
49
52
  return s.length;
50
53
  }
51
54
  })
52
55
  .finish();
53
56
  test('can call methods on both sides', async () => {
54
57
  const [leftTransport, rightTransport] = createDuplex();
55
- const left = connect(leftImpl, remote, leftTransport, { foo: 42 });
56
- const right = connect(rightImpl, local, rightTransport, { foo: 33 });
58
+ const left = connect(leftImpl, leftTransport, { foo: 42 });
59
+ const right = connect(rightImpl, rightTransport, { foo: 33 });
57
60
  expect(await left.callMethod('getLength', ["foobar"])).toStrictEqual(6);
58
61
  expect(await left.callMethod('getState', [])).toStrictEqual(33);
59
62
  expect(await right.callMethod('getState', [])).toStrictEqual(42);
@@ -62,8 +65,8 @@ test('can call methods on both sides', async () => {
62
65
  });
63
66
  test('throws an error on invalid param count', async () => {
64
67
  const [leftTransport, rightTransport] = createDuplex();
65
- const left = connect(leftImpl, remote, leftTransport, { foo: 42 });
66
- const right = connect(rightImpl, local, rightTransport, { foo: 33 });
68
+ const left = connect(leftImpl, leftTransport, { foo: 42 });
69
+ const right = connect(rightImpl, rightTransport, { foo: 33 });
67
70
  expect(left.callMethod('getLength',
68
71
  // @ts-expect-error Deliberatly added a param
69
72
  ["foo", "bar"])).rejects.toBeInstanceOf(Error); // TODO be more specific
@@ -73,14 +76,14 @@ test('throws an error on invalid param count', async () => {
73
76
  });
74
77
  test('throws an error on invalid return', async () => {
75
78
  const [leftTransport, rightTransport] = createDuplex();
76
- const left = connect(leftImpl, remote, leftTransport, { foo: 42 });
77
- const right = connect(rightImpl, local, rightTransport, { foo: 33 });
79
+ const left = connect(leftImpl, leftTransport, { foo: 42 });
80
+ const right = connect(rightImpl, rightTransport, { foo: 33 });
78
81
  expect(right.callMethod('returnInvalid', [])).rejects.toBeInstanceOf(FailedValidationError);
79
82
  });
80
83
  test('can send events', done => {
81
84
  const [leftTransport, rightTransport] = createDuplex();
82
- const left = connect(leftImpl, remote, leftTransport, { foo: 42 });
83
- const right = connect(rightImpl, local, rightTransport, { foo: 33 });
85
+ const left = connect(leftImpl, leftTransport, { foo: 42 });
86
+ const right = connect(rightImpl, rightTransport, { foo: 33 });
84
87
  left.getEvent('someevent').subscribe(msg => {
85
88
  expect(msg).toStrictEqual('foo');
86
89
  done();
@@ -1 +1 @@
1
- {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../src/integration.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACvC,OAAO,EAAE,KAAK,IAAI,CAAC,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAA;AAClC,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD,MAAM,KAAK,GAAG,QAAQ,CAAC;IACrB,OAAO,EAAE;QACP,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7C,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAE,CAAC,CAAC,MAAM,EAAE,CAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;QAC5D,aAAa,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;KACnD;IACD,MAAM,EAAE;QACN,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;KACtB;CACF,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,QAAQ,CAAC;IACtB,OAAO,EAAE;QACP,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;QAC7C,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAE,CAAC,CAAC,MAAM,EAAE,CAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;QAC5D,SAAS,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAE,CAAC,CAAC,MAAM,EAAE,CAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;KAC3D;CACF,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC;KAC9B,KAAK,EAAmB;KACxB,OAAO,CAAC;IACP,QAAQ,CAAC,GAAG;QACV,OAAO,GAAG,CAAC,GAAG,CAAC;IACjB,CAAC;IACD,QAAQ,CAAC,GAAG,EAAE,KAAK;QACjB,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC;IAClB,CAAC;IACD,yDAAyD;IACzD,aAAa;QACX,OAAO,UAAU,CAAC;IACpB,CAAC;CACF,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC;KAChC,KAAK,EAAmB;KACxB,OAAO,CAAC;IACP,QAAQ,CAAC,GAAG;QACV,OAAO,GAAG,CAAC,GAAG,CAAC;IACjB,CAAC;IACD,QAAQ,CAAC,GAAG,EAAE,KAAK;QACjB,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC;IAClB,CAAC;IACD,SAAS,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,CAAC,CAAC,MAAM,CAAC;IAClB,CAAC;CACF,CAAC;KACD,MAAM,EAAE,CAAC;AAGZ,IAAI,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;IAEhD,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,GAAG,YAAY,EAAE,CAAC;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACxE,MAAM,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAChE,MAAM,CAAC,MAAM,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAEjE,IAAI,CAAC,KAAK,EAAE,CAAC;IACb,KAAK,CAAC,KAAK,EAAE,CAAC;AAEhB,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;IACxD,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,GAAG,YAAY,EAAE,CAAC;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW;IAChC,6CAA6C;IAC7C,CAAE,KAAK,EAAE,KAAK,CAAE,CACjB,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,wBAAwB;IAC1D,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW;IAChC,+CAA+C;IAC/C,EAAG,CACJ,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,wBAAwB;AAC5D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;IACnD,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,GAAG,YAAY,EAAE,CAAC;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IAErE,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC;AAC9F,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,EAAE;IAC7B,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,GAAG,YAAY,EAAE,CAAC;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;IAErE,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE;QACzC,MAAM,CAAC,GAAG,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,EAAE,CAAC;IACT,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;AAEnC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../src/integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { JSONObject } from "./util.js";
2
+ type LogFn = (obj: JSONObject) => void;
3
+ /**
4
+ * Generic logging interface that is compatible with Pino.
5
+ */
6
+ export interface Logger {
7
+ fatal: LogFn;
8
+ error: LogFn;
9
+ warn: LogFn;
10
+ info: LogFn;
11
+ debug: LogFn;
12
+ trace: LogFn;
13
+ silent: LogFn;
14
+ }
15
+ export {};
16
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,KAAK,KAAK,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,KAAK,CAAC;IACZ,IAAI,EAAE,KAAK,CAAC;IACZ,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,KAAK,CAAC;CACf"}
package/lib/logger.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":""}
package/lib/proxy.d.ts CHANGED
@@ -1,13 +1,4 @@
1
- import type { Subject } from "rxjs";
2
1
  import type { RPC } from "./rpc.js";
3
- import type { Impl, Spec, MethodSpec, EventSpec } from "./types.js";
4
- import type { CallableType } from "reflect-types";
5
- type Promisify<T extends CallableType> = (...args: T['paramTypes']) => Promise<Awaited<T['returnType']>>;
6
- type Obj<M extends Record<string, MethodSpec>, E extends Record<string, EventSpec>> = {
7
- [K in keyof M]: Promisify<M[K]>;
8
- } & {
9
- [K in keyof E]: Subject<E[K]['ty']>;
10
- };
11
- export declare function createProxy<L extends Impl, R extends Spec>(rpc: RPC<L, R>): Obj<R["methods"], L["spec"]["events"]>;
12
- export {};
2
+ import type { ClientObj, Contract } from "./types.js";
3
+ export declare function createProxy<L extends Contract, R extends Contract, S extends object>(rpc: RPC<L, R, S>): ClientObj<L, R>;
13
4
  //# sourceMappingURL=proxy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,KAAK,SAAS,CAAC,CAAC,SAAS,YAAY,IACjC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,YAAY,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAEpE,KAAK,GAAG,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,IAC9E;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,GACnC;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;CAAE,CAAC;AAE5C,wBAAgB,WAAW,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,SAAS,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,0CAczE"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtD,wBAAgB,WAAW,CAAC,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,QAAQ,EAAE,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,mBAetG"}
package/lib/proxy.js CHANGED
@@ -1,11 +1,12 @@
1
1
  export function createProxy(rpc) {
2
- return new Proxy({}, {
2
+ // FIXME This `any` cast is a hack
3
+ return new Proxy(rpc, {
3
4
  get(target, p, receiver) {
4
5
  if (typeof (p) === 'string') {
5
- if (rpc.remote.hasMethod(p)) {
6
+ if (rpc.impl.remote.hasMethod(p)) {
6
7
  return (...args) => rpc.callMethod(p, args);
7
8
  }
8
- if (rpc.local.spec.hasEvent(p)) {
9
+ if (rpc.impl.local.hasEvent(p)) {
9
10
  return rpc.getEvent(p);
10
11
  }
11
12
  }
package/lib/proxy.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAaA,MAAM,UAAU,WAAW,CAAiC,GAAc;IACxE,OAAO,IAAI,KAAK,CAAyC,EAAS,EAAE;QAClE,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ;YACrB,IAAI,OAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC3B,IAAI,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC5B,OAAO,CAAC,GAAG,IAAW,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,IAAW,CAAC,CAAC;gBAC5D,CAAC;gBACD,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/B,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;YACD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,WAAW,CAA2D,GAAiB;IACrG,kCAAkC;IAClC,OAAO,IAAI,KAAK,CAAkB,GAAU,EAAE;QAC5C,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ;YACrB,IAAI,OAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;gBAC3B,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;oBACjC,OAAO,CAAC,GAAG,IAAW,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,IAAW,CAAC,CAAC;gBAC5D,CAAC;gBACD,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC/B,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACzB,CAAC;YACH,CAAC;YACD,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
package/lib/rpc.d.ts CHANGED
@@ -2,7 +2,8 @@ import { BehaviorSubject, Subject } from "rxjs";
2
2
  import { type Infer } from "reflect-types";
3
3
  import { type JSONValue } from "./util.js";
4
4
  import type { Transport } from "./transport.js";
5
- import type { Impl, Spec, InferTuple } from "./types.js";
5
+ import type { Contract, Impl, InferTuple } from "./types.js";
6
+ import type { Logger } from "./logger.js";
6
7
  export declare class Resource<T> {
7
8
  value: T;
8
9
  close: () => void;
@@ -14,11 +15,11 @@ export type MethodFn = (...args: any[]) => any;
14
15
  export type AnyEvents = Record<string, Subject<any>>;
15
16
  export type AnyMethods = Record<string, MethodFn>;
16
17
  export type RPCValue = JSONValue | AsyncIterable<any, any, any> | Resource<Subject<any>> | Resource<BehaviorSubject<any>>;
17
- export declare class RPC<L extends Impl, R extends Spec> {
18
+ export declare class RPC<L extends Contract, R extends Contract, S extends object> {
18
19
  private transport;
19
- local: L;
20
- remote: R;
20
+ impl: Impl<L, R, S>;
21
21
  private state;
22
+ private logger?;
22
23
  private nextMessageId;
23
24
  private nextStreamId;
24
25
  private nextSubjectId;
@@ -28,8 +29,9 @@ export declare class RPC<L extends Impl, R extends Spec> {
28
29
  private asyncGenerators;
29
30
  private events;
30
31
  private readerSubscription;
31
- constructor(transport: Transport, local: L, remote: R, state: L['state']);
32
- getEvent<K extends keyof L['spec']['events'] & string>(name: K): Subject<Infer<L['spec']['events'][K]['ty']>>;
32
+ private client;
33
+ constructor(transport: Transport, impl: Impl<L, R, S>, state: S, logger?: Logger | undefined);
34
+ getEvent<K extends keyof L['events'] & string>(name: K): Subject<Infer<L['events'][K]['ty']>>;
33
35
  getEvent(name: string): undefined;
34
36
  notify<K extends keyof R['events']>(eventName: K, value: Infer<R['events'][K]['ty']>): Promise<void>;
35
37
  hasMethod(name: string): boolean;
@@ -39,5 +41,5 @@ export declare class RPC<L extends Impl, R extends Spec> {
39
41
  private processMessage;
40
42
  close(): void;
41
43
  }
42
- export declare function connect<L extends Impl, R extends Spec>(local: L, remote: R, transport: Transport, state?: L['state']): RPC<L, R>;
44
+ export declare function connect<L extends Contract, R extends Contract, S extends object>(impl: Impl<L, R, S>, transport: Transport, state: S, logger?: Logger): RPC<L, R, S>;
43
45
  //# sourceMappingURL=rpc.d.ts.map
package/lib/rpc.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rpc.d.ts","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"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"}
package/lib/rpc.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { BehaviorSubject, Subject, Subscription } from "rxjs";
2
2
  import {} from "reflect-types";
3
- import { isPlainObject, Deferred } from "./util.js";
3
+ import { isPlainObject, Deferred, isPrimitive } from "./util.js";
4
4
  import { decodeEvent, decodeObservableComplete, decodeObservableEvent, decodeRequest, decodeRespondError, decodeRespondOk, decodeStreamElement, decodeStreamFinish, MSGID_EVENT, MSGID_OBSERVABLE_CLOSE, MSGID_OBSERVABLE_COMPLETE, MSGID_OBSERVABLE_ERROR, MSGID_OBSERVABLE_EVENT, MSGID_REQUEST, MSGID_RESPOND_ERROR, MSGID_RESPOND_OK, MSGID_STREAM_ELEMENT, MSGID_STREAM_FINISH, TYPE_ARRAY, TYPE_ASYNC_GENERATOR, TYPE_BEHAVIORSUBJECT, TYPE_OBJECT, TYPE_PRIMITIVE, TYPE_SUBJECT, TYPE_UNDEFINED, } from "./protocol.js";
5
5
  import { EventNotFoundError, MethodNotFoundError, ProtocolError, RemoteError, RPCError, FailedValidationError } from "./error.js";
6
- import { which } from "bun";
6
+ import { createProxy } from "./proxy.js";
7
7
  export class Resource {
8
8
  value;
9
9
  close;
@@ -15,17 +15,11 @@ export class Resource {
15
15
  export function isResource(value) {
16
16
  return value instanceof Resource;
17
17
  }
18
- function isPrimitive(value) {
19
- return value == null
20
- || typeof (value) === 'boolean'
21
- || typeof (value) === 'number'
22
- || typeof (value) === 'string';
23
- }
24
18
  export class RPC {
25
19
  transport;
26
- local;
27
- remote;
20
+ impl;
28
21
  state;
22
+ logger;
29
23
  // For sending data
30
24
  nextMessageId = 0;
31
25
  nextStreamId = 0;
@@ -38,11 +32,12 @@ export class RPC {
38
32
  events = Object.create(null);
39
33
  // Internal resources
40
34
  readerSubscription;
41
- constructor(transport, local, remote, state) {
35
+ client = createProxy(this);
36
+ constructor(transport, impl, state, logger) {
42
37
  this.transport = transport;
43
- this.local = local;
44
- this.remote = remote;
38
+ this.impl = impl;
45
39
  this.state = state;
40
+ this.logger = logger;
46
41
  // Process incoming messages
47
42
  this.readerSubscription = transport.input.subscribe(data => {
48
43
  try {
@@ -59,7 +54,7 @@ export class RPC {
59
54
  });
60
55
  }
61
56
  getEvent(name) {
62
- if (!this.local.spec.hasEvent(name)) {
57
+ if (!this.impl.local.hasEvent(name)) {
63
58
  return;
64
59
  }
65
60
  if (this.events[name] === undefined) {
@@ -71,11 +66,11 @@ export class RPC {
71
66
  await this.transport.write(JSON.stringify([MSGID_EVENT, eventName, this.encode(value)]));
72
67
  }
73
68
  hasMethod(name) {
74
- return this.local.spec.hasMethod(name);
69
+ return this.impl.local.hasMethod(name);
75
70
  }
76
71
  async callMethod(name, args) {
77
72
  const id = this.nextMessageId++;
78
- console.log(`send REQUEST ${id}`);
73
+ this.logger?.trace({ rpc: { direction: 'send', msgId: 'REQUEST', id, methodName: name } });
79
74
  const deferred = new Deferred();
80
75
  this.pending.set(id, { name, deferred });
81
76
  const encodedArgs = args.map(this.encode.bind(this));
@@ -250,28 +245,33 @@ export class RPC {
250
245
  case MSGID_EVENT:
251
246
  {
252
247
  const [name, rawValue] = decodeEvent(msg);
253
- console.log(`recv EVENT ${name}`);
248
+ this.logger?.trace({ rpc: { direction: 'recv', msgId: 'EVENT', eventName: name } });
254
249
  const subject = this.getEvent(name);
255
250
  if (subject === undefined) {
256
251
  throw new EventNotFoundError(name);
257
252
  }
258
253
  const value = this.decode(rawValue);
259
- const coerced = this.local.spec.validateEventValue(name, value);
254
+ const coerced = this.impl.local.validateEventValue(name, value);
260
255
  subject.next(coerced);
261
256
  break;
262
257
  }
263
258
  case MSGID_REQUEST:
264
259
  {
265
260
  const [id, name, encodedArgs] = decodeRequest(msg);
266
- console.log(`recv REQUEST ${id} (${name})`);
261
+ this.logger?.trace({ rpc: { direction: 'recv', msgId: 'REQUEST', id, methodName: name } });
267
262
  try {
268
263
  const args = encodedArgs.map(this.decode.bind(this));
269
- const method = this.local.getHandler(name);
264
+ const method = this.impl.getHandler(name);
270
265
  if (method === undefined) {
271
266
  throw new MethodNotFoundError(name);
272
267
  }
273
- const validArgs = this.local.spec.validateArgs(name, args);
274
- Promise.resolve(method(this.state, ...validArgs))
268
+ const validArgs = this.impl.local.validateArgs(name, args);
269
+ Promise.resolve(method({
270
+ client: this.client,
271
+ state: this.state,
272
+ // We force the compiler to treat `validArgs` as correctly typed
273
+ args: validArgs
274
+ }))
275
275
  .then(value => this.transport.write(JSON.stringify([MSGID_RESPOND_OK, id, this.encode(value)])))
276
276
  .catch(error => this.transport.write(JSON.stringify([MSGID_RESPOND_ERROR, id, error.message])));
277
277
  }
@@ -287,6 +287,7 @@ export class RPC {
287
287
  case MSGID_STREAM_ELEMENT:
288
288
  {
289
289
  const [id, rawValue] = decodeStreamElement(msg);
290
+ this.logger?.trace({ rpc: { direction: 'recv', msgId: 'STREAM_ELEMENT', id } });
290
291
  const element = this.decode(rawValue);
291
292
  const stream = this.asyncGenerators.get(id);
292
293
  if (stream === undefined) {
@@ -299,6 +300,7 @@ export class RPC {
299
300
  case MSGID_STREAM_FINISH:
300
301
  {
301
302
  const [id, rawValue] = decodeStreamFinish(msg);
303
+ this.logger?.trace({ rpc: { direction: 'recv', msgId: 'STREAM_FINISH', id } });
302
304
  const generator = this.asyncGenerators.get(id);
303
305
  if (generator === undefined) {
304
306
  throw new RemoteError(`Async generator with ID ${id} not found.`);
@@ -311,7 +313,7 @@ export class RPC {
311
313
  case MSGID_OBSERVABLE_EVENT:
312
314
  {
313
315
  const [id, rawValue] = decodeObservableEvent(msg);
314
- console.log(`recv OBSERVABLE_EVENT ${id}`);
316
+ this.logger?.trace({ rpc: { direction: 'recv', msgId: 'OBSERVABLE_EVENT', id } });
315
317
  const sub = this.recvSubjects.get(id);
316
318
  if (sub === undefined) {
317
319
  throw new RemoteError(`Observable with ID ${id} not found.`);
@@ -322,7 +324,7 @@ export class RPC {
322
324
  case MSGID_OBSERVABLE_COMPLETE:
323
325
  {
324
326
  const [id] = decodeObservableComplete(msg);
325
- console.log(`recv OBSERVABLE_COMPLETE ${id}`);
327
+ this.logger?.trace({ rpc: { direction: 'recv', msgId: 'OBSERVABLE_COMPLETE', id } });
326
328
  const subscriber = this.recvSubjects.get(id);
327
329
  if (subscriber === undefined) {
328
330
  throw new Error(`Observable with ID ${id} not found.`);
@@ -334,7 +336,7 @@ export class RPC {
334
336
  case MSGID_OBSERVABLE_CLOSE:
335
337
  {
336
338
  const [id] = msg[1];
337
- console.log(`recv OBSERVABLE_CLOSE ${id}`);
339
+ this.logger?.trace({ rpc: { direction: 'recv', msgId: 'OBSERVABLE_CLOSE', id } });
338
340
  const sub = this.sendSubscriptions.get(id);
339
341
  if (sub === undefined) {
340
342
  throw new RemoteError(`Could not find subscription with ID ${id}`);
@@ -346,7 +348,7 @@ export class RPC {
346
348
  case MSGID_RESPOND_OK:
347
349
  {
348
350
  const [id, value] = decodeRespondOk(msg);
349
- console.log(`recv RESPOND_OK ${id}`);
351
+ this.logger?.trace({ rpc: { direction: 'recv', msgId: 'RESPOND_OK', id } });
350
352
  const result = this.pending.get(id);
351
353
  if (result === undefined) {
352
354
  throw new RemoteError(`Pending request with ID ${id} not found.`);
@@ -356,7 +358,7 @@ export class RPC {
356
358
  const decoded = this.decode(value);
357
359
  let coerced;
358
360
  try {
359
- coerced = this.remote.validateReturns(name, decoded);
361
+ coerced = this.impl.remote.validateReturns(name, decoded);
360
362
  }
361
363
  catch (error) {
362
364
  if (error instanceof FailedValidationError) {
@@ -371,7 +373,7 @@ export class RPC {
371
373
  case MSGID_RESPOND_ERROR:
372
374
  {
373
375
  const [id, message] = decodeRespondError(msg);
374
- console.log(`recv RESPOND_ERROR ${id}`);
376
+ this.logger?.trace({ rpc: { direction: 'recv', msgId: 'RESPOND_ERROR', id } });
375
377
  const result = this.pending.get(id);
376
378
  if (result === undefined) {
377
379
  throw new RemoteError(`Pending request with ID ${id} not found for error response`);
@@ -389,7 +391,7 @@ export class RPC {
389
391
  this.readerSubscription.unsubscribe();
390
392
  }
391
393
  }
392
- export function connect(local, remote, transport, state) {
393
- return new RPC(transport, local, remote, state);
394
+ export function connect(impl, transport, state, logger) {
395
+ return new RPC(transport, impl, state, logger);
394
396
  }
395
397
  //# sourceMappingURL=rpc.js.map