@platformatic/runtime 0.35.5 → 0.37.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/fixtures/stackables/node_modules/foo/foo.js +61 -0
- package/fixtures/stackables/node_modules/foo/package.json +4 -0
- package/fixtures/stackables/platformatic.json +11 -0
- package/lib/api.js +1 -1
- package/lib/app.js +33 -53
- package/lib/compile.js +2 -2
- package/lib/start.js +1 -1
- package/lib/unified-api.js +37 -123
- package/package.json +9 -9
- package/test/api.test.js +3 -6
- package/test/cli/start.test.mjs +14 -0
- package/test/config.test.js +2 -1
- package/test/start.test.js +3 -2
- package/test/telemetry.test.js +1 -1
- package/test/unified-api.test.js +19 -123
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { schema } = require('@platformatic/service')
|
|
4
|
+
|
|
5
|
+
/** @type {import('fastify').FastifyPluginAsync<{}>} */
|
|
6
|
+
async function foo (app) {
|
|
7
|
+
const text = app.platformatic.config.foo.text
|
|
8
|
+
app.get('/foo', async (request, reply) => {
|
|
9
|
+
return text
|
|
10
|
+
})
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
foo.configType = 'foo'
|
|
14
|
+
foo.schema = {
|
|
15
|
+
$id: 'https://example.com/schemas/foo.json',
|
|
16
|
+
title: 'Platformatic Service',
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
server: schema.server,
|
|
20
|
+
plugins: schema.plugins,
|
|
21
|
+
metrics: schema.metrics,
|
|
22
|
+
watch: {
|
|
23
|
+
anyOf: [schema.watch, {
|
|
24
|
+
type: 'boolean'
|
|
25
|
+
}, {
|
|
26
|
+
type: 'string'
|
|
27
|
+
}]
|
|
28
|
+
},
|
|
29
|
+
$schema: {
|
|
30
|
+
type: 'string'
|
|
31
|
+
},
|
|
32
|
+
module: {
|
|
33
|
+
type: 'string'
|
|
34
|
+
},
|
|
35
|
+
foo: {
|
|
36
|
+
type: 'object',
|
|
37
|
+
properties: {
|
|
38
|
+
text: {
|
|
39
|
+
type: 'string'
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
required: ['text']
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
additionalProperties: false,
|
|
46
|
+
required: ['server']
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
foo.configManagerConfig = {
|
|
50
|
+
schema: foo.schema,
|
|
51
|
+
envWhitelist: ['PORT', 'HOSTNAME'],
|
|
52
|
+
allowToWatch: ['.env'],
|
|
53
|
+
schemaOptions: {
|
|
54
|
+
useDefaults: true,
|
|
55
|
+
coerceTypes: true,
|
|
56
|
+
allErrors: true,
|
|
57
|
+
strict: false
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = foo
|
package/lib/api.js
CHANGED
package/lib/app.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { once } = require('node:events')
|
|
4
|
-
const { dirname
|
|
4
|
+
const { dirname } = require('node:path')
|
|
5
5
|
const { FileWatcher } = require('@platformatic/utils')
|
|
6
6
|
const debounce = require('debounce')
|
|
7
7
|
const {
|
|
@@ -18,6 +18,7 @@ class PlatformaticApp {
|
|
|
18
18
|
#fileWatcher
|
|
19
19
|
#logger
|
|
20
20
|
#telemetryConfig
|
|
21
|
+
#debouncedRestart
|
|
21
22
|
|
|
22
23
|
constructor (appConfig, loaderPort, logger, telemetryConfig) {
|
|
23
24
|
this.appConfig = appConfig
|
|
@@ -33,6 +34,12 @@ class PlatformaticApp {
|
|
|
33
34
|
name: this.appConfig.id
|
|
34
35
|
})
|
|
35
36
|
this.#telemetryConfig = telemetryConfig
|
|
37
|
+
|
|
38
|
+
/* c8 ignore next 4 */
|
|
39
|
+
this.#debouncedRestart = debounce(() => {
|
|
40
|
+
this.server.log.info('files changed')
|
|
41
|
+
this.restart()
|
|
42
|
+
}, 100) // debounce restart for 100ms
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
getStatus () {
|
|
@@ -56,8 +63,9 @@ class PlatformaticApp {
|
|
|
56
63
|
await once(this.#loaderPort, 'message')
|
|
57
64
|
}
|
|
58
65
|
|
|
59
|
-
this.#setuplogger(this.config.configManager)
|
|
60
66
|
try {
|
|
67
|
+
await this.config.configManager.parseAndValidate()
|
|
68
|
+
this.#setuplogger(this.config.configManager)
|
|
61
69
|
await this.server.restart()
|
|
62
70
|
} catch (err) {
|
|
63
71
|
this.#logAndExit(err)
|
|
@@ -90,6 +98,7 @@ class PlatformaticApp {
|
|
|
90
98
|
// If this is a restart, have the fastify server restart itself. If this
|
|
91
99
|
// is not a restart, then create a new server.
|
|
92
100
|
this.server = await buildServer({
|
|
101
|
+
app: this.config.app,
|
|
93
102
|
...config,
|
|
94
103
|
configManager
|
|
95
104
|
})
|
|
@@ -157,8 +166,7 @@ class PlatformaticApp {
|
|
|
157
166
|
|
|
158
167
|
let _config
|
|
159
168
|
try {
|
|
160
|
-
_config = await loadConfig({}, ['-c', appConfig.config],
|
|
161
|
-
watch: true,
|
|
169
|
+
_config = await loadConfig({}, ['-c', appConfig.config], {
|
|
162
170
|
onMissingEnv (key) {
|
|
163
171
|
return appConfig.localServiceEnvVars.get(key)
|
|
164
172
|
}
|
|
@@ -172,30 +180,25 @@ class PlatformaticApp {
|
|
|
172
180
|
|
|
173
181
|
function applyOverrides () {
|
|
174
182
|
if (appConfig._configOverrides instanceof Map) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
})
|
|
195
|
-
} catch (err) {
|
|
196
|
-
configManager.stopWatching()
|
|
197
|
-
throw err
|
|
198
|
-
}
|
|
183
|
+
appConfig._configOverrides.forEach((value, key) => {
|
|
184
|
+
if (typeof key !== 'string') {
|
|
185
|
+
throw new Error('config path must be a string.')
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const parts = key.split('.')
|
|
189
|
+
let next = configManager.current
|
|
190
|
+
let obj
|
|
191
|
+
let i
|
|
192
|
+
|
|
193
|
+
for (i = 0; next !== undefined && i < parts.length; ++i) {
|
|
194
|
+
obj = next
|
|
195
|
+
next = obj[parts[i]]
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (i === parts.length) {
|
|
199
|
+
obj[parts.at(-1)] = value
|
|
200
|
+
}
|
|
201
|
+
})
|
|
199
202
|
}
|
|
200
203
|
}
|
|
201
204
|
|
|
@@ -203,16 +206,6 @@ class PlatformaticApp {
|
|
|
203
206
|
|
|
204
207
|
this.#hotReload = this.appConfig.hotReload
|
|
205
208
|
|
|
206
|
-
configManager.on('update', async (newConfig) => {
|
|
207
|
-
if (this.server) { // when we setup telemetry on config, we don't have a server yet
|
|
208
|
-
this.server.platformatic.config = newConfig
|
|
209
|
-
applyOverrides()
|
|
210
|
-
this.server.log.debug('config changed')
|
|
211
|
-
this.server.log.trace({ newConfig }, 'new config')
|
|
212
|
-
await this.restart()
|
|
213
|
-
}
|
|
214
|
-
})
|
|
215
|
-
|
|
216
209
|
configManager.on('error', (err) => {
|
|
217
210
|
/* c8 ignore next */
|
|
218
211
|
this.server.log.error({ err }, 'error reloading the configuration')
|
|
@@ -233,34 +226,22 @@ class PlatformaticApp {
|
|
|
233
226
|
}
|
|
234
227
|
const server = this.server
|
|
235
228
|
const { configManager } = server.platformatic
|
|
236
|
-
// TODO FileWatcher and ConfigManager both watch the configuration file
|
|
237
|
-
// we should remove the watching from the ConfigManager
|
|
238
229
|
const fileWatcher = new FileWatcher({
|
|
239
230
|
path: dirname(configManager.fullPath),
|
|
240
231
|
/* c8 ignore next 2 */
|
|
241
232
|
allowToWatch: this.#originalWatch?.allow,
|
|
242
|
-
watchIgnore:
|
|
233
|
+
watchIgnore: this.#originalWatch?.ignore || []
|
|
243
234
|
})
|
|
244
235
|
|
|
245
|
-
|
|
246
|
-
const restart = debounce(() => {
|
|
247
|
-
this.server.log.info('files changed')
|
|
248
|
-
this.restart()
|
|
249
|
-
}, 100) // debounce restart for 100ms
|
|
250
|
-
fileWatcher.on('update', restart)
|
|
236
|
+
fileWatcher.on('update', this.#debouncedRestart)
|
|
251
237
|
|
|
252
238
|
fileWatcher.startWatching()
|
|
253
239
|
server.log.debug('start watching files')
|
|
254
240
|
server.platformatic.fileWatcher = fileWatcher
|
|
255
|
-
server.platformatic.configManager.startWatching()
|
|
256
241
|
this.#fileWatcher = fileWatcher
|
|
257
242
|
}
|
|
258
243
|
|
|
259
244
|
async #stopFileWatching () {
|
|
260
|
-
// The configManager automatically watches for the config file changes
|
|
261
|
-
// therefore we need to stop it all the times.
|
|
262
|
-
await this.config.configManager.stopWatching()
|
|
263
|
-
|
|
264
245
|
const watcher = this.#fileWatcher
|
|
265
246
|
if (watcher) {
|
|
266
247
|
this.server.log.debug('stop watching files')
|
|
@@ -271,7 +252,6 @@ class PlatformaticApp {
|
|
|
271
252
|
}
|
|
272
253
|
|
|
273
254
|
#logAndExit (err) {
|
|
274
|
-
this.config?.configManager?.stopWatching()
|
|
275
255
|
this.#logger.error({ err })
|
|
276
256
|
process.exit(1)
|
|
277
257
|
}
|
package/lib/compile.js
CHANGED
|
@@ -9,7 +9,7 @@ const pretty = require('pino-pretty')
|
|
|
9
9
|
const { isatty } = require('node:tty')
|
|
10
10
|
|
|
11
11
|
async function compile (argv, logger) {
|
|
12
|
-
const { configManager, configType } = await loadConfig({}, argv,
|
|
12
|
+
const { configManager, configType } = await loadConfig({}, argv, {
|
|
13
13
|
watch: false
|
|
14
14
|
})
|
|
15
15
|
|
|
@@ -33,7 +33,7 @@ async function compile (argv, logger) {
|
|
|
33
33
|
for (const service of configManager.current.services) {
|
|
34
34
|
const childLogger = logger.child({ name: service.id })
|
|
35
35
|
|
|
36
|
-
const serviceConfig = await loadConfig({}, argv,
|
|
36
|
+
const serviceConfig = await loadConfig({}, argv, {
|
|
37
37
|
watch: false
|
|
38
38
|
})
|
|
39
39
|
|
package/lib/start.js
CHANGED
|
@@ -5,7 +5,7 @@ const { join } = require('node:path')
|
|
|
5
5
|
const { pathToFileURL } = require('node:url')
|
|
6
6
|
const { Worker } = require('node:worker_threads')
|
|
7
7
|
const closeWithGrace = require('close-with-grace')
|
|
8
|
-
const { loadConfig } = require('@platformatic/
|
|
8
|
+
const { loadConfig } = require('@platformatic/config')
|
|
9
9
|
const { parseInspectorOptions, platformaticRuntime } = require('./config')
|
|
10
10
|
const RuntimeApiClient = require('./api-client.js')
|
|
11
11
|
const kLoaderFile = pathToFileURL(join(__dirname, 'loader.mjs')).href
|
package/lib/unified-api.js
CHANGED
|
@@ -1,112 +1,41 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
const {
|
|
3
|
-
const parseArgs = require('minimist')
|
|
4
|
-
const ConfigManager = require('@platformatic/config')
|
|
2
|
+
const { Store, loadConfig, printConfigValidationErrors } = require('@platformatic/config')
|
|
5
3
|
const {
|
|
6
4
|
platformaticService,
|
|
7
5
|
buildServer,
|
|
8
|
-
|
|
9
|
-
start,
|
|
10
|
-
schema: serviceSchema
|
|
6
|
+
start
|
|
11
7
|
} = require('@platformatic/service')
|
|
12
8
|
const {
|
|
13
|
-
schema: dbSchema,
|
|
14
9
|
platformaticDB
|
|
15
10
|
} = require('@platformatic/db')
|
|
16
11
|
const {
|
|
17
|
-
schema: composerSchema,
|
|
18
12
|
platformaticComposer
|
|
19
13
|
} = require('@platformatic/composer')
|
|
20
14
|
const { buildServer: runtimeBuildServer } = require('./build-server')
|
|
21
15
|
const { platformaticRuntime, wrapConfigInRuntimeConfig } = require('./config')
|
|
22
|
-
const { schema: runtimeSchema } = require('./schema')
|
|
23
16
|
const {
|
|
24
17
|
start: runtimeStart,
|
|
25
18
|
startWithConfig: runtimeStartWithConfig
|
|
26
19
|
} = require('./start')
|
|
27
20
|
|
|
28
|
-
const
|
|
21
|
+
const store = new Store()
|
|
22
|
+
store.add(platformaticService)
|
|
23
|
+
store.add(platformaticDB)
|
|
24
|
+
store.add(platformaticComposer)
|
|
25
|
+
store.add(platformaticRuntime)
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (typeof
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const schema = config?.$schema
|
|
40
|
-
|
|
41
|
-
if (typeof schema !== 'string') {
|
|
42
|
-
throw new Error('configuration is missing a schema')
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const configType = schema.split('/').pop()
|
|
46
|
-
|
|
47
|
-
if (!kSupportedAppTypes.has(configType)) {
|
|
48
|
-
throw new Error(`unknown configuration type: '${configType}'`)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return configType
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function getConfigType (args = [], directory) {
|
|
55
|
-
try {
|
|
56
|
-
// The config type was not specified, so we need to figure it out.
|
|
57
|
-
// Try to get the config file from the provided arguments.
|
|
58
|
-
let { config } = parseArgs(args, { alias: { c: 'config' } })
|
|
59
|
-
|
|
60
|
-
if (!config) {
|
|
61
|
-
// Couldn't get the config file from the arguments, so look in the
|
|
62
|
-
// provided directory (or current directory) for any recognized
|
|
63
|
-
// config files.
|
|
64
|
-
const searchDir = directory ?? process.cwd()
|
|
65
|
-
const configFile = await ConfigManager.findConfigFile(searchDir)
|
|
66
|
-
|
|
67
|
-
config = resolve(searchDir, configFile)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// At this point, we have the config file. However, several different
|
|
71
|
-
// file formats are supported, so use the config manager to parse the
|
|
72
|
-
// file (without worrying about the validity of the file). We can then
|
|
73
|
-
// use the $schema field to determine the config type.
|
|
74
|
-
const configManager = new ConfigManager({ source: config })
|
|
75
|
-
const configString = await configManager.load()
|
|
76
|
-
const parsedConfig = configManager._parser(configString)
|
|
77
|
-
|
|
78
|
-
return await tryGetConfigTypeFromSchema(parsedConfig)
|
|
79
|
-
} catch (err) {
|
|
80
|
-
const configFiles = ConfigManager.listConfigFiles()
|
|
81
|
-
const msg = `
|
|
82
|
-
Missing config file!
|
|
83
|
-
Be sure to have a config file with one of the following names:
|
|
84
|
-
${configFiles.map((s) => ' * ' + s).join('\n')}
|
|
85
|
-
Alternatively run "npm create platformatic@latest" to generate a basic plt service config.
|
|
86
|
-
`
|
|
87
|
-
|
|
88
|
-
throw new Error(msg, { cause: err })
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async function getCurrentSchema (configType) {
|
|
93
|
-
if (configType === 'service') {
|
|
94
|
-
return serviceSchema.schema
|
|
95
|
-
} else if (configType === 'db') {
|
|
96
|
-
return dbSchema
|
|
97
|
-
} else if (configType === 'composer') {
|
|
98
|
-
return composerSchema
|
|
99
|
-
} else if (configType === 'runtime') {
|
|
100
|
-
return runtimeSchema
|
|
27
|
+
/* c8 ignore next 10 - for some reason c8 is not seeing this as covered. */
|
|
28
|
+
async function _buildServer (options) {
|
|
29
|
+
if (typeof options === 'string') {
|
|
30
|
+
const config = await _loadConfig({}, ['-c', options])
|
|
31
|
+
options = config.configManager.current
|
|
32
|
+
options.configManager = config.configManager
|
|
33
|
+
options.app = config.app
|
|
101
34
|
}
|
|
102
35
|
|
|
103
|
-
|
|
104
|
-
}
|
|
36
|
+
const app = options.app
|
|
105
37
|
|
|
106
|
-
|
|
107
|
-
async function _buildServer (options) {
|
|
108
|
-
const configType = await tryGetConfigTypeFromSchema(options)
|
|
109
|
-
const app = getApp(configType)
|
|
38
|
+
delete options.app
|
|
110
39
|
|
|
111
40
|
if (app === platformaticRuntime) {
|
|
112
41
|
return runtimeBuildServer(options)
|
|
@@ -115,51 +44,26 @@ async function _buildServer (options) {
|
|
|
115
44
|
return buildServer(options, app)
|
|
116
45
|
}
|
|
117
46
|
|
|
118
|
-
function
|
|
119
|
-
|
|
120
|
-
return platformaticService
|
|
121
|
-
} else if (configType === 'db') {
|
|
122
|
-
return platformaticDB
|
|
123
|
-
} else if (configType === 'composer') {
|
|
124
|
-
return platformaticComposer
|
|
125
|
-
} else if (configType === 'runtime') {
|
|
126
|
-
return platformaticRuntime
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
throw new Error('unknown kind: ' + configType)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async function _loadConfig (minimistConfig, args, configType, overrides) {
|
|
133
|
-
// If the config type was specified, then use that. Otherwise, compute it.
|
|
134
|
-
if (typeof configType !== 'string') {
|
|
135
|
-
configType = await getConfigType(args)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const app = getApp(configType)
|
|
139
|
-
const res = await loadConfig(minimistConfig, args, app, overrides)
|
|
140
|
-
res.configType = configType
|
|
141
|
-
res.app = app
|
|
142
|
-
|
|
143
|
-
return res
|
|
47
|
+
function _loadConfig (minimistConfig, args, overrides) {
|
|
48
|
+
return loadConfig(minimistConfig, args, store, overrides)
|
|
144
49
|
}
|
|
145
50
|
|
|
146
51
|
async function _start (args) {
|
|
147
|
-
const
|
|
52
|
+
const config = await _loadConfig({}, args)
|
|
148
53
|
|
|
149
|
-
if (configType === 'runtime') {
|
|
54
|
+
if (config.configType === 'runtime') {
|
|
150
55
|
return runtimeStart(args)
|
|
151
56
|
}
|
|
152
57
|
|
|
153
|
-
return start(
|
|
58
|
+
return start(config.app, args)
|
|
154
59
|
}
|
|
155
60
|
|
|
156
61
|
async function startCommand (args) {
|
|
157
62
|
try {
|
|
158
|
-
const
|
|
159
|
-
const config = await _loadConfig({}, args, configType)
|
|
63
|
+
const config = await _loadConfig({}, args)
|
|
160
64
|
let runtime
|
|
161
65
|
|
|
162
|
-
if (configType === 'runtime') {
|
|
66
|
+
if (config.configType === 'runtime') {
|
|
163
67
|
config.configManager.args = config.args
|
|
164
68
|
runtime = await runtimeStartWithConfig(config.configManager)
|
|
165
69
|
} else {
|
|
@@ -175,6 +79,19 @@ async function startCommand (args) {
|
|
|
175
79
|
}
|
|
176
80
|
|
|
177
81
|
function logErrorAndExit (err) {
|
|
82
|
+
if (err.filenames) {
|
|
83
|
+
console.error(`Missing config file!
|
|
84
|
+
Be sure to have a config file with one of the following names:
|
|
85
|
+
|
|
86
|
+
${err.filenames.map((s) => ' * ' + s).join('\n')}
|
|
87
|
+
|
|
88
|
+
In alternative run "npm create platformatic@latest" to generate a basic plt service config.`)
|
|
89
|
+
process.exit(1)
|
|
90
|
+
} else if (err.validationErrors) {
|
|
91
|
+
printConfigValidationErrors(err)
|
|
92
|
+
process.exit(1)
|
|
93
|
+
}
|
|
94
|
+
|
|
178
95
|
delete err?.stack
|
|
179
96
|
console.error(err?.message)
|
|
180
97
|
|
|
@@ -187,10 +104,7 @@ function logErrorAndExit (err) {
|
|
|
187
104
|
|
|
188
105
|
module.exports = {
|
|
189
106
|
buildServer: _buildServer,
|
|
190
|
-
getConfigType,
|
|
191
|
-
getCurrentSchema,
|
|
192
107
|
loadConfig: _loadConfig,
|
|
193
108
|
start: _start,
|
|
194
|
-
startCommand
|
|
195
|
-
getApp
|
|
109
|
+
startCommand
|
|
196
110
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"standard": "^17.1.0",
|
|
25
25
|
"tsd": "^0.28.1",
|
|
26
26
|
"typescript": "^5.1.6",
|
|
27
|
-
"@platformatic/sql-graphql": "0.
|
|
28
|
-
"@platformatic/sql-mapper": "0.
|
|
27
|
+
"@platformatic/sql-graphql": "0.37.0",
|
|
28
|
+
"@platformatic/sql-mapper": "0.37.0"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@hapi/topo": "^6.0.2",
|
|
@@ -42,12 +42,12 @@
|
|
|
42
42
|
"pino": "^8.14.1",
|
|
43
43
|
"pino-pretty": "^10.0.0",
|
|
44
44
|
"undici": "^5.22.1",
|
|
45
|
-
"@platformatic/composer": "0.
|
|
46
|
-
"@platformatic/config": "0.
|
|
47
|
-
"@platformatic/db": "0.
|
|
48
|
-
"@platformatic/service": "0.
|
|
49
|
-
"@platformatic/telemetry": "0.
|
|
50
|
-
"@platformatic/utils": "0.
|
|
45
|
+
"@platformatic/composer": "0.37.0",
|
|
46
|
+
"@platformatic/config": "0.37.0",
|
|
47
|
+
"@platformatic/db": "0.37.0",
|
|
48
|
+
"@platformatic/service": "0.37.0",
|
|
49
|
+
"@platformatic/telemetry": "0.37.0",
|
|
50
|
+
"@platformatic/utils": "0.37.0"
|
|
51
51
|
},
|
|
52
52
|
"standard": {
|
|
53
53
|
"ignore": [
|
package/test/api.test.js
CHANGED
|
@@ -4,7 +4,7 @@ const assert = require('node:assert')
|
|
|
4
4
|
const { join } = require('node:path')
|
|
5
5
|
const { test } = require('node:test')
|
|
6
6
|
|
|
7
|
-
const { loadConfig } = require('@platformatic/
|
|
7
|
+
const { loadConfig } = require('@platformatic/config')
|
|
8
8
|
const { buildServer, platformaticRuntime } = require('..')
|
|
9
9
|
const fixturesDir = join(__dirname, '..', 'fixtures')
|
|
10
10
|
|
|
@@ -349,9 +349,6 @@ test('should fail to get a service openapi schema if service does not expose it'
|
|
|
349
349
|
await app.close()
|
|
350
350
|
})
|
|
351
351
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
} catch (err) {
|
|
355
|
-
assert.strictEqual(err.message, 'Service with id \'without-openapi\' does not expose an OpenAPI schema')
|
|
356
|
-
}
|
|
352
|
+
const openapiSchema = await app.getServiceOpenapiSchema('without-openapi')
|
|
353
|
+
assert.strictEqual(openapiSchema, null)
|
|
357
354
|
})
|
package/test/cli/start.test.mjs
CHANGED
|
@@ -48,6 +48,10 @@ test('handles startup errors', async (t) => {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
assert(found)
|
|
51
|
+
|
|
52
|
+
// if we do not await this, the test will crash because the event loop has nothing to do
|
|
53
|
+
// but there is still a promise waiting
|
|
54
|
+
await child.catch(() => {})
|
|
51
55
|
})
|
|
52
56
|
|
|
53
57
|
test('exits on error', async () => {
|
|
@@ -115,3 +119,13 @@ test('starts the inspector', async (t) => {
|
|
|
115
119
|
assert(found)
|
|
116
120
|
child.kill('SIGINT')
|
|
117
121
|
})
|
|
122
|
+
|
|
123
|
+
test('stackable', async () => {
|
|
124
|
+
const config = join(import.meta.url, '..', '..', 'fixtures', 'stackables', 'platformatic.json')
|
|
125
|
+
const { child, url } = await start('start', '-c', config)
|
|
126
|
+
const res = await request(url + '/foo')
|
|
127
|
+
|
|
128
|
+
assert.strictEqual(res.statusCode, 200)
|
|
129
|
+
assert.deepStrictEqual(await res.body.text(), 'Hello World')
|
|
130
|
+
child.kill('SIGINT')
|
|
131
|
+
})
|
package/test/config.test.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
const assert = require('node:assert')
|
|
4
4
|
const { join } = require('node:path')
|
|
5
5
|
const { test } = require('node:test')
|
|
6
|
-
const { loadConfig
|
|
6
|
+
const { loadConfig } = require('@platformatic/config')
|
|
7
|
+
const { platformaticService } = require('@platformatic/service')
|
|
7
8
|
const { parseInspectorOptions, platformaticRuntime } = require('../lib/config')
|
|
8
9
|
const fixturesDir = join(__dirname, '..', 'fixtures')
|
|
9
10
|
|
package/test/start.test.js
CHANGED
|
@@ -6,7 +6,8 @@ const { join } = require('node:path')
|
|
|
6
6
|
const { test } = require('node:test')
|
|
7
7
|
const { MessageChannel } = require('node:worker_threads')
|
|
8
8
|
const { request } = require('undici')
|
|
9
|
-
const { loadConfig } = require('@platformatic/
|
|
9
|
+
const { loadConfig } = require('@platformatic/config')
|
|
10
|
+
const { platformaticDB } = require('@platformatic/db')
|
|
10
11
|
const { buildServer, platformaticRuntime } = require('..')
|
|
11
12
|
const { wrapConfigInRuntimeConfig } = require('../lib/config')
|
|
12
13
|
const { startWithConfig } = require('../lib/start')
|
|
@@ -160,7 +161,7 @@ test('handles uncaught exceptions with db app', async (t) => {
|
|
|
160
161
|
|
|
161
162
|
test('logs errors during db migrations', async (t) => {
|
|
162
163
|
const configFile = join(fixturesDir, 'dbAppWithMigrationError', 'platformatic.db.json')
|
|
163
|
-
const config = await loadConfig({}, ['-c', configFile],
|
|
164
|
+
const config = await loadConfig({}, ['-c', configFile], platformaticDB)
|
|
164
165
|
const runtimeConfig = await wrapConfigInRuntimeConfig(config)
|
|
165
166
|
const { port1, port2 } = new MessageChannel()
|
|
166
167
|
runtimeConfig.current.loggingPort = port2
|
package/test/telemetry.test.js
CHANGED
|
@@ -4,7 +4,7 @@ const assert = require('node:assert')
|
|
|
4
4
|
const { request } = require('undici')
|
|
5
5
|
const { test } = require('node:test')
|
|
6
6
|
const { join } = require('node:path')
|
|
7
|
-
const { loadConfig } = require('@platformatic/
|
|
7
|
+
const { loadConfig } = require('@platformatic/config')
|
|
8
8
|
const { platformaticRuntime } = require('..')
|
|
9
9
|
const { startWithConfig } = require('../lib/start')
|
|
10
10
|
const fixturesDir = join(__dirname, '..', 'fixtures')
|
package/test/unified-api.test.js
CHANGED
|
@@ -6,117 +6,10 @@ const { join } = require('node:path')
|
|
|
6
6
|
const { test } = require('node:test')
|
|
7
7
|
const {
|
|
8
8
|
buildServer,
|
|
9
|
-
getConfigType,
|
|
10
|
-
getCurrentSchema,
|
|
11
9
|
loadConfig
|
|
12
10
|
} = require('../lib/unified-api')
|
|
13
|
-
const { version } = require('../package.json')
|
|
14
11
|
const fixturesDir = join(__dirname, '..', 'fixtures')
|
|
15
12
|
|
|
16
|
-
test('getConfigType()', async (t) => {
|
|
17
|
-
await t.test('throws if there is no $schema', async () => {
|
|
18
|
-
const configFile = join(fixturesDir, 'configs', 'no-schema.config.json')
|
|
19
|
-
let err
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
await getConfigType(['-c', configFile])
|
|
23
|
-
} catch (error) {
|
|
24
|
-
err = error
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
assert(err)
|
|
28
|
-
assert.strictEqual(err.cause.message, 'configuration is missing a schema')
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
await t.test('throws if the schema type is unsupported', async () => {
|
|
32
|
-
const configFile = join(fixturesDir, 'configs', 'invalid-schema-type.config.json')
|
|
33
|
-
let err
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
await getConfigType(['-c', configFile])
|
|
37
|
-
} catch (error) {
|
|
38
|
-
err = error
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
assert(err)
|
|
42
|
-
assert.strictEqual(err.cause.message, 'unknown configuration type: \'trickortreat\'')
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
await t.test('gets type from config via args', async () => {
|
|
46
|
-
const configFile = join(fixturesDir, 'monorepo', 'serviceApp', 'platformatic.service.json')
|
|
47
|
-
const type = await getConfigType(['-c', configFile])
|
|
48
|
-
|
|
49
|
-
assert.strictEqual(type, 'service')
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
await t.test('gets type from config in provided directory', async () => {
|
|
53
|
-
const configDir = join(fixturesDir, 'monorepo', 'serviceApp')
|
|
54
|
-
const type = await getConfigType(undefined, configDir)
|
|
55
|
-
|
|
56
|
-
assert.strictEqual(type, 'service')
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
await t.test('gets db type from config in cwd', async (t) => {
|
|
60
|
-
const cwd = process.cwd()
|
|
61
|
-
|
|
62
|
-
t.after(() => {
|
|
63
|
-
process.chdir(cwd)
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
const configDir = join(fixturesDir, 'dbApp')
|
|
67
|
-
process.chdir(configDir)
|
|
68
|
-
const type = await getConfigType()
|
|
69
|
-
|
|
70
|
-
assert.strictEqual(type, 'db')
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
await t.test('gets composer type from config in cwd', async (t) => {
|
|
74
|
-
const cwd = process.cwd()
|
|
75
|
-
|
|
76
|
-
t.after(() => {
|
|
77
|
-
process.chdir(cwd)
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
const configDir = join(fixturesDir, 'monorepo', 'composerApp')
|
|
81
|
-
process.chdir(configDir)
|
|
82
|
-
const type = await getConfigType()
|
|
83
|
-
|
|
84
|
-
assert.strictEqual(type, 'composer')
|
|
85
|
-
})
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
test('getCurrentSchema()', async (t) => {
|
|
89
|
-
await t.test('gets service schema', async () => {
|
|
90
|
-
const schema = await getCurrentSchema('service')
|
|
91
|
-
|
|
92
|
-
assert(schema.$id.endsWith(`/v${version}/service`))
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
await t.test('gets db schema', async () => {
|
|
96
|
-
const schema = await getCurrentSchema('db')
|
|
97
|
-
|
|
98
|
-
assert(schema.$id.endsWith(`/v${version}/db`))
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
await t.test('gets composer schema', async () => {
|
|
102
|
-
const schema = await getCurrentSchema('composer')
|
|
103
|
-
|
|
104
|
-
assert(schema.$id.endsWith(`/v${version}/composer`))
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
await t.test('gets runtime schema', async () => {
|
|
108
|
-
const schema = await getCurrentSchema('runtime')
|
|
109
|
-
|
|
110
|
-
assert(schema.$id.endsWith(`/v${version}/runtime`))
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
await t.test('throws for unknown types', async () => {
|
|
114
|
-
await assert.rejects(async () => {
|
|
115
|
-
await getCurrentSchema('not-a-real-type')
|
|
116
|
-
}, /unknown configuration type/)
|
|
117
|
-
})
|
|
118
|
-
})
|
|
119
|
-
|
|
120
13
|
test('loadConfig()', async (t) => {
|
|
121
14
|
await t.test('can explicitly provide config type', async () => {
|
|
122
15
|
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
@@ -128,18 +21,6 @@ test('loadConfig()', async (t) => {
|
|
|
128
21
|
assert.strictEqual(config.configManager.schemaOptions.useDefaults, true)
|
|
129
22
|
})
|
|
130
23
|
|
|
131
|
-
await t.test('throws if explicit type is wrong', async () => {
|
|
132
|
-
// Prevent the failed validation from logging and exiting the process.
|
|
133
|
-
t.mock.method(process, 'exit', () => {})
|
|
134
|
-
t.mock.method(console, 'table', () => {})
|
|
135
|
-
|
|
136
|
-
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
137
|
-
|
|
138
|
-
await assert.rejects(async () => {
|
|
139
|
-
await loadConfig({}, ['-c', configFile], 'kaboom')
|
|
140
|
-
})
|
|
141
|
-
})
|
|
142
|
-
|
|
143
24
|
await t.test('can load a platformatic service project', async () => {
|
|
144
25
|
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
145
26
|
const config = await loadConfig({}, ['-c', configFile])
|
|
@@ -182,7 +63,10 @@ test('buildServer()', async (t) => {
|
|
|
182
63
|
await t.test('can build a service server', async (t) => {
|
|
183
64
|
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
184
65
|
const config = await loadConfig({}, ['-c', configFile])
|
|
185
|
-
const server = await buildServer(
|
|
66
|
+
const server = await buildServer({
|
|
67
|
+
app: config.app,
|
|
68
|
+
...config.configManager.current
|
|
69
|
+
})
|
|
186
70
|
|
|
187
71
|
t.after(async () => {
|
|
188
72
|
await server.close()
|
|
@@ -196,7 +80,10 @@ test('buildServer()', async (t) => {
|
|
|
196
80
|
await t.test('can build a db server', async (t) => {
|
|
197
81
|
const configFile = join(fixturesDir, 'dbApp', 'platformatic.db.json')
|
|
198
82
|
const config = await loadConfig({}, ['-c', configFile])
|
|
199
|
-
const server = await buildServer(
|
|
83
|
+
const server = await buildServer({
|
|
84
|
+
app: config.app,
|
|
85
|
+
...config.configManager.current
|
|
86
|
+
})
|
|
200
87
|
|
|
201
88
|
t.after(async () => {
|
|
202
89
|
await server.close()
|
|
@@ -210,7 +97,10 @@ test('buildServer()', async (t) => {
|
|
|
210
97
|
await t.test('can build a composer server', async (t) => {
|
|
211
98
|
const configFile = join(fixturesDir, 'composerApp', 'platformatic.composer.json')
|
|
212
99
|
const config = await loadConfig({}, ['-c', configFile])
|
|
213
|
-
const server = await buildServer(
|
|
100
|
+
const server = await buildServer({
|
|
101
|
+
app: config.app,
|
|
102
|
+
...config.configManager.current
|
|
103
|
+
})
|
|
214
104
|
|
|
215
105
|
t.after(async () => {
|
|
216
106
|
await server.close()
|
|
@@ -224,7 +114,10 @@ test('buildServer()', async (t) => {
|
|
|
224
114
|
await t.test('can build a runtime application', async (t) => {
|
|
225
115
|
const configFile = join(fixturesDir, 'configs', 'monorepo.json')
|
|
226
116
|
const config = await loadConfig({}, ['-c', configFile])
|
|
227
|
-
const server = await buildServer(
|
|
117
|
+
const server = await buildServer({
|
|
118
|
+
app: config.app,
|
|
119
|
+
...config.configManager.current
|
|
120
|
+
})
|
|
228
121
|
|
|
229
122
|
t.after(async () => {
|
|
230
123
|
await server.close()
|
|
@@ -244,6 +137,9 @@ test('buildServer()', async (t) => {
|
|
|
244
137
|
})
|
|
245
138
|
|
|
246
139
|
const address = await server.start()
|
|
140
|
+
|
|
141
|
+
assert.strictEqual(server.platformatic.configManager.fullPath, configFile)
|
|
142
|
+
|
|
247
143
|
// The address should be a valid URL.
|
|
248
144
|
new URL(address) // eslint-disable-line no-new
|
|
249
145
|
})
|