@platformatic/basic 3.41.0 → 3.43.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/config.d.ts +1 -0
- package/lib/capability.js +36 -6
- package/lib/schema.js +11 -0
- package/lib/worker/child-process.js +19 -6
- package/lib/worker/listeners.js +10 -3
- package/package.json +5 -5
- package/schema.json +4 -1
package/config.d.ts
CHANGED
package/lib/capability.js
CHANGED
|
@@ -21,6 +21,7 @@ import { tracingChannel } from 'node:diagnostics_channel'
|
|
|
21
21
|
import EventEmitter, { once } from 'node:events'
|
|
22
22
|
import { existsSync } from 'node:fs'
|
|
23
23
|
import { platform } from 'node:os'
|
|
24
|
+
import { isAbsolute, resolve } from 'node:path'
|
|
24
25
|
import { pathToFileURL } from 'node:url'
|
|
25
26
|
import { workerData } from 'node:worker_threads'
|
|
26
27
|
import pino from 'pino'
|
|
@@ -101,7 +102,7 @@ export class BaseCapability extends EventEmitter {
|
|
|
101
102
|
this.subprocessForceClose = false
|
|
102
103
|
this.subprocessTerminationSignal = 'SIGINT'
|
|
103
104
|
this.logger = this._initializeLogger()
|
|
104
|
-
this.reuseTcpPorts = this.config.reuseTcpPorts ?? this.runtimeConfig.reuseTcpPorts
|
|
105
|
+
this.reuseTcpPorts = (this.config.reuseTcpPorts ?? this.runtimeConfig.reuseTcpPorts) && features.node.reusePort
|
|
105
106
|
// True by default, can be overridden in subclasses. If false, it takes precedence over the runtime configuration
|
|
106
107
|
this.exitOnUnhandledErrors = true
|
|
107
108
|
|
|
@@ -132,7 +133,9 @@ export class BaseCapability extends EventEmitter {
|
|
|
132
133
|
setCustomHealthCheck: this.setCustomHealthCheck.bind(this),
|
|
133
134
|
setCustomReadinessCheck: this.setCustomReadinessCheck.bind(this),
|
|
134
135
|
notifyConfig: this.notifyConfig.bind(this),
|
|
135
|
-
logger: this.logger
|
|
136
|
+
logger: this.logger,
|
|
137
|
+
isEntrypoint: this.isEntrypoint,
|
|
138
|
+
reuseTcpPorts: this.reuseTcpPorts
|
|
136
139
|
})
|
|
137
140
|
|
|
138
141
|
if (globalThis.platformatic.prometheus) {
|
|
@@ -541,7 +544,8 @@ export class BaseCapability extends EventEmitter {
|
|
|
541
544
|
})
|
|
542
545
|
|
|
543
546
|
const [url, clientWs] = await once(this.childManager, 'url')
|
|
544
|
-
|
|
547
|
+
|
|
548
|
+
this.url = this._getEntrypointUrl(url)
|
|
545
549
|
this.clientWs = clientWs
|
|
546
550
|
|
|
547
551
|
await this._collectMetrics()
|
|
@@ -606,9 +610,8 @@ export class BaseCapability extends EventEmitter {
|
|
|
606
610
|
runtimeBasePath: this.runtimeConfig?.basePath ?? null,
|
|
607
611
|
wantsAbsoluteUrls: meta.gateway?.wantsAbsoluteUrls ?? false,
|
|
608
612
|
exitOnUnhandledErrors: this.runtimeConfig.exitOnUnhandledErrors ?? true,
|
|
609
|
-
/* c8 ignore next 2 - else */
|
|
610
|
-
port: (this.isEntrypoint ? this.serverConfig?.port || 0 : undefined) ?? true,
|
|
611
613
|
host: (this.isEntrypoint ? this.serverConfig?.hostname : undefined) ?? true,
|
|
614
|
+
port: this.serverConfig && typeof this.serverConfig.port === 'number' ? this.serverConfig.port : true,
|
|
612
615
|
additionalServerOptions:
|
|
613
616
|
typeof this.serverConfig?.backlog === 'number'
|
|
614
617
|
? {
|
|
@@ -655,7 +658,7 @@ export class BaseCapability extends EventEmitter {
|
|
|
655
658
|
// This is not really important for the URL but sometimes it also a sign
|
|
656
659
|
// that the process has been replaced and thus we need to update the client WebSocket
|
|
657
660
|
childManager.on('url', (url, clientWs) => {
|
|
658
|
-
this.url = url
|
|
661
|
+
this.url = this._getEntrypointUrl(url)
|
|
659
662
|
this.clientWs = clientWs
|
|
660
663
|
})
|
|
661
664
|
}
|
|
@@ -668,6 +671,16 @@ export class BaseCapability extends EventEmitter {
|
|
|
668
671
|
// This ensures subprocess uses the same Node.js version as the parent
|
|
669
672
|
if (executable === 'node') {
|
|
670
673
|
executable = process.execPath
|
|
674
|
+
// Search for the command in node_modules if needed
|
|
675
|
+
} else if (!isAbsolute(executable) && this.config.application?.preferLocalCommands) {
|
|
676
|
+
const applicationExecutable = resolve(this.root, 'node_modules', '.bin', executable)
|
|
677
|
+
const projectExecutable = resolve(process.cwd(), 'node_modules', '.bin', executable)
|
|
678
|
+
|
|
679
|
+
if (existsSync(applicationExecutable)) {
|
|
680
|
+
executable = applicationExecutable
|
|
681
|
+
} else if (existsSync(projectExecutable)) {
|
|
682
|
+
executable = projectExecutable
|
|
683
|
+
}
|
|
671
684
|
}
|
|
672
685
|
|
|
673
686
|
/* c8 ignore next 3 */
|
|
@@ -780,6 +793,23 @@ export class BaseCapability extends EventEmitter {
|
|
|
780
793
|
return promise
|
|
781
794
|
}
|
|
782
795
|
|
|
796
|
+
_getEntrypointUrl (raw) {
|
|
797
|
+
const port = this.config.application?.entrypointPort
|
|
798
|
+
|
|
799
|
+
if (typeof port !== 'number') {
|
|
800
|
+
return raw
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
const url = new URL(raw)
|
|
804
|
+
|
|
805
|
+
if (url.hostname === '[::]' || url.hostname === '0.0.0.0') {
|
|
806
|
+
url.hostname = 'localhost'
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
url.port = this.config.application.entrypointPort
|
|
810
|
+
return url.toString()
|
|
811
|
+
}
|
|
812
|
+
|
|
783
813
|
async #collectMetrics () {
|
|
784
814
|
const metricsConfig = {
|
|
785
815
|
defaultMetrics: true,
|
package/lib/schema.js
CHANGED
|
@@ -57,6 +57,17 @@ const buildableApplication = {
|
|
|
57
57
|
},
|
|
58
58
|
default: {},
|
|
59
59
|
additionalProperties: false
|
|
60
|
+
},
|
|
61
|
+
entrypointPort: {
|
|
62
|
+
type: 'number'
|
|
63
|
+
},
|
|
64
|
+
changeDirectoryBeforeExecution: {
|
|
65
|
+
type: 'boolean',
|
|
66
|
+
default: false
|
|
67
|
+
},
|
|
68
|
+
preferLocalCommands: {
|
|
69
|
+
type: 'boolean',
|
|
70
|
+
default: true
|
|
60
71
|
}
|
|
61
72
|
},
|
|
62
73
|
additionalProperties: false,
|
|
@@ -15,6 +15,7 @@ import { hostname, platform, tmpdir } from 'node:os'
|
|
|
15
15
|
import { basename, join, resolve } from 'node:path'
|
|
16
16
|
import { Duplex } from 'node:stream'
|
|
17
17
|
import { fileURLToPath } from 'node:url'
|
|
18
|
+
import { isMainThread } from 'node:worker_threads'
|
|
18
19
|
import pino from 'pino'
|
|
19
20
|
import { Agent, Pool, setGlobalDispatcher } from 'undici'
|
|
20
21
|
import { WebSocket } from 'ws'
|
|
@@ -369,7 +370,7 @@ export class ChildProcess extends ITC {
|
|
|
369
370
|
// Create a duplex stream that sends output via notify
|
|
370
371
|
const replStream = new Duplex({
|
|
371
372
|
read () {},
|
|
372
|
-
write: (chunk,
|
|
373
|
+
write: (chunk, _encoding, callback) => {
|
|
373
374
|
this.notify('repl:output', { data: chunk.toString() })
|
|
374
375
|
callback()
|
|
375
376
|
}
|
|
@@ -434,7 +435,7 @@ export class ChildProcess extends ITC {
|
|
|
434
435
|
let promise = null
|
|
435
436
|
const timeout = 1000
|
|
436
437
|
|
|
437
|
-
const sendHealthSignal = async
|
|
438
|
+
const sendHealthSignal = async signal => {
|
|
438
439
|
if (typeof signal !== 'object') {
|
|
439
440
|
throw new Error('Health signal must be an object')
|
|
440
441
|
}
|
|
@@ -513,13 +514,21 @@ export class ChildProcess extends ITC {
|
|
|
513
514
|
return
|
|
514
515
|
}
|
|
515
516
|
|
|
516
|
-
|
|
517
|
+
let port = globalThis.platformatic.port
|
|
517
518
|
const host = globalThis.platformatic.host
|
|
519
|
+
const isEntrypoint = globalThis.platformatic.isEntrypoint
|
|
518
520
|
const additionalOptions = globalThis.platformatic.additionalServerOptions ?? {}
|
|
519
521
|
|
|
520
|
-
if (port !== false) {
|
|
521
|
-
|
|
522
|
-
|
|
522
|
+
if (typeof port !== 'number' && port !== false) {
|
|
523
|
+
port = 0
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// Check if we need to override the port only if a static port is being requested
|
|
527
|
+
if (port !== false && port !== 0) {
|
|
528
|
+
// The user application has requested a specific port, which is not the entrypoint one. Override it.
|
|
529
|
+
if (options.port !== port && isEntrypoint) {
|
|
530
|
+
options.port = port
|
|
531
|
+
}
|
|
523
532
|
}
|
|
524
533
|
|
|
525
534
|
if (typeof host === 'string') {
|
|
@@ -711,6 +720,10 @@ async function main () {
|
|
|
711
720
|
await importFile(script)
|
|
712
721
|
}
|
|
713
722
|
|
|
723
|
+
if (data.config.application?.changeDirectoryBeforeExecution && data.root && isMainThread) {
|
|
724
|
+
process.chdir(fileURLToPath(data.root))
|
|
725
|
+
}
|
|
726
|
+
|
|
714
727
|
const childProcess = new ChildProcess(executable)
|
|
715
728
|
globalThis[Symbol.for('plt.children.itc')] = childProcess
|
|
716
729
|
globalThis.platformatic.itc = childProcess
|
package/lib/worker/listeners.js
CHANGED
|
@@ -10,15 +10,22 @@ export function createServerListener (overridePort = true, overrideHost = false,
|
|
|
10
10
|
return
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
if (overridePort !== false) {
|
|
14
|
-
|
|
15
|
-
options.port = hasFixedPort ? overridePort : 0
|
|
13
|
+
if (typeof overridePort !== 'number' && overridePort !== false) {
|
|
14
|
+
overridePort = 0
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
if (typeof overrideHost === 'string') {
|
|
19
18
|
options.host = overrideHost
|
|
20
19
|
}
|
|
21
20
|
|
|
21
|
+
// Check if we need to override the port only if a static port is being requested
|
|
22
|
+
if (overridePort !== false && overridePort !== 0) {
|
|
23
|
+
// The user application has requested a specific port, which is not the entrypoint one. Override it.
|
|
24
|
+
if (options.port !== overridePort && globalThis.platformatic.isEntrypoint) {
|
|
25
|
+
options.port = overridePort
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
22
29
|
Object.assign(options, additionalOptions)
|
|
23
30
|
globalThis.platformatic?.events?.emitAndNotify('serverOptions', options)
|
|
24
31
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/basic",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.43.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -25,10 +25,10 @@
|
|
|
25
25
|
"split2": "^4.2.0",
|
|
26
26
|
"undici": "^7.0.0",
|
|
27
27
|
"ws": "^8.18.0",
|
|
28
|
-
"@platformatic/foundation": "3.
|
|
29
|
-
"@platformatic/itc": "3.
|
|
30
|
-
"@platformatic/telemetry": "3.
|
|
31
|
-
"@platformatic/metrics": "3.
|
|
28
|
+
"@platformatic/foundation": "3.43.0",
|
|
29
|
+
"@platformatic/itc": "3.43.0",
|
|
30
|
+
"@platformatic/telemetry": "3.43.0",
|
|
31
|
+
"@platformatic/metrics": "3.43.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"cleaner-spec-reporter": "^0.5.0",
|
package/schema.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://schemas.platformatic.dev/@platformatic/basic/3.
|
|
2
|
+
"$id": "https://schemas.platformatic.dev/@platformatic/basic/3.43.0.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"title": "Platformatic Basic Config",
|
|
5
5
|
"type": "object",
|
|
@@ -1647,6 +1647,9 @@
|
|
|
1647
1647
|
"type": "string"
|
|
1648
1648
|
}
|
|
1649
1649
|
},
|
|
1650
|
+
"envfile": {
|
|
1651
|
+
"type": "string"
|
|
1652
|
+
},
|
|
1650
1653
|
"sourceMaps": {
|
|
1651
1654
|
"type": "boolean",
|
|
1652
1655
|
"default": false
|