rpc-express-toolkit 4.2.1 → 4.3.2

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 CHANGED
File without changes
package/README.md CHANGED
@@ -42,9 +42,61 @@ app.listen(3000);
42
42
  ### Client
43
43
 
44
44
  ```javascript
45
- const { RpcClient } = require('rpc-express-toolkit');
45
+ const { RpcClient, RpcSafeClient } = require('rpc-express-toolkit');
46
+
46
47
  const client = new RpcClient('http://localhost:3000/api');
47
48
  const sum = await client.call('add', { a: 1, b: 2 });
49
+
50
+ const safeClient = new RpcSafeClient('http://localhost:3000/api');
51
+ await safeClient.notify('add', { a: 0, b: 0 });
52
+ ```
53
+
54
+ `RpcClient` and `RpcSafeClient` are re-exported from the shared `rpc-toolkit-js-client` package, so existing Node.js imports from `rpc-express-toolkit` continue to work.
55
+
56
+ ### Browser Client Assets
57
+
58
+ Serve the shared browser client bundles from the endpoint:
59
+
60
+ ```javascript
61
+ const { RpcEndpoint } = require('rpc-express-toolkit');
62
+
63
+ RpcEndpoint.serveScripts(app);
64
+ ```
65
+
66
+ Default paths:
67
+
68
+ ```text
69
+ /vendor/rpc-client/rpc-client.js
70
+ /vendor/rpc-client/rpc-client.min.js
71
+ /vendor/rpc-client/rpc-client.mjs
72
+ /vendor/rpc-client/rpc-client.min.mjs
73
+ ```
74
+
75
+ Classic browser script:
76
+
77
+ ```html
78
+ <script src="/vendor/rpc-client/rpc-client.min.js"></script>
79
+ <script>
80
+ const client = new RpcToolkitClient.RpcClient('/api');
81
+ const safeClient = new RpcToolkitClient.RpcSafeClient('/api');
82
+
83
+ client.call('add', { a: 1, b: 2 }).then(console.log);
84
+ safeClient.notify('add', { a: 0, b: 0 });
85
+ </script>
86
+ ```
87
+
88
+ Module script:
89
+
90
+ ```html
91
+ <script type="module">
92
+ import { RpcClient, RpcSafeClient } from '/vendor/rpc-client/rpc-client.mjs';
93
+
94
+ const client = new RpcClient('/api');
95
+ const safeClient = new RpcSafeClient('/api');
96
+
97
+ console.log(await client.call('add', { a: 1, b: 2 }));
98
+ await safeClient.notify('add', { a: 0, b: 0 });
99
+ </script>
48
100
  ```
49
101
 
50
102
  ### Safe Type Disambiguation (optional)
@@ -60,6 +112,31 @@ Safe type disambiguation is disabled by default for maximum JSON-RPC 2.0 compati
60
112
  - `client.batch([...])`: batch.
61
113
  - `client.notify(method, params?)`: notification.
62
114
 
115
+ ## Authentication And Method Restrictions
116
+
117
+ Authentication is supported through the built-in `auth` middleware. The `auth` option is a function that receives the Express request. Returning a truthy value allows the RPC call; returning a falsy value rejects it with JSON-RPC error `-32001` and message `Authentication required`. Throwing also rejects the call and returns a JSON-RPC error based on the thrown error.
118
+
119
+ ```js
120
+ const rpc = new RpcEndpoint(app, context, {
121
+ auth: async (req) => {
122
+ const token = req.headers.authorization;
123
+ return token === 'Bearer secret-token';
124
+ },
125
+ });
126
+
127
+ rpc.addMethod('ping', () => 'pong');
128
+ ```
129
+
130
+ For simple method-level restriction, use `methodWhitelist`:
131
+
132
+ ```js
133
+ const rpc = new RpcEndpoint(app, context, {
134
+ methodWhitelist: ['ping', 'status.read'],
135
+ });
136
+ ```
137
+
138
+ Calls to methods outside the whitelist are rejected. This is a basic method restriction mechanism, not a complete role or permission system. Project-specific authorization rules can be implemented with middleware hooks such as `beforeCall`; see `README_ADVANCED.md`.
139
+
63
140
  ### Safe Import (opt-in)
64
141
 
