@platformatic/runtime 0.26.1 → 0.27.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/composerApp/api1.json +65 -0
- package/fixtures/composerApp/platformatic.composer.json +23 -0
- package/fixtures/configs/invalid-schema-type.config.json +20 -0
- package/fixtures/configs/no-schema.config.json +19 -0
- package/fixtures/dbApp/platformatic.db.json +22 -0
- package/fixtures/start-command.js +9 -0
- package/fixtures/starter.js +9 -0
- package/index.js +5 -25
- package/lib/app.js +18 -12
- package/lib/build-server.js +28 -0
- package/lib/start.js +2 -2
- package/lib/unified-api.js +171 -0
- package/lib/worker.js +28 -1
- package/package.json +16 -13
- package/test/app.test.js +36 -13
- package/test/cli/start.test.mjs +4 -4
- package/test/unified-api.test.js +321 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"openapi": "3.0.3",
|
|
3
|
+
"info": {
|
|
4
|
+
"version": "8.3.1",
|
|
5
|
+
"title": "@fastify/swagger"
|
|
6
|
+
},
|
|
7
|
+
"components": {
|
|
8
|
+
"schemas": {}
|
|
9
|
+
},
|
|
10
|
+
"paths": {
|
|
11
|
+
"/users": {
|
|
12
|
+
"get": {
|
|
13
|
+
"responses": {
|
|
14
|
+
"200": {
|
|
15
|
+
"description": "Default Response"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"post": {
|
|
20
|
+
"responses": {
|
|
21
|
+
"200": {
|
|
22
|
+
"description": "Default Response"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"put": {
|
|
27
|
+
"responses": {
|
|
28
|
+
"200": {
|
|
29
|
+
"description": "Default Response"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"/users/{id}": {
|
|
35
|
+
"get": {
|
|
36
|
+
"responses": {
|
|
37
|
+
"200": {
|
|
38
|
+
"description": "Default Response"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"post": {
|
|
43
|
+
"responses": {
|
|
44
|
+
"200": {
|
|
45
|
+
"description": "Default Response"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"put": {
|
|
50
|
+
"responses": {
|
|
51
|
+
"200": {
|
|
52
|
+
"description": "Default Response"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"delete": {
|
|
57
|
+
"responses": {
|
|
58
|
+
"200": {
|
|
59
|
+
"description": "Default Response"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://platformatic.dev/schemas/v0.23.2/composer",
|
|
3
|
+
"server": {
|
|
4
|
+
"hostname": "127.0.0.1",
|
|
5
|
+
"port": 0,
|
|
6
|
+
"logger": {
|
|
7
|
+
"level": "info"
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"composer": {
|
|
11
|
+
"services": [
|
|
12
|
+
{
|
|
13
|
+
"id": "api1",
|
|
14
|
+
"origin": "http://127.0.0.1",
|
|
15
|
+
"openapi": {
|
|
16
|
+
"file": "./api1.json"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"refreshTimeout": 1000
|
|
21
|
+
},
|
|
22
|
+
"watch": false
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://platformatic.dev/schemas/v0.22.0/trickortreat",
|
|
3
|
+
"server": {
|
|
4
|
+
"hostname": "127.0.0.1",
|
|
5
|
+
"port": 0,
|
|
6
|
+
"logger": {
|
|
7
|
+
"level": "info",
|
|
8
|
+
"name": "hello server"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"plugins": {
|
|
12
|
+
"paths": ["./plugin.js"],
|
|
13
|
+
"hotReload": false
|
|
14
|
+
},
|
|
15
|
+
"service": {
|
|
16
|
+
"openapi": true
|
|
17
|
+
},
|
|
18
|
+
"metrics": false,
|
|
19
|
+
"watch": false
|
|
20
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"server": {
|
|
3
|
+
"hostname": "127.0.0.1",
|
|
4
|
+
"port": 0,
|
|
5
|
+
"logger": {
|
|
6
|
+
"level": "info",
|
|
7
|
+
"name": "hello server"
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"plugins": {
|
|
11
|
+
"paths": ["./plugin.js"],
|
|
12
|
+
"hotReload": false
|
|
13
|
+
},
|
|
14
|
+
"service": {
|
|
15
|
+
"openapi": true
|
|
16
|
+
},
|
|
17
|
+
"metrics": false,
|
|
18
|
+
"watch": false
|
|
19
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://platformatic.dev/schemas/v0.22.0/db",
|
|
3
|
+
"server": {
|
|
4
|
+
"hostname": "127.0.0.1",
|
|
5
|
+
"port": 0
|
|
6
|
+
},
|
|
7
|
+
"migrations": {
|
|
8
|
+
"dir": "migrations",
|
|
9
|
+
"table": "versions"
|
|
10
|
+
},
|
|
11
|
+
"types": {
|
|
12
|
+
"autogenerate": false
|
|
13
|
+
},
|
|
14
|
+
"db": {
|
|
15
|
+
"connectionString": "sqlite://db.sqlite",
|
|
16
|
+
"graphql": true,
|
|
17
|
+
"ignore": {
|
|
18
|
+
"versions": true
|
|
19
|
+
},
|
|
20
|
+
"events": false
|
|
21
|
+
}
|
|
22
|
+
}
|
package/index.js
CHANGED
|
@@ -1,33 +1,13 @@
|
|
|
1
1
|
'use strict'
|
|
2
|
-
const
|
|
2
|
+
const { buildServer } = require('./lib/build-server')
|
|
3
3
|
const { platformaticRuntime } = require('./lib/config')
|
|
4
|
-
const { start
|
|
5
|
-
|
|
6
|
-
async function buildServer (options = {}) {
|
|
7
|
-
if (!options.configManager) {
|
|
8
|
-
// Instantiate a new config manager from the current options.
|
|
9
|
-
const cm = new ConfigManager({
|
|
10
|
-
...platformaticRuntime.configManagerConfig,
|
|
11
|
-
source: options
|
|
12
|
-
})
|
|
13
|
-
await cm.parseAndValidate()
|
|
14
|
-
|
|
15
|
-
if (typeof options === 'string') {
|
|
16
|
-
options = { configManager: cm }
|
|
17
|
-
} else {
|
|
18
|
-
options.configManager = cm
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// The transformConfig() function can't be sent between threads.
|
|
23
|
-
delete options.configManager._transformConfig
|
|
24
|
-
|
|
25
|
-
return startWithConfig(options.configManager)
|
|
26
|
-
}
|
|
4
|
+
const { start } = require('./lib/start')
|
|
5
|
+
const unifiedApi = require('./lib/unified-api')
|
|
27
6
|
|
|
28
7
|
module.exports = {
|
|
29
8
|
buildServer,
|
|
30
9
|
platformaticRuntime,
|
|
31
10
|
schema: platformaticRuntime.schema,
|
|
32
|
-
start
|
|
11
|
+
start,
|
|
12
|
+
unifiedApi
|
|
33
13
|
}
|
package/lib/app.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
const { once } = require('node:events')
|
|
3
3
|
const { dirname } = require('node:path')
|
|
4
|
-
const {
|
|
5
|
-
addLoggerToTheConfig
|
|
6
|
-
} = require('@platformatic/service')
|
|
4
|
+
const { FileWatcher } = require('@platformatic/utils')
|
|
7
5
|
const {
|
|
8
6
|
buildServer,
|
|
9
7
|
loadConfig
|
|
10
|
-
} = require('
|
|
11
|
-
const { FileWatcher } = require('@platformatic/utils')
|
|
8
|
+
} = require('./unified-api')
|
|
12
9
|
|
|
13
10
|
class PlatformaticApp {
|
|
14
11
|
#hotReload
|
|
@@ -16,8 +13,9 @@ class PlatformaticApp {
|
|
|
16
13
|
#restarting
|
|
17
14
|
#started
|
|
18
15
|
#originalWatch
|
|
16
|
+
#logger
|
|
19
17
|
|
|
20
|
-
constructor (appConfig, loaderPort) {
|
|
18
|
+
constructor (appConfig, loaderPort, logger) {
|
|
21
19
|
this.appConfig = appConfig
|
|
22
20
|
this.config = null
|
|
23
21
|
this.#hotReload = false
|
|
@@ -26,6 +24,7 @@ class PlatformaticApp {
|
|
|
26
24
|
this.server = null
|
|
27
25
|
this.#started = false
|
|
28
26
|
this.#originalWatch = null
|
|
27
|
+
this.#logger = logger
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
async restart (force) {
|
|
@@ -61,6 +60,7 @@ class PlatformaticApp {
|
|
|
61
60
|
|
|
62
61
|
this.#originalWatch = config.watch
|
|
63
62
|
config.watch = false
|
|
63
|
+
this.#setuplogger(configManager)
|
|
64
64
|
|
|
65
65
|
try {
|
|
66
66
|
// If this is a restart, have the fastify server restart itself. If this
|
|
@@ -189,11 +189,7 @@ class PlatformaticApp {
|
|
|
189
189
|
}
|
|
190
190
|
}
|
|
191
191
|
|
|
192
|
-
|
|
193
|
-
if (configManager.current.server) {
|
|
194
|
-
addLoggerToTheConfig(configManager.current)
|
|
195
|
-
configManager.current.server.logger.name = this.appConfig.id
|
|
196
|
-
}
|
|
192
|
+
this.#setuplogger(configManager)
|
|
197
193
|
|
|
198
194
|
this.#hotReload = args.hotReload && this.appConfig.hotReload
|
|
199
195
|
|
|
@@ -219,6 +215,16 @@ class PlatformaticApp {
|
|
|
219
215
|
})
|
|
220
216
|
}
|
|
221
217
|
|
|
218
|
+
#setuplogger (configManager) {
|
|
219
|
+
// Set the logger if not present (and the config supports it).
|
|
220
|
+
if (configManager.current.server) {
|
|
221
|
+
const childLogger = this.#logger.child({
|
|
222
|
+
name: this.appConfig.id
|
|
223
|
+
}, { level: configManager.current.server.logger?.level || 'info' })
|
|
224
|
+
configManager.current.server.logger = childLogger
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
222
228
|
#startFileWatching () {
|
|
223
229
|
const server = this.server
|
|
224
230
|
const { configManager } = server.platformatic
|
|
@@ -253,7 +259,7 @@ class PlatformaticApp {
|
|
|
253
259
|
|
|
254
260
|
#logAndExit (err) {
|
|
255
261
|
this.config?.configManager?.stopWatching()
|
|
256
|
-
|
|
262
|
+
this.#logger.error({ err })
|
|
257
263
|
process.exit(1)
|
|
258
264
|
}
|
|
259
265
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const ConfigManager = require('@platformatic/config')
|
|
3
|
+
const { platformaticRuntime } = require('./config')
|
|
4
|
+
const { startWithConfig } = require('./start')
|
|
5
|
+
|
|
6
|
+
async function buildServer (options = {}) {
|
|
7
|
+
if (!options.configManager) {
|
|
8
|
+
// Instantiate a new config manager from the current options.
|
|
9
|
+
const cm = new ConfigManager({
|
|
10
|
+
...platformaticRuntime.configManagerConfig,
|
|
11
|
+
source: options
|
|
12
|
+
})
|
|
13
|
+
await cm.parseAndValidate()
|
|
14
|
+
|
|
15
|
+
if (typeof options === 'string') {
|
|
16
|
+
options = { configManager: cm }
|
|
17
|
+
} else {
|
|
18
|
+
options.configManager = cm
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// The transformConfig() function can't be sent between threads.
|
|
23
|
+
delete options.configManager._transformConfig
|
|
24
|
+
|
|
25
|
+
return startWithConfig(options.configManager)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = { buildServer }
|
package/lib/start.js
CHANGED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const { resolve } = require('node:path')
|
|
3
|
+
const parseArgs = require('minimist')
|
|
4
|
+
const ConfigManager = require('@platformatic/config')
|
|
5
|
+
const {
|
|
6
|
+
platformaticService,
|
|
7
|
+
buildServer,
|
|
8
|
+
loadConfig,
|
|
9
|
+
start,
|
|
10
|
+
schema: serviceSchema
|
|
11
|
+
} = require('@platformatic/service')
|
|
12
|
+
const {
|
|
13
|
+
schema: dbSchema,
|
|
14
|
+
platformaticDB
|
|
15
|
+
} = require('@platformatic/db')
|
|
16
|
+
const {
|
|
17
|
+
schema: composerSchema,
|
|
18
|
+
platformaticComposer
|
|
19
|
+
} = require('@platformatic/composer')
|
|
20
|
+
const { buildServer: runtimeBuildServer } = require('./build-server')
|
|
21
|
+
const { platformaticRuntime } = require('./config')
|
|
22
|
+
const { schema: runtimeSchema } = require('./schema')
|
|
23
|
+
const { start: runtimeStart } = require('./start')
|
|
24
|
+
|
|
25
|
+
const kSupportedAppTypes = new Set(['service', 'db', 'composer', 'runtime'])
|
|
26
|
+
|
|
27
|
+
async function tryGetConfigTypeFromSchema (config) {
|
|
28
|
+
/* c8 ignore next 6 - c8 is not seeing this as covered for some reason. */
|
|
29
|
+
if (typeof config === 'string') {
|
|
30
|
+
// Handle config file paths.
|
|
31
|
+
const loadedConfig = await loadConfig({}, ['-c', config], platformaticService)
|
|
32
|
+
|
|
33
|
+
config = loadedConfig.configManager.current
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const schema = config?.$schema
|
|
37
|
+
|
|
38
|
+
if (typeof schema !== 'string') {
|
|
39
|
+
throw new Error('configuration is missing a schema')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const configType = schema.split('/').pop()
|
|
43
|
+
|
|
44
|
+
if (!kSupportedAppTypes.has(configType)) {
|
|
45
|
+
throw new Error(`unknown configuration type: '${configType}'`)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return configType
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function getConfigType (args = [], directory) {
|
|
52
|
+
try {
|
|
53
|
+
// The config type was not specified, so we need to figure it out.
|
|
54
|
+
// Try to get the config file from the provided arguments.
|
|
55
|
+
let { config } = parseArgs(args, { alias: { c: 'config' } })
|
|
56
|
+
|
|
57
|
+
if (!config) {
|
|
58
|
+
// Couldn't get the config file from the arguments, so look in the
|
|
59
|
+
// provided directory (or current directory) for any recognized
|
|
60
|
+
// config files.
|
|
61
|
+
const searchDir = directory ?? process.cwd()
|
|
62
|
+
const configFile = await ConfigManager.findConfigFile(searchDir)
|
|
63
|
+
|
|
64
|
+
config = resolve(searchDir, configFile)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// At this point, we have the config file. However, several different
|
|
68
|
+
// file formats are supported, so use the config manager to parse the
|
|
69
|
+
// file (without worrying about the validity of the file). We can then
|
|
70
|
+
// use the $schema field to determine the config type.
|
|
71
|
+
const configManager = new ConfigManager({ source: config })
|
|
72
|
+
const configString = await configManager.load()
|
|
73
|
+
const parsedConfig = configManager._parser(configString)
|
|
74
|
+
|
|
75
|
+
return await tryGetConfigTypeFromSchema(parsedConfig)
|
|
76
|
+
} catch (err) {
|
|
77
|
+
const configFiles = ConfigManager.listConfigFiles()
|
|
78
|
+
const msg = `
|
|
79
|
+
Missing config file!
|
|
80
|
+
Be sure to have a config file with one of the following names:
|
|
81
|
+
${configFiles.map((s) => ' * ' + s).join('\n')}
|
|
82
|
+
Alternatively run "npm create platformatic@latest" to generate a basic plt service config.
|
|
83
|
+
`
|
|
84
|
+
|
|
85
|
+
throw new Error(msg, { cause: err })
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function getCurrentSchema (configType) {
|
|
90
|
+
if (configType === 'service') {
|
|
91
|
+
return serviceSchema.schema
|
|
92
|
+
} else if (configType === 'db') {
|
|
93
|
+
return dbSchema
|
|
94
|
+
} else if (configType === 'composer') {
|
|
95
|
+
return composerSchema
|
|
96
|
+
} else if (configType === 'runtime') {
|
|
97
|
+
return runtimeSchema
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
throw new Error(`unknown configuration type: '${configType}'`)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* c8 ignore next 10 - for some reason c8 is not seeing this as covered. */
|
|
104
|
+
async function _buildServer (options) {
|
|
105
|
+
const configType = await tryGetConfigTypeFromSchema(options)
|
|
106
|
+
const app = getApp(configType)
|
|
107
|
+
|
|
108
|
+
if (app === platformaticRuntime) {
|
|
109
|
+
return runtimeBuildServer(options)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return buildServer(options, app)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function getApp (configType) {
|
|
116
|
+
if (configType === 'service') {
|
|
117
|
+
return platformaticService
|
|
118
|
+
} else if (configType === 'db') {
|
|
119
|
+
return platformaticDB
|
|
120
|
+
} else if (configType === 'composer') {
|
|
121
|
+
return platformaticComposer
|
|
122
|
+
} else if (configType === 'runtime') {
|
|
123
|
+
return platformaticRuntime
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
throw new Error('unknown kind: ' + configType)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async function _loadConfig (minimistConfig, args, configType, overrides) {
|
|
130
|
+
// If the config type was specified, then use that. Otherwise, compute it.
|
|
131
|
+
if (typeof configType !== 'string') {
|
|
132
|
+
configType = await getConfigType(args)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return loadConfig(minimistConfig, args, getApp(configType), overrides)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async function _start (args) {
|
|
139
|
+
const configType = await getConfigType(args)
|
|
140
|
+
|
|
141
|
+
if (configType === 'runtime') {
|
|
142
|
+
return runtimeStart(args)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return start(getApp(configType), args)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function startCommand (args) {
|
|
149
|
+
try {
|
|
150
|
+
await _start(args)
|
|
151
|
+
} catch (err) {
|
|
152
|
+
delete err?.stack
|
|
153
|
+
console.error(err?.message)
|
|
154
|
+
|
|
155
|
+
if (err?.cause) {
|
|
156
|
+
console.error(`${err.cause}`)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
process.exit(1)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
module.exports = {
|
|
164
|
+
buildServer: _buildServer,
|
|
165
|
+
getConfigType,
|
|
166
|
+
getCurrentSchema,
|
|
167
|
+
loadConfig: _loadConfig,
|
|
168
|
+
start: _start,
|
|
169
|
+
startCommand,
|
|
170
|
+
getApp
|
|
171
|
+
}
|
package/lib/worker.js
CHANGED
|
@@ -10,12 +10,38 @@ const globalDispatcher = new FastifyUndiciDispatcher({
|
|
|
10
10
|
// setting the domain here allows for fail-fast scenarios
|
|
11
11
|
domain: '.plt.local'
|
|
12
12
|
})
|
|
13
|
+
const pino = require('pino')
|
|
14
|
+
const { isatty } = require('tty')
|
|
15
|
+
|
|
13
16
|
const applications = new Map()
|
|
14
17
|
let entrypoint
|
|
15
18
|
|
|
16
19
|
delete globalThis.LOADER_PORT
|
|
17
20
|
setGlobalDispatcher(globalDispatcher)
|
|
18
21
|
|
|
22
|
+
let transport
|
|
23
|
+
|
|
24
|
+
/* c8 ignore next 5 */
|
|
25
|
+
if (isatty(1)) {
|
|
26
|
+
transport = pino.transport({
|
|
27
|
+
target: 'pino-pretty'
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const logger = pino(transport)
|
|
32
|
+
|
|
33
|
+
process.once('uncaughtException', (err) => {
|
|
34
|
+
logger.error({ err }, 'runtime error')
|
|
35
|
+
throw err
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// Tested by test/cli/start.test.mjs by C8 does not see it.
|
|
39
|
+
/* c8 ignore next 4 */
|
|
40
|
+
process.once('unhandledRejection', (err) => {
|
|
41
|
+
logger.error({ err }, 'runtime error')
|
|
42
|
+
throw err
|
|
43
|
+
})
|
|
44
|
+
|
|
19
45
|
parentPort.on('message', async (msg) => {
|
|
20
46
|
for (const app of applications.values()) {
|
|
21
47
|
await app.handleProcessLevelEvent(msg)
|
|
@@ -39,6 +65,7 @@ parentPort.on('message', async (msg) => {
|
|
|
39
65
|
case 'plt:stop':
|
|
40
66
|
process.exit() // Exit the worker thread.
|
|
41
67
|
break
|
|
68
|
+
/* c8 ignore next 3 */
|
|
42
69
|
case undefined:
|
|
43
70
|
// Ignore
|
|
44
71
|
break
|
|
@@ -52,7 +79,7 @@ async function main () {
|
|
|
52
79
|
|
|
53
80
|
for (let i = 0; i < services.length; ++i) {
|
|
54
81
|
const service = services[i]
|
|
55
|
-
const app = new PlatformaticApp(service, loaderPort)
|
|
82
|
+
const app = new PlatformaticApp(service, loaderPort, logger)
|
|
56
83
|
|
|
57
84
|
applications.set(service.id, app)
|
|
58
85
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -17,12 +17,12 @@
|
|
|
17
17
|
},
|
|
18
18
|
"homepage": "https://github.com/platformatic/platformatic#readme",
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"c8": "^
|
|
21
|
-
"execa": "^7.
|
|
20
|
+
"c8": "^8.0.0",
|
|
21
|
+
"execa": "^7.1.1",
|
|
22
22
|
"snazzy": "^9.0.0",
|
|
23
|
-
"split2": "^4.
|
|
24
|
-
"standard": "^17.
|
|
25
|
-
"tsd": "^0.28.
|
|
23
|
+
"split2": "^4.2.0",
|
|
24
|
+
"standard": "^17.1.0",
|
|
25
|
+
"tsd": "^0.28.1"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@hapi/topo": "^6.0.2",
|
|
@@ -30,15 +30,18 @@
|
|
|
30
30
|
"commist": "^3.2.0",
|
|
31
31
|
"desm": "^1.3.0",
|
|
32
32
|
"es-main": "^1.2.0",
|
|
33
|
-
"fastify": "^4.
|
|
34
|
-
"fastify-undici-dispatcher": "^0.4.
|
|
33
|
+
"fastify": "^4.18.0",
|
|
34
|
+
"fastify-undici-dispatcher": "^0.4.1",
|
|
35
35
|
"help-me": "^4.2.0",
|
|
36
36
|
"minimist": "^1.2.8",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"@platformatic/
|
|
41
|
-
"@platformatic/
|
|
37
|
+
"pino": "^8.14.1",
|
|
38
|
+
"pino-pretty": "^10.0.0",
|
|
39
|
+
"undici": "^5.22.1",
|
|
40
|
+
"@platformatic/composer": "0.27.0",
|
|
41
|
+
"@platformatic/config": "0.27.0",
|
|
42
|
+
"@platformatic/db": "0.27.0",
|
|
43
|
+
"@platformatic/service": "0.27.0",
|
|
44
|
+
"@platformatic/utils": "0.27.0"
|
|
42
45
|
},
|
|
43
46
|
"standard": {
|
|
44
47
|
"ignore": [
|
package/test/app.test.js
CHANGED
|
@@ -5,8 +5,17 @@ const { join } = require('node:path')
|
|
|
5
5
|
const { test } = require('node:test')
|
|
6
6
|
const { PlatformaticApp } = require('../lib/app')
|
|
7
7
|
const fixturesDir = join(__dirname, '..', 'fixtures')
|
|
8
|
+
const pino = require('pino')
|
|
9
|
+
const split = require('split2')
|
|
10
|
+
|
|
11
|
+
function getLoggerAndStream () {
|
|
12
|
+
const stream = split(JSON.parse)
|
|
13
|
+
const logger = pino(stream)
|
|
14
|
+
return { logger, stream }
|
|
15
|
+
}
|
|
8
16
|
|
|
9
17
|
test('logs errors during startup', async (t) => {
|
|
18
|
+
const { logger, stream } = getLoggerAndStream()
|
|
10
19
|
const appPath = join(fixturesDir, 'serviceAppThrowsOnStart')
|
|
11
20
|
const configFile = join(appPath, 'platformatic.service.json')
|
|
12
21
|
const config = {
|
|
@@ -16,9 +25,8 @@ test('logs errors during startup', async (t) => {
|
|
|
16
25
|
entrypoint: true,
|
|
17
26
|
hotReload: true
|
|
18
27
|
}
|
|
19
|
-
const app = new PlatformaticApp(config, null)
|
|
28
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
20
29
|
|
|
21
|
-
t.mock.method(console, 'error', () => {})
|
|
22
30
|
t.mock.method(process, 'exit', () => { throw new Error('exited') })
|
|
23
31
|
|
|
24
32
|
await assert.rejects(async () => {
|
|
@@ -26,11 +34,18 @@ test('logs errors during startup', async (t) => {
|
|
|
26
34
|
}, /exited/)
|
|
27
35
|
assert.strictEqual(process.exit.mock.calls.length, 1)
|
|
28
36
|
assert.strictEqual(process.exit.mock.calls[0].arguments[0], 1)
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
|
|
38
|
+
stream.end()
|
|
39
|
+
const lines = []
|
|
40
|
+
for await (const line of stream) {
|
|
41
|
+
lines.push(line)
|
|
42
|
+
}
|
|
43
|
+
const lastLine = lines[lines.length - 1]
|
|
44
|
+
assert.strictEqual(lastLine.msg, 'boom')
|
|
31
45
|
})
|
|
32
46
|
|
|
33
47
|
test('errors when starting an already started application', async (t) => {
|
|
48
|
+
const { logger } = getLoggerAndStream()
|
|
34
49
|
const appPath = join(fixturesDir, 'monorepo', 'serviceApp')
|
|
35
50
|
const configFile = join(appPath, 'platformatic.service.json')
|
|
36
51
|
const config = {
|
|
@@ -43,7 +58,7 @@ test('errors when starting an already started application', async (t) => {
|
|
|
43
58
|
dependents: [],
|
|
44
59
|
localServiceEnvVars: new Map([['PLT_WITH_LOGGER_URL', ' ']])
|
|
45
60
|
}
|
|
46
|
-
const app = new PlatformaticApp(config, null)
|
|
61
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
47
62
|
|
|
48
63
|
t.after(app.stop.bind(app))
|
|
49
64
|
await app.start()
|
|
@@ -53,6 +68,7 @@ test('errors when starting an already started application', async (t) => {
|
|
|
53
68
|
})
|
|
54
69
|
|
|
55
70
|
test('errors when stopping an already stopped application', async (t) => {
|
|
71
|
+
const { logger } = getLoggerAndStream()
|
|
56
72
|
const appPath = join(fixturesDir, 'monorepo', 'serviceApp')
|
|
57
73
|
const configFile = join(appPath, 'platformatic.service.json')
|
|
58
74
|
const config = {
|
|
@@ -65,7 +81,7 @@ test('errors when stopping an already stopped application', async (t) => {
|
|
|
65
81
|
dependents: [],
|
|
66
82
|
localServiceEnvVars: new Map([['PLT_WITH_LOGGER_URL', ' ']])
|
|
67
83
|
}
|
|
68
|
-
const app = new PlatformaticApp(config, null)
|
|
84
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
69
85
|
|
|
70
86
|
await assert.rejects(async () => {
|
|
71
87
|
await app.stop()
|
|
@@ -73,6 +89,7 @@ test('errors when stopping an already stopped application', async (t) => {
|
|
|
73
89
|
})
|
|
74
90
|
|
|
75
91
|
test('does not restart while restarting', async (t) => {
|
|
92
|
+
const { logger } = getLoggerAndStream()
|
|
76
93
|
const appPath = join(fixturesDir, 'monorepo', 'serviceApp')
|
|
77
94
|
const configFile = join(appPath, 'platformatic.service.json')
|
|
78
95
|
const config = {
|
|
@@ -85,7 +102,7 @@ test('does not restart while restarting', async (t) => {
|
|
|
85
102
|
dependents: [],
|
|
86
103
|
localServiceEnvVars: new Map([['PLT_WITH_LOGGER_URL', ' ']])
|
|
87
104
|
}
|
|
88
|
-
const app = new PlatformaticApp(config, null)
|
|
105
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
89
106
|
|
|
90
107
|
t.after(app.stop.bind(app))
|
|
91
108
|
await app.start()
|
|
@@ -101,6 +118,7 @@ test('does not restart while restarting', async (t) => {
|
|
|
101
118
|
})
|
|
102
119
|
|
|
103
120
|
test('restarts on SIGUSR2', async (t) => {
|
|
121
|
+
const { logger } = getLoggerAndStream()
|
|
104
122
|
const appPath = join(fixturesDir, 'monorepo', 'serviceApp')
|
|
105
123
|
const configFile = join(appPath, 'platformatic.service.json')
|
|
106
124
|
const config = {
|
|
@@ -113,7 +131,7 @@ test('restarts on SIGUSR2', async (t) => {
|
|
|
113
131
|
dependents: [],
|
|
114
132
|
localServiceEnvVars: new Map([['PLT_WITH_LOGGER_URL', ' ']])
|
|
115
133
|
}
|
|
116
|
-
const app = new PlatformaticApp(config, null)
|
|
134
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
117
135
|
|
|
118
136
|
t.after(app.stop.bind(app))
|
|
119
137
|
await app.start()
|
|
@@ -123,6 +141,7 @@ test('restarts on SIGUSR2', async (t) => {
|
|
|
123
141
|
})
|
|
124
142
|
|
|
125
143
|
test('stops on signals other than SIGUSR2', async (t) => {
|
|
144
|
+
const { logger } = getLoggerAndStream()
|
|
126
145
|
const appPath = join(fixturesDir, 'monorepo', 'serviceApp')
|
|
127
146
|
const configFile = join(appPath, 'platformatic.service.json')
|
|
128
147
|
const config = {
|
|
@@ -135,7 +154,7 @@ test('stops on signals other than SIGUSR2', async (t) => {
|
|
|
135
154
|
dependents: [],
|
|
136
155
|
localServiceEnvVars: new Map([['PLT_WITH_LOGGER_URL', ' ']])
|
|
137
156
|
}
|
|
138
|
-
const app = new PlatformaticApp(config, null)
|
|
157
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
139
158
|
|
|
140
159
|
t.after(async () => {
|
|
141
160
|
try {
|
|
@@ -151,6 +170,7 @@ test('stops on signals other than SIGUSR2', async (t) => {
|
|
|
151
170
|
})
|
|
152
171
|
|
|
153
172
|
test('stops on uncaught exceptions', async (t) => {
|
|
173
|
+
const { logger } = getLoggerAndStream()
|
|
154
174
|
const appPath = join(fixturesDir, 'monorepo', 'serviceApp')
|
|
155
175
|
const configFile = join(appPath, 'platformatic.service.json')
|
|
156
176
|
const config = {
|
|
@@ -163,7 +183,7 @@ test('stops on uncaught exceptions', async (t) => {
|
|
|
163
183
|
dependents: [],
|
|
164
184
|
localServiceEnvVars: new Map([['PLT_WITH_LOGGER_URL', ' ']])
|
|
165
185
|
}
|
|
166
|
-
const app = new PlatformaticApp(config, null)
|
|
186
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
167
187
|
|
|
168
188
|
t.after(async () => {
|
|
169
189
|
try {
|
|
@@ -193,8 +213,9 @@ test('supports configuration overrides', async (t) => {
|
|
|
193
213
|
}
|
|
194
214
|
|
|
195
215
|
await t.test('throws on non-string config paths', async (t) => {
|
|
216
|
+
const { logger } = getLoggerAndStream()
|
|
196
217
|
config._configOverrides = new Map([[null, 5]])
|
|
197
|
-
const app = new PlatformaticApp(config, null)
|
|
218
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
198
219
|
|
|
199
220
|
t.after(async () => {
|
|
200
221
|
try {
|
|
@@ -210,8 +231,9 @@ test('supports configuration overrides', async (t) => {
|
|
|
210
231
|
})
|
|
211
232
|
|
|
212
233
|
await t.test('ignores invalid config paths', async (t) => {
|
|
234
|
+
const { logger } = getLoggerAndStream()
|
|
213
235
|
config._configOverrides = new Map([['foo.bar.baz', 5]])
|
|
214
|
-
const app = new PlatformaticApp(config, null)
|
|
236
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
215
237
|
|
|
216
238
|
t.after(async () => {
|
|
217
239
|
try {
|
|
@@ -225,11 +247,12 @@ test('supports configuration overrides', async (t) => {
|
|
|
225
247
|
})
|
|
226
248
|
|
|
227
249
|
await t.test('sets valid config paths', async (t) => {
|
|
250
|
+
const { logger } = getLoggerAndStream()
|
|
228
251
|
config._configOverrides = new Map([
|
|
229
252
|
['server.keepAliveTimeout', 1],
|
|
230
253
|
['server.port', 0]
|
|
231
254
|
])
|
|
232
|
-
const app = new PlatformaticApp(config, null)
|
|
255
|
+
const app = new PlatformaticApp(config, null, logger)
|
|
233
256
|
|
|
234
257
|
t.after(async () => {
|
|
235
258
|
try {
|
package/test/cli/start.test.mjs
CHANGED
|
@@ -29,14 +29,14 @@ test('handles startup errors', async (t) => {
|
|
|
29
29
|
const { execa } = await import('execa')
|
|
30
30
|
const config = join(import.meta.url, '..', '..', 'fixtures', 'configs', 'service-throws-on-start.json')
|
|
31
31
|
const child = execa(process.execPath, [cliPath, 'start', '-c', config], { encoding: 'utf8' })
|
|
32
|
-
let
|
|
32
|
+
let stdout = ''
|
|
33
33
|
let found = false
|
|
34
34
|
|
|
35
|
-
for await (const messages of on(child.
|
|
35
|
+
for await (const messages of on(child.stdout, 'data')) {
|
|
36
36
|
for (const message of messages) {
|
|
37
|
-
|
|
37
|
+
stdout += message
|
|
38
38
|
|
|
39
|
-
if (/Error: boom/.test(
|
|
39
|
+
if (/Error: boom/.test(stdout)) {
|
|
40
40
|
found = true
|
|
41
41
|
break
|
|
42
42
|
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const assert = require('node:assert')
|
|
3
|
+
const { spawn } = require('node:child_process')
|
|
4
|
+
const { once } = require('node:events')
|
|
5
|
+
const { join } = require('node:path')
|
|
6
|
+
const { test } = require('node:test')
|
|
7
|
+
const {
|
|
8
|
+
buildServer,
|
|
9
|
+
getConfigType,
|
|
10
|
+
getCurrentSchema,
|
|
11
|
+
loadConfig
|
|
12
|
+
} = require('../lib/unified-api')
|
|
13
|
+
const { version } = require('../package.json')
|
|
14
|
+
const fixturesDir = join(__dirname, '..', 'fixtures')
|
|
15
|
+
|
|
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
|
+
test('loadConfig()', async (t) => {
|
|
121
|
+
await t.test('can explicitly provide config type', async () => {
|
|
122
|
+
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
123
|
+
const config = await loadConfig({}, ['-c', configFile], undefined, 'service')
|
|
124
|
+
|
|
125
|
+
assert.strictEqual(config.args.config, configFile)
|
|
126
|
+
assert.strictEqual(config.configManager.fullPath, configFile)
|
|
127
|
+
assert.strictEqual(config.configManager.current.server.logger.name, 'service-with-logger')
|
|
128
|
+
assert.strictEqual(config.configManager.schemaOptions.useDefaults, true)
|
|
129
|
+
})
|
|
130
|
+
|
|
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
|
+
await t.test('can load a platformatic service project', async () => {
|
|
144
|
+
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
145
|
+
const config = await loadConfig({}, ['-c', configFile])
|
|
146
|
+
|
|
147
|
+
assert.strictEqual(config.args.config, configFile)
|
|
148
|
+
assert.strictEqual(config.configManager.fullPath, configFile)
|
|
149
|
+
assert.strictEqual(config.configManager.current.server.logger.name, 'service-with-logger')
|
|
150
|
+
assert.strictEqual(config.configManager.schemaOptions.useDefaults, true)
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
await t.test('can load a platformatic db project', async () => {
|
|
154
|
+
const configFile = join(fixturesDir, 'dbApp', 'platformatic.db.json')
|
|
155
|
+
const config = await loadConfig({}, ['-c', configFile])
|
|
156
|
+
|
|
157
|
+
assert.strictEqual(config.args.config, configFile)
|
|
158
|
+
assert.strictEqual(config.configManager.fullPath, configFile)
|
|
159
|
+
assert.strictEqual(config.configManager.current.db.graphql, true)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
await t.test('can load a platformatic composer project', async () => {
|
|
163
|
+
const configFile = join(fixturesDir, 'composerApp', 'platformatic.composer.json')
|
|
164
|
+
const config = await loadConfig({}, ['-c', configFile])
|
|
165
|
+
|
|
166
|
+
assert.strictEqual(config.args.config, configFile)
|
|
167
|
+
assert.strictEqual(config.configManager.fullPath, configFile)
|
|
168
|
+
assert.strictEqual(config.configManager.current.composer.refreshTimeout, 1000)
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
await t.test('can load a platformatic runtime project', async () => {
|
|
172
|
+
const configFile = join(fixturesDir, 'configs', 'monorepo.json')
|
|
173
|
+
const config = await loadConfig({}, ['-c', configFile])
|
|
174
|
+
|
|
175
|
+
assert.strictEqual(config.args.config, configFile)
|
|
176
|
+
assert.strictEqual(config.configManager.fullPath, configFile)
|
|
177
|
+
assert.strictEqual(config.configManager.current.entrypoint, 'serviceApp')
|
|
178
|
+
})
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
test('buildServer()', async (t) => {
|
|
182
|
+
await t.test('can build a service server', async (t) => {
|
|
183
|
+
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
184
|
+
const config = await loadConfig({}, ['-c', configFile])
|
|
185
|
+
const server = await buildServer(config.configManager.current)
|
|
186
|
+
|
|
187
|
+
t.after(async () => {
|
|
188
|
+
await server.close()
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
const address = await server.start()
|
|
192
|
+
// The address should be a valid URL.
|
|
193
|
+
new URL(address) // eslint-disable-line no-new
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
await t.test('can build a db server', async (t) => {
|
|
197
|
+
const configFile = join(fixturesDir, 'dbApp', 'platformatic.db.json')
|
|
198
|
+
const config = await loadConfig({}, ['-c', configFile])
|
|
199
|
+
const server = await buildServer(config.configManager.current)
|
|
200
|
+
|
|
201
|
+
t.after(async () => {
|
|
202
|
+
await server.close()
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
const address = await server.start()
|
|
206
|
+
// The address should be a valid URL.
|
|
207
|
+
new URL(address) // eslint-disable-line no-new
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
await t.test('can build a composer server', async (t) => {
|
|
211
|
+
const configFile = join(fixturesDir, 'composerApp', 'platformatic.composer.json')
|
|
212
|
+
const config = await loadConfig({}, ['-c', configFile])
|
|
213
|
+
const server = await buildServer(config.configManager.current)
|
|
214
|
+
|
|
215
|
+
t.after(async () => {
|
|
216
|
+
await server.close()
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
const address = await server.start()
|
|
220
|
+
// The address should be a valid URL.
|
|
221
|
+
new URL(address) // eslint-disable-line no-new
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
await t.test('can build a runtime application', async (t) => {
|
|
225
|
+
const configFile = join(fixturesDir, 'configs', 'monorepo.json')
|
|
226
|
+
const config = await loadConfig({}, ['-c', configFile])
|
|
227
|
+
const server = await buildServer(config.configManager.current)
|
|
228
|
+
|
|
229
|
+
t.after(async () => {
|
|
230
|
+
await server.close()
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
const address = await server.start()
|
|
234
|
+
// The address should be a valid URL.
|
|
235
|
+
new URL(address) // eslint-disable-line no-new
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
await t.test('input can be a filename', async (t) => {
|
|
239
|
+
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
240
|
+
const server = await buildServer(configFile)
|
|
241
|
+
|
|
242
|
+
t.after(async () => {
|
|
243
|
+
await server.close()
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
const address = await server.start()
|
|
247
|
+
// The address should be a valid URL.
|
|
248
|
+
new URL(address) // eslint-disable-line no-new
|
|
249
|
+
})
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
test('start()', async (t) => {
|
|
253
|
+
await t.test('can start a service server', async (t) => {
|
|
254
|
+
const scriptFile = join(fixturesDir, 'starter.js')
|
|
255
|
+
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
256
|
+
const child = spawn(process.execPath, [scriptFile, configFile])
|
|
257
|
+
child.stdout.pipe(process.stdout)
|
|
258
|
+
child.stderr.pipe(process.stderr)
|
|
259
|
+
const [exitCode] = await once(child, 'exit')
|
|
260
|
+
|
|
261
|
+
assert.strictEqual(exitCode, 42)
|
|
262
|
+
})
|
|
263
|
+
|
|
264
|
+
await t.test('can start a db server', async (t) => {
|
|
265
|
+
const scriptFile = join(fixturesDir, 'starter.js')
|
|
266
|
+
const configFile = join(fixturesDir, 'dbApp', 'platformatic.db.json')
|
|
267
|
+
const child = spawn(process.execPath, [scriptFile, configFile])
|
|
268
|
+
const [exitCode] = await once(child, 'exit')
|
|
269
|
+
|
|
270
|
+
assert.strictEqual(exitCode, 42)
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
await t.test('can start a composer server', async () => {
|
|
274
|
+
const scriptFile = join(fixturesDir, 'starter.js')
|
|
275
|
+
const configFile = join(fixturesDir, 'composerApp', 'platformatic.composer.json')
|
|
276
|
+
const child = spawn(process.execPath, [scriptFile, configFile])
|
|
277
|
+
const [exitCode] = await once(child, 'exit')
|
|
278
|
+
|
|
279
|
+
assert.strictEqual(exitCode, 42)
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
await t.test('can start a runtime application', async () => {
|
|
283
|
+
const scriptFile = join(fixturesDir, 'starter.js')
|
|
284
|
+
const configFile = join(fixturesDir, 'configs', 'monorepo.json')
|
|
285
|
+
const child = spawn(process.execPath, [scriptFile, configFile])
|
|
286
|
+
const [exitCode] = await once(child, 'exit')
|
|
287
|
+
|
|
288
|
+
assert.strictEqual(exitCode, 42)
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
test('startCommand()', async (t) => {
|
|
293
|
+
await t.test('can start a server', async (t) => {
|
|
294
|
+
const scriptFile = join(fixturesDir, 'start-command.js')
|
|
295
|
+
const configFile = join(fixturesDir, 'monorepo', 'serviceAppWithLogger', 'platformatic.service.json')
|
|
296
|
+
const child = spawn(process.execPath, [scriptFile, configFile])
|
|
297
|
+
child.stderr.pipe(process.stderr)
|
|
298
|
+
const [exitCode] = await once(child, 'exit')
|
|
299
|
+
|
|
300
|
+
assert.strictEqual(exitCode, 42)
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
await t.test('exits on error', async (t) => {
|
|
304
|
+
const scriptFile = join(fixturesDir, 'start-command.js')
|
|
305
|
+
const configFile = join(fixturesDir, 'serviceApp', 'platformatic.not-found.json')
|
|
306
|
+
const child = spawn(process.execPath, [scriptFile, configFile])
|
|
307
|
+
const [exitCode] = await once(child, 'exit')
|
|
308
|
+
|
|
309
|
+
assert.strictEqual(exitCode, 1)
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
await t.test('can start a runtime application', async (t) => {
|
|
313
|
+
const scriptFile = join(fixturesDir, 'start-command.js')
|
|
314
|
+
const configFile = join(fixturesDir, 'configs', 'monorepo.json')
|
|
315
|
+
const child = spawn(process.execPath, [scriptFile, configFile])
|
|
316
|
+
child.stderr.pipe(process.stderr)
|
|
317
|
+
const [exitCode] = await once(child, 'exit')
|
|
318
|
+
|
|
319
|
+
assert.strictEqual(exitCode, 42)
|
|
320
|
+
})
|
|
321
|
+
})
|