rpc-express-toolkit 2.3.1 → 2.3.3

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 CHANGED
@@ -561,24 +561,26 @@ const clientWithHeaders = new RpcClient('https://api.example.com/rpc', {
561
561
  'User-Agent': 'MyApp/1.0'
562
562
  });
563
563
 
564
- // Client per sviluppo con certificato self-signed (accetta qualsiasi certificato, NON usare in produzione)
564
+ // Development client with self-signed certificate (accepts any certificate, DO NOT use in production)
565
565
  const devClient = new RpcClient('https://localhost:3000/api', {
566
566
  'Authorization': 'Bearer dev-token'
567
567
  }, {
568
- rejectUnauthorized: false // Solo per sviluppo!
568
+ rejectUnauthorized: false // Development only!
569
569
  });
570
570
 
571
- // Client per sviluppo con CA self-signed (modo sicuro: accetta solo la tua CA)
571
+ // Development client with custom self-signed CA (safer: accepts only your CA)
572
572
  const ca = fs.readFileSync('path/to/your/selfsigned-ca.pem');
573
573
  const devClientWithCA = new RpcClient('https://localhost:3000/api', {
574
574
  'Authorization': 'Bearer dev-token'
575
575
  }, {
576
- ca // Passa il certificato della tua CA self-signed
577
- // oppure: agent: new require('https').Agent({ ca, rejectUnauthorized: true })
576
+ ca // Pass your self-signed CA certificate
577
+ // or: agent: new require('https').Agent({ ca, rejectUnauthorized: true })
578
578
  });
