@platformatic/runtime 2.74.3 → 3.0.0-alpha.2

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.
@@ -1,67 +0,0 @@
1
- 'use strict'
2
-
3
- const { join } = require('node:path')
4
- const { createRequire } = require('node:module')
5
- const ConfigManager = require('@platformatic/config')
6
- const { platformaticRuntime } = require('./config')
7
- const { buildRuntime } = require('./start')
8
- const { loadConfig } = require('./utils')
9
-
10
- async function buildServerRuntime (options = {}, args = undefined) {
11
- const { serviceMap } = options
12
-
13
- if (!options.configManager) {
14
- delete options.serviceMap
15
-
16
- // Instantiate a new config manager from the current options.
17
- const cm = new ConfigManager({
18
- ...platformaticRuntime.configManagerConfig,
19
- source: options
20
- })
21
- await cm.parseAndValidate()
22
-
23
- cm.current.serviceMap = serviceMap
24
-
25
- if (typeof options === 'string') {
26
- options = { configManager: cm }
27
- } else {
28
- options.configManager = cm
29
- }
30
- }
31
-
32
- if (args) {
33
- options.configManager.args = args
34
- }
35
-
36
- return buildRuntime(options.configManager, options.env)
37
- }
38
-
39
- async function buildServer (options, args) {
40
- if (typeof options === 'string') {
41
- const config = await loadConfig({}, ['-c', options])
42
- options = config.configManager.current
43
- options.configManager = config.configManager
44
- options.app = config.app
45
- }
46
-
47
- const app = options.app
48
-
49
- delete options.app
50
-
51
- if (app === platformaticRuntime || !app) {
52
- return buildServerRuntime(options, args)
53
- }
54
-
55
- if (app.buildServer) {
56
- return app.buildServer(options)
57
- }
58
-
59
- // App is a stackable. Hopefully we have `@platformatic/service` available.
60
- const projectRoot = join(options.configManager.dirname, 'package.json')
61
- const require = createRequire(projectRoot)
62
- const { buildServer } = require('@platformatic/service')
63
-
64
- return buildServer(options, app)
65
- }
66
-
67
- module.exports = { buildServer }
package/lib/compile.js DELETED
@@ -1,108 +0,0 @@
1
- 'use strict'
2
-
3
- const { createRequire } = require('node:module')
4
- const { dirname, join } = require('node:path')
5
- const { isatty } = require('node:tty')
6
- const { pathToFileURL } = require('node:url')
7
-
8
- const tsCompiler = require('@platformatic/ts-compiler')
9
- const pino = require('pino')
10
- const pretty = require('pino-pretty')
11
-
12
- const { loadConfig } = require('./utils')
13
-
14
- async function compile (argv, logger) {
15
- const { configManager, configType, app } = await loadConfig(
16
- {},
17
- argv,
18
- {
19
- watch: false
20
- },
21
- false
22
- )
23
- /* c8 ignore next */
24
- if (!logger) {
25
- let stream
26
-
27
- if (isatty(process.stdout.fd)) {
28
- stream = pretty({
29
- translateTime: 'SYS:HH:MM:ss',
30
- ignore: 'hostname,pid'
31
- })
32
- }
33
-
34
- logger = pino(stream)
35
- }
36
-
37
- let compiled = false
38
- const compileOptions = {
39
- clean: argv.includes('--clean')
40
- }
41
- if (configType === 'runtime') {
42
- for (const service of configManager.current.services) {
43
- const childLogger = logger.child({ name: service.id })
44
-
45
- const serviceConfigPath = service.config
46
- const { configManager, app } = await loadConfig(
47
- {},
48
- ['-c', serviceConfigPath],
49
- {
50
- onMissingEnv (key) {
51
- return service.localServiceEnvVars.get(key)
52
- },
53
- watch: false
54
- },
55
- false
56
- )
57
-
58
- const tsOptions = await extract(configManager, app)
59
-
60
- if (tsOptions) {
61
- const serviceWasCompiled = await tsCompiler.compile({
62
- ...compileOptions,
63
- ...tsOptions,
64
- cwd: service.path,
65
- logger: childLogger
66
- })
67
- compiled ||= serviceWasCompiled
68
- }
69
- }
70
- } else {
71
- const tsOptions = await extract(configManager, app)
72
- if (tsOptions) {
73
- compiled = await tsCompiler.compile({
74
- ...compileOptions,
75
- ...tsOptions,
76
- cwd: dirname(configManager.fullPath),
77
- logger
78
- })
79
- }
80
- }
81
-
82
- return compiled
83
- }
84
-
85
- async function extract (configManager, app) {
86
- let extractTypeScriptCompileOptionsFromConfig = app.extractTypeScriptCompileOptionsFromConfig
87
-
88
- if (!extractTypeScriptCompileOptionsFromConfig) {
89
- // This is a bit of a hack, but it is needed to avoid a circular dependency
90
- // it also allow for customizations if needed
91
- const _require = createRequire(join(configManager.dirname, 'package.json'))
92
- const toLoad = _require.resolve('@platformatic/service')
93
- try {
94
- extractTypeScriptCompileOptionsFromConfig = (await import(pathToFileURL(toLoad)))
95
- .extractTypeScriptCompileOptionsFromConfig
96
- } catch {}
97
- // If we can't load `@platformatic/service` we just return null
98
- // and we won't be compiling typescript
99
- }
100
-
101
- if (!extractTypeScriptCompileOptionsFromConfig) {
102
- return null
103
- }
104
-
105
- return extractTypeScriptCompileOptionsFromConfig(configManager.current)
106
- }
107
-
108
- module.exports.compile = compile
@@ -1,32 +0,0 @@
1
- # Platformatic Runtime API
2
-
3
- This is a generated [Platformatic Runtime](https://docs.platformatic.dev/docs/runtime/overview) application.
4
-
5
- ## Requirements
6
-
7
- Platformatic supports macOS, Linux and Windows ([WSL](https://docs.microsoft.com/windows/wsl/) recommended).
8
- You'll need to have [Node.js](https://nodejs.org/) >= v18.8.0 or >= v20.6.0
9
-
10
- ## Setup
11
-
12
- 1. Install dependencies:
13
-
14
- ```bash
15
- npm install
16
- ```
17
-
18
- ## Usage
19
-
20
- Run the API with:
21
-
22
- ```bash
23
- npm start
24
- ```
25
-
26
- ## Adding a Service
27
-
28
- Adding a new service to this project is as simple as running `create-platformatic` again, like so:
29
-
30
- ```
31
- npx create-platformatic
32
- ```
@@ -1,10 +0,0 @@
1
- 'use strict'
2
-
3
- const createError = require('@fastify/error')
4
-
5
- const ERROR_PREFIX = 'PLT_RUNTIME_GEN'
6
-
7
- module.exports = {
8
- NoServiceNamedError: createError(`${ERROR_PREFIX}_NO_SERVICE_FOUND`, 'No service named \'%s\' has been added to this runtime.'),
9
- NoEntryPointError: createError(`${ERROR_PREFIX}_NO_ENTRYPOINT`, 'No entrypoint had been defined.'),
10
- }
@@ -1,37 +0,0 @@
1
- import { BaseGenerator } from '@platformatic/generators'
2
- import { FileGenerator } from '@platformatic/generators/lib/file-generator'
3
-
4
- type Service = {
5
- config: FileGenerator.FileGenerator | BaseGenerator.BaseGenerator
6
- }
7
- type GeneratorMetadata = {
8
- targetDirectory: string
9
- env: KeyValue
10
- }
11
-
12
- type KeyValue = {
13
- [key: string]: string
14
- }
15
-
16
- type RuntimeGeneratorOptions = BaseGenerator.BaseGeneratorOptions & {
17
- logLevel: string
18
- }
19
-
20
- export namespace RuntimeGenerator {
21
- export class RuntimeGenerator extends BaseGenerator.BaseGenerator {
22
- services: Service[]
23
- entryPoint: Service
24
- constructor (opts?: RuntimeGeneratorOptions)
25
-
26
- addService (service: Service, name: string): Promise<void>
27
-
28
- setEntryPoint (entryPoint: string): void
29
-
30
- setServicesDirectory (): void
31
-
32
- setServicesConfig (configToOverride: object): void
33
-
34
- getRuntimeEnv (): KeyValue
35
- writeServicesFiles (): Promise<GeneratorMetadata>
36
- }
37
- }
package/lib/start.js DELETED
@@ -1,211 +0,0 @@
1
- 'use strict'
2
-
3
- const inspector = require('node:inspector')
4
- const { writeFile } = require('node:fs/promises')
5
- const { join, resolve, dirname } = require('node:path')
6
-
7
- const { printConfigValidationErrors } = require('@platformatic/config')
8
- const {
9
- errors: { ensureLoggableError }
10
- } = require('@platformatic/utils')
11
- const closeWithGrace = require('close-with-grace')
12
- const pino = require('pino')
13
- const pretty = require('pino-pretty')
14
-
15
- const pkg = require('../package.json')
16
- const { parseInspectorOptions, wrapConfigInRuntimeConfig } = require('./config')
17
- const { Runtime } = require('./runtime')
18
- const errors = require('./errors')
19
- const { getRuntimeLogsDir, loadConfig } = require('./utils')
20
-
21
- async function restartRuntime (runtime) {
22
- runtime.logger.info('Received SIGUSR2, restarting all services ...')
23
-
24
- try {
25
- await runtime.restart()
26
- } catch (err) {
27
- runtime.logger.error({ err: ensureLoggableError(err) }, 'Failed to restart services.')
28
- }
29
- }
30
-
31
- async function buildRuntime (configManager, env) {
32
- env = env || Object.assign({}, process.env, configManager.env)
33
-
34
- if (inspector.url() && !env.VSCODE_INSPECTOR_OPTIONS) {
35
- throw new errors.NodeInspectorFlagsNotSupportedError()
36
- }
37
-
38
- if (configManager.args) {
39
- parseInspectorOptions(configManager)
40
- }
41
-
42
- const dirname = configManager.dirname
43
- const runtimeLogsDir = getRuntimeLogsDir(dirname, process.pid)
44
-
45
- const runtime = new Runtime(configManager, runtimeLogsDir, env)
46
-
47
- /* c8 ignore next 3 */
48
- const restartListener = restartRuntime.bind(null, runtime)
49
- process.on('SIGUSR2', restartListener)
50
- runtime.on('closed', () => {
51
- process.removeListener('SIGUSR2', restartListener)
52
- })
53
-
54
- try {
55
- await runtime.init()
56
- } catch (e) {
57
- await runtime.close()
58
- throw e
59
- }
60
-
61
- return runtime
62
- }
63
-
64
- async function start (args) {
65
- const config = await loadConfig({}, args)
66
-
67
- if (config.configType !== 'runtime') {
68
- const configManager = await wrapConfigInRuntimeConfig(config)
69
- config.configManager = configManager
70
- }
71
-
72
- const app = await buildRuntime(config.configManager)
73
- await app.start()
74
- return app
75
- }
76
-
77
- async function setupAndStartRuntime (config) {
78
- const MAX_PORT = 65535
79
- let runtimeConfig
80
-
81
- if (config.configType === 'runtime') {
82
- config.configManager.args = config.args
83
- runtimeConfig = config.configManager
84
- } else {
85
- const wrappedConfig = await wrapConfigInRuntimeConfig(config)
86
- wrappedConfig.args = config.args
87
- runtimeConfig = wrappedConfig
88
- }
89
-
90
- let runtime = await buildRuntime(runtimeConfig)
91
-
92
- let address = null
93
- const startErr = null
94
-
95
- runtimeConfig.current.server ??= { port: 0 }
96
- let port = runtimeConfig.current.server.port
97
- while (address === null) {
98
- try {
99
- address = await runtime.start()
100
- } catch (err) {
101
- if (err.code === 'EADDRINUSE' || err.code === 'EACCES') {
102
- // Get the actual port from the error message if original port was 0
103
- if (!port) {
104
- const mo = err.message.match(/ address already in use (.+)/)
105
- const url = new URL(`http://${mo[1]}`)
106
- port = Number(url.port)
107
- }
108
-
109
- port++
110
- await runtime.close()
111
-
112
- if (port > MAX_PORT) {
113
- throw err
114
- }
115
-
116
- runtimeConfig.current.server.port = port
117
- runtime = await buildRuntime(runtimeConfig)
118
- } else {
119
- throw err
120
- }
121
- }
122
- }
123
- if (startErr?.code === 'PLT_RUNTIME_EADDR_IN_USE') {
124
- const logger = pino(
125
- pretty({
126
- translateTime: 'SYS:HH:MM:ss',
127
- ignore: 'hostname,pid'
128
- })
129
- )
130
- logger.warn(`Port: ${port} is already in use!`)
131
- logger.warn(`Changing the port to ${runtimeConfig.current.server.port}`)
132
- }
133
- return { address, runtime }
134
- }
135
-
136
- async function startCommand (args, throwAllErrors = false, returnRuntime = false) {
137
- try {
138
- const config = await loadConfig(
139
- {
140
- alias: {
141
- p: 'production'
142
- },
143
- boolean: ['p', 'production']
144
- },
145
- args
146
- )
147
-
148
- const startResult = await setupAndStartRuntime(config)
149
-
150
- const runtime = startResult.runtime
151
- const res = startResult.address
152
-
153
- closeWithGrace(async event => {
154
- if (event.err instanceof Error) {
155
- console.error(event.err)
156
- }
157
- await runtime.close()
158
- })
159
-
160
- return returnRuntime ? runtime : res
161
- } catch (err) {
162
- if (throwAllErrors && err.code !== 'PLT_RUNTIME_RUNTIME_ABORT') {
163
- throw err
164
- }
165
-
166
- if (err.code === 'PLT_CONFIG_NO_CONFIG_FILE_FOUND' && args.length === 1) {
167
- const config = {
168
- $schema: `https://schemas.platformatic.dev/@platformatic/service/${pkg.version}.json`,
169
- server: {
170
- hostname: '127.0.0.1',
171
- port: 3042,
172
- logger: {
173
- level: 'info'
174
- }
175
- },
176
- plugins: {
177
- paths: [args[0]]
178
- },
179
- service: {
180
- openapi: true
181
- },
182
- watch: true
183
- }
184
- const toWrite = join(dirname(resolve(args[0])), 'platformatic.service.json')
185
- console.log(`No config file found, creating ${join(dirname(args[0]), 'platformatic.service.json')}`)
186
- await writeFile(toWrite, JSON.stringify(config, null, 2))
187
- return startCommand(['--config', toWrite])
188
- }
189
-
190
- if (err.filenames) {
191
- console.error(`Missing config file!
192
- Be sure to have a config file with one of the following names:
193
-
194
- ${err.filenames.map(s => ' * ' + s).join('\n')}
195
-
196
- In alternative run "npm create platformatic@latest" to generate a basic plt service config.`)
197
- process.exit(1)
198
- } else if (err.validationErrors) {
199
- printConfigValidationErrors(err)
200
- process.exit(1)
201
- }
202
-
203
- if (err.code !== 'PLT_RUNTIME_RUNTIME_ABORT') {
204
- console.error(err)
205
- }
206
-
207
- process.exit(1)
208
- }
209
- }
210
-
211
- module.exports = { buildRuntime, start, startCommand, setupAndStartRuntime }
@@ -1,33 +0,0 @@
1
- 'use strict'
2
-
3
- const defaultStackable = {
4
- init: () => {},
5
- start: () => {
6
- throw new Error('Stackable start not implemented')
7
- },
8
- stop: () => {},
9
- build: () => {},
10
- getUrl: () => null,
11
- updateContext: () => {},
12
- getConfig: () => null,
13
- getEnv: () => null,
14
- getInfo: () => null,
15
- getDispatchFunc: () => null,
16
- getDispatchTarget: () => null,
17
- getOpenapiSchema: () => null,
18
- getGraphqlSchema: () => null,
19
- getCustomHealthCheck: () => null,
20
- getCustomReadinessCheck: () => null,
21
- getMeta: () => ({}),
22
- getMetrics: () => null,
23
- inject: () => {
24
- throw new Error('Stackable inject not implemented')
25
- },
26
- log: ({ message }) => {
27
- console.log(message)
28
- },
29
- getBootstrapDependencies: () => [],
30
- getWatchConfig: () => ({ enabled: false })
31
- }
32
-
33
- module.exports = defaultStackable
package/runtime.mjs DELETED
@@ -1,54 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- import { readFile } from 'node:fs/promises'
4
- import commist from 'commist'
5
- import { join } from 'desm'
6
- import isMain from 'es-main'
7
- import helpMe from 'help-me'
8
- import parseArgs from 'minimist'
9
- import { startCommand } from './index.js'
10
- import { compile as compileCmd } from './lib/compile.js'
11
-
12
- export const compile = compileCmd
13
-
14
- const help = helpMe({
15
- dir: join(import.meta.url, 'help'),
16
- // the default
17
- ext: '.txt',
18
- })
19
-
20
- const program = commist({ maxDistance: 2 })
21
-
22
- program.register('help', help.toStdout)
23
- program.register('help start', help.toStdout.bind(null, ['start']))
24
- program.register('help compile', help.toStdout.bind(null, ['compile']))
25
- program.register('start', startCommand)
26
- program.register('compile', compile)
27
-
28
- export async function run (argv) {
29
- const args = parseArgs(argv, {
30
- alias: {
31
- v: 'version',
32
- },
33
- })
34
-
35
- if (args.version) {
36
- console.log('v' + JSON.parse(await readFile(join(import.meta.url, 'package.json'), 'utf-8')).version)
37
- process.exit(0)
38
- }
39
-
40
- /* c8 ignore next 4 */
41
- return {
42
- output: await program.parseAsync(argv),
43
- help,
44
- }
45
- }
46
-
47
- if (isMain(import.meta)) {
48
- try {
49
- await run(process.argv.slice(2))
50
- } catch (err) {
51
- console.error(err)
52
- process.exit(1)
53
- }
54
- }