@platformatic/runtime 1.53.3 → 2.0.0-alpha.10

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.
Files changed (178) hide show
  1. package/config.d.ts +284 -0
  2. package/eslint.config.js +8 -0
  3. package/fixtures/botched-start/platformatic.runtime.json +1 -1
  4. package/fixtures/botched-start/services/a/platformatic.service.json +1 -1
  5. package/fixtures/composerApp/platformatic.composer.json +1 -1
  6. package/fixtures/configs/{monorepo-hotreload.json → invalid-autoload-with-services.json} +8 -8
  7. package/fixtures/configs/invalid-entrypoint.json +1 -1
  8. package/fixtures/configs/invalid-schema-type.config.json +1 -1
  9. package/fixtures/configs/missing-property.config.json +1 -1
  10. package/fixtures/configs/missing-service-config.json +1 -1
  11. package/fixtures/configs/monorepo-composer-no-autoload.json +32 -0
  12. package/fixtures/configs/monorepo-composer.json +2 -2
  13. package/fixtures/configs/monorepo-create-cycle.json +2 -3
  14. package/fixtures/configs/monorepo-missing-dependencies.json +9 -0
  15. package/fixtures/configs/monorepo-no-cycles.json +2 -3
  16. package/fixtures/configs/monorepo-openapi.json +2 -2
  17. package/fixtures/configs/{hotreload.json → monorepo-watch-env.json} +2 -3
  18. package/fixtures/configs/monorepo-watch-single.json +12 -0
  19. package/fixtures/configs/monorepo-watch.json +26 -9
  20. package/fixtures/configs/monorepo-with-dependencies.json +2 -2
  21. package/fixtures/configs/{monorepo-client-without-id.json → monorepo-with-management-api-without-metrics.json} +5 -8
  22. package/fixtures/configs/monorepo-with-management-api.json +2 -3
  23. package/fixtures/configs/monorepo-with-metrics.json +1 -2
  24. package/fixtures/configs/monorepo.json +2 -3
  25. package/fixtures/configs/no-services.config.json +1 -1
  26. package/fixtures/configs/no-sources.config.json +1 -1
  27. package/fixtures/configs/service-throws-on-start.json +1 -1
  28. package/fixtures/configs/service-with-env-port.json +2 -3
  29. package/fixtures/configs/service-with-stdio.json +12 -0
  30. package/fixtures/configs/{monorepo-hotreload-env.json → watch.json} +2 -3
  31. package/fixtures/crash-on-bootstrap/platformatic.runtime.json +15 -0
  32. package/fixtures/crash-on-bootstrap/services/service-1/platformatic.service.json +14 -0
  33. package/fixtures/crash-on-bootstrap/services/service-1/plugin.js +5 -0
  34. package/fixtures/crash-on-bootstrap/services/service-2/platformatic.service.json +14 -0
  35. package/fixtures/crash-on-bootstrap/services/service-2/plugin.js +5 -0
  36. package/fixtures/dbApp/platformatic.db.json +1 -1
  37. package/fixtures/dbAppNoName/platformatic.db.json +1 -1
  38. package/fixtures/dbAppNoPackageJson/platformatic.db.json +1 -1
  39. package/fixtures/dbAppWithMigrationError/platformatic.db.json +1 -1
  40. package/fixtures/do-not-reload-dependencies/platformatic.service.json +1 -1
  41. package/fixtures/do-not-restart-on-crash/platformatic.runtime.json +3 -2
  42. package/fixtures/do-not-restart-on-crash/services/a/platformatic.service.json +1 -1
  43. package/fixtures/express/platformatic.runtime.json +1 -1
  44. package/fixtures/express/services/a/platformatic.service.json +1 -1
  45. package/fixtures/express/services/b/platformatic.service.json +1 -1
  46. package/fixtures/external-client/platformatic.service.json +1 -1
  47. package/fixtures/interceptors/idp.js +2 -2
  48. package/fixtures/interceptors/platformatic.runtime.json +1 -1
  49. package/fixtures/interceptors/services/a/platformatic.service.json +1 -1
  50. package/fixtures/interceptors-2/platformatic.runtime.json +1 -1
  51. package/fixtures/interceptors-2/services/a/platformatic.service.json +1 -1
  52. package/fixtures/leven/platformatic.runtime.json +2 -3
  53. package/fixtures/leven/services/deeply-spittle/platformatic.service.json +1 -1
  54. package/fixtures/leven/services/rainy-empire/platformatic.composer.json +1 -1
  55. package/fixtures/management-api/platformatic.json +8 -4
  56. package/fixtures/management-api/services/service-1/platformatic.json +1 -1
  57. package/fixtures/management-api/services/service-1/plugin.js +4 -3
  58. package/fixtures/management-api/services/service-2/platformatic.json +1 -1
  59. package/fixtures/management-api/services/service-db/platformatic.db.json +1 -1
  60. package/fixtures/management-api-custom-labels/platformatic.json +2 -3
  61. package/fixtures/management-api-custom-labels/services/service-1/platformatic.json +1 -1
  62. package/fixtures/management-api-custom-labels/services/service-1/plugin.js +4 -3
  63. package/fixtures/management-api-custom-labels/services/service-2/platformatic.json +1 -1
  64. package/fixtures/management-api-custom-labels/services/service-db/platformatic.db.json +1 -1
  65. package/fixtures/management-api-without-metrics/platformatic.json +3 -3
  66. package/fixtures/management-api-without-metrics/services/service-1/platformatic.json +1 -1
  67. package/fixtures/monorepo/composerApp/platformatic.composer.json +1 -2
  68. package/fixtures/monorepo/dbApp/platformatic.db.json +1 -1
  69. package/fixtures/monorepo/serviceApp/platformatic.service.json +3 -2
  70. package/fixtures/monorepo/serviceApp/with-logger/with-logger.cjs +2 -2
  71. package/fixtures/monorepo/serviceApp/with-logger/with-logger.d.ts +7 -7
  72. package/fixtures/monorepo/serviceAppWithLogger/platformatic.service.json +1 -1
  73. package/fixtures/monorepo/serviceAppWithLogger/plugin.js +12 -0
  74. package/fixtures/monorepo/serviceAppWithMultiplePlugins/platformatic.service.json +3 -2
  75. package/fixtures/monorepo-missing-dependencies/composer/platformatic.json +24 -0
  76. package/fixtures/monorepo-openapi/serviceAppWithoutOpenapi/platformatic.service.json +1 -1
  77. package/fixtures/monorepo-watch/service1/platformatic.service.json +1 -1
  78. package/fixtures/monorepo-with-dependencies/main/platformatic.json +1 -1
  79. package/fixtures/monorepo-with-dependencies/service-1/platformatic.json +1 -1
  80. package/fixtures/monorepo-with-dependencies/service-2/platformatic.json +1 -1
  81. package/fixtures/no-env.service.json +1 -1
  82. package/fixtures/preload/platformatic.runtime.json +1 -1
  83. package/fixtures/preload/services/a/platformatic.service.json +1 -1
  84. package/fixtures/prom-server/platformatic.json +2 -3
  85. package/fixtures/prom-server/services/service-1/platformatic.json +1 -1
  86. package/fixtures/prom-server/services/service-2/platformatic.json +1 -1
  87. package/fixtures/restart-on-crash/platformatic.runtime.json +1 -1
  88. package/fixtures/restart-on-crash/services/a/platformatic.service.json +1 -1
  89. package/fixtures/sample-runtime/package.json +1 -1
  90. package/fixtures/sample-runtime/platformatic.json +2 -3
  91. package/fixtures/sample-runtime/services/rival/package.json +1 -1
  92. package/fixtures/sample-runtime/services/rival/platformatic.json +1 -1
  93. package/fixtures/sample-runtime-with-2-services/package.json +1 -1
  94. package/fixtures/sample-runtime-with-2-services/platformatic.json +2 -3
  95. package/fixtures/sample-runtime-with-2-services/services/foobar/package.json +1 -1
  96. package/fixtures/sample-runtime-with-2-services/services/foobar/platformatic.json +1 -1
  97. package/fixtures/sample-runtime-with-2-services/services/rival/package.json +1 -1
  98. package/fixtures/sample-runtime-with-2-services/services/rival/platformatic.json +1 -1
  99. package/fixtures/server/logger-transport/platformatic.runtime.json +2 -3
  100. package/fixtures/server/logger-transport/services/echo/platformatic.service.json +1 -1
  101. package/fixtures/server/overrides-service/platformatic.runtime.json +2 -3
  102. package/fixtures/server/overrides-service/services/echo/platformatic.service.json +1 -1
  103. package/fixtures/server/runtime-server/platformatic.runtime.json +2 -3
  104. package/fixtures/server/runtime-server/services/echo/platformatic.service.json +1 -1
  105. package/fixtures/serviceAppThrowsOnStart/platformatic.service.json +1 -1
  106. package/fixtures/stackables/node_modules/foo/foo.js +2 -1
  107. package/fixtures/start-command-in-runtime.js +1 -1
  108. package/fixtures/stdio/platformatic.service.json +6 -0
  109. package/fixtures/stdio/plugin.js +24 -0
  110. package/fixtures/telemetry/platformatic.runtime.json +2 -3
  111. package/fixtures/telemetry/services/echo/platformatic.service.json +1 -1
  112. package/fixtures/telemetry/services/echo/routes/span.js +16 -2
  113. package/fixtures/telemetry/services/service-1/platformatic.service.json +19 -0
  114. package/fixtures/telemetry/services/service-1/routes/echo.js +7 -0
  115. package/fixtures/typescript/platformatic.runtime.json +2 -3
  116. package/fixtures/typescript/services/composer/platformatic.composer.json +1 -1
  117. package/fixtures/typescript/services/movies/global.d.ts +2 -3
  118. package/fixtures/typescript/services/movies/platformatic.db.json +1 -1
  119. package/fixtures/typescript/services/movies/types/Movie.d.ts +3 -3
  120. package/fixtures/typescript/services/movies/types/index.d.ts +6 -6
  121. package/fixtures/typescript/services/titles/client/client.d.ts +35 -35
  122. package/fixtures/typescript/services/titles/platformatic.service.json +1 -1
  123. package/fixtures/typescript-custom-flags/platformatic.runtime.json +2 -3
  124. package/fixtures/typescript-custom-flags/services/composer/platformatic.composer.json +1 -1
  125. package/fixtures/typescript-custom-flags/services/movies/global.d.ts +2 -3
  126. package/fixtures/typescript-custom-flags/services/movies/platformatic.db.json +1 -1
  127. package/fixtures/typescript-custom-flags/services/movies/types/Movie.d.ts +3 -3
  128. package/fixtures/typescript-custom-flags/services/movies/types/index.d.ts +6 -6
  129. package/fixtures/typescript-custom-flags/services/titles/client/client.d.ts +35 -35
  130. package/fixtures/typescript-custom-flags/services/titles/platformatic.service.json +1 -1
  131. package/fixtures/typescript-no-env/platformatic.runtime.json +2 -3
  132. package/fixtures/typescript-no-env/services/composer/platformatic.composer.json +1 -1
  133. package/fixtures/typescript-no-env/services/movies/global.d.ts +2 -3
  134. package/fixtures/typescript-no-env/services/movies/platformatic.db.json +1 -1
  135. package/fixtures/typescript-no-env/services/movies/types/Movie.d.ts +3 -3
  136. package/fixtures/typescript-no-env/services/movies/types/index.d.ts +6 -6
  137. package/fixtures/typescript-no-env/services/titles/client/client.d.ts +35 -35
  138. package/fixtures/typescript-no-env/services/titles/platformatic.service.json +1 -1
  139. package/index.d.ts +7 -8
  140. package/index.js +15 -10
  141. package/index.test-d.ts +10 -12
  142. package/lib/build-server.js +23 -15
  143. package/lib/compile.js +56 -13
  144. package/lib/config.js +27 -139
  145. package/lib/dependencies.js +59 -0
  146. package/lib/errors.js +6 -2
  147. package/lib/generator/errors.js +1 -1
  148. package/lib/generator/runtime-generator.d.ts +15 -15
  149. package/lib/generator/runtime-generator.js +81 -66
  150. package/lib/logger.js +55 -0
  151. package/lib/management-api.js +29 -44
  152. package/lib/prom-server.js +5 -9
  153. package/lib/runtime.js +1005 -0
  154. package/lib/schema.js +46 -44
  155. package/lib/start.js +49 -117
  156. package/lib/upgrade.js +4 -3
  157. package/lib/utils.js +49 -1
  158. package/lib/versions/v1.36.0.js +1 -1
  159. package/lib/versions/v1.5.0.js +1 -1
  160. package/lib/versions/v2.0.0.js +17 -0
  161. package/lib/worker/app.js +266 -0
  162. package/lib/worker/default-stackable.js +32 -0
  163. package/lib/worker/itc.js +149 -0
  164. package/lib/worker/main.js +129 -0
  165. package/lib/worker/metrics.js +106 -0
  166. package/lib/worker/symbols.js +7 -0
  167. package/package.json +44 -44
  168. package/runtime.mjs +11 -6
  169. package/schema.json +25 -13
  170. package/fixtures/monorepo/serviceApp/platformatic.service-client-without-id.json +0 -21
  171. package/lib/api-client.js +0 -497
  172. package/lib/api.js +0 -397
  173. package/lib/app.js +0 -365
  174. package/lib/load-config.js +0 -20
  175. package/lib/loader.mjs +0 -103
  176. package/lib/message-port-writable.js +0 -50
  177. package/lib/worker.js +0 -182
  178. /package/lib/{interceptors.js → worker/interceptors.js} +0 -0