579
+
580
+ **⚠️ Security Warning**: Use `rejectUnauthorized: false` for development only. For better security, always prefer the `ca` solution to accept only your self-signed CA. In production always use valid certificates signed by a trusted CA.
579
581
  ```
580
582
 
581
- **⚠️ Security Warning**: Usa `rejectUnauthorized: false` solo in sviluppo. Per maggiore sicurezza, preferisci sempre la soluzione con `ca` per accettare solo la tua CA self-signed. In produzione usa sempre certificati validi e firmati da una CA attendibile.
583
+ **⚠️ Security Warning**: Use `rejectUnauthorized: false` for development only. For better security, always prefer the `ca` solution to accept only your self-signed CA. In production always use valid certificates signed by a trusted CA.
582
584
 
583
585
  ### Built-in Middlewares
584
586
 
@@ -1,5 +1,11 @@
1
1
  /**
2
- * Example demonstrating how to use RpcClient with self-signed certificates
2
+ * Example demonstratin // Example 3: Best practices
3
+ console.log('3. Best Practices:');
4
+ console.log(' ✓ Always use SSL validation in production');
5
+ console.log(' ✓ Disable validation only for development with self-signed certificates');
6
+ console.log(' ✓ Use environment variables to control SSL behavior');
7
+ console.log(' ✓ Never commit process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0" to production');
8
+ console.log(' ✓ Consider using valid development certificates instead of disabling validation\n');o use RpcClient with self-signed certificates
3
9
  * in development environments.
4
10
  *
5
11
  * WARNING: Only use rejectUnauthorized: false in development!
@@ -20,11 +26,11 @@ async function demonstrateSSLOptions() {
20
26
 
21
27
 
22
28
 
23
- // Example 2: Development client per self-signed certificates (bypassa TUTTA la validazione SSL)
29
+ // Example 2: Development client for self-signed certificates (bypasses ALL SSL validation)
24
30
  console.log('2. Development Client (bypasses SSL validation):');
25
- console.log(' ⚠️ Per bypassare la validazione SSL in Node.js, imposta PRIMA di avviare il client:');
31
+ console.log(' ⚠️ To bypass SSL validation in Node.js, set BEFORE starting the client:');
26
32
  console.log(' process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";');
27
- console.log(' ✓ Tutte le richieste accetteranno certificati self-signed (solo per sviluppo!)\n');
33
+ console.log(' ✓ All requests will accept self-signed certificates (development only!)\n');
28
34
 
29
35
  // Example 3: Best practice
30
36
  console.log('3. Best Practices:');
@@ -41,9 +47,9 @@ async function demonstrateSSLOptions() {
41
47
  const environmentClient = new RpcClient(baseUrl, {
42
48
  'Authorization': `Bearer ${process.env.API_TOKEN || 'default-token'}`,
43
49
  'X-Environment': process.env.NODE_ENV || 'development'
44
- }, isDevelopment ? { ca } : {});
50
+ });
45
51
  console.log(` ✓ Created client for ${isDevelopment ? 'development' : 'production'} environment`);
46
- console.log(` ✓ SSL validation: ${isDevelopment ? 'custom CA (dev only)' : 'enabled (secure)'}\n`);
52
+ console.log(` ✓ SSL validation: ${isDevelopment ? 'controlled by NODE_TLS_REJECT_UNAUTHORIZED' : 'enabled (secure)'}\n`);
47
53
 
48
54
  // Example usage (commented out since we don't have a real server)
49
55
  /*
@@ -56,7 +62,7 @@ async function demonstrateSSLOptions() {
56
62
  }
57
63
  */
58
64
 
59
- console.log('4. Best Practices:');
65
+ console.log('5. Best Practices Summary:');
60
66
  console.log(' ✓ Always use strict SSL validation in production');
61
67
  console.log(' ✓ Only disable SSL validation for development with self-signed certificates');
62
68
  console.log(' ✓ Use environment variables to control SSL behavior');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rpc-express-toolkit",
3
- "version": "2.3.1",
4
- "description": "Enterprise-ready JSON-RPC 2.0 toolkit for Express.js with simplified APIs, structured logging, middleware system, schema validation, comprehensive BigInt/Date support. Semplificato: gestione SSL avanzata rimossa, vedi README.",
3
+ "version": "2.3.3",
4
+ "description": "Enterprise-ready JSON-RPC 2.0 toolkit for Express.js with simplified APIs, structured logging, middleware system, schema validation, comprehensive BigInt/Date support. Advanced SSL options removed, see README.",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
7
7
  "files": [
@@ -52,10 +52,10 @@ class RpcClient {
52
52
 
53
53
  // Store fetch options for Node.js environments
54
54
  this.#fetchOptions = {};
55
- // SSL validation: la gestione avanzata (agent/ca) è rimossa per semplicità e compatibilità.
56
- // Per bypassare i certificati self-signed in sviluppo, imposta:
55
+ // SSL validation: advanced options (agent/ca) have been removed for simplicity and compatibility.
56
+ // To bypass self-signed certificates in development, set:
57
57
  // process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
58
- // Vedi README per dettagli e best practice.
58
+ // See README for details and best practices.
59
59
  }
60
60
 
61
61
  /**
@@ -74,11 +74,11 @@ class RpcClient {
74
74
  * @param {Object} [overrideHeaders={}] Optional headers to override defaults for this request.
75
75
  * @returns {Promise<any>} The result of the RPC call.
76
76
  */
77
- async call(method, params = {}, id = undefined, overrideHeaders = {}) {
77
+ async call(method, params, id = undefined, overrideHeaders = {}) {
78
78
  // Auto-generate ID if not provided (null means notification)
79
79
  const requestId = id === undefined ? this.#generateId() : id;
80
80
 
81
- // Costruisci il payload secondo lo standard: params omesso se undefined/null
81
+ // Build the payload according to the spec: params omitted if undefined/null
82
82
  const requestBody = {
83
83
  jsonrpc: "2.0",
84
84
  method,
@@ -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;#i;constructor(t,e={},r={}){this.#t=t,this.#e={"Content-Type":"application/json",...e},this.#r=1e3*Date.now()+Math.floor(1e3*Math.random()),this.#i={}}#s(){return++this.#r}async call(t,e={},r=void 0,i={}){const s={jsonrpc:"2.0",method:t,id:void 0===r?this.#s():r};null!=e&&(s.params=e);try{const t=await fetchFn(this.#t,{method:"POST",headers:{...this.#e,...i},body:JSON.stringify(s),...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=>{const e={jsonrpc:"2.0",method:t.method,id:void 0!==t.id?t.id:this.#s()};return void 0!==t.params&&null!==t.params&&(e.params=t.params),e});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
+ 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={}){this.#t=t,this.#e={"Content-Type":"application/json",...e},this.#r=1e3*Date.now()+Math.floor(1e3*Math.random()),this.#i={}}#s(){return++this.#r}async call(t,e,r=void 0,i={}){const s={jsonrpc:"2.0",method:t,id:void 0===r?this.#s():r};null!=e&&(s.params=e);try{const t=await fetchFn(this.#t,{method:"POST",headers:{...this.#e,...i},body:JSON.stringify(s),...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=>{const e={jsonrpc:"2.0",method:t.method,id:void 0!==t.id?t.id:this.#s()};return void 0!==t.params&&null!==t.params&&(e.params=t.params),e});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;
package/src/logger.js CHANGED
@@ -100,7 +100,7 @@ class Logger {
100
100
  id,
101
101
  duration: `${duration}ms`,
102
102
  resultType: typeof result,
103
- resultSize: JSON.stringify(result).length
103
+ resultSize: result ? JSON.stringify(result).length : 0
104
104
  });
105
105
  }
106
106