@platformatic/basic 2.0.0-alpha.9 → 2.0.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 +39 -19
- package/lib/base.js +10 -4
- package/lib/worker/child-manager.js +2 -2
- package/lib/worker/child-process.js +17 -5
- package/lib/worker/child-transport.js +2 -2
- package/package.json +8 -7
- package/schema.json +1 -1
package/index.js
CHANGED
|
@@ -7,13 +7,34 @@ import pino from 'pino'
|
|
|
7
7
|
import { packageJson, schema } from './lib/schema.js'
|
|
8
8
|
import { importFile } from './lib/utils.js'
|
|
9
9
|
|
|
10
|
+
const importStackablePackageMarker = '__pltImportStackablePackage.js'
|
|
11
|
+
|
|
12
|
+
export const configCandidates = [
|
|
13
|
+
'platformatic.application.json',
|
|
14
|
+
'platformatic.json',
|
|
15
|
+
'watt.json',
|
|
16
|
+
'platformatic.application.yaml',
|
|
17
|
+
'platformatic.yaml',
|
|
18
|
+
'watt.yaml',
|
|
19
|
+
'platformatic.application.yml',
|
|
20
|
+
'platformatic.yml',
|
|
21
|
+
'watt.yml',
|
|
22
|
+
'platformatic.application.toml',
|
|
23
|
+
'platformatic.toml',
|
|
24
|
+
'watt.toml',
|
|
25
|
+
'platformatic.application.tml',
|
|
26
|
+
'platformatic.tml',
|
|
27
|
+
'watt.tml'
|
|
28
|
+
]
|
|
29
|
+
|
|
10
30
|
function isImportFailedError (error, pkg) {
|
|
11
|
-
if (error.code !== 'ERR_MODULE_NOT_FOUND') {
|
|
31
|
+
if (error.code !== 'ERR_MODULE_NOT_FOUND' && error.code !== 'MODULE_NOT_FOUND') {
|
|
12
32
|
return false
|
|
13
33
|
}
|
|
14
34
|
|
|
15
35
|
const match = error.message.match(/Cannot find package '(.+)' imported from (.+)/)
|
|
16
|
-
|
|
36
|
+
|
|
37
|
+
return match?.[1] === pkg || error.requireStack?.[0].endsWith(importStackablePackageMarker)
|
|
17
38
|
}
|
|
18
39
|
|
|
19
40
|
async function importStackablePackage (opts, pkg, autodetectDescription) {
|
|
@@ -27,7 +48,7 @@ async function importStackablePackage (opts, pkg, autodetectDescription) {
|
|
|
27
48
|
}
|
|
28
49
|
|
|
29
50
|
// Scope to the service
|
|
30
|
-
const require = createRequire(resolve(opts.context.directory,
|
|
51
|
+
const require = createRequire(resolve(opts.context.directory, importStackablePackageMarker))
|
|
31
52
|
const imported = require.resolve(pkg)
|
|
32
53
|
return await importFile(imported)
|
|
33
54
|
}
|
|
@@ -36,17 +57,10 @@ async function importStackablePackage (opts, pkg, autodetectDescription) {
|
|
|
36
57
|
throw e
|
|
37
58
|
}
|
|
38
59
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (rootFolder) {
|
|
44
|
-
errorMessage += `in the package.json file in the folder ${rootFolder}.`
|
|
45
|
-
} else {
|
|
46
|
-
errorMessage += 'in the root package.json file.'
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
throw new Error(errorMessage)
|
|
60
|
+
const serviceDirectory = relative(workerData.dirname, opts.context.directory)
|
|
61
|
+
throw new Error(
|
|
62
|
+
`Unable to import package '${pkg}'. Please add it as a dependency in the package.json file in the folder ${serviceDirectory}.`
|
|
63
|
+
)
|
|
50
64
|
}
|
|
51
65
|
}
|
|
52
66
|
|
|
@@ -65,10 +79,13 @@ async function buildStackable (opts) {
|
|
|
65
79
|
const hadConfig = opts.config
|
|
66
80
|
|
|
67
81
|
if (!hadConfig) {
|
|
68
|
-
const candidate
|
|
82
|
+
for (const candidate of configCandidates) {
|
|
83
|
+
const candidatePath = resolve(root, candidate)
|
|
69
84
|
|
|
70
|
-
|
|
71
|
-
|
|
85
|
+
if (existsSync(candidatePath)) {
|
|
86
|
+
opts.config = candidatePath
|
|
87
|
+
break
|
|
88
|
+
}
|
|
72
89
|
}
|
|
73
90
|
}
|
|
74
91
|
|
|
@@ -91,7 +108,10 @@ async function buildStackable (opts) {
|
|
|
91
108
|
const imported = await importStackablePackage(opts, toImport, autodetectDescription)
|
|
92
109
|
|
|
93
110
|
const serviceRoot = relative(process.cwd(), opts.context.directory)
|
|
94
|
-
if (
|
|
111
|
+
if (
|
|
112
|
+
!hadConfig &&
|
|
113
|
+
!existsSync(resolve(serviceRoot, 'platformatic.json') || existsSync(resolve(serviceRoot, 'watt.json')))
|
|
114
|
+
) {
|
|
95
115
|
const logger = pino({
|
|
96
116
|
level: opts.context.serverConfig?.logger?.level ?? 'warn',
|
|
97
117
|
name: opts.context.serviceId
|
|
@@ -100,7 +120,7 @@ async function buildStackable (opts) {
|
|
|
100
120
|
logger.warn(
|
|
101
121
|
[
|
|
102
122
|
`Platformatic has auto-detected that service ${opts.context.serviceId} ${autodetectDescription}.\n`,
|
|
103
|
-
`We suggest you create a platformatic.
|
|
123
|
+
`We suggest you create a platformatic.json or watt.json file in the folder ${serviceRoot} with the "$schema" `,
|
|
104
124
|
`property set to "https://schemas.platformatic.dev/${toImport}/${packageJson.version}.json".`
|
|
105
125
|
].join('')
|
|
106
126
|
)
|
package/lib/base.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { deepmerge } from '@platformatic/utils'
|
|
1
2
|
import { parseCommandString } from 'execa'
|
|
2
3
|
import { spawn } from 'node:child_process'
|
|
3
4
|
import { once } from 'node:events'
|
|
@@ -19,10 +20,11 @@ export class BaseStackable {
|
|
|
19
20
|
this.type = type
|
|
20
21
|
this.version = version
|
|
21
22
|
this.id = options.context.serviceId
|
|
23
|
+
this.telemetryConfig = options.context.telemetryConfig
|
|
22
24
|
this.options = options
|
|
23
25
|
this.root = root
|
|
24
26
|
this.configManager = configManager
|
|
25
|
-
this.serverConfig = options.context.serverConfig
|
|
27
|
+
this.serverConfig = deepmerge(options.context.serverConfig ?? {}, configManager.current.server ?? {})
|
|
26
28
|
this.openapiSchema = null
|
|
27
29
|
this.getGraphqlSchema = null
|
|
28
30
|
this.isEntrypoint = options.context.isEntrypoint
|
|
@@ -30,7 +32,7 @@ export class BaseStackable {
|
|
|
30
32
|
|
|
31
33
|
// Setup the logger
|
|
32
34
|
const pinoOptions = {
|
|
33
|
-
level:
|
|
35
|
+
level: this.serverConfig?.logger?.level ?? 'trace'
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
if (this.id) {
|
|
@@ -54,6 +56,10 @@ export class BaseStackable {
|
|
|
54
56
|
return this.configManager.current
|
|
55
57
|
}
|
|
56
58
|
|
|
59
|
+
async getEnv () {
|
|
60
|
+
return this.configManager.env
|
|
61
|
+
}
|
|
62
|
+
|
|
57
63
|
async getWatchConfig () {
|
|
58
64
|
const config = this.configManager.current
|
|
59
65
|
|
|
@@ -175,7 +181,6 @@ export class BaseStackable {
|
|
|
175
181
|
async startWithCommand (command, loader) {
|
|
176
182
|
const config = this.configManager.current
|
|
177
183
|
const basePath = config.application?.basePath ? cleanBasePath(config.application?.basePath) : ''
|
|
178
|
-
|
|
179
184
|
this.#childManager = new ChildManager({
|
|
180
185
|
logger: this.logger,
|
|
181
186
|
loader,
|
|
@@ -185,7 +190,8 @@ export class BaseStackable {
|
|
|
185
190
|
root: pathToFileURL(this.root).toString(),
|
|
186
191
|
basePath,
|
|
187
192
|
logLevel: this.logger.level,
|
|
188
|
-
port: (this.isEntrypoint ? this.serverConfig?.port || 0 : undefined) ?? true
|
|
193
|
+
port: (this.isEntrypoint ? this.serverConfig?.port || 0 : undefined) ?? true,
|
|
194
|
+
telemetry: this.telemetryConfig
|
|
189
195
|
}
|
|
190
196
|
})
|
|
191
197
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ITC, generateNotification } from '@platformatic/itc'
|
|
2
|
-
import { createDirectory,
|
|
2
|
+
import { createDirectory, ensureLoggableError } from '@platformatic/utils'
|
|
3
3
|
import { once } from 'node:events'
|
|
4
4
|
import { rm, writeFile } from 'node:fs/promises'
|
|
5
5
|
import { createServer } from 'node:http'
|
|
@@ -213,7 +213,7 @@ export class ChildManager extends ITC {
|
|
|
213
213
|
}
|
|
214
214
|
|
|
215
215
|
#handleUnexpectedError (error, message, exitCode) {
|
|
216
|
-
this.#logger.error({ err:
|
|
216
|
+
this.#logger.error({ err: ensureLoggableError(error) }, message)
|
|
217
217
|
process.exit(exitCode)
|
|
218
218
|
}
|
|
219
219
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { ITC } from '@platformatic/itc'
|
|
2
|
-
import {
|
|
2
|
+
import { setupNodeHTTPTelemetry } from '@platformatic/telemetry'
|
|
3
|
+
import { createPinoWritable, ensureLoggableError } from '@platformatic/utils'
|
|
3
4
|
import { tracingChannel } from 'node:diagnostics_channel'
|
|
4
5
|
import { once } from 'node:events'
|
|
5
6
|
import { readFile } from 'node:fs/promises'
|
|
6
7
|
import { register } from 'node:module'
|
|
7
8
|
import { platform, tmpdir } from 'node:os'
|
|
8
9
|
import { basename, resolve } from 'node:path'
|
|
10
|
+
import { fileURLToPath } from 'node:url'
|
|
9
11
|
import { isMainThread } from 'node:worker_threads'
|
|
10
12
|
import pino from 'pino'
|
|
11
13
|
import { getGlobalDispatcher, setGlobalDispatcher } from 'undici'
|
|
@@ -90,6 +92,7 @@ export class ChildProcess extends ITC {
|
|
|
90
92
|
|
|
91
93
|
this.listen()
|
|
92
94
|
this.#setupLogger()
|
|
95
|
+
this.#setupTelemetry()
|
|
93
96
|
this.#setupHandlers()
|
|
94
97
|
this.#setupServer()
|
|
95
98
|
this.#setupInterceptors()
|
|
@@ -115,7 +118,7 @@ export class ChildProcess extends ITC {
|
|
|
115
118
|
try {
|
|
116
119
|
this.#listener(JSON.parse(message))
|
|
117
120
|
} catch (error) {
|
|
118
|
-
this.#logger.error({ err:
|
|
121
|
+
this.#logger.error({ err: ensureLoggableError(error) }, 'Handling a message failed.')
|
|
119
122
|
process.exit(exitCodes.PROCESS_MESSAGE_HANDLING_FAILED)
|
|
120
123
|
}
|
|
121
124
|
})
|
|
@@ -158,12 +161,18 @@ export class ChildProcess extends ITC {
|
|
|
158
161
|
})
|
|
159
162
|
|
|
160
163
|
Reflect.defineProperty(process, 'stdout', { value: createPinoWritable(this.#logger, 'info') })
|
|
161
|
-
Reflect.defineProperty(process, 'stderr', { value: createPinoWritable(this.#logger, 'error') })
|
|
164
|
+
Reflect.defineProperty(process, 'stderr', { value: createPinoWritable(this.#logger, 'error', true) })
|
|
162
165
|
} else {
|
|
163
166
|
this.#logger = pino({ level: 'info', name: globalThis.platformatic.id })
|
|
164
167
|
}
|
|
165
168
|
}
|
|
166
169
|
|
|
170
|
+
#setupTelemetry () {
|
|
171
|
+
if (globalThis.platformatic.telemetry) {
|
|
172
|
+
setupNodeHTTPTelemetry(globalThis.platformatic.telemetry, this.#logger)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
167
176
|
#setupServer () {
|
|
168
177
|
const subscribers = {
|
|
169
178
|
asyncStart ({ options }) {
|
|
@@ -196,9 +205,8 @@ export class ChildProcess extends ITC {
|
|
|
196
205
|
|
|
197
206
|
#setupHandlers () {
|
|
198
207
|
function handleUnhandled (type, err) {
|
|
199
|
-
process._rawDebug(globalThis.platformatic.id, err)
|
|
200
208
|
this.#logger.error(
|
|
201
|
-
{ err:
|
|
209
|
+
{ err: ensureLoggableError(err) },
|
|
202
210
|
`Child process for service ${globalThis.platformatic.id} threw an ${type}.`
|
|
203
211
|
)
|
|
204
212
|
|
|
@@ -216,6 +224,10 @@ async function main () {
|
|
|
216
224
|
|
|
217
225
|
globalThis.platformatic = data
|
|
218
226
|
|
|
227
|
+
if (data.root && isMainThread) {
|
|
228
|
+
process.chdir(fileURLToPath(data.root))
|
|
229
|
+
}
|
|
230
|
+
|
|
219
231
|
if (loader) {
|
|
220
232
|
register(loader, { data })
|
|
221
233
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { generateRequest } from '@platformatic/itc'
|
|
2
|
-
import {
|
|
2
|
+
import { ensureLoggableError } from '@platformatic/utils'
|
|
3
3
|
import { once } from 'node:events'
|
|
4
4
|
import { platform } from 'node:os'
|
|
5
5
|
import { workerData } from 'node:worker_threads'
|
|
@@ -9,7 +9,7 @@ import { getSocketPath } from './child-manager.js'
|
|
|
9
9
|
|
|
10
10
|
function logDirectError (message, error) {
|
|
11
11
|
process._rawDebug(`Logger thread for child process of service ${workerData.id} ${message}.`, {
|
|
12
|
-
error:
|
|
12
|
+
error: ensureLoggableError(error)
|
|
13
13
|
})
|
|
14
14
|
}
|
|
15
15
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/basic",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -23,15 +23,16 @@
|
|
|
23
23
|
"split2": "^4.2.0",
|
|
24
24
|
"undici": "^6.19.5",
|
|
25
25
|
"ws": "^8.18.0",
|
|
26
|
-
"@platformatic/config": "2.0.0
|
|
27
|
-
"@platformatic/itc": "2.0.0
|
|
28
|
-
"@platformatic/
|
|
26
|
+
"@platformatic/config": "2.0.0",
|
|
27
|
+
"@platformatic/itc": "2.0.0",
|
|
28
|
+
"@platformatic/telemetry": "2.0.0",
|
|
29
|
+
"@platformatic/utils": "2.0.0"
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"borp": "^0.17.0",
|
|
32
33
|
"eslint": "9",
|
|
33
34
|
"express": "^4.19.2",
|
|
34
|
-
"fastify": "5.0.0
|
|
35
|
+
"fastify": "^5.0.0",
|
|
35
36
|
"json-schema-to-typescript": "^15.0.0",
|
|
36
37
|
"neostandard": "^0.11.1",
|
|
37
38
|
"next": "^14.2.5",
|
|
@@ -39,8 +40,8 @@
|
|
|
39
40
|
"react-dom": "^18.3.1",
|
|
40
41
|
"typescript": "^5.5.4",
|
|
41
42
|
"vite": "^5.4.0",
|
|
42
|
-
"@platformatic/
|
|
43
|
-
"@platformatic/
|
|
43
|
+
"@platformatic/service": "2.0.0",
|
|
44
|
+
"@platformatic/composer": "2.0.0"
|
|
44
45
|
},
|
|
45
46
|
"scripts": {
|
|
46
47
|
"gen-schema": "node lib/schema.js > schema.json",
|
package/schema.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://schemas.platformatic.dev/@platformatic/basic/2.0.0
|
|
2
|
+
"$id": "https://schemas.platformatic.dev/@platformatic/basic/2.0.0.json",
|
|
3
3
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4
4
|
"title": "Platformatic Stackable",
|
|
5
5
|
"type": "object",
|