rpc-express-toolkit 2.0.1 → 2.1.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/README.md +28 -5
- package/examples/ssl-development-example.js +75 -0
- package/package.json +3 -1
- package/src/clients/rpc-client.js +24 -1
- package/src/clients/rpc-client.min.js +1 -1
- package/src/clients/rpc-client.min.mjs +1 -1
- package/src/clients/rpc-client.mjs +32 -1
- package/src/index.d.ts +3 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](LICENSE)
|
|
4
4
|
[](https://www.npmjs.com/package/rpc-express-toolkit)
|
|
5
|
-
[](https://github.com/n-car/rpc-express-toolkit/actions/workflows/ci.yml)
|
|
6
6
|
[](https://coveralls.io/github/n-car/rpc-express-toolkit?branch=main)
|
|
7
7
|
|
|
8
8
|
An enterprise-ready JSON-RPC 2.0 toolkit for Express.js applications with simplified APIs, structured logging, middleware system, schema validation, batch processing, and comprehensive BigInt/Date serialization support.
|
|
@@ -514,6 +514,33 @@ logger.error('Database error', {
|
|
|
514
514
|
// [2024-01-01T10:00:00.050Z] INFO: RPC success - {"method":"getUser","id":"req-123","duration":50,"resultSize":245}
|
|
515
515
|
```
|
|
516
516
|
|
|
517
|
+
### Client Configuration
|
|
518
|
+
|
|
519
|
+
The `RpcClient` supports various configuration options for different environments:
|
|
520
|
+
|
|
521
|
+
```javascript
|
|
522
|
+
const { RpcClient } = require('rpc-express-toolkit');
|
|
523
|
+
|
|
524
|
+
// Basic client
|
|
525
|
+
const client = new RpcClient('https://api.example.com/rpc');
|
|
526
|
+
|
|
527
|
+
// Client with custom headers
|
|
528
|
+
const clientWithHeaders = new RpcClient('https://api.example.com/rpc', {
|
|
529
|
+
'Authorization': 'Bearer your-token',
|
|
530
|
+
'X-API-Key': 'your-api-key',
|
|
531
|
+
'User-Agent': 'MyApp/1.0'
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// Client for development with self-signed certificates
|
|
535
|
+
const devClient = new RpcClient('https://localhost:3000/api', {
|
|
536
|
+
'Authorization': 'Bearer dev-token'
|
|
537
|
+
}, {
|
|
538
|
+
rejectUnauthorized: false // Only for development!
|
|
539
|
+
});
|
|
540
|
+
```
|
|
541
|
+
|
|
542
|
+
**⚠️ Security Warning**: Only use `rejectUnauthorized: false` in development environments with self-signed certificates. Never use this in production as it disables SSL certificate validation and makes your application vulnerable to man-in-the-middle attacks.
|
|
543
|
+
|
|
517
544
|
### Built-in Middlewares
|
|
518
545
|
|
|
519
546
|
```javascript
|
|
@@ -721,10 +748,6 @@ This project uses ESLint and Prettier for code formatting. Run `npm run lint` to
|
|
|
721
748
|
|
|
722
749
|
## Security
|
|
723
750
|
|
|
724
|
-
### Vulnerability Reporting
|
|
725
|
-
|
|
726
|
-
If you discover a security vulnerability, please send an email to security@example.com. All security vulnerabilities will be promptly addressed.
|
|
727
|
-
|
|
728
751
|
### Best Practices
|
|
729
752
|
|
|
730
753
|
- Always validate input parameters using schema validation
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example demonstrating how to use RpcClient with self-signed certificates
|
|
3
|
+
* in development environments.
|
|
4
|
+
*
|
|
5
|
+
* WARNING: Only use rejectUnauthorized: false in development!
|
|
6
|
+
* Never use this in production as it disables SSL certificate validation.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { RpcClient } = require('../src/index.js');
|
|
10
|
+
|
|
11
|
+
async function demonstrateSSLOptions() {
|
|
12
|
+
console.log('=== RPC Client SSL Configuration Example ===\n');
|
|
13
|
+
|
|
14
|
+
// Example 1: Standard production client (default - strict SSL)
|
|
15
|
+
console.log('1. Production Client (strict SSL validation):');
|
|
16
|
+
const productionClient = new RpcClient('https://api.example.com/rpc', {
|
|
17
|
+
'Authorization': 'Bearer prod-token'
|
|
18
|
+
});
|
|
19
|
+
console.log(' ✓ Created client with strict SSL validation (default)\n');
|
|
20
|
+
|
|
21
|
+
// Example 2: Development client for self-signed certificates
|
|
22
|
+
console.log('2. Development Client (bypasses SSL validation):');
|
|
23
|
+
const developmentClient = new RpcClient('https://localhost:3000/api', {
|
|
24
|
+
'Authorization': 'Bearer dev-token',
|
|
25
|
+
'X-Environment': 'development'
|
|
26
|
+
}, {
|
|
27
|
+
rejectUnauthorized: false // Only for development!
|
|
28
|
+
});
|
|
29
|
+
console.log(' ✓ Created client that bypasses SSL certificate validation');
|
|
30
|
+
console.log(' ⚠️ WARNING: Only use this for development with self-signed certificates!\n');
|
|
31
|
+
|
|
32
|
+
// Example 3: Demonstrate how to choose configuration based on environment
|
|
33
|
+
console.log('3. Environment-based Configuration:');
|
|
34
|
+
|
|
35
|
+
const isDevelopment = process.env.NODE_ENV === 'development';
|
|
36
|
+
const baseUrl = isDevelopment ? 'https://localhost:3000/api' : 'https://api.production.com/rpc';
|
|
37
|
+
|
|
38
|
+
const environmentClient = new RpcClient(baseUrl, {
|
|
39
|
+
'Authorization': `Bearer ${process.env.API_TOKEN || 'default-token'}`,
|
|
40
|
+
'X-Environment': process.env.NODE_ENV || 'development'
|
|
41
|
+
}, {
|
|
42
|
+
// Only bypass SSL validation in development
|
|
43
|
+
...(isDevelopment && { rejectUnauthorized: false })
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
console.log(` ✓ Created client for ${isDevelopment ? 'development' : 'production'} environment`);
|
|
47
|
+
console.log(` ✓ SSL validation: ${isDevelopment ? 'disabled (dev only)' : 'enabled (secure)'}\n`);
|
|
48
|
+
|
|
49
|
+
// Example usage (commented out since we don't have a real server)
|
|
50
|
+
/*
|
|
51
|
+
try {
|
|
52
|
+
// This would work with a real server
|
|
53
|
+
const result = await developmentClient.call('ping', {});
|
|
54
|
+
console.log('Server response:', result);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error('Error calling server:', error.message);
|
|
57
|
+
}
|
|
58
|
+
*/
|
|
59
|
+
|
|
60
|
+
console.log('4. Best Practices:');
|
|
61
|
+
console.log(' ✓ Always use strict SSL validation in production');
|
|
62
|
+
console.log(' ✓ Only disable SSL validation for development with self-signed certificates');
|
|
63
|
+
console.log(' ✓ Use environment variables to control SSL behavior');
|
|
64
|
+
console.log(' ✓ Never commit rejectUnauthorized: false to production code');
|
|
65
|
+
console.log(' ✓ Consider using proper development certificates instead of disabling validation\n');
|
|
66
|
+
|
|
67
|
+
console.log('=== Example Complete ===');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Run the example if this file is executed directly
|
|
71
|
+
if (require.main === module) {
|
|
72
|
+
demonstrateSSLOptions().catch(console.error);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = { demonstrateSSLOptions };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rpc-express-toolkit",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Enterprise-ready JSON-RPC 2.0 toolkit for Express.js with simplified APIs, structured logging, middleware system, schema validation, and comprehensive BigInt/Date support.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
14
|
"test": "jest",
|
|
15
|
+
"test:coverage": "jest --coverage",
|
|
16
|
+
"test:watch": "jest --watch",
|
|
15
17
|
"lint": "eslint src/ examples/",
|
|
16
18
|
"lint:fix": "eslint src/ examples/ --fix",
|
|
17
19
|
"clean": "node -e \"require('fs').existsSync('dist') && require('fs').rmSync('dist', {recursive: true})\"",
|
|
@@ -33,12 +33,15 @@ class RpcClient {
|
|
|
33
33
|
#endpoint;
|
|
34
34
|
#defaultHeaders;
|
|
35
35
|
#requestId;
|
|
36
|
+
#fetchOptions;
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
39
|
* @param {string} endpoint The JSON-RPC endpoint URL.
|
|
39
40
|
* @param {Object} [defaultHeaders={}] Optional default headers to include in requests.
|
|
41
|
+
* @param {Object} [options={}] Optional configuration options.
|
|
42
|
+
* @param {boolean} [options.rejectUnauthorized=true] Whether to reject unauthorized SSL certificates. Set to false for development with self-signed certificates.
|
|
40
43
|
*/
|
|
41
|
-
constructor(endpoint, defaultHeaders = {}) {
|
|
44
|
+
constructor(endpoint, defaultHeaders = {}, options = {}) {
|
|
42
45
|
this.#endpoint = endpoint;
|
|
43
46
|
this.#defaultHeaders = {
|
|
44
47
|
"Content-Type": "application/json", // Default header
|
|
@@ -46,6 +49,24 @@ class RpcClient {
|
|
|
46
49
|
};
|
|
47
50
|
// Initialize request ID counter with timestamp + random component for uniqueness
|
|
48
51
|
this.#requestId = Date.now() * 1000 + Math.floor(Math.random() * 1000);
|
|
52
|
+
|
|
53
|
+
// Store fetch options for Node.js environments
|
|
54
|
+
this.#fetchOptions = {};
|
|
55
|
+
|
|
56
|
+
// Handle SSL certificate validation option for Node.js
|
|
57
|
+
if (typeof process !== 'undefined' && process.env && options.rejectUnauthorized === false) {
|
|
58
|
+
// Set up agent for Node.js fetch implementations
|
|
59
|
+
if (typeof require !== 'undefined') {
|
|
60
|
+
try {
|
|
61
|
+
const https = require('https');
|
|
62
|
+
this.#fetchOptions.agent = new https.Agent({
|
|
63
|
+
rejectUnauthorized: false
|
|
64
|
+
});
|
|
65
|
+
} catch (e) {
|
|
66
|
+
// Ignore if https module is not available
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
49
70
|
}
|
|
50
71
|
|
|
51
72
|
/**
|
|
@@ -85,6 +106,7 @@ class RpcClient {
|
|
|
85
106
|
// Since we have BigInt.prototype.toJSON, we don't need manual serialization
|
|
86
107
|
// JSON.stringify will handle BigInt and Date automatically
|
|
87
108
|
body: JSON.stringify(requestBody),
|
|
109
|
+
...this.#fetchOptions, // Include any additional fetch options (e.g., SSL settings)
|
|
88
110
|
});
|
|
89
111
|
|
|
90
112
|
if (!response.ok) {
|
|
@@ -136,6 +158,7 @@ class RpcClient {
|
|
|
136
158
|
...overrideHeaders,
|
|
137
159
|
},
|
|
138
160
|
body: JSON.stringify(batchRequests),
|
|
161
|
+
...this.#fetchOptions, // Include any additional fetch options (e.g., SSL settings)
|
|
139
162
|
});
|
|
140
163
|
|
|
141
164
|
if (!response.ok) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
let fetchFn;if("undefined"==typeof BigInt||BigInt.prototype.toJSON||(BigInt.prototype.toJSON=function(){return this.toString()}),"undefined"!=typeof fetch)fetchFn=fetch;else try{fetchFn=require("node-fetch")}catch(t){if("undefined"==typeof globalThis||!globalThis.fetch)throw new Error("fetch is not available. Please install node-fetch or use Node.js 18+");fetchFn=globalThis.fetch}class RpcClient{#t;#e;#r;constructor(t,e={}){this.#t=t,this.#e={"Content-Type":"application/json",...e},this.#r=1e3*Date.now()+Math.floor(1e3*Math.random())}
|
|
1
|
+
let fetchFn;if("undefined"==typeof BigInt||BigInt.prototype.toJSON||(BigInt.prototype.toJSON=function(){return this.toString()}),"undefined"!=typeof fetch)fetchFn=fetch;else try{fetchFn=require("node-fetch")}catch(t){if("undefined"==typeof globalThis||!globalThis.fetch)throw new Error("fetch is not available. Please install node-fetch or use Node.js 18+");fetchFn=globalThis.fetch}class RpcClient{#t;#e;#r;#i;constructor(t,e={},r={}){if(this.#t=t,this.#e={"Content-Type":"application/json",...e},this.#r=1e3*Date.now()+Math.floor(1e3*Math.random()),this.#i={},"undefined"!=typeof process&&process.env&&!1===r.rejectUnauthorized&&"undefined"!=typeof require)try{const t=require("https");this.#i.agent=new t.Agent({rejectUnauthorized:!1})}catch(t){}}#n(){return++this.#r}async call(t,e={},r=void 0,i={}){const n={jsonrpc:"2.0",method:t,params:e,id:void 0===r?this.#n():r};try{const t=await fetchFn(this.#t,{method:"POST",headers:{...this.#e,...i},body:JSON.stringify(n),...this.#i});if(!t.ok)throw new Error(`HTTP Error: ${t.status} ${t.statusText}`);const e=await t.json();if(e.error)throw e.error;return this.deserializeBigIntsAndDates(e.result)}catch(t){throw console.error("RPC call failed:",t),t}}async notify(t,e={},r={}){await this.call(t,e,null,r)}async batch(t,e={}){const r=t.map(t=>({jsonrpc:"2.0",method:t.method,params:t.params||{},id:void 0!==t.id?t.id:this.#n()}));try{const t=await fetchFn(this.#t,{method:"POST",headers:{...this.#e,...e},body:JSON.stringify(r),...this.#i});if(!t.ok)throw new Error(`HTTP Error: ${t.status} ${t.statusText}`);const i=await t.json();if(Array.isArray(i))return i.map(t=>{if(t.error)throw t.error;return this.deserializeBigIntsAndDates(t.result)});if(i.error)throw i.error;return[this.deserializeBigIntsAndDates(i.result)]}catch(t){throw console.error("Batch RPC call failed:",t),t}}serializeBigIntsAndDates(t){if("bigint"==typeof t)return t.toString();if(Array.isArray(t))return t.map(t=>this.serializeBigIntsAndDates(t));if(t instanceof Date)return t.toISOString();if(t&&"object"==typeof t){const e={};for(const[r,i]of Object.entries(t))e[r]=this.serializeBigIntsAndDates(i);return e}return t}deserializeBigIntsAndDates(t){const e=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/;if("string"==typeof t){if(/^-?\d+n?$/.test(t))return BigInt(t.replace(/n$/,""));if(e.test(t)){const e=new Date(t);if(!isNaN(e.getTime()))return e}}return Array.isArray(t)?t.map(t=>this.deserializeBigIntsAndDates(t)):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).map(([t,e])=>[t,this.deserializeBigIntsAndDates(e)])):t}}module.exports=RpcClient,module.exports.RpcClient=RpcClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
let t;if("undefined"==typeof BigInt||BigInt.prototype.toJSON||(BigInt.prototype.toJSON=function(){return this.toString()}),"undefined"!=typeof fetch)t=fetch;else try{const{default:e}=await import("node-fetch");t=e}catch(e){if("undefined"==typeof globalThis||!globalThis.fetch)throw new Error("fetch is not available. Please install node-fetch or use Node.js 18+");t=globalThis.fetch}export class RpcClient{#t;#e;#r;constructor(t,e={}){this.#t=t,this.#e={"Content-Type":"application/json",...e},this.#r=1e3*Date.now()+Math.floor(1e3*Math.random())}async call(e,r={},
|
|
1
|
+
let t;if("undefined"==typeof BigInt||BigInt.prototype.toJSON||(BigInt.prototype.toJSON=function(){return this.toString()}),"undefined"!=typeof fetch)t=fetch;else try{const{default:e}=await import("node-fetch");t=e}catch(e){if("undefined"==typeof globalThis||!globalThis.fetch)throw new Error("fetch is not available. Please install node-fetch or use Node.js 18+");t=globalThis.fetch}export class RpcClient{#t;#e;#r;#i;constructor(t,e={},r={}){if(this.#t=t,this.#e={"Content-Type":"application/json",...e},this.#r=1e3*Date.now()+Math.floor(1e3*Math.random()),this.#i={},"undefined"!=typeof process&&process.env&&!1===r.rejectUnauthorized&&"undefined"!=typeof require)try{const t=require("https");this.#i.agent=new t.Agent({rejectUnauthorized:!1})}catch(t){import("https").then(t=>{this.#i.agent=new t.Agent({rejectUnauthorized:!1})}).catch(()=>{})}}async call(e,r={},i=null,s={}){null===i&&(i=++this.#r);const n={jsonrpc:"2.0",method:e,params:r,id:i};try{const e=await t(this.#t,{method:"POST",headers:{...this.#e,...s},body:JSON.stringify(n),...this.#i});if(!e.ok)throw new Error(`HTTP Error: ${e.status} ${e.statusText}`);const r=await e.json();if(r.error)throw r.error;return this.deserializeBigIntsAndDates(r.result)}catch(t){throw console.error("RPC call failed:",t),t}}async notify(e,r={},i={}){const s={jsonrpc:"2.0",method:e,params:r};try{const e=await t(this.#t,{method:"POST",headers:{...this.#e,...i},body:JSON.stringify(s),...this.#i});if(!e.ok)throw new Error(`HTTP Error: ${e.status} ${e.statusText}`)}catch(t){throw console.error("RPC notification failed:",t),t}}async batch(e,r={}){const i=e.map(t=>{const e={jsonrpc:"2.0",method:t.method,params:t.params||{}};return t.notification||(e.id=void 0!==t.id?t.id:++this.#r),e});try{const e=await t(this.#t,{method:"POST",headers:{...this.#e,...r},body:JSON.stringify(i),...this.#i});if(!e.ok)throw new Error(`HTTP Error: ${e.status} ${e.statusText}`);const s=await e.json();if(Array.isArray(s))return s.map(t=>{if(t.error)throw t.error;return this.deserializeBigIntsAndDates(t.result)});if(s.error)throw s.error;return[this.deserializeBigIntsAndDates(s.result)]}catch(t){throw console.error("RPC batch call failed:",t),t}}serializeBigIntsAndDates(t){if("bigint"==typeof t)return t.toString();if(Array.isArray(t))return t.map(t=>this.serializeBigIntsAndDates(t));if(t instanceof Date)return t.toISOString();if(t&&"object"==typeof t){const e={};for(const[r,i]of Object.entries(t))e[r]=this.serializeBigIntsAndDates(i);return e}return t}deserializeBigIntsAndDates(t){const e=/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})?$/;if("string"==typeof t){if(/^-?\d+n?$/.test(t))return BigInt(t.replace(/n$/,""));if(e.test(t)){const e=new Date(t);if(!isNaN(e.getTime()))return e}}return Array.isArray(t)?t.map(t=>this.deserializeBigIntsAndDates(t)):t&&"object"==typeof t?Object.fromEntries(Object.entries(t).map(([t,e])=>[t,this.deserializeBigIntsAndDates(e)])):t}}
|
|
@@ -34,12 +34,15 @@ export class RpcClient {
|
|
|
34
34
|
#endpoint;
|
|
35
35
|
#defaultHeaders;
|
|
36
36
|
#requestId;
|
|
37
|
+
#fetchOptions;
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* @param {string} endpoint The JSON-RPC endpoint URL.
|
|
40
41
|
* @param {Object} [defaultHeaders={}] Optional default headers to include in requests.
|
|
42
|
+
* @param {Object} [options={}] Optional configuration options.
|
|
43
|
+
* @param {boolean} [options.rejectUnauthorized=true] Whether to reject unauthorized SSL certificates. Set to false for development with self-signed certificates.
|
|
41
44
|
*/
|
|
42
|
-
constructor(endpoint, defaultHeaders = {}) {
|
|
45
|
+
constructor(endpoint, defaultHeaders = {}, options = {}) {
|
|
43
46
|
this.#endpoint = endpoint;
|
|
44
47
|
this.#defaultHeaders = {
|
|
45
48
|
"Content-Type": "application/json", // Default header
|
|
@@ -47,6 +50,31 @@ export class RpcClient {
|
|
|
47
50
|
};
|
|
48
51
|
// Initialize request ID counter with timestamp + random component for uniqueness
|
|
49
52
|
this.#requestId = Date.now() * 1000 + Math.floor(Math.random() * 1000);
|
|
53
|
+
|
|
54
|
+
// Store fetch options for Node.js environments
|
|
55
|
+
this.#fetchOptions = {};
|
|
56
|
+
|
|
57
|
+
// Handle SSL certificate validation option for Node.js
|
|
58
|
+
if (typeof process !== 'undefined' && process.env && options.rejectUnauthorized === false) {
|
|
59
|
+
// Set up agent for Node.js fetch implementations
|
|
60
|
+
if (typeof require !== 'undefined') {
|
|
61
|
+
try {
|
|
62
|
+
const https = require('https');
|
|
63
|
+
this.#fetchOptions.agent = new https.Agent({
|
|
64
|
+
rejectUnauthorized: false
|
|
65
|
+
});
|
|
66
|
+
} catch (e) {
|
|
67
|
+
// For ES modules, we'll try dynamic import
|
|
68
|
+
import('https').then(httpsModule => {
|
|
69
|
+
this.#fetchOptions.agent = new httpsModule.Agent({
|
|
70
|
+
rejectUnauthorized: false
|
|
71
|
+
});
|
|
72
|
+
}).catch(() => {
|
|
73
|
+
// Ignore if https module is not available
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
50
78
|
}
|
|
51
79
|
|
|
52
80
|
/**
|
|
@@ -80,6 +108,7 @@ export class RpcClient {
|
|
|
80
108
|
// Since we have BigInt.prototype.toJSON, we don't need manual serialization
|
|
81
109
|
// JSON.stringify will handle BigInt and Date automatically
|
|
82
110
|
body: JSON.stringify(requestBody),
|
|
111
|
+
...this.#fetchOptions, // Include any additional fetch options (e.g., SSL settings)
|
|
83
112
|
});
|
|
84
113
|
|
|
85
114
|
if (!response.ok) {
|
|
@@ -121,6 +150,7 @@ export class RpcClient {
|
|
|
121
150
|
...overrideHeaders,
|
|
122
151
|
},
|
|
123
152
|
body: JSON.stringify(requestBody),
|
|
153
|
+
...this.#fetchOptions, // Include any additional fetch options (e.g., SSL settings)
|
|
124
154
|
});
|
|
125
155
|
|
|
126
156
|
if (!response.ok) {
|
|
@@ -162,6 +192,7 @@ export class RpcClient {
|
|
|
162
192
|
...overrideHeaders,
|
|
163
193
|
},
|
|
164
194
|
body: JSON.stringify(requestBodies),
|
|
195
|
+
...this.#fetchOptions, // Include any additional fetch options (e.g., SSL settings)
|
|
165
196
|
});
|
|
166
197
|
|
|
167
198
|
if (!response.ok) {
|
package/src/index.d.ts
CHANGED
|
@@ -90,8 +90,10 @@ declare class RpcClient {
|
|
|
90
90
|
*
|
|
91
91
|
* @param endpoint - JSON-RPC endpoint URL
|
|
92
92
|
* @param defaultHeaders - Default headers to include in requests
|
|
93
|
+
* @param options - Configuration options
|
|
94
|
+
* @param options.rejectUnauthorized - Whether to reject unauthorized SSL certificates (default: true). Set to false for development with self-signed certificates.
|
|
93
95
|
*/
|
|
94
|
-
constructor(endpoint: string, defaultHeaders?: Record<string, string
|
|
96
|
+
constructor(endpoint: string, defaultHeaders?: Record<string, string>, options?: { rejectUnauthorized?: boolean });
|
|
95
97
|
|
|
96
98
|
/**
|
|
97
99
|
* Make a JSON-RPC call to the server.
|