@platformatic/runtime 3.0.0-alpha.5 → 3.0.0-alpha.6
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/config.d.ts +10 -7
- package/eslint.config.js +2 -4
- package/index.d.ts +11 -11
- package/index.js +35 -46
- package/lib/config.js +80 -102
- package/lib/dependencies.js +27 -29
- package/lib/errors.js +65 -99
- package/lib/generator.js +160 -164
- package/lib/logger.js +6 -8
- package/lib/management-api.js +36 -39
- package/lib/prom-server.js +10 -14
- package/lib/runtime.js +752 -715
- package/lib/scheduler.js +13 -15
- package/lib/schema.js +11 -8
- package/lib/shared-http-cache.js +5 -9
- package/lib/upgrade.js +5 -9
- package/lib/utils.js +6 -14
- package/lib/version.js +7 -0
- package/lib/versions/v1.36.0.js +2 -4
- package/lib/versions/v1.5.0.js +2 -4
- package/lib/versions/v2.0.0.js +3 -5
- package/lib/versions/v3.0.0.js +16 -0
- package/lib/worker/{app.js → controller.js} +46 -56
- package/lib/worker/http-cache.js +11 -14
- package/lib/worker/interceptors.js +14 -18
- package/lib/worker/itc.js +74 -74
- package/lib/worker/main.js +45 -49
- package/lib/worker/messaging.js +23 -27
- package/lib/worker/round-robin-map.js +23 -19
- package/lib/worker/shared-context.js +2 -6
- package/lib/worker/symbols.js +12 -29
- package/package.json +21 -21
- package/schema.json +254 -20
package/config.d.ts
CHANGED
|
@@ -37,13 +37,16 @@ export type PlatformaticRuntimeConfig = {
|
|
|
37
37
|
};
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
|
+
applications?: {
|
|
41
|
+
[k: string]: unknown;
|
|
42
|
+
}[];
|
|
40
43
|
services?: {
|
|
41
44
|
[k: string]: unknown;
|
|
42
45
|
}[];
|
|
43
|
-
workers?: number | string;
|
|
44
46
|
web?: {
|
|
45
47
|
[k: string]: unknown;
|
|
46
48
|
}[];
|
|
49
|
+
workers?: number | string;
|
|
47
50
|
logger?: {
|
|
48
51
|
level: (
|
|
49
52
|
| ("fatal" | "error" | "warn" | "info" | "debug" | "trace" | "silent")
|
|
@@ -131,7 +134,7 @@ export type PlatformaticRuntimeConfig = {
|
|
|
131
134
|
restartOnError?: boolean | number;
|
|
132
135
|
gracefulShutdown?: {
|
|
133
136
|
runtime: number | string;
|
|
134
|
-
|
|
137
|
+
application: number | string;
|
|
135
138
|
};
|
|
136
139
|
health?: {
|
|
137
140
|
enabled?: boolean | string;
|
|
@@ -250,11 +253,11 @@ export type PlatformaticRuntimeConfig = {
|
|
|
250
253
|
telemetry?: {
|
|
251
254
|
enabled?: boolean | string;
|
|
252
255
|
/**
|
|
253
|
-
* The name of the
|
|
256
|
+
* The name of the application. Defaults to the folder name if not specified.
|
|
254
257
|
*/
|
|
255
|
-
|
|
258
|
+
applicationName: string;
|
|
256
259
|
/**
|
|
257
|
-
* The version of the
|
|
260
|
+
* The version of the application (optional)
|
|
258
261
|
*/
|
|
259
262
|
version?: string;
|
|
260
263
|
/**
|
|
@@ -330,9 +333,9 @@ export type PlatformaticRuntimeConfig = {
|
|
|
330
333
|
watchDisabled?: boolean;
|
|
331
334
|
[k: string]: unknown;
|
|
332
335
|
};
|
|
333
|
-
|
|
336
|
+
applicationTimeout?: number | string;
|
|
334
337
|
messagingTimeout?: number | string;
|
|
335
|
-
|
|
338
|
+
resolvedApplicationsBasePath?: string;
|
|
336
339
|
env?: {
|
|
337
340
|
[k: string]: string;
|
|
338
341
|
};
|
package/eslint.config.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import neostandard from 'neostandard'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
module.exports = neostandard({
|
|
3
|
+
export default neostandard({
|
|
6
4
|
ts: true,
|
|
7
5
|
ignores: [...neostandard.resolveIgnoresFromGitignore(), 'test/tmp/**/*', 'dist/**/*']
|
|
8
6
|
})
|
package/index.d.ts
CHANGED
|
@@ -8,33 +8,33 @@ import { PlatformaticRuntimeConfig } from './config'
|
|
|
8
8
|
|
|
9
9
|
export type RuntimeConfiguration = Promise<Configuration<PlatformaticRuntimeConfig>>
|
|
10
10
|
|
|
11
|
-
export type
|
|
11
|
+
export type ApplicationCommandContext = {
|
|
12
12
|
colorette: typeof colorette
|
|
13
13
|
parseArgs: typeof parseArgs
|
|
14
14
|
logFatalError: typeof logFatalError
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export type
|
|
17
|
+
export type ApplicationCommand = (
|
|
18
18
|
logger: Logger,
|
|
19
19
|
configuration: Configuration<unknown>,
|
|
20
20
|
args: string[],
|
|
21
|
-
context:
|
|
21
|
+
context: ApplicationCommandContext
|
|
22
22
|
) => Promise<void>
|
|
23
23
|
|
|
24
|
-
export interface
|
|
25
|
-
|
|
26
|
-
commands: Record<string,
|
|
24
|
+
export interface ApplicationsCommands {
|
|
25
|
+
applications: Record<string, Configuration<unknown>>
|
|
26
|
+
commands: Record<string, ApplicationCommand>
|
|
27
27
|
help: Record<string, string | (() => string)>
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export module errors {
|
|
31
31
|
export const RuntimeExitedError: () => FastifyError
|
|
32
32
|
export const UnknownRuntimeAPICommandError: (command: string) => FastifyError
|
|
33
|
-
export const
|
|
34
|
-
export const
|
|
33
|
+
export const ApplicationNotFoundError: (id: string) => FastifyError
|
|
34
|
+
export const ApplicationNotStartedError: (id: string) => FastifyError
|
|
35
35
|
export const FailedToRetrieveOpenAPISchemaError: (id: string, error: string) => FastifyError
|
|
36
36
|
export const ApplicationAlreadyStartedError: () => FastifyError
|
|
37
|
-
export const
|
|
37
|
+
export const RuntimeNotStartedError: () => FastifyError
|
|
38
38
|
export const ConfigPathMustBeStringError: () => FastifyError
|
|
39
39
|
export const NoConfigFileFoundError: (id: string) => FastifyError
|
|
40
40
|
export const InvalidEntrypointError: (entrypoint: string) => FastifyError
|
|
@@ -51,7 +51,7 @@ export module symbols {
|
|
|
51
51
|
export declare const kConfig: unique symbol
|
|
52
52
|
export declare const kId: unique symbol
|
|
53
53
|
export declare const kFullId: unique symbol
|
|
54
|
-
export declare const
|
|
54
|
+
export declare const kApplicationId: unique symbol
|
|
55
55
|
export declare const kWorkerId: unique symbol
|
|
56
56
|
export declare const kITC: unique symbol
|
|
57
57
|
export declare const kHealthCheckTimer: unique symbol
|
|
@@ -91,4 +91,4 @@ export function create (
|
|
|
91
91
|
|
|
92
92
|
export declare function transform (config: RuntimeConfiguration): Promise<RuntimeConfiguration> | RuntimeConfiguration
|
|
93
93
|
|
|
94
|
-
export declare function
|
|
94
|
+
export declare function loadApplicationsCommands (): Promise<ApplicationsCommands>
|
package/index.js
CHANGED
|
@@ -1,31 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const inspector = require('node:inspector')
|
|
4
|
-
const {
|
|
5
|
-
kMetadata,
|
|
6
|
-
loadConfigurationModule,
|
|
1
|
+
import { resolve, validationOptions } from '@platformatic/basic'
|
|
2
|
+
import {
|
|
7
3
|
abstractLogger,
|
|
8
|
-
|
|
9
|
-
loadConfiguration: utilsLoadConfiguration,
|
|
4
|
+
ensureLoggableError,
|
|
10
5
|
extractModuleFromSchemaUrl,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
findRuntimeConfigurationFile,
|
|
7
|
+
kMetadata,
|
|
8
|
+
loadConfigurationModule,
|
|
9
|
+
loadConfiguration as utilsLoadConfiguration
|
|
10
|
+
} from '@platformatic/foundation'
|
|
11
|
+
import inspector from 'node:inspector'
|
|
12
|
+
import { transform, wrapInRuntimeConfig } from './lib/config.js'
|
|
13
|
+
import { NodeInspectorFlagsNotSupportedError } from './lib/errors.js'
|
|
14
|
+
import { Runtime } from './lib/runtime.js'
|
|
15
|
+
import { schema } from './lib/schema.js'
|
|
16
|
+
import { upgrade } from './lib/upgrade.js'
|
|
21
17
|
|
|
22
18
|
async function restartRuntime (runtime) {
|
|
23
|
-
runtime.logger.info('Received SIGUSR2, restarting all
|
|
19
|
+
runtime.logger.info('Received SIGUSR2, restarting all applications ...')
|
|
24
20
|
|
|
25
21
|
try {
|
|
26
22
|
await runtime.restart()
|
|
27
23
|
} catch (err) {
|
|
28
|
-
runtime.logger.error({ err: ensureLoggableError(err) }, 'Failed to restart
|
|
24
|
+
runtime.logger.error({ err: ensureLoggableError(err) }, 'Failed to restart applications.')
|
|
29
25
|
}
|
|
30
26
|
}
|
|
31
27
|
|
|
@@ -38,7 +34,7 @@ function handleSignal (runtime) {
|
|
|
38
34
|
})
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
async function loadConfiguration (configOrRoot, sourceOrConfig, context) {
|
|
37
|
+
export async function loadConfiguration (configOrRoot, sourceOrConfig, context) {
|
|
42
38
|
const { root, source } = await resolve(configOrRoot, sourceOrConfig, 'runtime')
|
|
43
39
|
|
|
44
40
|
// First of all, load the configuration without any validation
|
|
@@ -58,8 +54,8 @@ async function loadConfiguration (configOrRoot, sourceOrConfig, context) {
|
|
|
58
54
|
})
|
|
59
55
|
}
|
|
60
56
|
|
|
61
|
-
async function
|
|
62
|
-
const
|
|
57
|
+
export async function loadApplicationsCommands () {
|
|
58
|
+
const applications = {}
|
|
63
59
|
const commands = {}
|
|
64
60
|
const help = {}
|
|
65
61
|
|
|
@@ -79,18 +75,18 @@ async function loadServicesCommands () {
|
|
|
79
75
|
throw new Error('No runtime configuration file found.')
|
|
80
76
|
}
|
|
81
77
|
} catch {
|
|
82
|
-
return {
|
|
78
|
+
return { applications, commands, help }
|
|
83
79
|
}
|
|
84
80
|
|
|
85
|
-
for (const
|
|
81
|
+
for (const application of config.applications) {
|
|
86
82
|
try {
|
|
87
|
-
const
|
|
88
|
-
const pkg = await loadConfigurationModule(
|
|
83
|
+
const applicationConfig = await utilsLoadConfiguration(application.config)
|
|
84
|
+
const pkg = await loadConfigurationModule(application.path, applicationConfig)
|
|
89
85
|
|
|
90
86
|
if (pkg.createCommands) {
|
|
91
|
-
const definition = await pkg.createCommands(
|
|
87
|
+
const definition = await pkg.createCommands(application.id)
|
|
92
88
|
for (const command of Object.keys(definition.commands)) {
|
|
93
|
-
|
|
89
|
+
applications[command] = application
|
|
94
90
|
}
|
|
95
91
|
|
|
96
92
|
Object.assign(commands, definition.commands)
|
|
@@ -98,14 +94,14 @@ async function loadServicesCommands () {
|
|
|
98
94
|
}
|
|
99
95
|
/* c8 ignore next 3 - Hard to test */
|
|
100
96
|
} catch {
|
|
101
|
-
// No-op, ignore the
|
|
97
|
+
// No-op, ignore the application
|
|
102
98
|
}
|
|
103
99
|
}
|
|
104
100
|
|
|
105
|
-
return {
|
|
101
|
+
return { applications, commands, help }
|
|
106
102
|
}
|
|
107
103
|
|
|
108
|
-
async function create (configOrRoot, sourceOrConfig, context) {
|
|
104
|
+
export async function create (configOrRoot, sourceOrConfig, context) {
|
|
109
105
|
const config = await loadConfiguration(configOrRoot, sourceOrConfig, context)
|
|
110
106
|
|
|
111
107
|
if (inspector.url() && !config[kMetadata].env.VSCODE_INSPECTOR_OPTIONS) {
|
|
@@ -147,17 +143,10 @@ async function create (configOrRoot, sourceOrConfig, context) {
|
|
|
147
143
|
return runtime
|
|
148
144
|
}
|
|
149
145
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
module.exports.Runtime = Runtime
|
|
158
|
-
module.exports.wrapInRuntimeConfig = wrapInRuntimeConfig
|
|
159
|
-
module.exports.version = platformaticVersion
|
|
160
|
-
module.exports.loadConfiguration = loadConfiguration
|
|
161
|
-
module.exports.create = create
|
|
162
|
-
module.exports.transform = transform
|
|
163
|
-
module.exports.loadServicesCommands = loadServicesCommands
|
|
146
|
+
export { transform, wrapInRuntimeConfig } from './lib/config.js'
|
|
147
|
+
export * as errors from './lib/errors.js'
|
|
148
|
+
export { RuntimeGenerator as Generator, WrappedGenerator } from './lib/generator.js'
|
|
149
|
+
export { Runtime } from './lib/runtime.js'
|
|
150
|
+
export { schema } from './lib/schema.js'
|
|
151
|
+
export * from './lib/version.js'
|
|
152
|
+
export * as symbols from './lib/worker/symbols.js'
|
package/lib/config.js
CHANGED
|
@@ -1,44 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const { readdir } = require('node:fs/promises')
|
|
5
|
-
const { createRequire } = require('node:module')
|
|
6
|
-
const { importStackableAndConfig, validationOptions } = require('@platformatic/basic')
|
|
7
|
-
const {
|
|
8
|
-
kMetadata,
|
|
9
|
-
omitProperties,
|
|
10
|
-
loadModule,
|
|
11
|
-
runtimeUnwrappablePropertiesList,
|
|
1
|
+
import { importCapabilityAndConfig, validationOptions } from '@platformatic/basic'
|
|
2
|
+
import {
|
|
3
|
+
extractModuleFromSchemaUrl,
|
|
12
4
|
findConfigurationFile,
|
|
13
|
-
|
|
5
|
+
kMetadata,
|
|
14
6
|
loadConfiguration,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
loadConfigurationModule,
|
|
8
|
+
loadModule,
|
|
9
|
+
omitProperties,
|
|
10
|
+
runtimeUnwrappablePropertiesList
|
|
11
|
+
} from '@platformatic/foundation'
|
|
12
|
+
import { readdir, readFile } from 'node:fs/promises'
|
|
13
|
+
import { createRequire } from 'node:module'
|
|
14
|
+
import { isAbsolute, join, resolve as resolvePath } from 'node:path'
|
|
15
|
+
import {
|
|
18
16
|
InspectAndInspectBrkError,
|
|
19
|
-
|
|
20
|
-
InvalidServicesWithWebError,
|
|
21
|
-
MissingEntrypointError,
|
|
17
|
+
InspectorHostError,
|
|
22
18
|
InspectorPortError,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
InvalidEntrypointError,
|
|
20
|
+
MissingEntrypointError
|
|
21
|
+
} from './errors.js'
|
|
22
|
+
import { schema } from './schema.js'
|
|
23
|
+
import { upgrade } from './upgrade.js'
|
|
27
24
|
|
|
28
|
-
async function wrapInRuntimeConfig (config, context) {
|
|
29
|
-
let
|
|
25
|
+
export async function wrapInRuntimeConfig (config, context) {
|
|
26
|
+
let applicationId = 'main'
|
|
30
27
|
try {
|
|
31
|
-
const packageJson = join(config[kMetadata].root, 'package.json')
|
|
32
|
-
|
|
28
|
+
const packageJson = JSON.parse(await readFile(join(config[kMetadata].root, 'package.json'), 'utf-8'))
|
|
29
|
+
applicationId = packageJson?.name ?? 'main'
|
|
33
30
|
|
|
34
|
-
if (
|
|
35
|
-
|
|
31
|
+
if (applicationId.startsWith('@')) {
|
|
32
|
+
applicationId = applicationId.split('/')[1]
|
|
36
33
|
}
|
|
37
34
|
} catch (err) {
|
|
38
35
|
// on purpose, the package.json might be missing
|
|
39
36
|
}
|
|
40
37
|
|
|
41
|
-
// If the
|
|
38
|
+
// If the application supports its (so far, only @platformatic/service and descendants)
|
|
42
39
|
const { hostname, port, http2, https } = config.server ?? {}
|
|
43
40
|
const server = { hostname, port, http2, https }
|
|
44
41
|
const production = context?.isProduction ?? context?.production
|
|
@@ -50,10 +47,10 @@ async function wrapInRuntimeConfig (config, context) {
|
|
|
50
47
|
server,
|
|
51
48
|
watch: !production,
|
|
52
49
|
...omitProperties(config.runtime ?? {}, runtimeUnwrappablePropertiesList),
|
|
53
|
-
entrypoint:
|
|
54
|
-
|
|
50
|
+
entrypoint: applicationId,
|
|
51
|
+
applications: [
|
|
55
52
|
{
|
|
56
|
-
id:
|
|
53
|
+
id: applicationId,
|
|
57
54
|
path: config[kMetadata].root,
|
|
58
55
|
config: config[kMetadata].path
|
|
59
56
|
}
|
|
@@ -70,7 +67,7 @@ async function wrapInRuntimeConfig (config, context) {
|
|
|
70
67
|
})
|
|
71
68
|
}
|
|
72
69
|
|
|
73
|
-
function parseInspectorOptions (config, inspect, inspectBreak) {
|
|
70
|
+
export function parseInspectorOptions (config, inspect, inspectBreak) {
|
|
74
71
|
const hasInspect = inspect != null
|
|
75
72
|
const hasInspectBrk = inspectBreak != null
|
|
76
73
|
|
|
@@ -112,19 +109,9 @@ function parseInspectorOptions (config, inspect, inspectBreak) {
|
|
|
112
109
|
config.watch = false
|
|
113
110
|
}
|
|
114
111
|
|
|
115
|
-
async function transform (config, _, context) {
|
|
112
|
+
export async function transform (config, _, context) {
|
|
116
113
|
const production = context?.isProduction ?? context?.production
|
|
117
|
-
|
|
118
|
-
let services
|
|
119
|
-
if (config.web?.length) {
|
|
120
|
-
if (config.services?.length) {
|
|
121
|
-
throw new InvalidServicesWithWebError()
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
services = config.web
|
|
125
|
-
} else {
|
|
126
|
-
services = config.services ?? []
|
|
127
|
-
}
|
|
114
|
+
const applications = [...(config.applications ?? []), ...(config.services ?? []), ...(config.web ?? [])]
|
|
128
115
|
|
|
129
116
|
const watchType = typeof config.watch
|
|
130
117
|
if (watchType === 'string') {
|
|
@@ -158,109 +145,105 @@ async function transform (config, _, context) {
|
|
|
158
145
|
config = join(entryPath, configFilename)
|
|
159
146
|
}
|
|
160
147
|
|
|
161
|
-
const
|
|
162
|
-
const
|
|
148
|
+
const application = { id, config, path: entryPath, useHttp: !!mapping.useHttp, health: mapping.health }
|
|
149
|
+
const existingApplicationId = applications.findIndex(application => application.id === id)
|
|
163
150
|
|
|
164
|
-
if (
|
|
165
|
-
|
|
151
|
+
if (existingApplicationId !== -1) {
|
|
152
|
+
applications[existingApplicationId] = { ...application, ...applications[existingApplicationId] }
|
|
166
153
|
} else {
|
|
167
|
-
|
|
154
|
+
applications.push(application)
|
|
168
155
|
}
|
|
169
156
|
}
|
|
170
157
|
}
|
|
171
158
|
|
|
172
|
-
config.serviceMap = new Map()
|
|
173
159
|
config.inspectorOptions = undefined
|
|
174
160
|
parseInspectorOptions(config, context?.inspect, context?.inspectBreak)
|
|
175
161
|
|
|
176
162
|
let hasValidEntrypoint = false
|
|
177
163
|
|
|
178
|
-
for (let i = 0; i <
|
|
179
|
-
const
|
|
164
|
+
for (let i = 0; i < applications.length; ++i) {
|
|
165
|
+
const application = applications[i]
|
|
180
166
|
|
|
181
167
|
// We need to have absolute paths here, ot the `loadConfig` will fail
|
|
182
168
|
// Make sure we don't resolve if env var was not replaced
|
|
183
|
-
if (
|
|
184
|
-
|
|
169
|
+
if (application.path && !isAbsolute(application.path) && !application.path.match(/^\{.*\}$/)) {
|
|
170
|
+
application.path = resolvePath(config[kMetadata].root, application.path)
|
|
185
171
|
}
|
|
186
172
|
|
|
187
|
-
if (
|
|
188
|
-
|
|
173
|
+
if (application.path && application.config) {
|
|
174
|
+
application.config = resolvePath(application.path, application.config)
|
|
189
175
|
}
|
|
190
176
|
|
|
191
177
|
try {
|
|
192
178
|
let pkg
|
|
193
179
|
|
|
194
|
-
if (
|
|
195
|
-
const config = await loadConfiguration(
|
|
196
|
-
pkg = await loadConfigurationModule(
|
|
180
|
+
if (application.config) {
|
|
181
|
+
const config = await loadConfiguration(application.config)
|
|
182
|
+
pkg = await loadConfigurationModule(application.path, config)
|
|
197
183
|
|
|
198
|
-
|
|
199
|
-
|
|
184
|
+
application.type = extractModuleFromSchemaUrl(config, true).module
|
|
185
|
+
application.skipTelemetryHooks = pkg.skipTelemetryHooks
|
|
200
186
|
} else {
|
|
201
|
-
const { moduleName,
|
|
202
|
-
pkg =
|
|
187
|
+
const { moduleName, capability } = await importCapabilityAndConfig(application.path)
|
|
188
|
+
pkg = capability
|
|
203
189
|
|
|
204
|
-
|
|
190
|
+
application.type = moduleName
|
|
205
191
|
}
|
|
206
192
|
|
|
207
|
-
|
|
193
|
+
application.skipTelemetryHooks = pkg.skipTelemetryHooks
|
|
208
194
|
|
|
209
195
|
// This is needed to work around Rust bug on dylibs:
|
|
210
196
|
// https://github.com/rust-lang/rust/issues/91979
|
|
211
197
|
// https://github.com/rollup/rollup/issues/5761
|
|
212
|
-
const _require = createRequire(
|
|
198
|
+
const _require = createRequire(application.path)
|
|
213
199
|
for (const m of pkg.modulesToLoad ?? []) {
|
|
214
200
|
const toLoad = _require.resolve(m)
|
|
215
201
|
loadModule(_require, toLoad).catch(() => {})
|
|
216
202
|
}
|
|
217
203
|
} catch (err) {
|
|
218
204
|
// This should not happen, it happens on running some unit tests if we prepare the runtime
|
|
219
|
-
// when not all the
|
|
220
|
-
// to ddetermine the type of the
|
|
221
|
-
|
|
205
|
+
// when not all the applications configs are available. Given that we are running this only
|
|
206
|
+
// to ddetermine the type of the application, it's safe to ignore this error and default to unknown
|
|
207
|
+
application.type = 'unknown'
|
|
222
208
|
}
|
|
223
209
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
service.localUrl = `http://${service.id}.plt.local`
|
|
210
|
+
application.entrypoint = application.id === config.entrypoint
|
|
211
|
+
application.dependencies = []
|
|
212
|
+
application.localUrl = `http://${application.id}.plt.local`
|
|
228
213
|
|
|
229
|
-
if (typeof
|
|
230
|
-
|
|
214
|
+
if (typeof application.watch === 'undefined') {
|
|
215
|
+
application.watch = config.watch
|
|
231
216
|
}
|
|
232
217
|
|
|
233
|
-
if (
|
|
218
|
+
if (application.entrypoint) {
|
|
234
219
|
hasValidEntrypoint = true
|
|
235
220
|
}
|
|
236
|
-
|
|
237
|
-
config.serviceMap.set(service.id, service)
|
|
238
221
|
}
|
|
239
222
|
|
|
240
223
|
// If there is no entrypoint, autodetect one
|
|
241
224
|
if (!config.entrypoint) {
|
|
242
|
-
// If there is only one
|
|
243
|
-
if (
|
|
244
|
-
|
|
245
|
-
config.entrypoint =
|
|
225
|
+
// If there is only one application, it becomes the entrypoint
|
|
226
|
+
if (applications.length === 1) {
|
|
227
|
+
applications[0].entrypoint = true
|
|
228
|
+
config.entrypoint = applications[0].id
|
|
246
229
|
hasValidEntrypoint = true
|
|
247
230
|
} else {
|
|
248
|
-
// Search if exactly
|
|
249
|
-
const
|
|
231
|
+
// Search if exactly application uses @platformatic/gateway
|
|
232
|
+
const gateways = []
|
|
250
233
|
|
|
251
|
-
for (const
|
|
252
|
-
if (!
|
|
234
|
+
for (const application of applications) {
|
|
235
|
+
if (!application.config) {
|
|
253
236
|
continue
|
|
254
237
|
}
|
|
255
238
|
|
|
256
|
-
if (
|
|
257
|
-
|
|
239
|
+
if (application.type === '@platformatic/gateway') {
|
|
240
|
+
gateways.push(application.id)
|
|
258
241
|
}
|
|
259
242
|
}
|
|
260
243
|
|
|
261
|
-
if (
|
|
262
|
-
|
|
263
|
-
config.entrypoint =
|
|
244
|
+
if (gateways.length === 1) {
|
|
245
|
+
applications.find(s => s.id === gateways[0]).entrypoint = true
|
|
246
|
+
config.entrypoint = gateways[0]
|
|
264
247
|
hasValidEntrypoint = true
|
|
265
248
|
}
|
|
266
249
|
}
|
|
@@ -269,16 +252,17 @@ async function transform (config, _, context) {
|
|
|
269
252
|
if (!hasValidEntrypoint && !context.allowMissingEntrypoint) {
|
|
270
253
|
if (config.entrypoint) {
|
|
271
254
|
throw new InvalidEntrypointError(config.entrypoint)
|
|
272
|
-
} else if (
|
|
255
|
+
} else if (applications.length >= 1) {
|
|
273
256
|
throw new MissingEntrypointError()
|
|
274
257
|
}
|
|
275
|
-
// If there are no
|
|
258
|
+
// If there are no applications, and no entrypoint it's an empty app.
|
|
276
259
|
// It won't start, but we should be able to parse and operate on it,
|
|
277
|
-
// like adding other
|
|
260
|
+
// like adding other applications.
|
|
278
261
|
}
|
|
279
262
|
|
|
280
|
-
config.
|
|
263
|
+
config.applications = applications
|
|
281
264
|
config.web = undefined
|
|
265
|
+
config.services = undefined
|
|
282
266
|
config.logger ??= {}
|
|
283
267
|
|
|
284
268
|
if (production) {
|
|
@@ -295,9 +279,3 @@ async function transform (config, _, context) {
|
|
|
295
279
|
|
|
296
280
|
return config
|
|
297
281
|
}
|
|
298
|
-
|
|
299
|
-
module.exports = {
|
|
300
|
-
wrapInRuntimeConfig,
|
|
301
|
-
parseInspectorOptions,
|
|
302
|
-
transform
|
|
303
|
-
}
|
package/lib/dependencies.js
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { Sorter } from '@hapi/topo'
|
|
2
|
+
import { closest } from 'fastest-levenshtein'
|
|
3
|
+
import { MissingDependencyError } from './errors.js'
|
|
4
|
+
import { RoundRobinMap } from './worker/round-robin-map.js'
|
|
5
|
+
|
|
6
|
+
function missingDependencyErrorMessage (clientName, application, applications) {
|
|
7
|
+
const allNames = applications
|
|
8
|
+
.map(s => s.id)
|
|
9
|
+
.filter(id => id !== application.id)
|
|
10
|
+
.sort()
|
|
11
11
|
const closestName = closest(clientName, allNames)
|
|
12
|
-
let errorMsg = `
|
|
12
|
+
let errorMsg = `application '${application.id}' has unknown dependency: '${clientName}'.`
|
|
13
13
|
if (closestName) {
|
|
14
14
|
errorMsg += ` Did you mean '${closestName}'?`
|
|
15
15
|
}
|
|
16
16
|
if (allNames.length) {
|
|
17
|
-
errorMsg += ` Known
|
|
17
|
+
errorMsg += ` Known applications are: ${allNames.join(', ')}.`
|
|
18
18
|
}
|
|
19
19
|
return errorMsg
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
function checkDependencies (
|
|
23
|
-
const
|
|
22
|
+
export function checkDependencies (applications) {
|
|
23
|
+
const allApplications = new Set(applications.map(s => s.id))
|
|
24
24
|
|
|
25
|
-
for (const
|
|
26
|
-
for (const dependency of
|
|
27
|
-
if (dependency.local && !
|
|
28
|
-
throw new
|
|
25
|
+
for (const application of applications) {
|
|
26
|
+
for (const dependency of application.dependencies) {
|
|
27
|
+
if (dependency.local && !allApplications.has(dependency.id)) {
|
|
28
|
+
throw new MissingDependencyError(missingDependencyErrorMessage(dependency.id, application, applications))
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
function topologicalSort (workers, config) {
|
|
35
|
-
const topo = new
|
|
34
|
+
export function topologicalSort (workers, config) {
|
|
35
|
+
const topo = new Sorter()
|
|
36
36
|
|
|
37
|
-
for (const
|
|
38
|
-
const localDependencyIds = Array.from(
|
|
37
|
+
for (const application of config.applications) {
|
|
38
|
+
const localDependencyIds = Array.from(application.dependencies)
|
|
39
39
|
.filter(dep => dep.local)
|
|
40
40
|
.map(dep => dep.id)
|
|
41
41
|
|
|
42
|
-
topo.add(
|
|
43
|
-
group:
|
|
42
|
+
topo.add(application, {
|
|
43
|
+
group: application.id,
|
|
44
44
|
after: localDependencyIds,
|
|
45
45
|
manual: true
|
|
46
46
|
})
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
config.
|
|
49
|
+
config.applications = topo.sort()
|
|
50
50
|
|
|
51
51
|
return new RoundRobinMap(
|
|
52
52
|
Array.from(workers.entries()).sort((a, b) => {
|
|
@@ -54,12 +54,10 @@ function topologicalSort (workers, config) {
|
|
|
54
54
|
return 0
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const aIndex = config.
|
|
58
|
-
const bIndex = config.
|
|
57
|
+
const aIndex = config.applications.findIndex(s => s.id === a[0])
|
|
58
|
+
const bIndex = config.applications.findIndex(s => s.id === b[0])
|
|
59
59
|
return aIndex - bIndex
|
|
60
60
|
}),
|
|
61
61
|
workers.configuration
|
|
62
62
|
)
|
|
63
63
|
}
|
|
64
|
-
|
|
65
|
-
module.exports = { checkDependencies, topologicalSort }
|