@platformatic/service 1.16.0 → 1.18.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.
@@ -0,0 +1,11 @@
1
+ Creates a new Platformatic Service application.
2
+
3
+ Options are
4
+
5
+ * `dir <string>` - the directory where to create the project (Default: `process.cwd() + 'platformatic-composer'`)
6
+ * `port <string>` - the port where the application will listen (Default: `3042`)
7
+ * `hostname <string>` - the hostname where the application will listen (Default: `0.0.0.0`)
8
+ * `git <boolean>` - Init the git repository (Default: `true`)
9
+ * `typescript <boolean>` - Use Typescript (Default: `false`)
10
+ * `install <boolean>` - Run or not `npm install` after creating the files (Default: `true`)
11
+ * `plugin <boolean>` - Creates a sample plugin and tests (Default: `true`)
package/help/help.txt CHANGED
@@ -1,5 +1,6 @@
1
1
  Available commands:
2
2
 
3
+ * `create` - creates a new Platformatic Service application.
3
4
  * `help` - show this help message.
4
5
  * `help <command>` - show more information about a command.
5
6
  * `start` - start the server.
package/index.js CHANGED
@@ -28,6 +28,11 @@ async function platformaticService (app, opts) {
28
28
  const beforePlugins = opts.beforePlugins || arguments[2] || []
29
29
 
30
30
  if (isKeyEnabled('metrics', config)) {
31
+ if (config.metrics.server === 'own' && parseInt(config.server.port) === parseInt(config.metrics.port)) {
32
+ app.log.warn('In order to serve metrics on the same port as the core applicaton, set metrics.server to "parent".')
33
+ config.metrics.server = 'parent'
34
+ }
35
+
31
36
  app.register(setupMetrics, config.metrics)
32
37
  }
33
38
 
package/lib/create.mjs ADDED
@@ -0,0 +1,85 @@
1
+ 'use strict'
2
+ import minimist from 'minimist'
3
+ import { Generator } from '../lib/generator/service-generator.js'
4
+ import { join } from 'node:path'
5
+ import { getPkgManager } from '@platformatic/utils'
6
+ import { execa } from 'execa'
7
+ import ora from 'ora'
8
+ import { Table } from 'console-table-printer'
9
+ import pino from 'pino'
10
+ import pinoPretty from 'pino-pretty'
11
+
12
+ function printAppSummary (args, logger) {
13
+ logger.info('Creating a Platformatic Service app with this config: ')
14
+ const table = [
15
+ { config: 'Directory', value: args.dir },
16
+ { config: 'Language', value: args.typescript ? 'Typescript' : 'Javascript' },
17
+ { config: 'Init Git Repository', value: args.git },
18
+ { config: 'Install Dependencies', value: args.install },
19
+ { config: 'Sample Plugin and Tests', value: args.plugin }
20
+ ]
21
+
22
+ const p = new Table({
23
+ columns: [
24
+ { name: 'config', alignment: 'right' },
25
+ { name: 'value', alignment: 'left' }
26
+ ]
27
+ })
28
+
29
+ p.addRows(table)
30
+ p.printTable()
31
+ }
32
+ async function createService (_args) {
33
+ const stream = pinoPretty({
34
+ translateTime: 'SYS:HH:MM:ss',
35
+ ignore: 'hostname,pid',
36
+ minimumLevel: 'debug',
37
+ sync: true
38
+ })
39
+
40
+ const logger = pino(stream)
41
+
42
+ const args = minimist(process.argv.slice(2), {
43
+ string: ['dir', 'port', 'hostname'],
44
+ boolean: ['typescript', 'install', 'plugin', 'git'],
45
+ default: {
46
+ dir: join(process.cwd(), 'platformatic-service'),
47
+ port: 3042,
48
+ hostname: '0.0.0.0',
49
+ plugin: true,
50
+ typescript: false,
51
+ git: false,
52
+ install: true
53
+ }
54
+
55
+ })
56
+
57
+ printAppSummary(args, logger)
58
+
59
+ const gen = new Generator({})
60
+ gen.setConfig({
61
+ port: args.port,
62
+ hostname: args.hostname,
63
+ plugin: args.plugin,
64
+ tests: args.plugin,
65
+ typescript: args.typescript,
66
+ initGitRepository: args.git,
67
+ targetDirectory: args.dir
68
+ })
69
+
70
+ try {
71
+ await gen.run()
72
+ if (args.install) {
73
+ const pkgManager = getPkgManager()
74
+ const spinner = ora('Installing dependencies...').start()
75
+ await execa(pkgManager, ['install'], { cwd: args.dir })
76
+ spinner.succeed()
77
+ }
78
+
79
+ logger.info('Done! 🎉')
80
+ } catch (err) {
81
+ logger.error(err.message)
82
+ }
83
+ }
84
+
85
+ export { createService }
@@ -8,26 +8,44 @@ const basicAuth = require('@fastify/basic-auth')
8
8
  const fastifyAccepts = require('@fastify/accepts')
9
9
  const Fastify = require('fastify')
10
10
 
11
- // This is a global server to match global
11
+ // This is a global httpServer to match global
12
12
  // prometheus. It's an antipattern, so do
13
13
  // not use it elsewhere.
14
- let server = null
14
+ let httpServer = null
15
15
 
16
16
  module.exports = fp(async function (app, opts) {
17
- let port = 9090
18
- let host = '0.0.0.0'
19
- if (typeof opts === 'object') {
20
- if (undefined !== opts.port) {
21
- port = opts.port
17
+ const server = opts.server ?? 'own'
18
+ const hostname = opts.hostname ?? '0.0.0.0'
19
+ const port = opts.port ?? 9090
20
+ const metricsEndpoint = opts.endpoint ?? '/metrics'
21
+ const auth = opts.auth ?? null
22
+
23
+ let basicAuthValidator = null
24
+ if (auth) {
25
+ const { username, password } = auth
26
+ basicAuthValidator = function (user, pass, req, reply, done) {
27
+ if (username !== user || password !== pass) {
28
+ return reply.code(401).send({ message: 'Unauthorized' })
29
+ }
30
+ return done()
22
31
  }
23
- /* c8 ignore next 3 */
24
- if (undefined !== opts.hostname) {
25
- host = opts.hostname
32
+
33
+ if (server === 'parent') {
34
+ await app.register(basicAuth, {
35
+ validate: basicAuthValidator
36
+ })
37
+
38
+ app.addHook('onRoute', (routeOptions) => {
39
+ if (routeOptions.url === metricsEndpoint) {
40
+ routeOptions.onRequest = app.basicAuth
41
+ }
42
+ })
26
43
  }
27
44
  }
45
+
28
46
  app.register(metricsPlugin, {
29
47
  defaultMetrics: { enabled: true },
30
- endpoint: null,
48
+ endpoint: server === 'parent' ? metricsEndpoint : null,
31
49
  name: 'metrics',
32
50
  routeMetrics: { enabled: true },
33
51
  clearRegisterOnInit: true
@@ -56,24 +74,28 @@ module.exports = fp(async function (app, opts) {
56
74
  app.metrics.client.register.registerMetric(eluMetric)
57
75
  })
58
76
 
59
- if (server && server.address().port !== port) {
60
- await new Promise((resolve) => server.close(resolve))
61
- server = null
77
+ if (httpServer && httpServer.address().port !== port) {
78
+ await new Promise((resolve) => httpServer.close(resolve))
79
+ httpServer = null
80
+ }
81
+
82
+ if (server === 'parent') {
83
+ return
62
84
  }
63
85
 
64
- if (!server) {
65
- server = http.createServer()
66
- server.listen(port, host)
67
- server.unref()
86
+ if (!httpServer) {
87
+ httpServer = http.createServer()
88
+ httpServer.listen(port, hostname)
89
+ httpServer.unref()
68
90
  }
69
91
 
70
92
  const promServer = Fastify({
71
93
  name: 'Prometheus server',
72
94
  serverFactory: (handler) => {
73
- server.removeAllListeners('request')
74
- server.removeAllListeners('clientError')
75
- server.on('request', handler)
76
- return server
95
+ httpServer.removeAllListeners('request')
96
+ httpServer.removeAllListeners('clientError')
97
+ httpServer.on('request', handler)
98
+ return httpServer
77
99
  },
78
100
  logger: app.log.child({ name: 'prometheus' })
79
101
  })
@@ -81,7 +103,7 @@ module.exports = fp(async function (app, opts) {
81
103
  promServer.register(fastifyAccepts)
82
104
 
83
105
  const metricsEndpointOptions = {
84
- url: '/metrics',
106
+ url: metricsEndpoint,
85
107
  method: 'GET',
86
108
  logLevel: 'warn',
87
109
  handler: async (req, reply) => {
@@ -95,15 +117,9 @@ module.exports = fp(async function (app, opts) {
95
117
  }
96
118
  }
97
119
 
98
- if (opts.auth) {
99
- const { username, password } = opts.auth
120
+ if (auth) {
100
121
  await promServer.register(basicAuth, {
101
- validate: function (user, pass, req, reply, done) {
102
- if (username !== user || password !== pass) {
103
- return reply.code(401).send({ message: 'Unauthorized' })
104
- }
105
- return done()
106
- }
122
+ validate: basicAuthValidator
107
123
  })
108
124
  metricsEndpointOptions.onRequest = promServer.basicAuth
109
125
  }
package/lib/schema.js CHANGED
@@ -555,6 +555,11 @@ const metrics = {
555
555
  ]
556
556
  },
557
557
  hostname: { type: 'string' },
558
+ endpoint: { type: 'string' },
559
+ server: {
560
+ type: 'string',
561
+ enum: ['own', 'parent']
562
+ },
558
563
  auth: {
559
564
  type: 'object',
560
565
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/service",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -20,7 +20,7 @@
20
20
  "@fastify/aws-lambda": "^3.3.0",
21
21
  "@fastify/compress": "^6.5.0",
22
22
  "bindings": "^1.5.0",
23
- "c8": "^8.0.1",
23
+ "c8": "^9.0.0",
24
24
  "glob": "^10.3.10",
25
25
  "json-schema-to-typescript": "^13.1.1",
26
26
  "openapi-types": "^12.1.3",
@@ -31,7 +31,7 @@
31
31
  "standard": "^17.1.0",
32
32
  "strip-ansi": "^7.1.0",
33
33
  "ts-standard": "^12.0.2",
34
- "tsd": "^0.29.0",
34
+ "tsd": "^0.30.0",
35
35
  "typescript": "^5.2.2",
36
36
  "undici": "^6.0.0",
37
37
  "vscode-json-languageservice": "^5.3.6",
@@ -58,6 +58,7 @@
58
58
  "code-block-writer": "^12.0.0",
59
59
  "colorette": "^2.0.20",
60
60
  "commist": "^3.2.0",
61
+ "console-table-printer": "^2.11.2",
61
62
  "desm": "^1.3.0",
62
63
  "env-schema": "^5.2.0",
63
64
  "es-main": "^1.3.0",
@@ -71,19 +72,20 @@
71
72
  "mercurius": "^13.1.0",
72
73
  "minimist": "^1.2.8",
73
74
  "openapi-schema-diff": "^0.0.1",
75
+ "ora": "^6.3.1",
74
76
  "pino": "^8.15.3",
75
77
  "pino-pretty": "^10.2.0",
76
78
  "rfdc": "^1.3.0",
77
79
  "ua-parser-js": "^1.0.36",
78
80
  "undici": "^6.0.0",
79
- "@platformatic/authenticate": "1.16.0",
80
- "@platformatic/config": "1.16.0",
81
- "@platformatic/generators": "1.16.0",
82
- "@platformatic/scalar-theme": "1.16.0",
83
- "@platformatic/telemetry": "1.16.0",
84
- "@platformatic/utils": "1.16.0",
85
- "@platformatic/client": "1.16.0",
86
- "@platformatic/metaconfig": "1.16.0"
81
+ "@platformatic/authenticate": "1.18.0",
82
+ "@platformatic/client": "1.18.0",
83
+ "@platformatic/config": "1.18.0",
84
+ "@platformatic/metaconfig": "1.18.0",
85
+ "@platformatic/generators": "1.18.0",
86
+ "@platformatic/scalar-theme": "1.18.0",
87
+ "@platformatic/telemetry": "1.18.0",
88
+ "@platformatic/utils": "1.18.0"
87
89
  },
88
90
  "standard": {
89
91
  "ignore": [
package/service.mjs CHANGED
@@ -11,7 +11,7 @@ import { generateJsonSchemaConfig } from './lib/gen-schema.js'
11
11
  import { bumpVersion } from './lib/bump-version.js'
12
12
  import { updateVersion } from './lib/update-version.js'
13
13
  import { generateTypes } from './lib/gen-types.mjs'
14
-
14
+ import { createService } from './lib/create.mjs'
15
15
  import { buildCompileCmd } from './lib/compile.js'
16
16
 
17
17
  import { start, platformaticService } from './index.js'
@@ -43,6 +43,7 @@ program.register('start', (argv) => {
43
43
  start(platformaticService, argv).catch(printAndExitLoadConfigError)
44
44
  })
45
45
 
46
+ program.register('create', wrapCommand(createService))
46
47
  program.register('compile', buildCompileCmd(platformaticService))
47
48
  program.register('types', wrapCommand(generateTypes))
48
49
  program.register('schema config', wrapCommand(generateJsonSchemaConfig))
package/.taprc DELETED
@@ -1,2 +0,0 @@
1
- timeout: 500
2
- coverage: false