@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
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* UPnP Plugin for the express-suite plugin system.
|
|
4
|
+
*
|
|
5
|
+
* Integrates the UPnP port mapping lifecycle (UpnpManager) with the
|
|
6
|
+
* application plugin system. Register this plugin to automatically
|
|
7
|
+
* manage UPnP port mappings during application startup and shutdown.
|
|
8
|
+
*
|
|
9
|
+
* Requirements: 5.1, 5.2, 5.3, 5.4, 5.5
|
|
10
|
+
*
|
|
11
|
+
* @module plugins/upnp
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { UpnpPlugin } from '@digitaldefiance/node-express-suite';
|
|
16
|
+
*
|
|
17
|
+
* // Register with defaults (reads config from environment)
|
|
18
|
+
* app.plugins.register(new UpnpPlugin());
|
|
19
|
+
*
|
|
20
|
+
* // Register with config overrides
|
|
21
|
+
* app.plugins.register(new UpnpPlugin({
|
|
22
|
+
* config: { enabled: true, httpPort: 8080 },
|
|
23
|
+
* descriptionPrefix: 'My App',
|
|
24
|
+
* }));
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.UpnpPlugin = void 0;
|
|
29
|
+
const upnp_config_1 = require("../services/upnp-config");
|
|
30
|
+
const upnp_manager_1 = require("../services/upnp-manager");
|
|
31
|
+
/**
|
|
32
|
+
* UPnP plugin implementing {@link IApplicationPlugin}.
|
|
33
|
+
*
|
|
34
|
+
* Manages UPnP port mapping lifecycle through the express-suite plugin system.
|
|
35
|
+
* On `init`, reads configuration (from environment or overrides) and starts
|
|
36
|
+
* the UpnpManager. On `stop`, shuts down the manager and removes mappings.
|
|
37
|
+
*
|
|
38
|
+
* @template TID - Platform ID type (defaults to Buffer)
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```typescript
|
|
42
|
+
* const plugin = new UpnpPlugin({ descriptionPrefix: 'My App' });
|
|
43
|
+
* pluginManager.register(plugin);
|
|
44
|
+
*
|
|
45
|
+
* // After init, access the manager for endpoint queries
|
|
46
|
+
* const endpoints = await plugin.getManager()?.getExternalEndpoints();
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
class UpnpPlugin {
|
|
50
|
+
name = 'upnp';
|
|
51
|
+
version = '1.0.0';
|
|
52
|
+
manager = null;
|
|
53
|
+
options;
|
|
54
|
+
/**
|
|
55
|
+
* Create a new UpnpPlugin.
|
|
56
|
+
*
|
|
57
|
+
* @param options - Optional plugin configuration
|
|
58
|
+
*/
|
|
59
|
+
constructor(options) {
|
|
60
|
+
this.options = options ?? {};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Initialize the UPnP plugin.
|
|
64
|
+
*
|
|
65
|
+
* Builds configuration from environment variables (with optional overrides),
|
|
66
|
+
* creates a UpnpManager, and initializes port mappings.
|
|
67
|
+
*
|
|
68
|
+
* If UPnP is disabled in the configuration, skips initialization and logs
|
|
69
|
+
* a message.
|
|
70
|
+
*
|
|
71
|
+
* **Validates: Requirements 5.2, 5.4, 5.5**
|
|
72
|
+
*
|
|
73
|
+
* @param _app - The application instance (unused, config comes from env)
|
|
74
|
+
*/
|
|
75
|
+
async init(_app) {
|
|
76
|
+
// Build config: use override if provided, else load from environment
|
|
77
|
+
const config = this.options.config
|
|
78
|
+
? upnp_config_1.UpnpConfig.fromEnvironment({
|
|
79
|
+
...process.env,
|
|
80
|
+
...this.envOverridesFromConfig(this.options.config),
|
|
81
|
+
})
|
|
82
|
+
: upnp_config_1.UpnpConfig.fromEnvironment();
|
|
83
|
+
if (!config.enabled) {
|
|
84
|
+
console.log('[UPnP Plugin] UPnP is disabled, skipping initialization');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
this.manager = new upnp_manager_1.UpnpManager({
|
|
88
|
+
config,
|
|
89
|
+
descriptionPrefix: this.options.descriptionPrefix,
|
|
90
|
+
});
|
|
91
|
+
await this.manager.initialize();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Stop the UPnP plugin.
|
|
95
|
+
*
|
|
96
|
+
* Shuts down the UpnpManager, removing all port mappings and cleaning up.
|
|
97
|
+
*
|
|
98
|
+
* **Validates: Requirement 5.3**
|
|
99
|
+
*/
|
|
100
|
+
async stop() {
|
|
101
|
+
if (this.manager) {
|
|
102
|
+
await this.manager.shutdown();
|
|
103
|
+
this.manager = null;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Get the underlying UpnpManager instance.
|
|
108
|
+
*
|
|
109
|
+
* Returns `null` if the plugin has not been initialized or UPnP is disabled.
|
|
110
|
+
* Use this to query external endpoints or inspect manager state.
|
|
111
|
+
*
|
|
112
|
+
* @returns The UpnpManager instance, or `null` if not initialized
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```typescript
|
|
116
|
+
* const manager = plugin.getManager();
|
|
117
|
+
* if (manager) {
|
|
118
|
+
* const endpoints = await manager.getExternalEndpoints();
|
|
119
|
+
* console.log(endpoints);
|
|
120
|
+
* }
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
getManager() {
|
|
124
|
+
return this.manager;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Convert a partial IUpnpConfig into environment variable overrides.
|
|
128
|
+
*
|
|
129
|
+
* Maps each defined config field to its corresponding `UPNP_*` environment
|
|
130
|
+
* variable name, converting values to strings. These overrides are merged
|
|
131
|
+
* with `process.env` before passing to `UpnpConfig.fromEnvironment`.
|
|
132
|
+
*
|
|
133
|
+
* @param config - Partial configuration with fields to override
|
|
134
|
+
* @returns Record of environment variable name → string value
|
|
135
|
+
*/
|
|
136
|
+
envOverridesFromConfig(config) {
|
|
137
|
+
const env = {};
|
|
138
|
+
if (config.enabled !== undefined)
|
|
139
|
+
env['UPNP_ENABLED'] = String(config.enabled);
|
|
140
|
+
if (config.httpPort !== undefined)
|
|
141
|
+
env['UPNP_HTTP_PORT'] = String(config.httpPort);
|
|
142
|
+
if (config.websocketPort !== undefined)
|
|
143
|
+
env['UPNP_WEBSOCKET_PORT'] = String(config.websocketPort);
|
|
144
|
+
if (config.ttl !== undefined)
|
|
145
|
+
env['UPNP_TTL'] = String(config.ttl);
|
|
146
|
+
if (config.refreshInterval !== undefined)
|
|
147
|
+
env['UPNP_REFRESH_INTERVAL'] = String(config.refreshInterval);
|
|
148
|
+
if (config.protocol !== undefined)
|
|
149
|
+
env['UPNP_PROTOCOL'] = config.protocol;
|
|
150
|
+
if (config.retryAttempts !== undefined)
|
|
151
|
+
env['UPNP_RETRY_ATTEMPTS'] = String(config.retryAttempts);
|
|
152
|
+
if (config.retryDelay !== undefined)
|
|
153
|
+
env['UPNP_RETRY_DELAY'] = String(config.retryDelay);
|
|
154
|
+
return env;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
exports.UpnpPlugin = UpnpPlugin;
|
|
158
|
+
//# sourceMappingURL=upnp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upnp.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/plugins/upnp.ts"],"names":[],"mappings":"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"}
|
package/src/services/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,OAAO,CAAC;AACtB,cAAc,qBAAqB,CAAC;AACpC,cAAc,OAAO,CAAC;AACtB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,YAAY,CAAC;AAC3B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,OAAO,CAAC;AACtB,cAAc,qBAAqB,CAAC;AACpC,cAAc,OAAO,CAAC;AACtB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC"}
|
package/src/services/index.js
CHANGED
|
@@ -19,4 +19,7 @@ tslib_1.__exportStar(require("./symmetric"), exports);
|
|
|
19
19
|
tslib_1.__exportStar(require("./system-user"), exports);
|
|
20
20
|
tslib_1.__exportStar(require("./user"), exports);
|
|
21
21
|
tslib_1.__exportStar(require("./xor"), exports);
|
|
22
|
+
tslib_1.__exportStar(require("./upnp"), exports);
|
|
23
|
+
tslib_1.__exportStar(require("./upnp-config"), exports);
|
|
24
|
+
tslib_1.__exportStar(require("./upnp-manager"), exports);
|
|
22
25
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/services/index.ts"],"names":[],"mappings":";;;AAAA,wDAA8B;AAC9B,iDAAuB;AACvB,qDAA2B;AAC3B,oEAA0C;AAC1C,0DAAgC;AAChC,+DAAqC;AACrC,gEAAsC;AACtC,gDAAsB;AACtB,8DAAoC;AACpC,gDAAsB;AACtB,yDAA+B;AAC/B,qDAA2B;AAC3B,yDAA+B;AAC/B,iDAAuB;AACvB,sDAA4B;AAC5B,wDAA8B;AAC9B,iDAAuB;AACvB,gDAAsB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/services/index.ts"],"names":[],"mappings":";;;AAAA,wDAA8B;AAC9B,iDAAuB;AACvB,qDAA2B;AAC3B,oEAA0C;AAC1C,0DAAgC;AAChC,+DAAqC;AACrC,gEAAsC;AACtC,gDAAsB;AACtB,8DAAoC;AACpC,gDAAsB;AACtB,yDAA+B;AAC/B,qDAA2B;AAC3B,yDAA+B;AAC/B,iDAAuB;AACvB,sDAA4B;AAC5B,wDAA8B;AAC9B,iDAAuB;AACvB,gDAAsB;AACtB,iDAAuB;AACvB,wDAA8B;AAC9B,yDAA+B"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UPnP Configuration Loader and Validator.
|
|
3
|
+
*
|
|
4
|
+
* Reads UPnP settings from environment variables, applies defaults
|
|
5
|
+
* for missing values, and validates all configuration parameters.
|
|
6
|
+
* Use the static {@link UpnpConfig.fromEnvironment} factory method
|
|
7
|
+
* to create validated instances.
|
|
8
|
+
*
|
|
9
|
+
* Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9
|
|
10
|
+
*/
|
|
11
|
+
import { IUpnpConfig, UpnpProtocol } from '../interfaces/network/upnpTypes';
|
|
12
|
+
/**
|
|
13
|
+
* Error thrown when UPnP configuration validation fails.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* try {
|
|
18
|
+
* const config = UpnpConfig.fromEnvironment({ UPNP_HTTP_PORT: '99999' });
|
|
19
|
+
* } catch (err) {
|
|
20
|
+
* if (err instanceof UpnpConfigValidationError) {
|
|
21
|
+
* console.error(`Invalid config: ${err.message}`);
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class UpnpConfigValidationError extends Error {
|
|
27
|
+
/**
|
|
28
|
+
* @param message - Description of the validation failure
|
|
29
|
+
*/
|
|
30
|
+
constructor(message: string);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* UPnP configuration loaded from environment variables.
|
|
34
|
+
*
|
|
35
|
+
* Reads `UPNP_*` env vars, falls back to {@link UPNP_CONFIG_DEFAULTS},
|
|
36
|
+
* and validates all values on construction. Use the static
|
|
37
|
+
* {@link UpnpConfig.fromEnvironment} factory method to create instances.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* // Load from process.env (production usage)
|
|
42
|
+
* const config = UpnpConfig.fromEnvironment();
|
|
43
|
+
*
|
|
44
|
+
* // Load from custom env (testing)
|
|
45
|
+
* const testConfig = UpnpConfig.fromEnvironment({
|
|
46
|
+
* UPNP_ENABLED: 'true',
|
|
47
|
+
* UPNP_HTTP_PORT: '8080',
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* console.log(config.enabled); // false (default)
|
|
51
|
+
* console.log(config.httpPort); // 3000 (default)
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export declare class UpnpConfig implements IUpnpConfig {
|
|
55
|
+
/** Whether UPnP is enabled */
|
|
56
|
+
readonly enabled: boolean;
|
|
57
|
+
/** HTTP/Express port to map externally */
|
|
58
|
+
readonly httpPort: number;
|
|
59
|
+
/** WebSocket port to map externally */
|
|
60
|
+
readonly websocketPort: number;
|
|
61
|
+
/** Mapping time-to-live in seconds */
|
|
62
|
+
readonly ttl: number;
|
|
63
|
+
/** Refresh interval in milliseconds */
|
|
64
|
+
readonly refreshInterval: number;
|
|
65
|
+
/** UPnP protocol to use (upnp, natpmp, or auto) */
|
|
66
|
+
readonly protocol: UpnpProtocol;
|
|
67
|
+
/** Number of retry attempts for failed operations */
|
|
68
|
+
readonly retryAttempts: number;
|
|
69
|
+
/** Delay between retries in milliseconds */
|
|
70
|
+
readonly retryDelay: number;
|
|
71
|
+
/**
|
|
72
|
+
* Private constructor — use {@link UpnpConfig.fromEnvironment} to create instances.
|
|
73
|
+
*
|
|
74
|
+
* @param config - Validated configuration values
|
|
75
|
+
*/
|
|
76
|
+
private constructor();
|
|
77
|
+
/**
|
|
78
|
+
* Create an UpnpConfig from the current process environment.
|
|
79
|
+
* Missing variables fall back to {@link UPNP_CONFIG_DEFAULTS}.
|
|
80
|
+
*
|
|
81
|
+
* @param env - Environment variable map (defaults to `process.env`)
|
|
82
|
+
* @returns A validated UpnpConfig instance
|
|
83
|
+
* @throws {UpnpConfigValidationError} If any value is invalid
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* // Use process.env
|
|
88
|
+
* const config = UpnpConfig.fromEnvironment();
|
|
89
|
+
*
|
|
90
|
+
* // Use custom env for testing
|
|
91
|
+
* const config = UpnpConfig.fromEnvironment({
|
|
92
|
+
* UPNP_ENABLED: 'true',
|
|
93
|
+
* UPNP_HTTP_PORT: '8080',
|
|
94
|
+
* UPNP_TTL: '7200',
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
static fromEnvironment(env?: Record<string, string | undefined>): UpnpConfig;
|
|
99
|
+
/**
|
|
100
|
+
* Validate all configuration values. Throws on the first invalid value.
|
|
101
|
+
*
|
|
102
|
+
* @param config - The configuration object to validate
|
|
103
|
+
* @throws {UpnpConfigValidationError} If any value is outside its valid range:
|
|
104
|
+
* - `httpPort` / `websocketPort`: must be 1–65535
|
|
105
|
+
* - `ttl`: must be 60–86400 seconds (24 hours max)
|
|
106
|
+
* - `refreshInterval`: must be positive and less than `ttl * 1000`
|
|
107
|
+
* - `retryAttempts`: must be 1–10
|
|
108
|
+
* - `retryDelay`: must be 1000–60000 ms
|
|
109
|
+
* - `protocol`: must be a valid {@link UpnpProtocol} value
|
|
110
|
+
*/
|
|
111
|
+
static validate(config: IUpnpConfig): void;
|
|
112
|
+
/**
|
|
113
|
+
* Parse a string environment variable as an integer.
|
|
114
|
+
*
|
|
115
|
+
* @param value - The raw environment variable value
|
|
116
|
+
* @param fallback - Default value when the variable is undefined or empty
|
|
117
|
+
* @returns The parsed integer or the fallback value
|
|
118
|
+
* @throws {UpnpConfigValidationError} If the value is not a valid integer
|
|
119
|
+
*/
|
|
120
|
+
private static parseIntEnv;
|
|
121
|
+
/**
|
|
122
|
+
* Parse a string environment variable as a {@link UpnpProtocol} value.
|
|
123
|
+
*
|
|
124
|
+
* @param value - The raw environment variable value
|
|
125
|
+
* @param fallback - Default protocol when the variable is undefined or empty
|
|
126
|
+
* @returns The parsed protocol or the fallback value
|
|
127
|
+
* @throws {UpnpConfigValidationError} If the value is not a valid protocol
|
|
128
|
+
*/
|
|
129
|
+
private static parseProtocol;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=upnp-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upnp-config.d.ts","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/services/upnp-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,WAAW,EAEX,YAAY,EACb,MAAM,iCAAiC,CAAC;AAEzC;;;;;;;;;;;;;GAaG;AACH,qBAAa,yBAA0B,SAAQ,KAAK;IAClD;;OAEG;gBACS,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,UAAW,YAAW,WAAW;IAC5C,8BAA8B;IAC9B,SAAgB,OAAO,EAAE,OAAO,CAAC;IACjC,0CAA0C;IAC1C,SAAgB,QAAQ,EAAE,MAAM,CAAC;IACjC,uCAAuC;IACvC,SAAgB,aAAa,EAAE,MAAM,CAAC;IACtC,sCAAsC;IACtC,SAAgB,GAAG,EAAE,MAAM,CAAC;IAC5B,uCAAuC;IACvC,SAAgB,eAAe,EAAE,MAAM,CAAC;IACxC,mDAAmD;IACnD,SAAgB,QAAQ,EAAE,YAAY,CAAC;IACvC,qDAAqD;IACrD,SAAgB,aAAa,EAAE,MAAM,CAAC;IACtC,4CAA4C;IAC5C,SAAgB,UAAU,EAAE,MAAM,CAAC;IAEnC;;;;OAIG;IACH,OAAO;IAWP;;;;;;;;;;;;;;;;;;;;OAoBG;WACW,eAAe,CAC3B,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GACpD,UAAU;IAqCb;;;;;;;;;;;OAWG;WACW,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IA8EjD;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAgB1B;;;;;;;OAOG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;CAgB7B"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* UPnP Configuration Loader and Validator.
|
|
4
|
+
*
|
|
5
|
+
* Reads UPnP settings from environment variables, applies defaults
|
|
6
|
+
* for missing values, and validates all configuration parameters.
|
|
7
|
+
* Use the static {@link UpnpConfig.fromEnvironment} factory method
|
|
8
|
+
* to create validated instances.
|
|
9
|
+
*
|
|
10
|
+
* Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.UpnpConfig = exports.UpnpConfigValidationError = void 0;
|
|
14
|
+
const upnpTypes_1 = require("../interfaces/network/upnpTypes");
|
|
15
|
+
/**
|
|
16
|
+
* Error thrown when UPnP configuration validation fails.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* try {
|
|
21
|
+
* const config = UpnpConfig.fromEnvironment({ UPNP_HTTP_PORT: '99999' });
|
|
22
|
+
* } catch (err) {
|
|
23
|
+
* if (err instanceof UpnpConfigValidationError) {
|
|
24
|
+
* console.error(`Invalid config: ${err.message}`);
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
class UpnpConfigValidationError extends Error {
|
|
30
|
+
/**
|
|
31
|
+
* @param message - Description of the validation failure
|
|
32
|
+
*/
|
|
33
|
+
constructor(message) {
|
|
34
|
+
super(message);
|
|
35
|
+
this.name = 'UpnpConfigValidationError';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.UpnpConfigValidationError = UpnpConfigValidationError;
|
|
39
|
+
/**
|
|
40
|
+
* UPnP configuration loaded from environment variables.
|
|
41
|
+
*
|
|
42
|
+
* Reads `UPNP_*` env vars, falls back to {@link UPNP_CONFIG_DEFAULTS},
|
|
43
|
+
* and validates all values on construction. Use the static
|
|
44
|
+
* {@link UpnpConfig.fromEnvironment} factory method to create instances.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* // Load from process.env (production usage)
|
|
49
|
+
* const config = UpnpConfig.fromEnvironment();
|
|
50
|
+
*
|
|
51
|
+
* // Load from custom env (testing)
|
|
52
|
+
* const testConfig = UpnpConfig.fromEnvironment({
|
|
53
|
+
* UPNP_ENABLED: 'true',
|
|
54
|
+
* UPNP_HTTP_PORT: '8080',
|
|
55
|
+
* });
|
|
56
|
+
*
|
|
57
|
+
* console.log(config.enabled); // false (default)
|
|
58
|
+
* console.log(config.httpPort); // 3000 (default)
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
class UpnpConfig {
|
|
62
|
+
/** Whether UPnP is enabled */
|
|
63
|
+
enabled;
|
|
64
|
+
/** HTTP/Express port to map externally */
|
|
65
|
+
httpPort;
|
|
66
|
+
/** WebSocket port to map externally */
|
|
67
|
+
websocketPort;
|
|
68
|
+
/** Mapping time-to-live in seconds */
|
|
69
|
+
ttl;
|
|
70
|
+
/** Refresh interval in milliseconds */
|
|
71
|
+
refreshInterval;
|
|
72
|
+
/** UPnP protocol to use (upnp, natpmp, or auto) */
|
|
73
|
+
protocol;
|
|
74
|
+
/** Number of retry attempts for failed operations */
|
|
75
|
+
retryAttempts;
|
|
76
|
+
/** Delay between retries in milliseconds */
|
|
77
|
+
retryDelay;
|
|
78
|
+
/**
|
|
79
|
+
* Private constructor — use {@link UpnpConfig.fromEnvironment} to create instances.
|
|
80
|
+
*
|
|
81
|
+
* @param config - Validated configuration values
|
|
82
|
+
*/
|
|
83
|
+
constructor(config) {
|
|
84
|
+
this.enabled = config.enabled;
|
|
85
|
+
this.httpPort = config.httpPort;
|
|
86
|
+
this.websocketPort = config.websocketPort;
|
|
87
|
+
this.ttl = config.ttl;
|
|
88
|
+
this.refreshInterval = config.refreshInterval;
|
|
89
|
+
this.protocol = config.protocol;
|
|
90
|
+
this.retryAttempts = config.retryAttempts;
|
|
91
|
+
this.retryDelay = config.retryDelay;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Create an UpnpConfig from the current process environment.
|
|
95
|
+
* Missing variables fall back to {@link UPNP_CONFIG_DEFAULTS}.
|
|
96
|
+
*
|
|
97
|
+
* @param env - Environment variable map (defaults to `process.env`)
|
|
98
|
+
* @returns A validated UpnpConfig instance
|
|
99
|
+
* @throws {UpnpConfigValidationError} If any value is invalid
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* ```typescript
|
|
103
|
+
* // Use process.env
|
|
104
|
+
* const config = UpnpConfig.fromEnvironment();
|
|
105
|
+
*
|
|
106
|
+
* // Use custom env for testing
|
|
107
|
+
* const config = UpnpConfig.fromEnvironment({
|
|
108
|
+
* UPNP_ENABLED: 'true',
|
|
109
|
+
* UPNP_HTTP_PORT: '8080',
|
|
110
|
+
* UPNP_TTL: '7200',
|
|
111
|
+
* });
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
static fromEnvironment(env = process.env) {
|
|
115
|
+
const config = {
|
|
116
|
+
enabled: env['UPNP_ENABLED'] !== undefined
|
|
117
|
+
? env['UPNP_ENABLED'].toLowerCase() === 'true'
|
|
118
|
+
: upnpTypes_1.UPNP_CONFIG_DEFAULTS.enabled,
|
|
119
|
+
httpPort: UpnpConfig.parseIntEnv(env['UPNP_HTTP_PORT'], upnpTypes_1.UPNP_CONFIG_DEFAULTS.httpPort),
|
|
120
|
+
websocketPort: UpnpConfig.parseIntEnv(env['UPNP_WEBSOCKET_PORT'], upnpTypes_1.UPNP_CONFIG_DEFAULTS.websocketPort),
|
|
121
|
+
ttl: UpnpConfig.parseIntEnv(env['UPNP_TTL'], upnpTypes_1.UPNP_CONFIG_DEFAULTS.ttl),
|
|
122
|
+
refreshInterval: UpnpConfig.parseIntEnv(env['UPNP_REFRESH_INTERVAL'], upnpTypes_1.UPNP_CONFIG_DEFAULTS.refreshInterval),
|
|
123
|
+
protocol: UpnpConfig.parseProtocol(env['UPNP_PROTOCOL'], upnpTypes_1.UPNP_CONFIG_DEFAULTS.protocol),
|
|
124
|
+
retryAttempts: UpnpConfig.parseIntEnv(env['UPNP_RETRY_ATTEMPTS'], upnpTypes_1.UPNP_CONFIG_DEFAULTS.retryAttempts),
|
|
125
|
+
retryDelay: UpnpConfig.parseIntEnv(env['UPNP_RETRY_DELAY'], upnpTypes_1.UPNP_CONFIG_DEFAULTS.retryDelay),
|
|
126
|
+
};
|
|
127
|
+
UpnpConfig.validate(config);
|
|
128
|
+
return new UpnpConfig(config);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Validate all configuration values. Throws on the first invalid value.
|
|
132
|
+
*
|
|
133
|
+
* @param config - The configuration object to validate
|
|
134
|
+
* @throws {UpnpConfigValidationError} If any value is outside its valid range:
|
|
135
|
+
* - `httpPort` / `websocketPort`: must be 1–65535
|
|
136
|
+
* - `ttl`: must be 60–86400 seconds (24 hours max)
|
|
137
|
+
* - `refreshInterval`: must be positive and less than `ttl * 1000`
|
|
138
|
+
* - `retryAttempts`: must be 1–10
|
|
139
|
+
* - `retryDelay`: must be 1000–60000 ms
|
|
140
|
+
* - `protocol`: must be a valid {@link UpnpProtocol} value
|
|
141
|
+
*/
|
|
142
|
+
static validate(config) {
|
|
143
|
+
// Port validation (1–65535)
|
|
144
|
+
if (!Number.isInteger(config.httpPort) ||
|
|
145
|
+
config.httpPort < 1 ||
|
|
146
|
+
config.httpPort > 65535) {
|
|
147
|
+
throw new UpnpConfigValidationError(`httpPort must be an integer between 1 and 65535, got ${config.httpPort}`);
|
|
148
|
+
}
|
|
149
|
+
if (!Number.isInteger(config.websocketPort) ||
|
|
150
|
+
config.websocketPort < 1 ||
|
|
151
|
+
config.websocketPort > 65535) {
|
|
152
|
+
throw new UpnpConfigValidationError(`websocketPort must be an integer between 1 and 65535, got ${config.websocketPort}`);
|
|
153
|
+
}
|
|
154
|
+
// TTL validation (minimum 60 seconds, maximum 86400 seconds / 24 hours)
|
|
155
|
+
if (!Number.isInteger(config.ttl) ||
|
|
156
|
+
config.ttl < 60 ||
|
|
157
|
+
config.ttl > 86400) {
|
|
158
|
+
throw new UpnpConfigValidationError(`ttl must be an integer between 60 and 86400 seconds (24 hours), got ${config.ttl}`);
|
|
159
|
+
}
|
|
160
|
+
// Refresh interval must be less than TTL * 1000 (TTL is seconds, refresh is ms)
|
|
161
|
+
if (!Number.isInteger(config.refreshInterval) ||
|
|
162
|
+
config.refreshInterval <= 0) {
|
|
163
|
+
throw new UpnpConfigValidationError(`refreshInterval must be a positive integer, got ${config.refreshInterval}`);
|
|
164
|
+
}
|
|
165
|
+
if (config.refreshInterval >= config.ttl * 1000) {
|
|
166
|
+
throw new UpnpConfigValidationError(`refreshInterval (${config.refreshInterval}ms) must be less than ttl * 1000 (${config.ttl * 1000}ms)`);
|
|
167
|
+
}
|
|
168
|
+
// Retry attempts (1–10)
|
|
169
|
+
if (!Number.isInteger(config.retryAttempts) ||
|
|
170
|
+
config.retryAttempts < 1 ||
|
|
171
|
+
config.retryAttempts > 10) {
|
|
172
|
+
throw new UpnpConfigValidationError(`retryAttempts must be an integer between 1 and 10, got ${config.retryAttempts}`);
|
|
173
|
+
}
|
|
174
|
+
// Retry delay (1000–60000ms)
|
|
175
|
+
if (!Number.isInteger(config.retryDelay) ||
|
|
176
|
+
config.retryDelay < 1000 ||
|
|
177
|
+
config.retryDelay > 60000) {
|
|
178
|
+
throw new UpnpConfigValidationError(`retryDelay must be an integer between 1000 and 60000ms, got ${config.retryDelay}`);
|
|
179
|
+
}
|
|
180
|
+
// Protocol validation
|
|
181
|
+
const validProtocols = Object.values(upnpTypes_1.UpnpProtocol);
|
|
182
|
+
if (!validProtocols.includes(config.protocol)) {
|
|
183
|
+
throw new UpnpConfigValidationError(`protocol must be one of ${validProtocols.join(', ')}, got ${config.protocol}`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Parse a string environment variable as an integer.
|
|
188
|
+
*
|
|
189
|
+
* @param value - The raw environment variable value
|
|
190
|
+
* @param fallback - Default value when the variable is undefined or empty
|
|
191
|
+
* @returns The parsed integer or the fallback value
|
|
192
|
+
* @throws {UpnpConfigValidationError} If the value is not a valid integer
|
|
193
|
+
*/
|
|
194
|
+
static parseIntEnv(value, fallback) {
|
|
195
|
+
if (value === undefined || value === '') {
|
|
196
|
+
return fallback;
|
|
197
|
+
}
|
|
198
|
+
const parsed = Number.parseInt(value, 10);
|
|
199
|
+
if (Number.isNaN(parsed)) {
|
|
200
|
+
throw new UpnpConfigValidationError(`Expected integer value, got "${value}"`);
|
|
201
|
+
}
|
|
202
|
+
return parsed;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Parse a string environment variable as a {@link UpnpProtocol} value.
|
|
206
|
+
*
|
|
207
|
+
* @param value - The raw environment variable value
|
|
208
|
+
* @param fallback - Default protocol when the variable is undefined or empty
|
|
209
|
+
* @returns The parsed protocol or the fallback value
|
|
210
|
+
* @throws {UpnpConfigValidationError} If the value is not a valid protocol
|
|
211
|
+
*/
|
|
212
|
+
static parseProtocol(value, fallback) {
|
|
213
|
+
if (value === undefined || value === '') {
|
|
214
|
+
return fallback;
|
|
215
|
+
}
|
|
216
|
+
const lower = value.toLowerCase();
|
|
217
|
+
const validProtocols = Object.values(upnpTypes_1.UpnpProtocol);
|
|
218
|
+
if (!validProtocols.includes(lower)) {
|
|
219
|
+
throw new UpnpConfigValidationError(`protocol must be one of ${validProtocols.join(', ')}, got "${value}"`);
|
|
220
|
+
}
|
|
221
|
+
return lower;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
exports.UpnpConfig = UpnpConfig;
|
|
225
|
+
//# sourceMappingURL=upnp-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upnp-config.js","sourceRoot":"","sources":["../../../../../packages/digitaldefiance-node-express-suite/src/services/upnp-config.ts"],"names":[],"mappings":"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"}
|