@platformatic/runtime 2.0.0-alpha.3 → 2.0.0-alpha.4
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 -1
- package/fixtures/crash-on-bootstrap/platformatic.runtime.json +15 -0
- package/fixtures/crash-on-bootstrap/services/service-1/platformatic.service.json +14 -0
- package/fixtures/crash-on-bootstrap/services/service-1/plugin.js +5 -0
- package/fixtures/crash-on-bootstrap/services/service-2/platformatic.service.json +14 -0
- package/fixtures/crash-on-bootstrap/services/service-2/plugin.js +5 -0
- package/fixtures/telemetry/services/echo/routes/span.js +16 -2
- package/fixtures/telemetry/services/service-1/platformatic.service.json +19 -0
- package/fixtures/telemetry/services/service-1/routes/echo.js +7 -0
- package/lib/runtime.js +113 -43
- package/lib/worker/app.js +27 -1
- package/lib/worker/main.js +11 -4
- package/package.json +17 -15
- package/schema.json +1 -1
- package/lib/streams/message-port-writable.js +0 -44
- package/lib/streams/pino-writable.js +0 -30
package/config.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and run json-schema-to-typescript to regenerate this file.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type HttpsSchemasPlatformaticDevPlatformaticRuntime200Alpha4Json = {
|
|
9
9
|
[k: string]: unknown;
|
|
10
10
|
} & {
|
|
11
11
|
$schema?: string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://schemas.platformatic.dev/@platformatic/runtime/1.52.0.json",
|
|
3
|
+
"entrypoint": "service-1",
|
|
4
|
+
"autoload": {
|
|
5
|
+
"path": "./services"
|
|
6
|
+
},
|
|
7
|
+
"restartOnError": 100,
|
|
8
|
+
"server": {
|
|
9
|
+
"hostname": "127.0.0.1",
|
|
10
|
+
"port": "0",
|
|
11
|
+
"logger": {
|
|
12
|
+
"level": "info"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
+
|
|
3
|
+
const { request } = require('undici')
|
|
4
|
+
|
|
2
5
|
module.exports = async function (fastify, opts) {
|
|
3
6
|
// This returns the traceId set on the span by the service
|
|
4
|
-
fastify.get('/', async (
|
|
5
|
-
const traceId =
|
|
7
|
+
fastify.get('/', async (req, reply) => {
|
|
8
|
+
const traceId = req.span.spanContext().traceId
|
|
6
9
|
return { traceId }
|
|
7
10
|
})
|
|
11
|
+
|
|
12
|
+
fastify.get('/service-1/echo-headers', async (req, reply) => {
|
|
13
|
+
const res = await request('http://service-1.plt.local/echo-headers', {
|
|
14
|
+
method: 'GET',
|
|
15
|
+
headers: {
|
|
16
|
+
'content-type': 'application/json',
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
const body = await res.body.json()
|
|
20
|
+
return body
|
|
21
|
+
})
|
|
8
22
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://schemas.platformatic.dev/@platformatic/service/1.52.0.json",
|
|
3
|
+
"server": {
|
|
4
|
+
"hostname": "127.0.0.1",
|
|
5
|
+
"port": "0",
|
|
6
|
+
"logger": {
|
|
7
|
+
"level": "info"
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"service": {
|
|
11
|
+
"openapi": true
|
|
12
|
+
},
|
|
13
|
+
"plugins": {
|
|
14
|
+
"paths": [
|
|
15
|
+
"./routes"
|
|
16
|
+
],
|
|
17
|
+
"typescript": false
|
|
18
|
+
}
|
|
19
|
+
}
|
package/lib/runtime.js
CHANGED
|
@@ -28,6 +28,8 @@ const MAX_LISTENERS_COUNT = 100
|
|
|
28
28
|
const MAX_METRICS_QUEUE_LENGTH = 5 * 60 // 5 minutes in seconds
|
|
29
29
|
const COLLECT_METRICS_TIMEOUT = 1000
|
|
30
30
|
|
|
31
|
+
const MAX_BOOTSTRAP_ATTEMPTS = 5
|
|
32
|
+
|
|
31
33
|
class Runtime extends EventEmitter {
|
|
32
34
|
#configManager
|
|
33
35
|
#runtimeTmpDir
|
|
@@ -46,7 +48,8 @@ class Runtime extends EventEmitter {
|
|
|
46
48
|
#managementApi
|
|
47
49
|
#prometheusServer
|
|
48
50
|
#startedServices
|
|
49
|
-
#
|
|
51
|
+
#restartPromises
|
|
52
|
+
#bootstrapAttempts
|
|
50
53
|
|
|
51
54
|
constructor (configManager, runtimeLogsDir, env) {
|
|
52
55
|
super()
|
|
@@ -63,7 +66,8 @@ class Runtime extends EventEmitter {
|
|
|
63
66
|
this.#interceptor = createThreadInterceptor({ domain: '.plt.local' })
|
|
64
67
|
this.#status = undefined
|
|
65
68
|
this.#startedServices = new Map()
|
|
66
|
-
this.#
|
|
69
|
+
this.#restartPromises = new Map()
|
|
70
|
+
this.#bootstrapAttempts = new Map()
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
async init () {
|
|
@@ -126,8 +130,15 @@ class Runtime extends EventEmitter {
|
|
|
126
130
|
this.#updateStatus('starting')
|
|
127
131
|
|
|
128
132
|
// Important: do not use Promise.all here since it won't properly manage dependencies
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
try {
|
|
134
|
+
for (const service of this.#servicesIds) {
|
|
135
|
+
await this.startService(service)
|
|
136
|
+
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
// Wait for the next tick so that the error is logged first
|
|
139
|
+
await sleep(1)
|
|
140
|
+
await this.close()
|
|
141
|
+
throw error
|
|
131
142
|
}
|
|
132
143
|
|
|
133
144
|
this.#updateStatus('started')
|
|
@@ -145,13 +156,7 @@ class Runtime extends EventEmitter {
|
|
|
145
156
|
}
|
|
146
157
|
|
|
147
158
|
this.#updateStatus('stopping')
|
|
148
|
-
|
|
149
|
-
for (const timer of this.#crashedServicesTimers.values()) {
|
|
150
|
-
clearTimeout(timer)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
159
|
this.#startedServices.clear()
|
|
154
|
-
this.#crashedServicesTimers.clear()
|
|
155
160
|
|
|
156
161
|
await Promise.all(this.#servicesIds.map(service => this._stopService(service)))
|
|
157
162
|
|
|
@@ -209,12 +214,6 @@ class Runtime extends EventEmitter {
|
|
|
209
214
|
// This is set here so that if the service fails while starting we track the status
|
|
210
215
|
this.#startedServices.set(id, true)
|
|
211
216
|
|
|
212
|
-
// Make sure we don't restart twice
|
|
213
|
-
const crashedTimer = this.#crashedServicesTimers.get(id)
|
|
214
|
-
if (crashedTimer) {
|
|
215
|
-
clearTimeout(crashedTimer)
|
|
216
|
-
}
|
|
217
|
-
|
|
218
217
|
let service = await this.#getServiceById(id, false, false)
|
|
219
218
|
|
|
220
219
|
// The service was stopped, recreate the thread
|
|
@@ -226,10 +225,36 @@ class Runtime extends EventEmitter {
|
|
|
226
225
|
service = await this.#getServiceById(id)
|
|
227
226
|
}
|
|
228
227
|
|
|
229
|
-
|
|
228
|
+
try {
|
|
229
|
+
const serviceUrl = await sendViaITC(service, 'start')
|
|
230
|
+
if (serviceUrl) {
|
|
231
|
+
this.#url = serviceUrl
|
|
232
|
+
}
|
|
233
|
+
this.#bootstrapAttempts.set(id, 0)
|
|
234
|
+
} catch (error) {
|
|
235
|
+
// TODO: handle port allocation error here
|
|
236
|
+
if (error.code === 'EADDRINUSE') throw error
|
|
230
237
|
|
|
231
|
-
|
|
232
|
-
|
|
238
|
+
this.logger.error({ error }, `Failed to start service "${id}".`)
|
|
239
|
+
|
|
240
|
+
const config = this.#configManager.current
|
|
241
|
+
const restartOnError = config.restartOnError
|
|
242
|
+
|
|
243
|
+
let bootstrapAttempt = this.#bootstrapAttempts.get(id)
|
|
244
|
+
if (bootstrapAttempt++ >= MAX_BOOTSTRAP_ATTEMPTS || restartOnError === 0) {
|
|
245
|
+
this.logger.error(
|
|
246
|
+
`Failed to start service "${id}" after ${MAX_BOOTSTRAP_ATTEMPTS} attempts.`
|
|
247
|
+
)
|
|
248
|
+
throw error
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
this.logger.warn(
|
|
252
|
+
`Starting a service "${id}" in ${restartOnError}ms. ` +
|
|
253
|
+
`Attempt ${bootstrapAttempt} of ${MAX_BOOTSTRAP_ATTEMPTS}...`
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
this.#bootstrapAttempts.set(id, bootstrapAttempt)
|
|
257
|
+
await this.#restartCrashedService(id)
|
|
233
258
|
}
|
|
234
259
|
}
|
|
235
260
|
|
|
@@ -243,11 +268,13 @@ class Runtime extends EventEmitter {
|
|
|
243
268
|
|
|
244
269
|
this.#startedServices.set(id, false)
|
|
245
270
|
|
|
271
|
+
this.logger?.info(`Stopping service "${id}"...`)
|
|
272
|
+
|
|
246
273
|
// Always send the stop message, it will shut down workers that only had ITC and interceptors setup
|
|
247
274
|
try {
|
|
248
275
|
await Promise.race([sendViaITC(service, 'stop'), sleep(10000, 'timeout', { ref: false })])
|
|
249
276
|
} catch (error) {
|
|
250
|
-
this.logger
|
|
277
|
+
this.logger?.info(`Failed to stop service "${id}". Killing a worker thread.`, error)
|
|
251
278
|
}
|
|
252
279
|
|
|
253
280
|
// Wait for the worker thread to finish, we're going to create a new one if the service is ever restarted
|
|
@@ -638,6 +665,8 @@ class Runtime extends EventEmitter {
|
|
|
638
665
|
}
|
|
639
666
|
|
|
640
667
|
async #setupService (serviceConfig) {
|
|
668
|
+
if (this.#status === 'stopping' || this.#status === 'closed') return
|
|
669
|
+
|
|
641
670
|
const config = this.#configManager.current
|
|
642
671
|
const { autoload, restartOnError } = config
|
|
643
672
|
|
|
@@ -645,6 +674,10 @@ class Runtime extends EventEmitter {
|
|
|
645
674
|
const { port1: loggerDestination, port2: loggingPort } = new MessageChannel()
|
|
646
675
|
loggerDestination.on('message', this.#forwardThreadLog.bind(this))
|
|
647
676
|
|
|
677
|
+
if (!this.#bootstrapAttempts.has(id)) {
|
|
678
|
+
this.#bootstrapAttempts.set(id, 0)
|
|
679
|
+
}
|
|
680
|
+
|
|
648
681
|
const service = new Worker(kWorkerFile, {
|
|
649
682
|
workerData: {
|
|
650
683
|
config,
|
|
@@ -677,16 +710,21 @@ class Runtime extends EventEmitter {
|
|
|
677
710
|
loggerDestination.close()
|
|
678
711
|
loggingPort.close()
|
|
679
712
|
|
|
713
|
+
if (this.#status === 'stopping') return
|
|
714
|
+
|
|
680
715
|
// Wait for the next tick so that crashed from the thread are logged first
|
|
681
716
|
setImmediate(() => {
|
|
682
|
-
|
|
683
|
-
|
|
717
|
+
this.logger.warn(`Service "${id}" unexpectedly exited with code ${code}.`)
|
|
718
|
+
|
|
719
|
+
// Restart the service if it was started
|
|
720
|
+
if (started && this.#status === 'started') {
|
|
684
721
|
if (restartOnError > 0) {
|
|
685
|
-
this
|
|
722
|
+
this.logger.warn(`Restarting a service "${id}" in ${restartOnError}ms...`)
|
|
723
|
+
this.#restartCrashedService(id).catch((err) => {
|
|
724
|
+
this.logger.error({ err }, `Failed to restart service "${id}".`)
|
|
725
|
+
})
|
|
686
726
|
} else {
|
|
687
|
-
this.logger.warn(
|
|
688
|
-
`Service ${id} unexpectedly exited with code ${code}. The service is no longer available ...`
|
|
689
|
-
)
|
|
727
|
+
this.logger.warn(`The "${id}" service is no longer available.`)
|
|
690
728
|
}
|
|
691
729
|
}
|
|
692
730
|
})
|
|
@@ -698,6 +736,7 @@ class Runtime extends EventEmitter {
|
|
|
698
736
|
// Setup ITC
|
|
699
737
|
service[kITC] = new ITC({ port: service })
|
|
700
738
|
service[kITC].listen()
|
|
739
|
+
service[kITC].handle('getServiceMeta', this.#getServiceMeta.bind(this))
|
|
701
740
|
|
|
702
741
|
// Handle services changes
|
|
703
742
|
// This is not purposely activated on when this.#configManager.current.watch === true
|
|
@@ -713,9 +752,9 @@ class Runtime extends EventEmitter {
|
|
|
713
752
|
await this.startService(id)
|
|
714
753
|
}
|
|
715
754
|
|
|
716
|
-
this.logger
|
|
755
|
+
this.logger?.info(`Service ${id} has been successfully reloaded ...`)
|
|
717
756
|
} catch (e) {
|
|
718
|
-
this.logger
|
|
757
|
+
this.logger?.error(e)
|
|
719
758
|
}
|
|
720
759
|
})
|
|
721
760
|
|
|
@@ -743,26 +782,38 @@ class Runtime extends EventEmitter {
|
|
|
743
782
|
}
|
|
744
783
|
}
|
|
745
784
|
|
|
746
|
-
async #restartCrashedService (
|
|
747
|
-
const
|
|
748
|
-
const
|
|
785
|
+
async #restartCrashedService (id) {
|
|
786
|
+
const config = this.#configManager.current
|
|
787
|
+
const serviceConfig = config.services.find(s => s.id === id)
|
|
788
|
+
|
|
789
|
+
let restartPromise = this.#restartPromises.get(id)
|
|
790
|
+
if (restartPromise) {
|
|
791
|
+
await restartPromise
|
|
792
|
+
return
|
|
793
|
+
}
|
|
749
794
|
|
|
750
|
-
|
|
795
|
+
restartPromise = new Promise((resolve, reject) => {
|
|
796
|
+
setTimeout(async () => {
|
|
797
|
+
this.#restartPromises.delete(id)
|
|
751
798
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
await this.#setupService(serviceConfig)
|
|
799
|
+
try {
|
|
800
|
+
await this.#setupService(serviceConfig)
|
|
755
801
|
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
802
|
+
const started = this.#startedServices.get(id)
|
|
803
|
+
if (started) {
|
|
804
|
+
this.#startedServices.set(id, false)
|
|
805
|
+
await this.startService(id)
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
resolve()
|
|
809
|
+
} catch (err) {
|
|
810
|
+
reject(err)
|
|
759
811
|
}
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
}
|
|
763
|
-
}, restartTimeout).unref()
|
|
812
|
+
}, config.restartOnError)
|
|
813
|
+
})
|
|
764
814
|
|
|
765
|
-
this.#
|
|
815
|
+
this.#restartPromises.set(id, restartPromise)
|
|
816
|
+
await restartPromise
|
|
766
817
|
}
|
|
767
818
|
|
|
768
819
|
async #getServiceById (id, ensureStarted = false, mustExist = true) {
|
|
@@ -787,6 +838,25 @@ class Runtime extends EventEmitter {
|
|
|
787
838
|
return service
|
|
788
839
|
}
|
|
789
840
|
|
|
841
|
+
async #getServiceMeta (id) {
|
|
842
|
+
const service = this.#services.get(id)
|
|
843
|
+
|
|
844
|
+
if (!service) {
|
|
845
|
+
throw new errors.ServiceNotFoundError(id, Array.from(this.#services.keys()).join(', '))
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
try {
|
|
849
|
+
return await service[kITC].send('getServiceMeta')
|
|
850
|
+
} catch (e) {
|
|
851
|
+
// The service exports no meta, return an empty object
|
|
852
|
+
if (e.code === 'PLT_ITC_HANDLER_NOT_FOUND') {
|
|
853
|
+
return {}
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
throw e
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
|
|
790
860
|
async #getRuntimePackageJson () {
|
|
791
861
|
const runtimeDir = this.#configManager.dirname
|
|
792
862
|
const packageJsonPath = join(runtimeDir, 'package.json')
|
package/lib/worker/app.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { EventEmitter } = require('node:events')
|
|
4
4
|
const { FileWatcher } = require('@platformatic/utils')
|
|
5
|
+
const { getGlobalDispatcher, setGlobalDispatcher } = require('undici')
|
|
5
6
|
const debounce = require('debounce')
|
|
6
7
|
|
|
7
8
|
const errors = require('../errors')
|
|
@@ -31,6 +32,7 @@ class PlatformaticApp extends EventEmitter {
|
|
|
31
32
|
serviceId: this.appConfig.id,
|
|
32
33
|
directory: this.appConfig.path,
|
|
33
34
|
isEntrypoint: this.appConfig.entrypoint,
|
|
35
|
+
isProduction: false,
|
|
34
36
|
telemetryConfig,
|
|
35
37
|
metricsConfig,
|
|
36
38
|
serverConfig,
|
|
@@ -90,6 +92,8 @@ class PlatformaticApp extends EventEmitter {
|
|
|
90
92
|
context: this.#context,
|
|
91
93
|
})
|
|
92
94
|
this.stackable = this.#wrapStackable(stackable)
|
|
95
|
+
|
|
96
|
+
this.#updateDispatcher()
|
|
93
97
|
} catch (err) {
|
|
94
98
|
this.#logAndExit(err)
|
|
95
99
|
}
|
|
@@ -103,7 +107,7 @@ class PlatformaticApp extends EventEmitter {
|
|
|
103
107
|
this.#starting = true
|
|
104
108
|
|
|
105
109
|
try {
|
|
106
|
-
await this.stackable.init
|
|
110
|
+
await this.stackable.init()
|
|
107
111
|
} catch (err) {
|
|
108
112
|
this.#logAndExit(err)
|
|
109
113
|
}
|
|
@@ -219,6 +223,28 @@ class PlatformaticApp extends EventEmitter {
|
|
|
219
223
|
}
|
|
220
224
|
return newStackable
|
|
221
225
|
}
|
|
226
|
+
|
|
227
|
+
#updateDispatcher () {
|
|
228
|
+
const telemetryConfig = this.#context.telemetryConfig
|
|
229
|
+
const telemetryId = telemetryConfig?.serviceName
|
|
230
|
+
|
|
231
|
+
const interceptor = dispatch => {
|
|
232
|
+
return function InterceptedDispatch (opts, handler) {
|
|
233
|
+
if (telemetryId) {
|
|
234
|
+
opts.headers = {
|
|
235
|
+
...opts.headers,
|
|
236
|
+
'x-plt-telemetry-id': telemetryId,
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return dispatch(opts, handler)
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const dispatcher = getGlobalDispatcher()
|
|
244
|
+
.compose(interceptor)
|
|
245
|
+
|
|
246
|
+
setGlobalDispatcher(dispatcher)
|
|
247
|
+
}
|
|
222
248
|
}
|
|
223
249
|
|
|
224
250
|
module.exports = { PlatformaticApp }
|
package/lib/worker/main.js
CHANGED
|
@@ -13,8 +13,7 @@ const { wire } = require('undici-thread-interceptor')
|
|
|
13
13
|
const { PlatformaticApp } = require('./app')
|
|
14
14
|
const { setupITC } = require('./itc')
|
|
15
15
|
const loadInterceptors = require('./interceptors')
|
|
16
|
-
const { MessagePortWritable } = require('
|
|
17
|
-
const { createPinoWritable } = require('../streams/pino-writable')
|
|
16
|
+
const { MessagePortWritable, createPinoWritable } = require('@platformatic/utils')
|
|
18
17
|
const { kId, kITC } = require('./symbols')
|
|
19
18
|
|
|
20
19
|
process.on('uncaughtException', handleUnhandled.bind(null, 'uncaught exception'))
|
|
@@ -88,15 +87,23 @@ async function main () {
|
|
|
88
87
|
} else if (service.useHttp) {
|
|
89
88
|
serverConfig = {
|
|
90
89
|
port: 0,
|
|
91
|
-
|
|
90
|
+
hostname: '127.0.0.1',
|
|
92
91
|
keepAliveTimeout: 5000,
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
|
|
95
|
+
let telemetryConfig = config.telemetry
|
|
96
|
+
if (telemetryConfig) {
|
|
97
|
+
telemetryConfig = {
|
|
98
|
+
...telemetryConfig,
|
|
99
|
+
serviceName: `${telemetryConfig.serviceName}-${service.id}`,
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
96
103
|
// Create the application
|
|
97
104
|
app = new PlatformaticApp(
|
|
98
105
|
service,
|
|
99
|
-
|
|
106
|
+
telemetryConfig,
|
|
100
107
|
serverConfig,
|
|
101
108
|
!!config.managementApi,
|
|
102
109
|
!!config.watch,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"express": "^4.18.3",
|
|
27
27
|
"fast-jwt": "^4.0.0",
|
|
28
28
|
"get-port": "^7.1.0",
|
|
29
|
+
"json-schema-to-typescript": "^15.0.0",
|
|
29
30
|
"neostandard": "^0.11.1",
|
|
30
31
|
"pino-abstract-transport": "^1.1.0",
|
|
31
32
|
"split2": "^4.2.0",
|
|
@@ -33,11 +34,11 @@
|
|
|
33
34
|
"typescript": "^5.5.4",
|
|
34
35
|
"undici-oidc-interceptor": "^0.5.0",
|
|
35
36
|
"why-is-node-running": "^2.2.2",
|
|
36
|
-
"@platformatic/composer": "2.0.0-alpha.
|
|
37
|
-
"@platformatic/
|
|
38
|
-
"@platformatic/
|
|
39
|
-
"@platformatic/
|
|
40
|
-
"@platformatic/sql-mapper": "2.0.0-alpha.
|
|
37
|
+
"@platformatic/composer": "2.0.0-alpha.4",
|
|
38
|
+
"@platformatic/db": "2.0.0-alpha.4",
|
|
39
|
+
"@platformatic/service": "2.0.0-alpha.4",
|
|
40
|
+
"@platformatic/sql-graphql": "2.0.0-alpha.4",
|
|
41
|
+
"@platformatic/sql-mapper": "2.0.0-alpha.4"
|
|
41
42
|
},
|
|
42
43
|
"dependencies": {
|
|
43
44
|
"@fastify/error": "^3.4.1",
|
|
@@ -65,19 +66,20 @@
|
|
|
65
66
|
"undici": "^6.9.0",
|
|
66
67
|
"undici-thread-interceptor": "^0.5.0",
|
|
67
68
|
"ws": "^8.16.0",
|
|
68
|
-
"@platformatic/
|
|
69
|
-
"@platformatic/
|
|
70
|
-
"@platformatic/
|
|
71
|
-
"@platformatic/
|
|
72
|
-
"@platformatic/
|
|
73
|
-
"@platformatic/
|
|
74
|
-
"@platformatic/
|
|
69
|
+
"@platformatic/config": "2.0.0-alpha.4",
|
|
70
|
+
"@platformatic/basic": "2.0.0-alpha.4",
|
|
71
|
+
"@platformatic/generators": "2.0.0-alpha.4",
|
|
72
|
+
"@platformatic/itc": "2.0.0-alpha.4",
|
|
73
|
+
"@platformatic/telemetry": "2.0.0-alpha.4",
|
|
74
|
+
"@platformatic/ts-compiler": "2.0.0-alpha.4",
|
|
75
|
+
"@platformatic/utils": "2.0.0-alpha.4"
|
|
75
76
|
},
|
|
76
77
|
"scripts": {
|
|
77
78
|
"test": "npm run lint && borp --concurrency=1 --timeout=180000 && tsd",
|
|
78
79
|
"coverage": "npm run lint && borp -X=fixtures -X=test -C --concurrency=1 --timeout=180000 && tsd",
|
|
79
|
-
"lint": "eslint",
|
|
80
80
|
"gen-schema": "node lib/schema.js > schema.json",
|
|
81
|
-
"gen-types": "json2ts > config.d.ts < schema.json"
|
|
81
|
+
"gen-types": "json2ts > config.d.ts < schema.json",
|
|
82
|
+
"build": "pnpm run gen-schema && pnpm run gen-types",
|
|
83
|
+
"lint": "eslint"
|
|
82
84
|
}
|
|
83
85
|
}
|
package/schema.json
CHANGED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Writable } = require('node:stream')
|
|
4
|
-
|
|
5
|
-
class MessagePortWritable extends Writable {
|
|
6
|
-
#port
|
|
7
|
-
#metadata
|
|
8
|
-
|
|
9
|
-
constructor (options) {
|
|
10
|
-
const { port, metadata, ...opts } = options
|
|
11
|
-
|
|
12
|
-
super({ ...opts, decodeStrings: false })
|
|
13
|
-
this.#port = port
|
|
14
|
-
this.#metadata = metadata
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Since this is only invoked by pino, we only receive strings
|
|
18
|
-
_write (chunk, encoding, callback) {
|
|
19
|
-
this.#port.postMessage({ metadata: this.#metadata, logs: [chunk.toString(encoding ?? 'utf-8')] })
|
|
20
|
-
|
|
21
|
-
// Important: do not remove nextTick otherwise _writev will never be used
|
|
22
|
-
process.nextTick(callback)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Since this is only invoked by pino, we only receive strings
|
|
26
|
-
_writev (chunks, callback) {
|
|
27
|
-
this.#port.postMessage({ metadata: this.#metadata, logs: chunks.map(c => c.chunk.toString(c.encoding ?? 'utf-8')) })
|
|
28
|
-
|
|
29
|
-
// Important: do not remove nextTick otherwise _writev will never be used
|
|
30
|
-
process.nextTick(callback)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
_final (callback) {
|
|
34
|
-
this.#port.close()
|
|
35
|
-
callback()
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
_destroy (err, callback) {
|
|
39
|
-
this.#port.close()
|
|
40
|
-
callback(err)
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
module.exports = { MessagePortWritable }
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const { Writable } = require('node:stream')
|
|
4
|
-
const inspect = require('node:util')
|
|
5
|
-
|
|
6
|
-
class PinoWritable extends Writable {
|
|
7
|
-
#write
|
|
8
|
-
|
|
9
|
-
constructor (options) {
|
|
10
|
-
const { pino, level, ...opts } = options
|
|
11
|
-
|
|
12
|
-
super({ ...opts, decodeStrings: false })
|
|
13
|
-
this.#write = pino[level].bind(pino)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
_write (chunk, encoding, callback) {
|
|
17
|
-
this.#write({ raw: encoding === 'buffer' ? inspect(chunk) : chunk.toString(encoding ?? 'utf-8') })
|
|
18
|
-
callback()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// We don't define _writev as we have to serialize messages one by one so batching wouldn't make any sense.
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function createPinoWritable (pino, level) {
|
|
25
|
-
const writable = new PinoWritable({ pino, level })
|
|
26
|
-
writable.write = writable.write.bind(writable)
|
|
27
|
-
return writable
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
module.exports = { PinoWritable, createPinoWritable }
|