@theotherwillembotha/node-red-nginxproxymanager 0.0.52

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.
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NginxHttpClient = exports.NginxApiError = void 0;
4
+ class NginxApiError extends Error {
5
+ constructor(statusCode, apiMessage) {
6
+ super(`Nginx Proxy Manager API error ${statusCode}: ${apiMessage}`);
7
+ this.statusCode = statusCode;
8
+ this.apiMessage = apiMessage;
9
+ this.name = "NginxApiError";
10
+ }
11
+ }
12
+ exports.NginxApiError = NginxApiError;
13
+ /**
14
+ * Low-level HTTP transport for the Nginx Proxy Manager API.
15
+ * Handles authentication, token caching, and automatic re-auth on expiry.
16
+ */
17
+ class NginxHttpClient {
18
+ constructor(baseUrl, email, password) {
19
+ this.baseUrl = baseUrl;
20
+ this.email = email;
21
+ this.password = password;
22
+ this.token = null;
23
+ this.tokenExpires = null;
24
+ }
25
+ // ─── Auth ─────────────────────────────────────────────────────────────────
26
+ isTokenValid() {
27
+ if (!this.token || !this.tokenExpires)
28
+ return false;
29
+ // Refresh 30 seconds before actual expiry to avoid races
30
+ return this.tokenExpires.getTime() - Date.now() > 30_000;
31
+ }
32
+ async authenticate() {
33
+ const body = { identity: this.email, secret: this.password };
34
+ const response = await fetch(`${this.baseUrl}/api/tokens`, {
35
+ method: "POST",
36
+ headers: { "Content-Type": "application/json" },
37
+ body: JSON.stringify(body),
38
+ });
39
+ if (!response.ok) {
40
+ const text = await response.text();
41
+ throw new NginxApiError(response.status, text);
42
+ }
43
+ const data = (await response.json());
44
+ this.token = data.token;
45
+ this.tokenExpires = new Date(data.expires);
46
+ }
47
+ async ensureAuthenticated() {
48
+ if (!this.isTokenValid()) {
49
+ await this.authenticate();
50
+ }
51
+ }
52
+ // ─── Core request ─────────────────────────────────────────────────────────
53
+ async request(method, path, body) {
54
+ await this.ensureAuthenticated();
55
+ const headers = {
56
+ Authorization: `Bearer ${this.token}`,
57
+ "Content-Type": "application/json",
58
+ };
59
+ const init = { method, headers };
60
+ if (body !== undefined) {
61
+ init.body = JSON.stringify(body);
62
+ }
63
+ const response = await fetch(`${this.baseUrl}/api${path}`, init);
64
+ if (!response.ok) {
65
+ let message;
66
+ try {
67
+ const errBody = (await response.json());
68
+ message = errBody?.error?.message ?? response.statusText;
69
+ }
70
+ catch {
71
+ message = response.statusText;
72
+ }
73
+ throw new NginxApiError(response.status, message);
74
+ }
75
+ // 204 No Content
76
+ if (response.status === 204) {
77
+ return undefined;
78
+ }
79
+ return response.json();
80
+ }
81
+ // ─── HTTP verbs ───────────────────────────────────────────────────────────
82
+ get(path) {
83
+ return this.request("GET", path);
84
+ }
85
+ post(path, body) {
86
+ return this.request("POST", path, body);
87
+ }
88
+ put(path, body) {
89
+ return this.request("PUT", path, body);
90
+ }
91
+ delete(path) {
92
+ return this.request("DELETE", path);
93
+ }
94
+ }
95
+ exports.NginxHttpClient = NginxHttpClient;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // ─── Common ──────────────────────────────────────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
Binary file
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "@theotherwillembotha/node-red-nginxproxymanager",
3
+ "version": "0.0.52",
4
+ "description": "Node-RED nodes for managing Nginx Proxy Manager hosts, built on node-red-plugincore.",
5
+ "author": "Willem Botha (@theotherwillembotha)",
6
+ "license": "ISC",
7
+ "keywords": [
8
+ "node-red",
9
+ "nginx",
10
+ "nginx-proxy-manager",
11
+ "reverse-proxy",
12
+ "proxy"
13
+ ],
14
+ "main": "./build/index.js",
15
+ "exports": "./build/index.js",
16
+ "scripts": {
17
+ "test": "echo \"Error: no test specified\" && exit 1",
18
+ "build": "npm run clean && tsc && npm run generate-nodes && npm run copy-files",
19
+ "clean": "rm -rf ./build",
20
+ "generate-nodes": "node build/GenerateNodes.js",
21
+ "copy-files": "cp -r ./icons ./build/"
22
+ },
23
+ "files": [
24
+ "build/",
25
+ "icons/",
26
+ "LICENSE",
27
+ "README.md"
28
+ ],
29
+ "repository": {
30
+ "type": "git",
31
+ "url": "https://github.com/theotherwillembotha/nodered_nginxproxymanager.git"
32
+ },
33
+ "bugs": {
34
+ "url": "https://github.com/theotherwillembotha/nodered_nginxproxymanager/issues"
35
+ },
36
+ "homepage": "https://github.com/theotherwillembotha/nodered_nginxproxymanager#readme",
37
+ "engines": {
38
+ "node": ">=18",
39
+ "nodered": ">=4.0.0"
40
+ },
41
+ "dependencies": {
42
+ "@theotherwillembotha/node-red-plugincore": "^0.0.52"
43
+ },
44
+ "devDependencies": {
45
+ "@theotherwillembotha/node-red-plugincore": "../nodered_plugincore",
46
+ "@types/md5": "^2.3.5",
47
+ "@types/node": "^22.15.16",
48
+ "@types/node-red": "~1.3.5"
49
+ },
50
+ "node-red": {
51
+ "version": ">=4.0.0",
52
+ "nodes": {
53
+ "nginx": "./build/Nodes.js"
54
+ },
55
+ "plugins": {
56
+ "nginx": "./build/Plugins.js"
57
+ }
58
+ }
59
+ }