@platformatic/composer 2.41.0 → 2.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/index.js +11 -1
- package/lib/proxy.js +21 -6
- package/lib/stackable.js +36 -19
- package/package.json +10 -10
- package/schema.json +1 -1
package/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const deepEqual = require('fast-deep-equal')
|
|
4
4
|
const ConfigManager = require('@platformatic/config')
|
|
5
5
|
const { platformaticService, buildServer, buildStackable } = require('@platformatic/service')
|
|
6
|
+
const { isKeyEnabled } = require('@platformatic/utils')
|
|
6
7
|
|
|
7
8
|
const { schema } = require('./lib/schema')
|
|
8
9
|
const serviceProxy = require('./lib/proxy')
|
|
@@ -25,7 +26,7 @@ async function platformaticComposer (app, opts) {
|
|
|
25
26
|
let hasGraphqlServices, hasOpenapiServices
|
|
26
27
|
|
|
27
28
|
// When no services are specified, get the list from the runtime.
|
|
28
|
-
await ensureServices(config)
|
|
29
|
+
await ensureServices(opts.context?.stackable?.serviceId, config)
|
|
29
30
|
|
|
30
31
|
const { services } = configManager.current.composer
|
|
31
32
|
|
|
@@ -48,6 +49,15 @@ async function platformaticComposer (app, opts) {
|
|
|
48
49
|
generatedComposedOpenAPI = await openApiGenerator(app, config.composer)
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
if (isKeyEnabled('healthCheck', config.server)) {
|
|
53
|
+
if (typeof config.server.healthCheck !== 'object') {
|
|
54
|
+
config.server.healthCheck = {}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const stackable = opts.context.stackable
|
|
58
|
+
config.server.healthCheck.fn = stackable.isHealthy.bind(stackable)
|
|
59
|
+
}
|
|
60
|
+
|
|
51
61
|
app.register(serviceProxy, { ...config.composer, context: opts.context })
|
|
52
62
|
await app.register(platformaticService, { config: { ...config, openapi: false }, context: opts.context })
|
|
53
63
|
|
package/lib/proxy.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { getGlobalDispatcher } = require('undici')
|
|
4
3
|
const httpProxy = require('@fastify/http-proxy')
|
|
5
4
|
const fp = require('fastify-plugin')
|
|
5
|
+
const { workerData } = require('node:worker_threads')
|
|
6
|
+
const { getGlobalDispatcher } = require('undici')
|
|
6
7
|
|
|
7
8
|
const kITC = Symbol.for('plt.runtime.itc')
|
|
8
9
|
const kProxyRoute = Symbol('plt.composer.proxy.route')
|
|
@@ -14,12 +15,18 @@ async function resolveServiceProxyParameters (service) {
|
|
|
14
15
|
const meta = (await globalThis[kITC]?.send('getServiceMeta', service.id))?.composer ?? { prefix: service.id }
|
|
15
16
|
|
|
16
17
|
// If no prefix could be found, assume the service id
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
let prefix = (service.proxy?.prefix ?? meta.prefix ?? service.id).replace(/(\/$)/g, '')
|
|
19
19
|
let rewritePrefix = ''
|
|
20
20
|
let internalRewriteLocationHeader = true
|
|
21
21
|
|
|
22
22
|
if (meta.wantsAbsoluteUrls) {
|
|
23
|
+
const basePath = workerData.config.basePath
|
|
24
|
+
|
|
25
|
+
// Strip the runtime basepath from the prefix when it comes from the service meta
|
|
26
|
+
if (basePath && !service.proxy?.prefix && prefix.startsWith(basePath)) {
|
|
27
|
+
prefix = prefix.substring(basePath.length)
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
// The rewritePrefix purposely ignores service.proxy?.prefix to let
|
|
24
31
|
// the service always being able to configure their value
|
|
25
32
|
rewritePrefix = meta.prefix ?? service.id
|
|
@@ -138,7 +145,14 @@ module.exports = fp(async function (app, opts) {
|
|
|
138
145
|
})
|
|
139
146
|
}
|
|
140
147
|
|
|
141
|
-
const toReplace = url
|
|
148
|
+
const toReplace = url
|
|
149
|
+
? new RegExp(
|
|
150
|
+
url
|
|
151
|
+
.replace(/127\.0\.0\.1/, 'localhost')
|
|
152
|
+
.replace(/\[::\]/, 'localhost')
|
|
153
|
+
.replace('http://', 'https?://')
|
|
154
|
+
)
|
|
155
|
+
: null
|
|
142
156
|
|
|
143
157
|
const proxyOptions = {
|
|
144
158
|
websocket: true,
|
|
@@ -153,7 +167,7 @@ module.exports = fp(async function (app, opts) {
|
|
|
153
167
|
},
|
|
154
168
|
internalRewriteLocationHeader: false,
|
|
155
169
|
replyOptions: {
|
|
156
|
-
rewriteHeaders:
|
|
170
|
+
rewriteHeaders: headers => {
|
|
157
171
|
let location = headers.location
|
|
158
172
|
if (location) {
|
|
159
173
|
if (toReplace) {
|
|
@@ -186,7 +200,7 @@ module.exports = fp(async function (app, opts) {
|
|
|
186
200
|
...telemetryHeaders,
|
|
187
201
|
'x-forwarded-for': request.ip,
|
|
188
202
|
'x-forwarded-host': request.host,
|
|
189
|
-
'x-forwarded-proto': request.protocol
|
|
203
|
+
'x-forwarded-proto': request.protocol
|
|
190
204
|
}
|
|
191
205
|
|
|
192
206
|
request.log.trace({ headers }, 'rewritten headers before proxying')
|
|
@@ -209,6 +223,7 @@ module.exports = fp(async function (app, opts) {
|
|
|
209
223
|
if (host) {
|
|
210
224
|
await app.register(httpProxy, {
|
|
211
225
|
...proxyOptions,
|
|
226
|
+
prefix: '/',
|
|
212
227
|
constraints: { host }
|
|
213
228
|
})
|
|
214
229
|
|
package/lib/stackable.js
CHANGED
|
@@ -4,11 +4,12 @@ const { ServiceStackable } = require('@platformatic/service')
|
|
|
4
4
|
|
|
5
5
|
const kITC = Symbol.for('plt.runtime.itc')
|
|
6
6
|
|
|
7
|
-
async function ensureServices (config) {
|
|
7
|
+
async function ensureServices (composerId, config) {
|
|
8
8
|
if (config.composer?.services?.length) {
|
|
9
9
|
return
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
composerId ??= globalThis.platformatic?.serviceId
|
|
12
13
|
config.composer ??= {}
|
|
13
14
|
config.composer.services ??= []
|
|
14
15
|
|
|
@@ -17,16 +18,17 @@ async function ensureServices (config) {
|
|
|
17
18
|
|
|
18
19
|
if (services) {
|
|
19
20
|
config.composer.services = services
|
|
20
|
-
.filter(id => id !==
|
|
21
|
+
.filter(id => id !== composerId) // Remove ourself
|
|
21
22
|
.map(id => ({ id, proxy: { prefix: `/${id}` } }))
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
class ComposerStackable extends ServiceStackable {
|
|
26
27
|
#meta
|
|
28
|
+
#dependencies
|
|
27
29
|
|
|
28
30
|
async getBootstrapDependencies () {
|
|
29
|
-
await ensureServices(this.configManager.current)
|
|
31
|
+
await ensureServices(this.serviceId, this.configManager.current)
|
|
30
32
|
|
|
31
33
|
// We do not call init() on purpose, as we don't want to load the app just yet.
|
|
32
34
|
|
|
@@ -43,23 +45,10 @@ class ComposerStackable extends ServiceStackable {
|
|
|
43
45
|
)
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
this.#dependencies = dependencies
|
|
46
49
|
return dependencies
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
async #parseDependency (id, urlString) {
|
|
50
|
-
let url = this.#getServiceUrl(id)
|
|
51
|
-
|
|
52
|
-
if (urlString) {
|
|
53
|
-
const remoteUrl = await this.configManager.replaceEnv(urlString)
|
|
54
|
-
|
|
55
|
-
if (remoteUrl) {
|
|
56
|
-
url = remoteUrl
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return { id, url, local: url.endsWith('.plt.local') }
|
|
61
|
-
}
|
|
62
|
-
|
|
63
52
|
registerMeta (meta) {
|
|
64
53
|
this.#meta = Object.assign(this.#meta ?? {}, meta)
|
|
65
54
|
}
|
|
@@ -74,8 +63,36 @@ class ComposerStackable extends ServiceStackable {
|
|
|
74
63
|
}
|
|
75
64
|
}
|
|
76
65
|
|
|
77
|
-
|
|
78
|
-
|
|
66
|
+
async isHealthy () {
|
|
67
|
+
// Still booting, assume healthy
|
|
68
|
+
if (!this.#dependencies) {
|
|
69
|
+
return true
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const composedServices = this.#dependencies.map(dep => dep.id)
|
|
73
|
+
const workers = await globalThis[kITC].send('getWorkers')
|
|
74
|
+
|
|
75
|
+
for (const worker of Object.values(workers)) {
|
|
76
|
+
if (composedServices.includes(worker.service) && !worker.status.startsWith('start')) {
|
|
77
|
+
return false
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return true
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async #parseDependency (id, urlString) {
|
|
85
|
+
let url = `http://${id}.plt.local`
|
|
86
|
+
|
|
87
|
+
if (urlString) {
|
|
88
|
+
const remoteUrl = await this.configManager.replaceEnv(urlString)
|
|
89
|
+
|
|
90
|
+
if (remoteUrl) {
|
|
91
|
+
url = remoteUrl
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return { id, url, local: url.endsWith('.plt.local') }
|
|
79
96
|
}
|
|
80
97
|
}
|
|
81
98
|
module.exports = { ComposerStackable, ensureServices }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/composer",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.43.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"typescript": "^5.5.4",
|
|
32
32
|
"why-is-node-running": "2",
|
|
33
33
|
"ws": "^8.16.0",
|
|
34
|
-
"@platformatic/client": "2.
|
|
35
|
-
"@platformatic/
|
|
36
|
-
"@platformatic/
|
|
34
|
+
"@platformatic/client": "2.43.0",
|
|
35
|
+
"@platformatic/db": "2.43.0",
|
|
36
|
+
"@platformatic/config": "2.43.0"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@fastify/error": "^4.0.0",
|
|
@@ -67,12 +67,12 @@
|
|
|
67
67
|
"rfdc": "^1.3.1",
|
|
68
68
|
"semgrator": "^0.3.0",
|
|
69
69
|
"undici": "^7.0.0",
|
|
70
|
-
"@platformatic/config": "2.
|
|
71
|
-
"@platformatic/
|
|
72
|
-
"@platformatic/
|
|
73
|
-
"@platformatic/
|
|
74
|
-
"@platformatic/
|
|
75
|
-
"@platformatic/
|
|
70
|
+
"@platformatic/config": "2.43.0",
|
|
71
|
+
"@platformatic/generators": "2.43.0",
|
|
72
|
+
"@platformatic/scalar-theme": "2.43.0",
|
|
73
|
+
"@platformatic/telemetry": "2.43.0",
|
|
74
|
+
"@platformatic/service": "2.43.0",
|
|
75
|
+
"@platformatic/utils": "^2.43.0"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"test": "pnpm run lint && borp -T --timeout=300000 -c 1 && tsd",
|
package/schema.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://schemas.platformatic.dev/@platformatic/composer/2.
|
|
2
|
+
"$id": "https://schemas.platformatic.dev/@platformatic/composer/2.43.0.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"title": "Platformatic Composer",
|
|
5
5
|
"type": "object",
|