65
142
  [![npm (proxy)](https://img.shields.io/npm/v/rpc-express-toolkit-safe.svg)](https://www.npmjs.com/package/rpc-express-toolkit-safe)
@@ -70,16 +147,16 @@ When you control both client and server and want safer type round-trips, import
70
147
  ```js
71
148
  // Server (safe preset)
72
149
  const express = require('express');
73
- const { createSafeEndpoint } = require('rpc-express-toolkit/safe');
150
+ const { RpcSafeEndpoint } = require('rpc-express-toolkit/safe');
74
151
 
75
152
  const app = express();
76
153
  app.use(express.json());
77
154
 
78
- const rpc = createSafeEndpoint(app, {}, { endpoint: '/api' /* strictMode: true by default */ });
155
+ const rpc = new RpcSafeEndpoint(app, {}, { endpoint: '/api' /* strictMode: true by default */ });
79
156
 
80
157
  // Client (safe preset)
81
- const { createSafeClient } = require('rpc-express-toolkit/safe');
82
- const client = createSafeClient('http://localhost:3000/api');
158
+ const { RpcSafeClient } = require('rpc-express-toolkit/safe');
159
+ const client = new RpcSafeClient('http://localhost:3000/api');
83
160
  ```
84
161
 
85
162
  This keeps JSON-RPC 2.0 compliance as default for the main entrypoint, while offering a convenient safe-mode import for projects that prefer explicit type disambiguation.
@@ -95,14 +172,14 @@ npm install rpc-express-toolkit-safe
95
172
  ```js
96
173
  // Server
97
174
  const express = require('express');
98
- const { createSafeEndpoint } = require('rpc-express-toolkit-safe');
175
+ const { RpcSafeEndpoint } = require('rpc-express-toolkit-safe');
99
176
  const app = express();
100
177
  app.use(express.json());
101
- const rpc = createSafeEndpoint(app, {}, { endpoint: '/api' });
178
+ const rpc = new RpcSafeEndpoint(app, {}, { endpoint: '/api' });
102
179
 
103
180
  // Client
104
- const { createSafeClient } = require('rpc-express-toolkit-safe');
105
- const client = createSafeClient('http://localhost:3000/api');
181
+ const { RpcSafeClient } = require('rpc-express-toolkit-safe');
182
+ const client = new RpcSafeClient('http://localhost:3000/api');
106
183
  ```
107
184
 
108
185
  ## Introspection Methods
@@ -142,6 +219,8 @@ const methods = await client.call('__rpc.listMethods');
142
219
  const addInfo = await client.call('__rpc.describe', { method: 'add' });
143
220
  ```
144
221
 
222
+ In `__rpc.capabilities`, `auth` is a boolean indicating whether authentication middleware is configured. It does not expose roles, scopes, or permission rules.
223
+
145
224
  **Note:** The introspection prefix is configurable via `introspectionPrefix` option (default: `__rpc`). User methods starting with this prefix are rejected to prevent conflicts.
146
225
 
147
226
  ## Full Details
File without changes
@@ -1,68 +1,68 @@
1
- /**
2
- * Introspection Example - Client
3
- * Demonstrates how to use __rpc.* introspection methods
4
- */
5
-
6
- const { RpcClient } = require('../..');
7
-
8
- async function main() {
9
- const client = new RpcClient('http://localhost:3000/api');
10
-
11
- console.log('=== RPC Introspection Demo ===\n');
12
-
13
- // 1. List all methods
14
- console.log('1. __rpc.listMethods():');
15
- const methods = await client.call('__rpc.listMethods');
16
- console.log(' Available methods:', methods);
17
- console.log('');
18
-
19
- // 2. Get version info
20
- console.log('2. __rpc.version():');
21
- const version = await client.call('__rpc.version');
22
- console.log(' Toolkit:', version.toolkit);
23
- console.log(' Version:', version.version);
24
- console.log(' Express:', version.expressVersion);
25
- console.log(' Node:', version.nodeVersion);
26
- console.log('');
27
-
28
- // 3. Get server capabilities
29
- console.log('3. __rpc.capabilities():');
30
- const caps = await client.call('__rpc.capabilities');
31
- console.log(' Safe Mode:', caps.safeMode);
32
- console.log(' Batch Support:', caps.batch);
33
- console.log(' Introspection:', caps.introspection);
34
- console.log(' Method Count:', caps.methodCount);
35
- console.log('');
36
-
37
- // 4. Describe a specific method
38
- console.log('4. __rpc.describe({ method: "add" }):');
39
- const addInfo = await client.call('__rpc.describe', { method: 'add' });
40
- console.log(' Name:', addInfo.name);
41
- console.log(' Description:', addInfo.description);
42
- console.log(' Schema:', JSON.stringify(addInfo.schema, null, 2));
43
- console.log('');
44
-
45
- // 5. Describe all public methods
46
- console.log('5. __rpc.describeAll():');
47
- const allMethods = await client.call('__rpc.describeAll');
48
- allMethods.forEach((method) => {
49
- console.log(` - ${method.name}: ${method.description}`);
50
- });
51
- console.log('');
52
-
53
- // 6. Try to describe a private method (should fail)
54
- console.log('6. Try to describe private method:');
55
- try {
56
- await client.call('__rpc.describe', { method: 'internalCalculation' });
57
- } catch (error) {
58
- console.log(' Error:', error.message);
59
- }
60
- console.log('');
61
-
62
- // 7. Test a public method
63
- console.log('7. Call add method:');
64
- const sum = await client.call('add', { a: 5, b: 3 });
65
- console.log(' 5 + 3 =', sum);
66
- }
67
-
68
- main().catch(console.error);
1
+ /**
2
+ * Introspection Example - Client
3
+ * Demonstrates how to use __rpc.* introspection methods
4
+ */
5
+
6
+ const { RpcClient } = require('../..');
7
+
8
+ async function main() {
9
+ const client = new RpcClient('http://localhost:3000/api');
10
+
11
+ console.log('=== RPC Introspection Demo ===\n');
12
+
13
+ // 1. List all methods
14
+ console.log('1. __rpc.listMethods():');
15
+ const methods = await client.call('__rpc.listMethods');
16
+ console.log(' Available methods:', methods);
17
+ console.log('');
18
+
19
+ // 2. Get version info
20
+ console.log('2. __rpc.version():');
21
+ const version = await client.call('__rpc.version');
22
+ console.log(' Toolkit:', version.toolkit);
23
+ console.log(' Version:', version.version);
24
+ console.log(' Express:', version.expressVersion);
25
+ console.log(' Node:', version.nodeVersion);
26
+ console.log('');
27
+
28
+ // 3. Get server capabilities
29
+ console.log('3. __rpc.capabilities():');
30
+ const caps = await client.call('__rpc.capabilities');
31
+ console.log(' Safe Mode:', caps.safeMode);
32
+ console.log(' Batch Support:', caps.batch);
33
+ console.log(' Introspection:', caps.introspection);
34
+ console.log(' Method Count:', caps.methodCount);
35
+ console.log('');
36
+
37
+ // 4. Describe a specific method
38
+ console.log('4. __rpc.describe({ method: "add" }):');
39
+ const addInfo = await client.call('__rpc.describe', { method: 'add' });
40
+ console.log(' Name:', addInfo.name);
41
+ console.log(' Description:', addInfo.description);
42
+ console.log(' Schema:', JSON.stringify(addInfo.schema, null, 2));
43
+ console.log('');
44
+
45
+ // 5. Describe all public methods
46
+ console.log('5. __rpc.describeAll():');
47
+ const allMethods = await client.call('__rpc.describeAll');
48
+ allMethods.forEach((method) => {
49
+ console.log(` - ${method.name}: ${method.description}`);
50
+ });
51
+ console.log('');
52
+
53
+ // 6. Try to describe a private method (should fail)
54
+ console.log('6. Try to describe private method:');
55
+ try {
56
+ await client.call('__rpc.describe', { method: 'internalCalculation' });
57
+ } catch (error) {
58
+ console.log(' Error:', error.message);
59
+ }
60
+ console.log('');
61
+
62
+ // 7. Test a public method
63
+ console.log('7. Call add method:');
64
+ const sum = await client.call('add', { a: 5, b: 3 });
65
+ console.log(' 5 + 3 =', sum);
66
+ }
67
+
68
+ main().catch(console.error);
@@ -1,89 +1,89 @@
1
- /**
2
- * Introspection Example - Server
3
- * Demonstrates how to enable and use __rpc.* introspection methods
4
- */
5
-
6
- const express = require('express');
7
- const { RpcEndpoint } = require('../..');
8
-
9
- const app = express();
10
- app.use(express.json());
11
-
12
- // Context for methods
13
- const context = {
14
- database: 'mock-db',
15
- config: { maxValue: 1000 },
16
- };
17
-
18
- // Create endpoint with introspection enabled
19
- const rpc = new RpcEndpoint(app, context, {
20
- endpoint: '/api',
21
- enableIntrospection: true, // Enable __rpc.* methods
22
- introspectionPrefix: '__rpc', // Optional: customize prefix (default: __rpc)
23
- });
24
-
25
- // Public method with exposed schema
26
- rpc.addMethod('add', async (req, ctx, params) => params.a + params.b, {
27
- schema: {
28
- type: 'object',
29
- properties: {
30
- a: { type: 'number' },
31
- b: { type: 'number' },
32
- },
33
- required: ['a', 'b'],
34
- },
35
- exposeSchema: true,
36
- description: 'Add two numbers and return the sum',
37
- });
38
-
39
- // Public method with exposed schema
40
- rpc.addMethod('multiply', async (req, ctx, params) => params.a * params.b, {
41
- schema: {
42
- type: 'object',
43
- properties: {
44
- a: { type: 'number' },
45
- b: { type: 'number' },
46
- },
47
- required: ['a', 'b'],
48
- },
49
- exposeSchema: true,
50
- description: 'Multiply two numbers',
51
- });
52
-
53
- // Private method (schema not exposed)
54
- rpc.addMethod(
55
- 'internalCalculation',
56
- async (req, ctx, params) => params.value * 2 + 42,
57
- {
58
- schema: {
59
- type: 'object',
60
- properties: {
61
- value: { type: 'number' },
62
- },
63
- required: ['value'],
64
- },
65
- exposeSchema: false, // Schema is private
66
- description: 'Internal calculation (not exposed)',
67
- }
68
- );
69
-
70
- // Public method without schema
71
- rpc.addMethod('echo', async (req, ctx, params) => params, {
72
- exposeSchema: true,
73
- description: 'Echo back the parameters',
74
- });
75
-
76
- // Start server
77
- const PORT = process.env.PORT || 3000;
78
- app.listen(PORT, () => {
79
- console.log(
80
- `RPC Server with introspection running on http://localhost:${PORT}/api`
81
- );
82
- console.log('\nAvailable introspection methods:');
83
- console.log('- __rpc.listMethods()');
84
- console.log('- __rpc.describe({method: "add"})');
85
- console.log('- __rpc.describeAll()');
86
- console.log('- __rpc.version()');
87
- console.log('- __rpc.capabilities()');
88
- console.log('\nTry: node client.js');
89
- });
1
+ /**
2
+ * Introspection Example - Server
3
+ * Demonstrates how to enable and use __rpc.* introspection methods
4
+ */
5
+
6
+ const express = require('express');
7
+ const { RpcEndpoint } = require('../..');
8
+
9
+ const app = express();
10
+ app.use(express.json());
11
+
12
+ // Context for methods
13
+ const context = {
14
+ database: 'mock-db',
15
+ config: { maxValue: 1000 },
16
+ };
17
+
18
+ // Create endpoint with introspection enabled
19
+ const rpc = new RpcEndpoint(app, context, {
20
+ endpoint: '/api',
21
+ enableIntrospection: true, // Enable __rpc.* methods
22
+ introspectionPrefix: '__rpc', // Optional: customize prefix (default: __rpc)
23
+ });
24
+
25
+ // Public method with exposed schema
26
+ rpc.addMethod('add', async (req, ctx, params) => params.a + params.b, {
27
+ schema: {
28
+ type: 'object',
29
+ properties: {
30
+ a: { type: 'number' },
31
+ b: { type: 'number' },
32
+ },
33
+ required: ['a', 'b'],
34
+ },
35
+ exposeSchema: true,
36
+ description: 'Add two numbers and return the sum',
37
+ });
38
+
39
+ // Public method with exposed schema
40
+ rpc.addMethod('multiply', async (req, ctx, params) => params.a * params.b, {
41
+ schema: {
42
+ type: 'object',
43
+ properties: {
44
+ a: { type: 'number' },
45
+ b: { type: 'number' },
46
+ },
47
+ required: ['a', 'b'],
48
+ },
49
+ exposeSchema: true,
50
+ description: 'Multiply two numbers',
51
+ });
52
+
53
+ // Private method (schema not exposed)
54
+ rpc.addMethod(
55
+ 'internalCalculation',
56
+ async (req, ctx, params) => params.value * 2 + 42,
57
+ {
58
+ schema: {
59
+ type: 'object',
60
+ properties: {
61
+ value: { type: 'number' },
62
+ },
63
+ required: ['value'],
64
+ },
65
+ exposeSchema: false, // Schema is private
66
+ description: 'Internal calculation (not exposed)',
67
+ }
68
+ );
69
+
70
+ // Public method without schema
71
+ rpc.addMethod('echo', async (req, ctx, params) => params, {
72
+ exposeSchema: true,
73
+ description: 'Echo back the parameters',
74
+ });
75
+
76
+ // Start server
77
+ const PORT = process.env.PORT || 3000;
78
+ app.listen(PORT, () => {
79
+ console.log(
80
+ `RPC Server with introspection running on http://localhost:${PORT}/api`
81
+ );
82
+ console.log('\nAvailable introspection methods:');
83
+ console.log('- __rpc.listMethods()');
84
+ console.log('- __rpc.describe({method: "add"})');
85
+ console.log('- __rpc.describeAll()');
86
+ console.log('- __rpc.version()');
87
+ console.log('- __rpc.capabilities()');
88
+ console.log('\nTry: node client.js');
89
+ });
File without changes
File without changes
File without changes