rpc-express-toolkit 2.2.0 → 2.3.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 +16 -0
- package/examples/ssl-development-example.js +12 -21
- package/package.json +7 -3
- package/src/clients/rpc-client.js +4 -23
- package/src/clients/rpc-client.min.js +1 -1
- package/src/clients/rpc-client.min.mjs +1 -1
- package/src/clients/rpc-client.mjs +4 -22
- package/src/index.d.ts +1 -3
package/README.md
CHANGED
|
@@ -91,6 +91,7 @@ app.listen(3000, () => {
|
|
|
91
91
|
});
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
+
|
|
94
95
|
### Client Usage
|
|
95
96
|
|
|
96
97
|
```javascript
|
|
@@ -108,6 +109,21 @@ const client = new RpcClient('/api');
|
|
|
108
109
|
const user = await client.call('getUser', { userId: 123 });
|
|
109
110
|
```
|
|
110
111
|
|
|
112
|
+
#### SSL e certificati self-signed in sviluppo (Node.js)
|
|
113
|
+
|
|
114
|
+
Per bypassare la validazione dei certificati SSL (ad esempio con certificati self-signed in sviluppo), imposta **prima** di avviare il client:
|
|
115
|
+
|
|
116
|
+
```js
|
|
117
|
+
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Attenzione:**
|
|
121
|
+
- Questa impostazione disabilita la validazione SSL per tutte le richieste nel processo Node.js.
|
|
122
|
+
- Usala solo in ambienti di sviluppo!
|
|
123
|
+
- Non committare mai questa impostazione in produzione.
|
|
124
|
+
|
|
125
|
+
Le opzioni avanzate `agent` e `ca` sono state rimosse per semplicità e compatibilità con Node.js moderno.
|
|
126
|
+
|
|
111
127
|
## Advanced Usage
|
|
112
128
|
|
|
113
129
|
### Configuration Options
|
|
@@ -19,29 +19,20 @@ async function demonstrateSSLOptions() {
|
|
|
19
19
|
console.log(' ✓ Created client with strict SSL validation (default)\n');
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
// Example 2: Development client per self-signed certificates (bypassa TUTTA la validazione SSL)
|
|
23
24
|
console.log('2. Development Client (bypasses SSL validation):');
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}, {
|
|
28
|
-
rejectUnauthorized: false // Solo per sviluppo!
|
|
29
|
-
});
|
|
30
|
-
console.log(' ✓ Created client that bypasses SSL certificate validation');
|
|
31
|
-
console.log(' ⚠️ WARNING: Only use this for development with self-signed certificates!\n');
|
|
25
|
+
console.log(' ⚠️ Per bypassare la validazione SSL in Node.js, imposta PRIMA di avviare il client:');
|
|
26
|
+
console.log(' process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";');
|
|
27
|
+
console.log(' ✓ Tutte le richieste accetteranno certificati self-signed (solo per sviluppo!)\n');
|
|
32
28
|
|
|
33
|
-
// Example 3:
|
|
34
|
-
console.log('3.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}, {
|
|
41
|
-
ca // Passa il certificato della tua CA self-signed
|
|
42
|
-
});
|
|
43
|
-
console.log(' ✓ Created client that accepts only your self-signed CA');
|
|
44
|
-
console.log(' ⚠️ WARNING: This is safer than disabling validation, but use valid certificates in production!\n');
|
|
29
|
+
// Example 3: Best practice
|
|
30
|
+
console.log('3. Best Practices:');
|
|
31
|
+
console.log(' ✓ Usa sempre la validazione SSL in produzione');
|
|
32
|
+
console.log(' ✓ Disabilita la validazione solo per sviluppo con self-signed');
|
|
33
|
+
console.log(' ✓ Usa variabili d’ambiente per controllare il comportamento SSL');
|
|
34
|
+
console.log(' ✓ Non committare mai process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0" in produzione');
|
|
35
|
+
console.log(' ✓ Considera l’uso di certificati di sviluppo validi invece di disabilitare la validazione\n');
|
|
45
36
|
|
|
46
37
|
// Example 4: Demonstrate how to choose configuration based on environment
|
|
47
38
|
console.log('4. Environment-based Configuration:');
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rpc-express-toolkit",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Enterprise-ready JSON-RPC 2.0 toolkit for Express.js with simplified APIs, structured logging, middleware system, schema validation,
|
|
3
|
+
"version": "2.3.0",
|
|
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.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "src/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -39,7 +39,11 @@
|
|
|
39
39
|
"validation",
|
|
40
40
|
"bigint",
|
|
41
41
|
"enterprise",
|
|
42
|
-
"nodejs"
|
|
42
|
+
"nodejs",
|
|
43
|
+
"ssl",
|
|
44
|
+
"self-signed",
|
|
45
|
+
"secure",
|
|
46
|
+
"fetch"
|
|
43
47
|
],
|
|
44
48
|
"author": "Nicola Carpanese <nicola.carpanese@gmail.com>",
|
|
45
49
|
"license": "MIT",
|
|
@@ -52,29 +52,10 @@ class RpcClient {
|
|
|
52
52
|
|
|
53
53
|
// Store fetch options for Node.js environments
|
|
54
54
|
this.#fetchOptions = {};
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
// If options.agent is provided, use it directly
|
|
60
|
-
if (options.agent) {
|
|
61
|
-
this.#fetchOptions.agent = options.agent;
|
|
62
|
-
} else if (options.ca) {
|
|
63
|
-
// If options.ca is provided, create an agent with the custom CA
|
|
64
|
-
this.#fetchOptions.agent = new https.Agent({
|
|
65
|
-
ca: options.ca,
|
|
66
|
-
rejectUnauthorized: options.rejectUnauthorized !== false // true by default
|
|
67
|
-
});
|
|
68
|
-
} else if (options.rejectUnauthorized === false) {
|
|
69
|
-
// Legacy: allow disabling SSL validation for dev
|
|
70
|
-
this.#fetchOptions.agent = new https.Agent({
|
|
71
|
-
rejectUnauthorized: false
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
} catch (e) {
|
|
75
|
-
// Ignore if https module is not available
|
|
76
|
-
}
|
|
77
|
-
}
|
|
55
|
+
// SSL validation: la gestione avanzata (agent/ca) è rimossa per semplicità e compatibilità.
|
|
56
|
+
// Per bypassare i certificati self-signed in sviluppo, imposta:
|
|
57
|
+
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
58
|
+
// Vedi README per dettagli e best practice.
|
|
78
59
|
}
|
|
79
60
|
|
|
80
61
|
/**
|
|
@@ -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={}){
|
|
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,params:e,id:void 0===r?this.#s():r};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=>({jsonrpc:"2.0",method:t.method,params:t.params||{},id:void 0!==t.id?t.id:this.#s()}));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;#
|
|
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;#s;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.#s={}}async call(e,r={},s=null,i={}){null===s&&(s=++this.#r);const n={jsonrpc:"2.0",method:e,params:r,id:s};try{const e=await t(this.#t,{method:"POST",headers:{...this.#e,...i},body:JSON.stringify(n),...this.#s});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={},s={}){const i={jsonrpc:"2.0",method:e,params:r};try{const e=await t(this.#t,{method:"POST",headers:{...this.#e,...s},body:JSON.stringify(i),...this.#s});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 s=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(s),...this.#s});if(!e.ok)throw new Error(`HTTP Error: ${e.status} ${e.statusText}`);const i=await e.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("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,s]of Object.entries(t))e[r]=this.serializeBigIntsAndDates(s);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}}
|
|
@@ -53,28 +53,10 @@ export class RpcClient {
|
|
|
53
53
|
|
|
54
54
|
// Store fetch options for Node.js environments
|
|
55
55
|
this.#fetchOptions = {};
|
|
56
|
-
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
}
|
|
56
|
+
// SSL validation: la gestione avanzata (agent/ca) è rimossa per semplicità e compatibilità.
|
|
57
|
+
// Per bypassare i certificati self-signed in sviluppo, imposta:
|
|
58
|
+
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
59
|
+
// Vedi README per dettagli e best practice.
|
|
78
60
|
}
|
|
79
61
|
|
|
80
62
|
/**
|
package/src/index.d.ts
CHANGED
|
@@ -99,9 +99,7 @@ declare class RpcClient {
|
|
|
99
99
|
endpoint: string,
|
|
100
100
|
defaultHeaders?: Record<string, string>,
|
|
101
101
|
options?: {
|
|
102
|
-
|
|
103
|
-
ca?: string | Buffer;
|
|
104
|
-
agent?: any;
|
|
102
|
+
// Opzioni SSL avanzate rimosse: usa process.env.NODE_TLS_REJECT_UNAUTHORIZED per sviluppo
|
|
105
103
|
}
|
|
106
104
|
);
|
|
107
105
|
|