package/lib/app.js DELETED
@@ -1,365 +0,0 @@
1
- 'use strict'
2
-
3
- const { dirname } = require('node:path')
4
- const { EventEmitter, once } = require('node:events')
5
- const { FileWatcher } = require('@platformatic/utils')
6
- const debounce = require('debounce')
7
- const { buildServer } = require('./build-server')
8
- const { loadConfig } = require('./load-config')
9
- const errors = require('./errors')
10
-
11
- class PlatformaticApp extends EventEmitter {
12
- #hotReload
13
- #loaderPort
14
- #starting
15
- #started
16
- #originalWatch
17
- #fileWatcher
18
- #logger
19
- #telemetryConfig
20
- #serverConfig
21
- #debouncedRestart
22
- #hasManagementApi
23
- #metricsConfig
24
-
25
- constructor (appConfig, loaderPort, logger, telemetryConfig, serverConfig, hasManagementApi, metricsConfig) {
26
- super()
27
- this.appConfig = appConfig
28
- this.config = null
29
- this.#hotReload = false
30
- this.#loaderPort = loaderPort
31
- this.#starting = false
32
- this.#started = false
33
- this.server = null
34
- this.#originalWatch = null
35
- this.#fileWatcher = null
36
- this.#hasManagementApi = !!hasManagementApi
37
- this.#logger = logger.child({
38
- name: this.appConfig.id
39
- })
40
- this.#telemetryConfig = telemetryConfig
41
- this.#metricsConfig = metricsConfig
42
- this.#serverConfig = serverConfig
43
-
44
- /* c8 ignore next 4 */
45
- this.#debouncedRestart = debounce(() => {
46
- this.server.log.info('files changed')
47
- this.restart()
48
- }, 100) // debounce restart for 100ms
49
- }
50
-
51
- getStatus () {
52
- if (this.#starting) return 'starting'
53
- if (this.#started) return 'started'
54
- return 'stopped'
55
- }
56
-
57
- async restart (force) {
58
- if (this.#starting || !this.#started || (!this.#hotReload && !force)) {
59
- return
60
- }
61
-
62
- this.#starting = true
63
- this.#started = false
64
-
65
- // The CJS cache should not be cleared from the loader because v20 moved
66
- // the loader to a different thread with a different CJS cache.
67
- clearCjsCache()
68
-
69
- /* c8 ignore next 4 - tests may not pass in a MessagePort. */
70
- if (this.#loaderPort) {
71
- this.#loaderPort.postMessage('plt:clear-cache')
72
- await once(this.#loaderPort, 'message')
73
- }
74
-
75
- try {
76
- await this.config.configManager.parseAndValidate()
77
- await this.#updateConfig()
78
-
79
- this.#setuplogger(this.config.configManager)
80
- await this.server.restart()
81
- } catch (err) {
82
- // The restart failed. Log the error and
83
- // wait for another event.
84
- // The old app is still available
85
- this.#logger.error({ err })
86
- }
87
-
88
- this.#started = true
89
- this.#starting = false
90
- this.emit('start')
91
- this.emit('restart')
92
- }
93
-
94
- async start () {
95
- if (this.#starting || this.#started) {
96
- throw new errors.ApplicationAlreadyStartedError()
97
- }
98
-
99
- this.#starting = true
100
-
101
- await this.#initializeConfig()
102
- await this.#updateConfig()
103
-
104
- const configManager = this.config.configManager
105
- const config = configManager.current
106
-
107
- this.#setuplogger(configManager)
108
-
109
- try {
110
- // If this is a restart, have the fastify server restart itself. If this
111
- // is not a restart, then create a new server.
112
- this.server = await buildServer({
113
- app: this.config.app,
114
- ...config,
115
- id: this.appConfig.id,
116
- configManager
117
- })
118
- } catch (err) {
119
- this.#logAndExit(err)
120
- }
121
-
122
- if (
123
- (
124
- config.plugins !== undefined ||
125
- config.versions !== undefined
126
- ) &&
127
- this.#originalWatch?.enabled !== false
128
- ) {
129
- this.#startFileWatching()
130
- }
131
-
132
- if (this.appConfig.entrypoint || this.appConfig.useHttp) {
133
- try {
134
- await this.server.start()
135
- /* c8 ignore next 5 */
136
- } catch (err) {
137
- this.server.log.error({ err })
138
- this.#starting = false
139
- throw err
140
- }
141
- } else {
142
- // Make sure the server has run all the onReady hooks before returning.
143
- await this.server.ready()
144
- }
145
-
146
- this.#started = true
147
- this.#starting = false
148
- this.emit('start')
149
- }
150
-
151
- async stop () {
152
- if (!this.#started || this.#starting) {
153
- throw new errors.ApplicationNotStartedError()
154
- }
155
-
156
- await this.#stopFileWatching()
157
- await this.server.close()
158
-
159
- this.#started = false
160
- this.#starting = false
161
- this.emit('stop')
162
- }
163
-
164
- async handleProcessLevelEvent ({ signal, err }) {
165
- /* c8 ignore next 3 */
166
- if (!this.server) {
167
- return false
168
- }
169
-
170
- if (signal === 'SIGUSR2') {
171
- this.server.log.info('reloading configuration')
172
- await this.restart()
173
- return false
174
- }
175
-
176
- if (err) {
177
- this.server.log.error({
178
- err: {
179
- message: err?.message,
180
- stack: err?.stack
181
- }
182
- }, 'exiting')
183
- } else if (signal) {
184
- this.server.log.info({ signal }, 'received signal')
185
- }
186
-
187
- if (this.#starting) {
188
- await once(this, 'start')
189
- }
190
-
191
- if (this.#started) {
192
- await this.stop()
193
- this.server.log.info('server stopped')
194
- }
195
- }
196
-
197
- async #initializeConfig () {
198
- const appConfig = this.appConfig
199
-
200
- let _config
201
- try {
202
- _config = await loadConfig({}, ['-c', appConfig.config], {
203
- onMissingEnv (key) {
204
- return appConfig.localServiceEnvVars.get(key)
205
- }
206
- }, true, this.#logger)
207
- } catch (err) {
208
- this.#logAndExit(err)
209
- }
210
-
211
- this.config = _config
212
- const { configManager } = this.config
213
-
214
- function applyOverrides () {
215
- if (appConfig._configOverrides instanceof Map) {
216
- appConfig._configOverrides.forEach((value, key) => {
217
- if (typeof key !== 'string') {
218
- throw new errors.ConfigPathMustBeStringError()
219
- }
220
-
221
- const parts = key.split('.')
222
- let next = configManager.current
223
- let obj
224
- let i
225
-
226
- for (i = 0; next !== undefined && i < parts.length; ++i) {
227
- obj = next
228
- next = obj[parts[i]]
229
- }
230
-
231
- if (i === parts.length) {
232
- obj[parts.at(-1)] = value
233
- }
234
- })
235
- }
236
- }
237
-
238
- applyOverrides()
239
-
240
- this.#hotReload = this.appConfig.hotReload
241
-
242
- configManager.on('error', (err) => {
243
- /* c8 ignore next */
244
- this.server.log.error({ err }, 'error reloading the configuration')
245
- })
246
- }
247
-
248
- async #updateConfig () {
249
- this.#originalWatch = this.config.configManager.current.watch
250
- this.config.configManager.current.watch = { enabled: false }
251
-
252
- const { configManager } = this.config
253
- configManager.update({
254
- ...configManager.current,
255
- telemetry: this.#telemetryConfig,
256
- metrics: this.#metricsConfig
257
- })
258
-
259
- if (configManager.current.metrics !== false) {
260
- configManager.update({
261
- ...configManager.current,
262
- metrics: this.#metricsConfig
263
- })
264
- }
265
-
266
- if (this.#serverConfig) {
267
- configManager.update({
268
- ...configManager.current,
269
- server: this.#serverConfig
270
- })
271
- }
272
-
273
- if (
274
- (this.#hasManagementApi && configManager.current.metrics === undefined) ||
275
- configManager.current.metrics
276
- ) {
277
- const labels = configManager.current.metrics?.labels || {}
278
- const serviceId = this.appConfig.id
279
- configManager.update({
280
- ...configManager.current,
281
- metrics: {
282
- server: 'hide',
283
- defaultMetrics: { enabled: this.appConfig.entrypoint },
284
- ...configManager.current.metrics,
285
- labels: {
286
- serviceId,
287
- ...labels
288
- }
289
- }
290
- })
291
- }
292
-
293
- if (!this.appConfig.entrypoint) {
294
- configManager.update({
295
- ...configManager.current,
296
- server: {
297
- ...(configManager.current.server || {}),
298
- trustProxy: true
299
- }
300
- })
301
- }
302
- }
303
-
304
- #setuplogger (configManager) {
305
- configManager.current.server = configManager.current.server || {}
306
- const level = configManager.current.server.logger?.level
307
-
308
- configManager.current.server.logger = level
309
- ? this.#logger.child({ level })
310
- : this.#logger
311
- }
312
-
313
- #startFileWatching () {
314
- if (this.#fileWatcher) {
315
- return
316
- }
317
- const server = this.server
318
- const { configManager } = server.platformatic
319
- const fileWatcher = new FileWatcher({
320
- path: dirname(configManager.fullPath),
321
- /* c8 ignore next 2 */
322
- allowToWatch: this.#originalWatch?.allow,
323
- watchIgnore: this.#originalWatch?.ignore || []
324
- })
325
-
326
- fileWatcher.on('update', this.#debouncedRestart)
327
-
328
- fileWatcher.startWatching()
329
- server.log.debug('start watching files')
330
- server.platformatic.fileWatcher = fileWatcher
331
- this.#fileWatcher = fileWatcher
332
- }
333
-
334
- async #stopFileWatching () {
335
- const watcher = this.#fileWatcher
336
- if (watcher) {
337
- this.server.log.debug('stop watching files')
338
- await watcher.stopWatching()
339
- this.server.platformatic.fileWatcher = undefined
340
- this.#fileWatcher = null
341
- }
342
- }
343
-
344
- #logAndExit (err) {
345
- this.#logger.error({ err })
346
- process.exit(1)
347
- }
348
- }
349
-
350
- /* c8 ignore next 11 - c8 upgrade marked many existing things as uncovered */
351
- function clearCjsCache () {
352
- // This evicts all of the modules from the require() cache.
353
- // Note: This does not clean up children references to the deleted module.
354
- // It's likely not a big deal for most cases, but it is a leak. The child
355
- // references can be cleaned up, but it is expensive and involves walking
356
- // the entire require() cache. See the DEP0144 documentation for how to do
357
- // it.
358
- Object.keys(require.cache).forEach((key) => {
359
- if (!key.match(/node_modules/)) {
360
- delete require.cache[key]
361
- }
362
- })
363
- }
364
-
365
- module.exports = { PlatformaticApp }
@@ -1,20 +0,0 @@
1
- 'use strict'
2
-
3
- const { Store, loadConfig } = require('@platformatic/config')
4
-
5
- const { platformaticService } = require('@platformatic/service')
6
- const { platformaticDB } = require('@platformatic/db')
7
- const { platformaticComposer } = require('@platformatic/composer')
8
- const { platformaticRuntime } = require('./config')
9
-
10
- const store = new Store()
11
- store.add(platformaticService)
12
- store.add(platformaticDB)
13
- store.add(platformaticComposer)
14
- store.add(platformaticRuntime)
15
-
16
- function _loadConfig (minimistConfig, args, overrides, replaceEnv = true) {
17
- return loadConfig(minimistConfig, args, store, overrides, replaceEnv)
18
- }
19
-
20
- module.exports = { loadConfig: _loadConfig }
package/lib/loader.mjs DELETED
@@ -1,103 +0,0 @@
1
- import { createRequire, isBuiltin } from 'node:module'
2
- import { dirname, isAbsolute, resolve as pathResolve } from 'node:path'
3
- import { fileURLToPath, pathToFileURL } from 'node:url'
4
- import errors from './errors.js'
5
- const isWindows = process.platform === 'win32'
6
- let timestamp = process.hrtime.bigint()
7
- let port
8
-
9
- /* c8 ignore next 3 - c8 upgrade marked many existing things as uncovered */
10
- function bustEsmCache () {
11
- timestamp = process.hrtime.bigint()
12
- }
13
-
14
- function isRelativePath (p) {
15
- // This function is extracted from Node core, so it should work.
16
- /* c8 ignore next - c8 upgrade marked many existing things as uncovered */
17
- return p.charAt(0) === '.' &&
18
- /* c8 ignore next 9 */
19
- (
20
- p.length === 1 ||
21
- p.charAt(1) === '/' ||
22
- (isWindows && p.charAt(1) === '\\') ||
23
- (p.charAt(1) === '.' && ((
24
- p.length === 2 ||
25
- p.charAt(2) === '/') ||
26
- (isWindows && p.charAt(2) === '\\')))
27
- )
28
- }
29
-
30
- function specifierToFileUrl (specifier, referencingModuleId) {
31
- // Convert the specifier into an absolute path URL if possible. If the
32
- // specifier cannot be converted to a path (for example for a core module),
33
- // then return null.
34
- try {
35
- const url = new URL(specifier)
36
-
37
- if (url.protocol === 'file:') {
38
- return url.href
39
- } else {
40
- return null
41
- }
42
- } catch {
43
- // Ignore error.
44
- }
45
-
46
- /* c8 ignore next 3 - c8 upgrade marked many existing things as uncovered */
47
- if (isBuiltin(specifier)) {
48
- return null
49
- }
50
-
51
- /* c8 ignore next 3 */
52
- if (isAbsolute(specifier)) {
53
- return pathToFileURL(specifier).href
54
- }
55
-
56
- /* c8 ignore next 3 */
57
- if (!referencingModuleId) {
58
- throw new errors.CannotMapSpecifierToAbsolutePathError(specifier)
59
- }
60
-
61
- /* c8 ignore next 5 - c8 upgrade marked many existing things as uncovered */
62
- if (isRelativePath(specifier)) {
63
- return pathToFileURL(
64
- pathResolve(dirname(fileURLToPath(referencingModuleId)), specifier)
65
- ).href
66
- } else {
67
- // The specifier is something in node_modules/.
68
- const req = createRequire(referencingModuleId)
69
-
70
- return pathToFileURL(req.resolve(specifier)).href
71
- }
72
- }
73
-
74
- export async function resolve (specifier, context, nextResolve) {
75
- const url = specifierToFileUrl(specifier, context.parentURL)
76
-
77
- // If the specifier could not be mapped to a file, or the path is this file,
78
- // then don't do anything.
79
- if (typeof url !== 'string' || url === import.meta.url || url.match(/node_modules/)) {
80
- return nextResolve(specifier, context)
81
- }
82
-
83
- return nextResolve(`${url}?ts=${timestamp}`, context)
84
- }
85
-
86
- export function globalPreload (context) {
87
- port = context.port
88
- port.on('message', () => {
89
- /* c8 ignore next 3 - c8 upgrade marked many existing things as uncovered */
90
- bustEsmCache()
91
- port.postMessage('plt:cache-cleared')
92
- })
93
-
94
- return 'globalThis.LOADER_PORT = port;'
95
- }
96
-
97
- export async function initialize (data) {
98
- port = data.port
99
- port.on('message', () => {
100
- bustEsmCache()
101
- port.postMessage('plt:cache-cleared')
102
- })
103
- }
@@ -1,50 +0,0 @@
1
- 'use strict'
2
- const assert = require('node:assert')
3
- const { Writable } = require('node:stream')
4
-
5
- class MessagePortWritable extends Writable {
6
- constructor (options) {
7
- const opts = { ...options, objectMode: true }
8
-
9
- super(opts)
10
- this.port = opts.port
11
- this.metadata = opts.metadata
12
- }
13
-
14
- _write (chunk, encoding, callback) {
15
- this.port.postMessage({
16
- metadata: this.metadata,
17
- logs: [chunk.toString().trim()]
18
- })
19
- process.nextTick(callback)
20
- }
21
-
22
- _writev (chunks, callback) {
23
- // Process the logs here before trying to send them across the thread
24
- // boundary. Sometimes the chunks have an undocumented method on them
25
- // which will prevent sending the chunk itself across threads.
26
- const logs = chunks.map((chunk) => {
27
- // pino should always produce a string here.
28
- assert(typeof chunk.chunk === 'string')
29
- return chunk.chunk.trim()
30
- })
31
-
32
- this.port.postMessage({
33
- metadata: this.metadata,
34
- logs
35
- })
36
- setImmediate(callback)
37
- }
38
-
39
- _final (callback) {
40
- this.port.close()
41
- callback()
42
- }
43
-
44
- _destroy (err, callback) {
45
- this.port.close()
46
- callback(err)
47
- }
48
- }
49
-
50
- module.exports = { MessagePortWritable }
package/lib/worker.js DELETED
@@ -1,182 +0,0 @@
1
- 'use strict'
2
-
3
- const inspector = require('node:inspector')
4
- const { register, createRequire } = require('node:module')
5
- const { isatty } = require('node:tty')
6
- const { join } = require('node:path')
7
- const { pathToFileURL } = require('node:url')
8
- const {
9
- MessageChannel,
10
- parentPort,
11
- workerData
12
- } = require('node:worker_threads')
13
- const undici = require('undici')
14
- const pino = require('pino')
15
- const pretty = require('pino-pretty')
16
- const { setGlobalDispatcher, Agent } = require('undici')
17
- const RuntimeApi = require('./api')
18
- const { MessagePortWritable } = require('./message-port-writable')
19
- const loadInterceptors = require('./interceptors')
20
- let loaderPort
21
-
22
- if (typeof register === 'function' && workerData.config.loaderFile) {
23
- const { port1, port2 } = new MessageChannel()
24
- register(workerData.config.loaderFile, {
25
- data: { port: port2 },
26
- transferList: [port2]
27
- })
28
- loaderPort = port1
29
- } else if (globalThis.LOADER_PORT) {
30
- loaderPort = globalThis.LOADER_PORT
31
- delete globalThis.LOADER_PORT
32
- }
33
-
34
- globalThis.fetch = undici.fetch
35
-
36
- const config = workerData.config
37
-
38
- function createLogger (config) {
39
- const loggerConfig = { ...config.server?.logger }
40
- const cliStream = isatty(1) ? pretty() : pino.destination(1)
41
-
42
- if (!config.loggingPort && !config.managementApi) {
43
- return pino(loggerConfig, cliStream)
44
- }
45
-
46
- const multiStream = pino.multistream([
47
- { stream: cliStream, level: loggerConfig.level || 'info' }
48
- ])
49
-
50
- if (loggerConfig.transport) {
51
- const transport = pino.transport(loggerConfig.transport)
52
- multiStream.add({ level: loggerConfig.level || 'info', stream: transport })
53
- }
54
- if (config.loggingPort) {
55
- const portStream = new MessagePortWritable({
56
- metadata: config.loggingMetadata,
57
- port: config.loggingPort
58
- })
59
- multiStream.add({ level: 'trace', stream: portStream })
60
- }
61
- if (config.managementApi) {
62
- const logsFileMb = 5
63
- const logsLimitMb = config.managementApi?.logs?.maxSize || 200
64
-
65
- let logsLimitCount = Math.ceil(logsLimitMb / logsFileMb) - 1
66
- if (logsLimitCount < 1) {
67
- logsLimitCount = 1
68
- }
69
-
70
- const logsPath = join(workerData.runtimeLogsDir, 'logs')
71
- const pinoRoll = pino.transport({
72
- target: 'pino-roll',
73
- options: {
74
- file: logsPath,
75
- mode: 0o600,
76
- size: logsFileMb + 'm',
77
- mkdir: true,
78
- fsync: true,
79
- limit: {
80
- count: logsLimitCount
81
- }
82
- }
83
- })
84
- multiStream.add({ level: 'trace', stream: pinoRoll })
85
- }
86
- return pino({ level: 'trace' }, multiStream)
87
- }
88
-
89
- const logger = createLogger(config)
90
- if (config.server) {
91
- config.server.logger = logger
92
- }
93
-
94
- let stop
95
-
96
- /* c8 ignore next 4 */
97
- process.on('uncaughtException', (err) => {
98
- logger.error({ err }, 'runtime uncaught exception')
99
-
100
- if (stop) {
101
- stop().then(() => {
102
- setImmediate(process.exit.bind(process), 1)
103
- })
104
- } else {
105
- setImmediate(process.exit.bind(process), 1)
106
- }
107
- })
108
-
109
- // Tested by test/cli/start.test.mjs by C8 does not see it.
110
- /* c8 ignore next 4 */
111
- process.on('unhandledRejection', (err) => {
112
- logger.error({ err }, 'runtime unhandled rejection')
113
-
114
- if (stop) {
115
- stop().then(() => {
116
- setImmediate(process.exit.bind(process), 1)
117
- })
118
- } else {
119
- setImmediate(process.exit.bind(process), 1)
120
- }
121
- })
122
-
123
- async function main () {
124
- if (config.preload) {
125
- await import(pathToFileURL(config.preload))
126
- }
127
-
128
- const { inspectorOptions } = workerData.config
129
-
130
- if (inspectorOptions) {
131
- /* c8 ignore next 6 */
132
- if (inspectorOptions.hotReloadDisabled) {
133
- logger.info('debugging flags were detected. hot reloading has been disabled')
134
- }
135
-
136
- inspector.open(inspectorOptions.port, inspectorOptions.host, inspectorOptions.breakFirstLine)
137
- }
138
-
139
- const interceptors = {}
140
- const composedInterceptors = []
141
- if (config.undici?.interceptors) {
142
- const _require = createRequire(join(workerData.dirname, 'package.json'))
143
- for (const key of ['Agent', 'Pool', 'Client']) {
144
- if (config.undici.interceptors[key]) {
145
- interceptors[key] = await loadInterceptors(_require, config.undici.interceptors[key])
146
- }
147
- }
148
-
149
- if (Array.isArray(config.undici.interceptors)) {
150
- composedInterceptors.push(...await loadInterceptors(_require, config.undici.interceptors))
151
- }
152
- }
153
-
154
- const globalDispatcher = new Agent({
155
- ...config.undici,
156
- interceptors
157
- })
158
- setGlobalDispatcher(globalDispatcher)
159
-
160
- const runtime = new RuntimeApi(workerData.config, logger, loaderPort, composedInterceptors)
161
- runtime.startListening(parentPort)
162
-
163
- parentPort.postMessage('plt:init')
164
-
165
- let stopping = false
166
-
167
- stop = async function () {
168
- if (stopping) {
169
- return
170
- }
171
-
172
- stopping = true
173
- try {
174
- await runtime.stopServices()
175
- } catch (err) {
176
- logger.error({ err }, 'error while stopping services')
177
- }
178
- }
179
- }
180
-
181
- // No need to catch this because there is the unhadledRejection handler on top.
182
- main()