@iebh/tera-fy 1.8.0 → 1.9.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ # [1.9.0](https://github.com/IEBH/TERA-fy/compare/v1.8.0...v1.9.0) (2024-06-06)
4
+
5
+
6
+ ### Features
7
+
8
+ * **proxy:** Better in-use port detection + custom logging handler ([8bfa2d3](https://github.com/IEBH/TERA-fy/commit/8bfa2d3923ef8a71dff04983113eca0b8cff606f))
9
+
3
10
  # [1.8.0](https://github.com/IEBH/TERA-fy/compare/v1.7.4...v1.8.0) (2024-06-04)
4
11
 
5
12
 
@@ -1,3 +1,5 @@
1
+ import {create as createDomain} from 'node:domain';
2
+ import detectPort from 'detect-port';
1
3
  import Proxy from 'http-proxy';
2
4
 
3
5
  export class TeraProxy {
@@ -12,6 +14,8 @@ export class TeraProxy {
12
14
  * @param {String} [options.targetProtocol='https'] Target protocol to forward to
13
15
  * @param {String} [options.targetHost='tera-tools.com'] Target host to forward to
14
16
  * @param {Number} [options.targetPort=443] Target port to forward to
17
+ * @param {'ignore'|'throw'} [options.portConflict='ignore'] Action to take when something is already listening on the allocated port
18
+ * @param {Function} [options.onLog=console.log] Function to call with any logging output. Defaults to using console.log. Called as `(level:'INFO|'WARN', ...msg:any)`
15
19
  *
16
20
  * @returns {VitePlugin}
17
21
  */
@@ -23,6 +27,8 @@ export class TeraProxy {
23
27
  targetProtocol: 'https',
24
28
  targetHost: 'tera-tools.com',
25
29
  targetPort: 443,
30
+ portConflict: 'ignore',
31
+ onLog: (level, ...msg) => console.log(...msg),
26
32
  }
27
33
 
28
34
 
@@ -35,23 +41,50 @@ export class TeraProxy {
35
41
 
36
42
  /**
37
43
  * Boot the proxy
44
+ *
45
+ * @returns {Promise} A promise which resolves when the operation has completed
38
46
  */
39
47
  start() {
40
- if (this.proxyServer && !this.settings.force) return; // Server already running skip
41
-
42
- // Create proxy pass-thru
43
- this.proxyServer = Proxy.createProxyServer({
44
- changeOrigin: true,
45
- target: {
46
- protocol: this.settings.targetProtocol + ':',
47
- host: this.settings.targetHost,
48
- port: this.settings.targetPort,
49
- },
50
- });
48
+ if (this.proxyServer && !this.settings.force) return Promise.resolve(); // Server already running skip
51
49
 
52
- this.proxyServer.listen(this.settings.port, ()=> {
53
- console.log('Routing TERA traffic from', `http://${this.settings.host}:${this.settings.port}`, '→', `${this.settings.targetProtocol}://${this.settings.targetHost}:${this.settings.targetPort}`);
54
- });
50
+ return Promise.resolve()
51
+ .then(()=> detectPort(this.settings.port))
52
+ .then(gotPort => gotPort != this.settings.port && Promise.reject('PORT-CONFLICT'))
53
+ .then(() => this.proxyServer = Proxy.createProxyServer({ // Create proxy pass-thru
54
+ changeOrigin: true,
55
+ target: {
56
+ protocol: this.settings.targetProtocol + ':',
57
+ host: this.settings.targetHost,
58
+ port: this.settings.targetPort,
59
+ },
60
+ }))
61
+ .then(()=> new Promise((resolve, reject) => {
62
+ // Wrap listener in a domain so we can correctly catch EADDRINUSE
63
+ let domain = createDomain();
64
+ domain.on('error', err => {
65
+ if (err.code == 'EADDRINUSE') {
66
+ throw 'PORT-CONFLICT';
67
+ } else {
68
+ throw err;
69
+ }
70
+ });
71
+ this.proxyServer.listen(this.settings.port, ()=> {
72
+ this.settings.onLog('INFO', 'Routing TERA traffic from', `http://${this.settings.host}:${this.settings.port}`, '→', `${this.settings.targetProtocol}://${this.settings.targetHost}:${this.settings.targetPort}`);
73
+ resolve();
74
+ })
75
+ }))
76
+ .catch(e => {
77
+ if (e === 'PORT-CONFLICT') {
78
+ if (this.settings.portConflict == 'ignore') {
79
+ this.settings.onLog('WARN', 'Port', this.settings.port, 'is already allocated - assuming TERA is already running locally and skipping proxy');
80
+ return false; // Do nothing
81
+ } else {
82
+ throw err;
83
+ }
84
+ } else {
85
+ throw e; // Re-throw everything else
86
+ }
87
+ })
55
88
  }
56
89
 
57
90
 
@@ -59,8 +92,9 @@ export class TeraProxy {
59
92
  * Stop the proxy server
60
93
  * @returns {Promise} A promise which will resolve when the close operation has completed
61
94
  */
62
- async stop() {
63
- if (this.proxyServer) await new Promise(resolve => this.proxyServer.close(()=> resolve()));
95
+ stop() {
96
+ return Promise.resolve()
97
+ .then(()=> this.proxyServer && new Promise(resolve => this.proxyServer.close(()=> resolve())))
64
98
  }
65
99
 
66
100
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iebh/tera-fy",
3
- "version": "1.8.0",
3
+ "version": "1.9.0",
4
4
  "description": "TERA website worker",
5
5
  "scripts": {
6
6
  "dev": "esbuild --platform=browser --format=esm --bundle lib/terafy.client.js --outfile=dist/terafy.js --minify --serve --servedir=.",
@@ -69,6 +69,7 @@
69
69
  "node": ">=18"
70
70
  },
71
71
  "dependencies": {
72
+ "detect-port": "^1.6.1",
72
73
  "filesize": "^10.1.1",
73
74
  "http-proxy": "^1.18.1",
74
75
  "just-diff": "^6.0.2",