@digitaldefiance/node-express-suite 3.12.12 → 3.12.13
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/package.json +5 -2
- package/src/interfaces/index.d.ts +1 -0
- package/src/interfaces/index.d.ts.map +1 -1
- package/src/interfaces/index.js +1 -0
- package/src/interfaces/index.js.map +1 -1
- package/src/interfaces/network/index.d.ts +3 -0
- package/src/interfaces/network/index.d.ts.map +1 -0
- package/src/interfaces/network/index.js +6 -0
- package/src/interfaces/network/index.js.map +1 -0
- package/src/interfaces/network/upnpService.d.ts +86 -0
- package/src/interfaces/network/upnpService.d.ts.map +1 -0
- package/src/interfaces/network/upnpService.js +3 -0
- package/src/interfaces/network/upnpService.js.map +1 -0
- package/src/interfaces/network/upnpTypes.d.ts +120 -0
- package/src/interfaces/network/upnpTypes.d.ts.map +1 -0
- package/src/interfaces/network/upnpTypes.js +57 -0
- package/src/interfaces/network/upnpTypes.js.map +1 -0
- package/src/plugins/index.d.ts +1 -0
- package/src/plugins/index.d.ts.map +1 -1
- package/src/plugins/index.js +1 -0
- package/src/plugins/index.js.map +1 -1
- package/src/plugins/upnp.d.ts +129 -0
- package/src/plugins/upnp.d.ts.map +1 -0
- package/src/plugins/upnp.js +158 -0
- package/src/plugins/upnp.js.map +1 -0
- package/src/services/index.d.ts +3 -0
- package/src/services/index.d.ts.map +1 -1
- package/src/services/index.js +3 -0
- package/src/services/index.js.map +1 -1
- package/src/services/upnp-config.d.ts +131 -0
- package/src/services/upnp-config.d.ts.map +1 -0
- package/src/services/upnp-config.js +225 -0
- package/src/services/upnp-config.js.map +1 -0
- package/src/services/upnp-manager.d.ts +211 -0
- package/src/services/upnp-manager.d.ts.map +1 -0
- package/src/services/upnp-manager.js +447 -0
- package/src/services/upnp-manager.js.map +1 -0
- package/src/services/upnp.d.ts +241 -0
- package/src/services/upnp.d.ts.map +1 -0
- package/src/services/upnp.js +415 -0
- package/src/services/upnp.js.map +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digitaldefiance/node-express-suite",
|
|
3
|
-
"version": "3.12.
|
|
3
|
+
"version": "3.12.13",
|
|
4
4
|
"homepage": "https://github.com/Digital-Defiance/node-express-suite",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -58,15 +58,18 @@
|
|
|
58
58
|
"mongodb": "^6.20.0",
|
|
59
59
|
"mongodb-memory-server": "^10.1.4",
|
|
60
60
|
"mongoose": "^8.18.2",
|
|
61
|
+
"nat-upnp": "^1.1.1",
|
|
61
62
|
"reflect-metadata": "^0.2.2",
|
|
62
63
|
"zod": "^3.24.0"
|
|
63
64
|
},
|
|
64
65
|
"devDependencies": {
|
|
65
66
|
"@digitaldefiance/express-suite-test-utils": "1.1.1",
|
|
67
|
+
"@types/nat-upnp": "^1.1.5",
|
|
66
68
|
"@typescript-eslint/eslint-plugin": "^8.53.1",
|
|
67
69
|
"@typescript-eslint/parser": "^8.53.1",
|
|
68
70
|
"eslint-plugin-import": "^2.32.0",
|
|
69
|
-
"eslint-plugin-prettier": "^5.5.4"
|
|
71
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
72
|
+
"fast-check": "^4.3.0"
|
|
70
73
|
},
|
|
71
74
|
"files": [
|
|
72
75
|
"src",
|
|
@@ -25,6 +25,7 @@ export * from './jwt-consts';
|
|
|
25
25
|
export * from './jwt-sign-response';
|
|
26
26
|
export * from './models';
|
|
27
27
|
export * from './mongo-errors';
|
|
28
|
+
export * from './network';
|
|
28
29
|
export * from './openApi';
|
|
29
30
|
export * from './request-user';
|
|
30
31
|
export * from './required-string-keys';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yCAAyC,CAAC;AACxD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uCAAuC,CAAC;AACtD,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,yCAAyC,CAAC;AACxD,cAAc,wBAAwB,CAAC;AACvC,cAAc,uCAAuC,CAAC;AACtD,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,cAAc,CAAC;AAC7B,cAAc,qBAAqB,CAAC;AACpC,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,UAAU,CAAC;AACzB,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,kBAAkB,CAAC"}
|
package/src/interfaces/index.js
CHANGED
|
@@ -28,6 +28,7 @@ tslib_1.__exportStar(require("./jwt-consts"), exports);
|
|
|
28
28
|
tslib_1.__exportStar(require("./jwt-sign-response"), exports);
|
|
29
29
|
tslib_1.__exportStar(require("./models"), exports);
|
|
30
30
|
tslib_1.__exportStar(require("./mongo-errors"), exports);
|
|
31
|
+
tslib_1.__exportStar(require("./network"), exports);
|
|
31
32
|
tslib_1.__exportStar(require("./openApi"), exports);
|
|
32
33
|
tslib_1.__exportStar(require("./request-user"), exports);
|
|
33
34
|
tslib_1.__exportStar(require("./required-string-keys"), exports);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/index.ts"],"names":[],"mappings":";;;AAAA,+DAAqC;AACrC,kFAAwD;AACxD,iEAAuC;AACvC,gFAAsD;AACtD,0DAAgC;AAChC,wDAA8B;AAC9B,4DAAkC;AAClC,4DAAkC;AAClC,4DAAkC;AAClC,sDAA4B;AAC5B,8DAAoC;AACpC,+DAAqC;AACrC,uDAA6B;AAC7B,2DAAiC;AACjC,2DAAiC;AACjC,sEAA4C;AAC5C,0DAAgC;AAChC,wDAA8B;AAC9B,8DAAoC;AACpC,4DAAkC;AAClC,uDAA6B;AAC7B,yDAA+B;AAC/B,qEAA2C;AAC3C,uDAA6B;AAC7B,8DAAoC;AACpC,mDAAyB;AACzB,yDAA+B;AAC/B,oDAA0B;AAC1B,yDAA+B;AAC/B,iEAAuC;AACvC,mDAAyB;AACzB,+DAAqC;AACrC,iEAAuC;AACvC,yEAA+C;AAC/C,2DAAiC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/index.ts"],"names":[],"mappings":";;;AAAA,+DAAqC;AACrC,kFAAwD;AACxD,iEAAuC;AACvC,gFAAsD;AACtD,0DAAgC;AAChC,wDAA8B;AAC9B,4DAAkC;AAClC,4DAAkC;AAClC,4DAAkC;AAClC,sDAA4B;AAC5B,8DAAoC;AACpC,+DAAqC;AACrC,uDAA6B;AAC7B,2DAAiC;AACjC,2DAAiC;AACjC,sEAA4C;AAC5C,0DAAgC;AAChC,wDAA8B;AAC9B,8DAAoC;AACpC,4DAAkC;AAClC,uDAA6B;AAC7B,yDAA+B;AAC/B,qEAA2C;AAC3C,uDAA6B;AAC7B,8DAAoC;AACpC,mDAAyB;AACzB,yDAA+B;AAC/B,oDAA0B;AAC1B,oDAA0B;AAC1B,yDAA+B;AAC/B,iEAAuC;AACvC,mDAAyB;AACzB,+DAAqC;AACrC,iEAAuC;AACvC,yEAA+C;AAC/C,2DAAiC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/network/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/network/index.ts"],"names":[],"mappings":";;;AAAA,sDAA4B;AAC5B,wDAA8B"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { IUpnpMapping, PortMappingProtocol } from './upnpTypes';
|
|
2
|
+
/**
|
|
3
|
+
* Interface for UPnP/NAT-PMP port mapping service.
|
|
4
|
+
*
|
|
5
|
+
* Supports protocol auto-detection with fallback between UPnP and NAT-PMP.
|
|
6
|
+
* Implementations should track active mappings in memory and provide
|
|
7
|
+
* cleanup guarantees on close.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { IUpnpService } from '@digitaldefiance/node-express-suite';
|
|
12
|
+
*
|
|
13
|
+
* async function setupPortMapping(service: IUpnpService): Promise<void> {
|
|
14
|
+
* const externalIp = await service.getExternalIp();
|
|
15
|
+
* await service.createPortMapping({
|
|
16
|
+
* public: 3000,
|
|
17
|
+
* private: 3000,
|
|
18
|
+
* protocol: 'tcp',
|
|
19
|
+
* description: 'Express App HTTP',
|
|
20
|
+
* ttl: 3600,
|
|
21
|
+
* });
|
|
22
|
+
* console.log(`Accessible at ${externalIp}:3000`);
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export interface IUpnpService {
|
|
27
|
+
/**
|
|
28
|
+
* Query the router for the external (public) IP address.
|
|
29
|
+
* Results may be cached by the implementation to reduce router queries.
|
|
30
|
+
*
|
|
31
|
+
* @returns The external IP address as a string (e.g. `"203.0.113.42"`)
|
|
32
|
+
* @throws {UpnpServiceClosedError} If the service has been closed
|
|
33
|
+
* @throws {UpnpOperationError} If the IP cannot be retrieved after retries
|
|
34
|
+
*/
|
|
35
|
+
getExternalIp(): Promise<string>;
|
|
36
|
+
/**
|
|
37
|
+
* Create a port mapping on the router.
|
|
38
|
+
*
|
|
39
|
+
* @param mapping - The port mapping configuration to create
|
|
40
|
+
* @throws {PortRangeError} If any port is outside 1-65535
|
|
41
|
+
* @throws {UpnpServiceClosedError} If the service has been closed
|
|
42
|
+
* @throws {UpnpOperationError} If the mapping cannot be created after retries
|
|
43
|
+
*/
|
|
44
|
+
createPortMapping(mapping: IUpnpMapping): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Remove a specific port mapping from the router.
|
|
47
|
+
*
|
|
48
|
+
* @param publicPort - The external port number to unmap
|
|
49
|
+
* @param protocol - The transport protocol of the mapping to remove
|
|
50
|
+
* @throws {PortRangeError} If the port is outside 1-65535
|
|
51
|
+
* @throws {UpnpServiceClosedError} If the service has been closed
|
|
52
|
+
* @throws {UpnpOperationError} If the mapping cannot be removed after retries
|
|
53
|
+
*/
|
|
54
|
+
removePortMapping(publicPort: number, protocol: PortMappingProtocol): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Remove all port mappings created by this service.
|
|
57
|
+
*
|
|
58
|
+
* Attempts to remove each mapping individually. Failures on individual
|
|
59
|
+
* mappings do not prevent removal of remaining mappings.
|
|
60
|
+
*
|
|
61
|
+
* @throws {UpnpServiceClosedError} If the service has been closed
|
|
62
|
+
* @throws {UpnpOperationError} If one or more mappings cannot be removed
|
|
63
|
+
*/
|
|
64
|
+
removeAllMappings(): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Get all active port mappings managed by this service.
|
|
67
|
+
*
|
|
68
|
+
* Returns only mappings tracked in memory by this service instance,
|
|
69
|
+
* not all mappings on the router.
|
|
70
|
+
*
|
|
71
|
+
* @returns Array of active port mappings
|
|
72
|
+
* @throws {UpnpServiceClosedError} If the service has been closed
|
|
73
|
+
*/
|
|
74
|
+
getMappings(): Promise<IUpnpMapping[]>;
|
|
75
|
+
/**
|
|
76
|
+
* Close the UPnP client and release resources.
|
|
77
|
+
*
|
|
78
|
+
* Removes all active mappings before closing the underlying client.
|
|
79
|
+
* Should be called during service shutdown. After calling close,
|
|
80
|
+
* all subsequent operations will throw {@link UpnpServiceClosedError}.
|
|
81
|
+
*
|
|
82
|
+
* @throws {UpnpServiceClosedError} If the service has already been closed
|
|
83
|
+
*/
|
|
84
|
+
close(): Promise<void>;
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=upnpService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upnpService.d.ts","sourceRoot":"","sources":["../../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/network/upnpService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,YAAY;IAC3B;;;;;;;OAOG;IACH,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAEjC;;;;;;;OAOG;IACH,iBAAiB,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExD;;;;;;;;OAQG;IACH,iBAAiB,CACf,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;;;;;OAQG;IACH,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnC;;;;;;;;OAQG;IACH,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAEvC;;;;;;;;OAQG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upnpService.js","sourceRoot":"","sources":["../../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/network/upnpService.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UPnP protocol type for port mapping.
|
|
3
|
+
*
|
|
4
|
+
* Determines which NAT traversal protocol the service should use
|
|
5
|
+
* when communicating with the router.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { UpnpProtocol } from '@digitaldefiance/node-express-suite';
|
|
10
|
+
*
|
|
11
|
+
* // Auto-detect the best available protocol
|
|
12
|
+
* const protocol = UpnpProtocol.AUTO;
|
|
13
|
+
*
|
|
14
|
+
* // Force UPnP (most common)
|
|
15
|
+
* const upnp = UpnpProtocol.UPNP;
|
|
16
|
+
*
|
|
17
|
+
* // Force NAT-PMP (Apple routers)
|
|
18
|
+
* const natpmp = UpnpProtocol.NATPMP;
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare enum UpnpProtocol {
|
|
22
|
+
/** Standard UPnP IGD protocol (most routers) */
|
|
23
|
+
UPNP = "upnp",
|
|
24
|
+
/** NAT-PMP protocol (common on Apple routers) */
|
|
25
|
+
NATPMP = "natpmp",
|
|
26
|
+
/** Auto-detect: try UPnP first, fall back to NAT-PMP */
|
|
27
|
+
AUTO = "auto"
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Transport protocol for port mappings.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```typescript
|
|
34
|
+
* const protocol: PortMappingProtocol = 'tcp';
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export type PortMappingProtocol = 'tcp' | 'udp';
|
|
38
|
+
/**
|
|
39
|
+
* Represents a single UPnP port mapping on the router.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const mapping: IUpnpMapping = {
|
|
44
|
+
* public: 3000,
|
|
45
|
+
* private: 3000,
|
|
46
|
+
* protocol: 'tcp',
|
|
47
|
+
* description: 'Express App HTTP',
|
|
48
|
+
* ttl: 3600,
|
|
49
|
+
* };
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export interface IUpnpMapping {
|
|
53
|
+
/** External (public) port number */
|
|
54
|
+
public: number;
|
|
55
|
+
/** Internal (private) port number */
|
|
56
|
+
private: number;
|
|
57
|
+
/** Transport protocol */
|
|
58
|
+
protocol: PortMappingProtocol;
|
|
59
|
+
/** Human-readable description of the mapping */
|
|
60
|
+
description: string;
|
|
61
|
+
/** Time-to-live in seconds */
|
|
62
|
+
ttl: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* UPnP service configuration.
|
|
66
|
+
*
|
|
67
|
+
* All fields have sensible defaults provided by {@link UPNP_CONFIG_DEFAULTS}.
|
|
68
|
+
* In production, values are typically loaded from environment variables
|
|
69
|
+
* via {@link UpnpConfig.fromEnvironment}.
|
|
70
|
+
*
|
|
71
|
+
* @see UPNP_CONFIG_DEFAULTS for default values
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* const config: IUpnpConfig = {
|
|
76
|
+
* enabled: true,
|
|
77
|
+
* httpPort: 8080,
|
|
78
|
+
* websocketPort: 8080,
|
|
79
|
+
* ttl: 3600,
|
|
80
|
+
* refreshInterval: 1800000,
|
|
81
|
+
* protocol: UpnpProtocol.AUTO,
|
|
82
|
+
* retryAttempts: 3,
|
|
83
|
+
* retryDelay: 5000,
|
|
84
|
+
* };
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export interface IUpnpConfig {
|
|
88
|
+
/** Whether UPnP is enabled */
|
|
89
|
+
enabled: boolean;
|
|
90
|
+
/** HTTP/Express port to map */
|
|
91
|
+
httpPort: number;
|
|
92
|
+
/** WebSocket port to map */
|
|
93
|
+
websocketPort: number;
|
|
94
|
+
/** Mapping time-to-live in seconds */
|
|
95
|
+
ttl: number;
|
|
96
|
+
/** Refresh interval in milliseconds */
|
|
97
|
+
refreshInterval: number;
|
|
98
|
+
/** UPnP protocol to use */
|
|
99
|
+
protocol: UpnpProtocol;
|
|
100
|
+
/** Number of retry attempts */
|
|
101
|
+
retryAttempts: number;
|
|
102
|
+
/** Delay between retries in milliseconds */
|
|
103
|
+
retryDelay: number;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Default UPnP configuration values.
|
|
107
|
+
*
|
|
108
|
+
* Used as fallback when environment variables are not set.
|
|
109
|
+
* UPnP is disabled by default (opt-in).
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```typescript
|
|
113
|
+
* import { UPNP_CONFIG_DEFAULTS } from '@digitaldefiance/node-express-suite';
|
|
114
|
+
*
|
|
115
|
+
* // Use defaults with overrides
|
|
116
|
+
* const config = { ...UPNP_CONFIG_DEFAULTS, enabled: true, httpPort: 8080 };
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare const UPNP_CONFIG_DEFAULTS: Readonly<IUpnpConfig>;
|
|
120
|
+
//# sourceMappingURL=upnpTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upnpTypes.d.ts","sourceRoot":"","sources":["../../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/network/upnpTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,oBAAY,YAAY;IACtB,gDAAgD;IAChD,IAAI,SAAS;IACb,iDAAiD;IACjD,MAAM,WAAW;IACjB,wDAAwD;IACxD,IAAI,SAAS;CACd;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAAG,KAAK,GAAG,KAAK,CAAC;AAEhD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,gDAAgD;IAChD,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,WAAW;IAC1B,8BAA8B;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,+BAA+B;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,eAAe,EAAE,MAAM,CAAC;IACxB,2BAA2B;IAC3B,QAAQ,EAAE,YAAY,CAAC;IACvB,+BAA+B;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,WAAW,CAS7C,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UPNP_CONFIG_DEFAULTS = exports.UpnpProtocol = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* UPnP protocol type for port mapping.
|
|
6
|
+
*
|
|
7
|
+
* Determines which NAT traversal protocol the service should use
|
|
8
|
+
* when communicating with the router.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import { UpnpProtocol } from '@digitaldefiance/node-express-suite';
|
|
13
|
+
*
|
|
14
|
+
* // Auto-detect the best available protocol
|
|
15
|
+
* const protocol = UpnpProtocol.AUTO;
|
|
16
|
+
*
|
|
17
|
+
* // Force UPnP (most common)
|
|
18
|
+
* const upnp = UpnpProtocol.UPNP;
|
|
19
|
+
*
|
|
20
|
+
* // Force NAT-PMP (Apple routers)
|
|
21
|
+
* const natpmp = UpnpProtocol.NATPMP;
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
var UpnpProtocol;
|
|
25
|
+
(function (UpnpProtocol) {
|
|
26
|
+
/** Standard UPnP IGD protocol (most routers) */
|
|
27
|
+
UpnpProtocol["UPNP"] = "upnp";
|
|
28
|
+
/** NAT-PMP protocol (common on Apple routers) */
|
|
29
|
+
UpnpProtocol["NATPMP"] = "natpmp";
|
|
30
|
+
/** Auto-detect: try UPnP first, fall back to NAT-PMP */
|
|
31
|
+
UpnpProtocol["AUTO"] = "auto";
|
|
32
|
+
})(UpnpProtocol || (exports.UpnpProtocol = UpnpProtocol = {}));
|
|
33
|
+
/**
|
|
34
|
+
* Default UPnP configuration values.
|
|
35
|
+
*
|
|
36
|
+
* Used as fallback when environment variables are not set.
|
|
37
|
+
* UPnP is disabled by default (opt-in).
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { UPNP_CONFIG_DEFAULTS } from '@digitaldefiance/node-express-suite';
|
|
42
|
+
*
|
|
43
|
+
* // Use defaults with overrides
|
|
44
|
+
* const config = { ...UPNP_CONFIG_DEFAULTS, enabled: true, httpPort: 8080 };
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
exports.UPNP_CONFIG_DEFAULTS = {
|
|
48
|
+
enabled: false,
|
|
49
|
+
httpPort: 3000,
|
|
50
|
+
websocketPort: 3000,
|
|
51
|
+
ttl: 3600,
|
|
52
|
+
refreshInterval: 1800000,
|
|
53
|
+
protocol: UpnpProtocol.AUTO,
|
|
54
|
+
retryAttempts: 3,
|
|
55
|
+
retryDelay: 5000,
|
|
56
|
+
};
|
|
57
|
+
//# sourceMappingURL=upnpTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upnpTypes.js","sourceRoot":"","sources":["../../../../../../packages/digitaldefiance-node-express-suite/src/interfaces/network/upnpTypes.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,IAAY,YAOX;AAPD,WAAY,YAAY;IACtB,gDAAgD;IAChD,6BAAa,CAAA;IACb,iDAAiD;IACjD,iCAAiB,CAAA;IACjB,wDAAwD;IACxD,6BAAa,CAAA;AACf,CAAC,EAPW,YAAY,4BAAZ,YAAY,QAOvB;AAiFD;;;;;;;;;;;;;GAaG;AACU,QAAA,oBAAoB,GAA0B;IACzD,OAAO,EAAE,KAAK;IACd,QAAQ,EAAE,IAAI;IACd,aAAa,EAAE,IAAI;IACnB,GAAG,EAAE,IAAI;IACT,eAAe,EAAE,OAAO;IACxB,QAAQ,EAAE,YAAY,CAAC,IAAI;IAC3B,aAAa,EAAE,CAAC;IAChB,UAAU,EAAE,IAAI;CACR,CAAC"}
|
package/src/plugins/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/plugins/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/plugins/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,QAAQ,CAAC"}
|
package/src/plugins/index.js
CHANGED
|
@@ -3,4 +3,5 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./plugin-interface"), exports);
|
|
5
5
|
tslib_1.__exportStar(require("./plugin-manager"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./upnp"), exports);
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/src/plugins/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/plugins/index.ts"],"names":[],"mappings":";;;AAAA,6DAAmC;AACnC,2DAAiC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/plugins/index.ts"],"names":[],"mappings":";;;AAAA,6DAAmC;AACnC,2DAAiC;AACjC,iDAAuB"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UPnP Plugin for the express-suite plugin system.
|
|
3
|
+
*
|
|
4
|
+
* Integrates the UPnP port mapping lifecycle (UpnpManager) with the
|
|
5
|
+
* application plugin system. Register this plugin to automatically
|
|
6
|
+
* manage UPnP port mappings during application startup and shutdown.
|
|
7
|
+
*
|
|
8
|
+
* Requirements: 5.1, 5.2, 5.3, 5.4, 5.5
|
|
9
|
+
*
|
|
10
|
+
* @module plugins/upnp
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { UpnpPlugin } from '@digitaldefiance/node-express-suite';
|
|
15
|
+
*
|
|
16
|
+
* // Register with defaults (reads config from environment)
|
|
17
|
+
* app.plugins.register(new UpnpPlugin());
|
|
18
|
+
*
|
|
19
|
+
* // Register with config overrides
|
|
20
|
+
* app.plugins.register(new UpnpPlugin({
|
|
21
|
+
* config: { enabled: true, httpPort: 8080 },
|
|
22
|
+
* descriptionPrefix: 'My App',
|
|
23
|
+
* }));
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
import type { PlatformID } from '@digitaldefiance/node-ecies-lib';
|
|
27
|
+
import { IApplication } from '../interfaces/application';
|
|
28
|
+
import { IApplicationPlugin } from './plugin-interface';
|
|
29
|
+
import { UpnpManager } from '../services/upnp-manager';
|
|
30
|
+
import { IUpnpConfig } from '../interfaces/network/upnpTypes';
|
|
31
|
+
/**
|
|
32
|
+
* Options for configuring the UPnP plugin.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const options: UpnpPluginOptions = {
|
|
37
|
+
* config: { enabled: true, httpPort: 8080 },
|
|
38
|
+
* descriptionPrefix: 'My App',
|
|
39
|
+
* };
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export interface UpnpPluginOptions {
|
|
43
|
+
/** Override config instead of reading from environment */
|
|
44
|
+
config?: Partial<IUpnpConfig>;
|
|
45
|
+
/** Description prefix for port mapping labels */
|
|
46
|
+
descriptionPrefix?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* UPnP plugin implementing {@link IApplicationPlugin}.
|
|
50
|
+
*
|
|
51
|
+
* Manages UPnP port mapping lifecycle through the express-suite plugin system.
|
|
52
|
+
* On `init`, reads configuration (from environment or overrides) and starts
|
|
53
|
+
* the UpnpManager. On `stop`, shuts down the manager and removes mappings.
|
|
54
|
+
*
|
|
55
|
+
* @template TID - Platform ID type (defaults to Buffer)
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const plugin = new UpnpPlugin({ descriptionPrefix: 'My App' });
|
|
60
|
+
* pluginManager.register(plugin);
|
|
61
|
+
*
|
|
62
|
+
* // After init, access the manager for endpoint queries
|
|
63
|
+
* const endpoints = await plugin.getManager()?.getExternalEndpoints();
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare class UpnpPlugin<TID extends PlatformID = Buffer> implements IApplicationPlugin<TID> {
|
|
67
|
+
readonly name = "upnp";
|
|
68
|
+
readonly version = "1.0.0";
|
|
69
|
+
private manager;
|
|
70
|
+
private readonly options;
|
|
71
|
+
/**
|
|
72
|
+
* Create a new UpnpPlugin.
|
|
73
|
+
*
|
|
74
|
+
* @param options - Optional plugin configuration
|
|
75
|
+
*/
|
|
76
|
+
constructor(options?: UpnpPluginOptions);
|
|
77
|
+
/**
|
|
78
|
+
* Initialize the UPnP plugin.
|
|
79
|
+
*
|
|
80
|
+
* Builds configuration from environment variables (with optional overrides),
|
|
81
|
+
* creates a UpnpManager, and initializes port mappings.
|
|
82
|
+
*
|
|
83
|
+
* If UPnP is disabled in the configuration, skips initialization and logs
|
|
84
|
+
* a message.
|
|
85
|
+
*
|
|
86
|
+
* **Validates: Requirements 5.2, 5.4, 5.5**
|
|
87
|
+
*
|
|
88
|
+
* @param _app - The application instance (unused, config comes from env)
|
|
89
|
+
*/
|
|
90
|
+
init(_app: IApplication<TID>): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Stop the UPnP plugin.
|
|
93
|
+
*
|
|
94
|
+
* Shuts down the UpnpManager, removing all port mappings and cleaning up.
|
|
95
|
+
*
|
|
96
|
+
* **Validates: Requirement 5.3**
|
|
97
|
+
*/
|
|
98
|
+
stop(): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Get the underlying UpnpManager instance.
|
|
101
|
+
*
|
|
102
|
+
* Returns `null` if the plugin has not been initialized or UPnP is disabled.
|
|
103
|
+
* Use this to query external endpoints or inspect manager state.
|
|
104
|
+
*
|
|
105
|
+
* @returns The UpnpManager instance, or `null` if not initialized
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* const manager = plugin.getManager();
|
|
110
|
+
* if (manager) {
|
|
111
|
+
* const endpoints = await manager.getExternalEndpoints();
|
|
112
|
+
* console.log(endpoints);
|
|
113
|
+
* }
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
getManager(): UpnpManager | null;
|
|
117
|
+
/**
|
|
118
|
+
* Convert a partial IUpnpConfig into environment variable overrides.
|
|
119
|
+
*
|
|
120
|
+
* Maps each defined config field to its corresponding `UPNP_*` environment
|
|
121
|
+
* variable name, converting values to strings. These overrides are merged
|
|
122
|
+
* with `process.env` before passing to `UpnpConfig.fromEnvironment`.
|
|
123
|
+
*
|
|
124
|
+
* @param config - Partial configuration with fields to override
|
|
125
|
+
* @returns Record of environment variable name → string value
|
|
126
|
+
*/
|
|
127
|
+
private envOverridesFromConfig;
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=upnp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upnp.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/plugins/upnp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAE9D;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,MAAM,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9B,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,UAAU,CACrB,GAAG,SAAS,UAAU,GAAG,MAAM,CAC/B,YAAW,kBAAkB,CAAC,GAAG,CAAC;IAClC,QAAQ,CAAC,IAAI,UAAU;IACvB,QAAQ,CAAC,OAAO,WAAW;IAE3B,OAAO,CAAC,OAAO,CAA4B;IAC3C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAE5C;;;;OAIG;gBACS,OAAO,CAAC,EAAE,iBAAiB;IAIvC;;;;;;;;;;;;OAYG;IACG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBlD;;;;;;OAMG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B;;;;;;;;;;;;;;;;OAgBG;IACH,UAAU,IAAI,WAAW,GAAG,IAAI;IAIhC;;;;;;;;;OASG;IACH,OAAO,CAAC,sBAAsB;CAoB/B"}
|