@platformatic/composer 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.
Files changed (58) hide show
  1. package/config.d.ts +2 -30
  2. package/eslint.config.js +11 -2
  3. package/index.d.ts +58 -17
  4. package/index.js +29 -212
  5. package/lib/application.js +186 -0
  6. package/lib/commands/index.js +15 -0
  7. package/lib/commands/openapi-fetch-schemas.js +47 -0
  8. package/lib/composer-hook.js +9 -9
  9. package/lib/errors.js +15 -10
  10. package/lib/generator.js +127 -0
  11. package/lib/graphql-fetch.js +44 -46
  12. package/lib/graphql-generator.js +12 -10
  13. package/lib/graphql.js +13 -9
  14. package/lib/{proxy/not-host-constraints.js → not-host-constraints.js} +3 -5
  15. package/lib/openapi-composer.js +39 -41
  16. package/lib/openapi-config-schema.js +26 -30
  17. package/lib/openapi-generator.js +115 -112
  18. package/lib/openapi-load-config.js +14 -14
  19. package/lib/openapi-modifier.js +12 -21
  20. package/lib/openapi-scalar.js +3 -5
  21. package/lib/proxy.js +13 -12
  22. package/lib/{root-endpoint/index.js → root.js} +12 -12
  23. package/lib/schema.js +41 -25
  24. package/lib/stackable.js +29 -39
  25. package/lib/upgrade.js +6 -8
  26. package/lib/utils.js +5 -16
  27. package/lib/versions/2.0.0.js +4 -6
  28. package/lib/versions/3.0.0.js +14 -0
  29. package/package.json +15 -18
  30. package/schema.json +8 -153
  31. package/.c8rc +0 -6
  32. package/composer.mjs +0 -54
  33. package/help/create.txt +0 -11
  34. package/help/help.txt +0 -7
  35. package/help/openapi schemas fetch.txt +0 -9
  36. package/help/start.txt +0 -54
  37. package/index.test-d.ts +0 -23
  38. package/lib/create.mjs +0 -84
  39. package/lib/generator/README.md +0 -30
  40. package/lib/generator/composer-generator.d.ts +0 -11
  41. package/lib/generator/composer-generator.js +0 -128
  42. package/lib/openapi-fetch-schemas.mjs +0 -61
  43. /package/{lib/root-endpoint/public → public}/images/dark_mode.svg +0 -0
  44. /package/{lib/root-endpoint/public → public}/images/ellipse.svg +0 -0
  45. /package/{lib/root-endpoint/public → public}/images/external-link.svg +0 -0
  46. /package/{lib/root-endpoint/public → public}/images/favicon.ico +0 -0
  47. /package/{lib/root-endpoint/public → public}/images/graphiql.svg +0 -0
  48. /package/{lib/root-endpoint/public → public}/images/graphql.svg +0 -0
  49. /package/{lib/root-endpoint/public → public}/images/light_mode.svg +0 -0
  50. /package/{lib/root-endpoint/public → public}/images/openapi.svg +0 -0
  51. /package/{lib/root-endpoint/public → public}/images/platformatic-logo-dark.svg +0 -0
  52. /package/{lib/root-endpoint/public → public}/images/platformatic-logo-light.svg +0 -0
  53. /package/{lib/root-endpoint/public → public}/images/reverse-proxy.svg +0 -0
  54. /package/{lib/root-endpoint/public → public}/images/triangle_dark.svg +0 -0
  55. /package/{lib/root-endpoint/public → public}/images/triangle_light.svg +0 -0
  56. /package/{lib/root-endpoint/public → public}/index.html +0 -0
  57. /package/{lib/root-endpoint/public → public}/index.njk +0 -0
  58. /package/{lib/root-endpoint/public → public}/main.css +0 -0
package/lib/stackable.js CHANGED
@@ -1,38 +1,29 @@
1
- 'use strict'
2
-
3
- const { ServiceStackable } = require('@platformatic/service')
1
+ import { kMetadata, replaceEnv } from '@platformatic/foundation'
2
+ import { ServiceStackable } from '@platformatic/service'
3
+ import { ensureServices, platformaticComposer } from './application.js'
4
+ import { notHostConstraints } from './not-host-constraints.js'
5
+ import { packageJson } from './schema.js'
4
6
 
5
7
  const kITC = Symbol.for('plt.runtime.itc')
6
8
 
7
- async function ensureServices (composerId, config) {
8
- if (config.composer?.services?.length) {
9
- return
10
- }
11
-
12
- composerId ??= globalThis.platformatic?.serviceId
13
- config.composer ??= {}
14
- config.composer.services ??= []
9
+ export class ComposerStackable extends ServiceStackable {
10
+ #meta
11
+ #dependencies
15
12
 
16
- // When no services are defined, all services are exposed in the composer
17
- const services = await globalThis[kITC]?.send('listServices')
13
+ constructor (root, config, context) {
14
+ super(root, config, context)
15
+ this.type = 'composer'
16
+ this.version = packageJson.version
18
17
 
19
- if (services) {
20
- config.composer.services = services
21
- .filter(id => id !== composerId) // Remove ourself
22
- .map(id => ({ id, proxy: { prefix: `/${id}` } }))
18
+ this.applicationFactory = this.context.applicationFactory ?? platformaticComposer
19
+ this.fastifyOptions ??= {}
20
+ this.fastifyOptions.constraints = { notHost: notHostConstraints }
23
21
  }
24
- }
25
-
26
- class ComposerStackable extends ServiceStackable {
27
- #meta
28
- #dependencies
29
22
 
30
23
  async getBootstrapDependencies () {
31
- await ensureServices(this.serviceId, this.configManager.current)
32
-
33
- // We do not call init() on purpose, as we don't want to load the app just yet.
24
+ await ensureServices(this.serviceId, this.config)
34
25
 
35
- const composedServices = this.configManager.current.composer?.services
26
+ const composedServices = this.config.composer?.services
36
27
  const dependencies = []
37
28
 
38
29
  if (Array.isArray(composedServices)) {
@@ -64,20 +55,20 @@ class ComposerStackable extends ServiceStackable {
64
55
  }
65
56
 
66
57
  async isHealthy () {
67
- // Still booting, assume healthy
68
- if (!this.#dependencies) {
69
- return true
70
- }
71
-
72
- const composedServices = this.#dependencies.map(dep => dep.id)
73
- const workers = await globalThis[kITC].send('getWorkers')
74
-
75
- for (const worker of Object.values(workers)) {
76
- if (composedServices.includes(worker.service) && !worker.status.startsWith('start')) {
77
- return false
58
+ // If no dependencies (still booting), assume healthy
59
+ if (this.#dependencies) {
60
+ const composedServices = this.#dependencies.map(dep => dep.id)
61
+ const workers = await globalThis[kITC].send('getWorkers')
62
+
63
+ for (const worker of Object.values(workers)) {
64
+ if (composedServices.includes(worker.service) && !worker.status.startsWith('start')) {
65
+ globalThis[kITC].notify('event', { event: 'unhealthy' })
66
+ return false
67
+ }
78
68
  }
79
69
  }
80
70
 
71
+ globalThis[kITC].notify('event', { event: 'healthy' })
81
72
  return true
82
73
  }
83
74
 
@@ -85,7 +76,7 @@ class ComposerStackable extends ServiceStackable {
85
76
  let url = `http://${id}.plt.local`
86
77
 
87
78
  if (urlString) {
88
- const remoteUrl = await this.configManager.replaceEnv(urlString)
79
+ const remoteUrl = await replaceEnv(urlString, this.config[kMetadata].env)
89
80
 
90
81
  if (remoteUrl) {
91
82
  url = remoteUrl
@@ -95,4 +86,3 @@ class ComposerStackable extends ServiceStackable {
95
86
  return { id, url, local: url.endsWith('.plt.local') }
96
87
  }
97
88
  }
98
- module.exports = { ComposerStackable, ensureServices }
package/lib/upgrade.js CHANGED
@@ -1,15 +1,13 @@
1
- 'use strict'
2
-
3
- const { join } = require('path')
4
-
5
- module.exports = async function upgrade (config, version) {
6
- const { semgrator } = await import('semgrator')
1
+ import { abstractLogger } from '@platformatic/foundation'
2
+ import { resolve } from 'node:path'
3
+ import { semgrator } from 'semgrator'
7
4
 
5
+ export async function upgrade (logger, config, version) {
8
6
  const iterator = semgrator({
9
7
  version,
10
- path: join(__dirname, 'versions'),
8
+ path: resolve(import.meta.dirname, 'versions'),
11
9
  input: config,
12
- logger: this.logger.child({ name: '@platformatic/composer' }),
10
+ logger: logger?.child({ name: '@platformatic/composer' }) ?? abstractLogger
13
11
  })
14
12
 
15
13
  let result
package/lib/utils.js CHANGED
@@ -1,10 +1,6 @@
1
- 'use strict'
2
-
3
- function prefixWithSlash (url) {
1
+ export function prefixWithSlash (url) {
4
2
  if (typeof url === 'string') {
5
- return url.startsWith('/')
6
- ? url
7
- : `/${url}`
3
+ return url.startsWith('/') ? url : `/${url}`
8
4
  }
9
5
  return ''
10
6
  }
@@ -14,14 +10,7 @@ function prefixWithSlash (url) {
14
10
  * a service can have openapi and/or gql either from a remote service or from file
15
11
  * note service.origin is always been set if missing at index.js/platformaticComposer
16
12
  * @returns {boolean}
17
- */
18
- function isFetchable (service) {
19
- return Boolean(
20
- (service?.openapi && service.openapi.url) || service?.graphql
21
- )
22
- }
23
-
24
- module.exports = {
25
- prefixWithSlash,
26
- isFetchable,
13
+ */
14
+ export function isFetchable (service) {
15
+ return Boolean((service?.openapi && service.openapi.url) || service?.graphql)
27
16
  }
@@ -1,11 +1,9 @@
1
- 'use strict'
1
+ import { version } from '../schema.js'
2
2
 
3
- const pkg = require('../../package.json')
4
-
5
- module.exports = {
3
+ export default {
6
4
  version: '2.0.0',
7
- up: function (config) {
8
- config.$schema = `https://schemas.platformatic.dev/@platformatic/composer/${pkg.version}.json`
5
+ up (config) {
6
+ config.$schema = `https://schemas.platformatic.dev/@platformatic/composer/${version}.json`
9
7
  return config
10
8
  }
11
9
  }
@@ -0,0 +1,14 @@
1
+ export default {
2
+ version: '2.99.0',
3
+ up (config) {
4
+ if (typeof config.plugins?.typescript !== 'undefined') {
5
+ delete config.plugins.typescript
6
+ }
7
+
8
+ if (typeof config.clients !== 'undefined') {
9
+ delete config.clients
10
+ }
11
+
12
+ return config
13
+ }
14
+ }
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@platformatic/composer",
3
- "version": "2.74.3",
3
+ "version": "3.0.0-alpha.2",
4
4
  "description": "",
5
5
  "main": "index.js",
6
- "bin": {
7
- "plt-composer": "./composer.mjs"
8
- },
6
+ "types": "index.d.ts",
7
+ "type": "module",
9
8
  "author": "Platformatic Inc. <oss@platformatic.dev> (https://platformatic.dev)",
10
9
  "repository": {
11
10
  "type": "git",
@@ -33,9 +32,8 @@
33
32
  "typescript": "^5.5.4",
34
33
  "why-is-node-running": "2",
35
34
  "ws": "^8.16.0",
36
- "@platformatic/client": "2.74.3",
37
- "@platformatic/config": "2.74.3",
38
- "@platformatic/db": "2.74.3"
35
+ "@platformatic/client": "3.0.0-alpha.2",
36
+ "@platformatic/db": "3.0.0-alpha.2"
39
37
  },
40
38
  "dependencies": {
41
39
  "@fastify/error": "^4.0.0",
@@ -48,10 +46,7 @@
48
46
  "@platformatic/graphql-composer": "^0.10.0",
49
47
  "@scalar/fastify-api-reference": "1.33.0",
50
48
  "ajv": "^8.12.0",
51
- "commist": "^3.2.0",
52
49
  "console-table-printer": "^2.12.0",
53
- "desm": "^1.3.1",
54
- "es-main": "^1.3.0",
55
50
  "execa": "^9.0.0",
56
51
  "fast-deep-equal": "^3.1.3",
57
52
  "fastify": "^5.0.0",
@@ -64,20 +59,22 @@
64
59
  "my-ua-parser": "^2.0.2",
65
60
  "nunjucks": "^3.2.4",
66
61
  "ora": "^6.3.1",
67
- "pino": "^9.0.0",
62
+ "pino": "^9.9.0",
68
63
  "pino-pretty": "^13.0.0",
69
64
  "rfdc": "^1.3.1",
70
65
  "semgrator": "^0.3.0",
71
66
  "undici": "^7.0.0",
72
- "@platformatic/config": "2.74.3",
73
- "@platformatic/scalar-theme": "2.74.3",
74
- "@platformatic/service": "2.74.3",
75
- "@platformatic/generators": "2.74.3",
76
- "@platformatic/utils": "^2.74.3",
77
- "@platformatic/telemetry": "2.74.3"
67
+ "@platformatic/basic": "3.0.0-alpha.2",
68
+ "@platformatic/service": "3.0.0-alpha.2",
69
+ "@platformatic/scalar-theme": "3.0.0-alpha.2",
70
+ "@platformatic/telemetry": "3.0.0-alpha.2",
71
+ "@platformatic/foundation": "^3.0.0-alpha.2"
72
+ },
73
+ "engines": {
74
+ "node": ">=22.18.0"
78
75
  },
79
76
  "scripts": {
80
- "test": "pnpm run lint && borp -T --timeout=1200000 -c 1 && tsd",
77
+ "test": "pnpm run lint && borp -T --timeout 1200000 -c 1",
81
78
  "gen-schema": "node lib/schema.js > schema.json",
82
79
  "gen-types": "json2ts > config.d.ts < schema.json",
83
80
  "build": "pnpm run gen-schema && pnpm run gen-types",
package/schema.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/@platformatic/composer/2.74.3.json",
2
+ "$id": "https://schemas.platformatic.dev/@platformatic/composer/3.0.0-alpha.2.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
- "title": "Platformatic Composer",
4
+ "title": "Platformatic Composer Config",
5
5
  "type": "object",
6
6
  "properties": {
7
7
  "basePath": {
@@ -1115,77 +1115,6 @@
1115
1115
  "default": {},
1116
1116
  "additionalProperties": false
1117
1117
  },
1118
- "metrics": {
1119
- "anyOf": [
1120
- {
1121
- "type": "boolean"
1122
- },
1123
- {
1124
- "type": "object",
1125
- "properties": {
1126
- "port": {
1127
- "anyOf": [
1128
- {
1129
- "type": "integer"
1130
- },
1131
- {
1132
- "type": "string"
1133
- }
1134
- ]
1135
- },
1136
- "hostname": {
1137
- "type": "string"
1138
- },
1139
- "endpoint": {
1140
- "type": "string"
1141
- },
1142
- "server": {
1143
- "type": "string",
1144
- "enum": [
1145
- "own",
1146
- "parent",
1147
- "hide"
1148
- ]
1149
- },
1150
- "defaultMetrics": {
1151
- "type": "object",
1152
- "properties": {
1153
- "enabled": {
1154
- "type": "boolean"
1155
- }
1156
- },
1157
- "required": [
1158
- "enabled"
1159
- ],
1160
- "additionalProperties": false
1161
- },
1162
- "auth": {
1163
- "type": "object",
1164
- "properties": {
1165
- "username": {
1166
- "type": "string"
1167
- },
1168
- "password": {
1169
- "type": "string"
1170
- }
1171
- },
1172
- "additionalProperties": false,
1173
- "required": [
1174
- "username",
1175
- "password"
1176
- ]
1177
- },
1178
- "labels": {
1179
- "type": "object",
1180
- "additionalProperties": {
1181
- "type": "string"
1182
- }
1183
- }
1184
- },
1185
- "additionalProperties": false
1186
- }
1187
- ]
1188
- },
1189
1118
  "types": {
1190
1119
  "type": "object",
1191
1120
  "properties": {
@@ -1292,45 +1221,6 @@
1292
1221
  }
1293
1222
  ]
1294
1223
  }
1295
- },
1296
- "typescript": {
1297
- "anyOf": [
1298
- {
1299
- "type": "object",
1300
- "properties": {
1301
- "enabled": {
1302
- "anyOf": [
1303
- {
1304
- "type": "boolean"
1305
- },
1306
- {
1307
- "type": "string"
1308
- }
1309
- ]
1310
- },
1311
- "tsConfig": {
1312
- "type": "string",
1313
- "resolvePath": true
1314
- },
1315
- "outDir": {
1316
- "type": "string",
1317
- "resolvePath": true
1318
- },
1319
- "flags": {
1320
- "type": "array",
1321
- "items": {
1322
- "type": "string"
1323
- }
1324
- }
1325
- }
1326
- },
1327
- {
1328
- "type": "boolean"
1329
- },
1330
- {
1331
- "type": "string"
1332
- }
1333
- ]
1334
1224
  }
1335
1225
  },
1336
1226
  "additionalProperties": false,
@@ -1347,47 +1237,12 @@
1347
1237
  }
1348
1238
  ]
1349
1239
  },
1350
- "clients": {
1351
- "type": "array",
1352
- "items": {
1353
- "type": "object",
1354
- "properties": {
1355
- "serviceId": {
1356
- "type": "string"
1357
- },
1358
- "name": {
1359
- "type": "string"
1360
- },
1361
- "type": {
1362
- "type": "string",
1363
- "enum": [
1364
- "openapi",
1365
- "graphql"
1366
- ]
1367
- },
1368
- "path": {
1369
- "type": "string",
1370
- "resolvePath": true
1371
- },
1372
- "schema": {
1373
- "type": "string",
1374
- "resolvePath": true
1375
- },
1376
- "url": {
1377
- "type": "string"
1378
- },
1379
- "fullResponse": {
1380
- "type": "boolean"
1381
- },
1382
- "fullRequest": {
1383
- "type": "boolean"
1384
- },
1385
- "validateResponse": {
1386
- "type": "boolean"
1387
- }
1388
- },
1389
- "additionalProperties": false
1390
- }
1240
+ "application": {
1241
+ "type": "object",
1242
+ "properties": {},
1243
+ "additionalProperties": false,
1244
+ "required": [],
1245
+ "default": {}
1391
1246
  },
1392
1247
  "runtime": {
1393
1248
  "type": "object",
package/.c8rc DELETED
@@ -1,6 +0,0 @@
1
- {
2
- "exclude": [
3
- "fixtures/*",
4
- "test/*"
5
- ]
6
- }
package/composer.mjs DELETED
@@ -1,54 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- import { readFile } from 'fs/promises'
4
-
5
- import commist from 'commist'
6
- import parseArgs from 'minimist'
7
- import isMain from 'es-main'
8
- import helpMe from 'help-me'
9
- import { join } from 'desm'
10
- import { start } from '@platformatic/service'
11
- import { printAndExitLoadConfigError } from '@platformatic/config'
12
-
13
- import { fetchOpenApiSchemas } from './lib/openapi-fetch-schemas.mjs'
14
- import { platformaticComposer } from './index.js'
15
- import { createComposer } from './lib/create.mjs'
16
- const help = helpMe({
17
- dir: join(import.meta.url, 'help'),
18
- // the default
19
- ext: '.txt',
20
- })
21
-
22
- const program = commist({ maxDistance: 2 })
23
-
24
- program.register('start', (argv) => {
25
- start(platformaticComposer, argv).catch(printAndExitLoadConfigError)
26
- })
27
- program.register('openapi schemas fetch', (argv) => {
28
- return fetchOpenApiSchemas(argv).catch(printAndExitLoadConfigError)
29
- })
30
- program.register('create', createComposer)
31
-
32
- export async function runComposer (argv) {
33
- const args = parseArgs(argv, {
34
- alias: {
35
- v: 'version',
36
- },
37
- })
38
-
39
- if (args.version) {
40
- console.log('v' + JSON.parse(await readFile(join(import.meta.url, 'package.json'), 'utf-8')).version)
41
- process.exit(0)
42
- }
43
-
44
- const output = await program.parseAsync(argv)
45
-
46
- return {
47
- output,
48
- help,
49
- }
50
- }
51
-
52
- if (isMain(import.meta)) {
53
- await runComposer(process.argv.splice(2))
54
- }
package/help/create.txt DELETED
@@ -1,11 +0,0 @@
1
- Creates a new Platformatic Composer 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 DELETED
@@ -1,7 +0,0 @@
1
- Available commands:
2
-
3
- * `create` - creates a new Platformatic Composer application.
4
- * `help` - show this help message.
5
- * `help <command>` - shows more information about a command.
6
- * `start` - start the server.
7
- * `openapi schemas fetch` - fetch OpenAPI schemas from services.
@@ -1,9 +0,0 @@
1
- Fetch OpenAPI schemas from remote services to use in your Platformatic project.
2
-
3
- ``` bash
4
- $ platformatic composer openapi schemas fetch
5
- ```
6
-
7
- It will fetch all the schemas from the remote services and store them by path
8
- set in the `platformatic.json` file. If the path is not set, it will
9
- skip fetching the schema.
package/help/start.txt DELETED
@@ -1,54 +0,0 @@
1
- Start the Platformatic Composer server with the following command:
2
-
3
- ``` bash
4
- $ platformatic composer start
5
- ```
6
-
7
- You will need a configuration file. Here is an example to get you started,
8
- save the following as `platformatic.json`:
9
-
10
- ``` json
11
- {
12
- "server": {
13
- "hostname": "127.0.0.1",
14
- "port": 0,
15
- "logger": {
16
- "level": "info"
17
- }
18
- },
19
- "composer": {
20
- "services": [
21
- {
22
- "id": "service1",
23
- "origin": "http://127.0.0.1:3051",
24
- "openapi": {
25
- "url": "/documentation/json"
26
- }
27
- },
28
- {
29
- "id": "service2",
30
- "origin": "http://127.0.0.1:3052",
31
- "openapi": {
32
- "file": "./schemas/service2.openapi.json"
33
- }
34
- }
35
- ],
36
- "refreshTimeout": 1000
37
- }
38
- }
39
- ```
40
-
41
- By sending the SIGUSR2 signal, the server can be reloaded.
42
-
43
- Options:
44
-
45
- * `-c, --config FILE` - Specify a configuration file to use.
46
-
47
- If not specified, the configuration will be loaded from any of the following, in the current directory.
48
-
49
- * `platformatic.json`, or
50
- * `platformatic.yml`, or
51
- * `platformatic.tml`
52
-
53
- You can find more details about the configuration format here:
54
- * [Platformatic Composer Configuration](https://docs.platformatic.dev/docs/composer/configuration)
package/index.test-d.ts DELETED
@@ -1,23 +0,0 @@
1
- import { buildServer, PlatformaticApp, PlatformaticComposerConfig } from '.'
2
- import ConfigManager from '@platformatic/config'
3
- import { expectType } from 'tsd'
4
-
5
- declare module 'fastify' {
6
- interface FastifyInstance {
7
- platformatic: PlatformaticApp<PlatformaticComposerConfig>
8
- }
9
- }
10
-
11
- async function main (): Promise<void> {
12
- // TODO this configuration is incomplete, type it fully
13
- const server = await buildServer({
14
- server: {
15
- port: 3042,
16
- host: '127.0.0.1'
17
- }
18
- })
19
-
20
- expectType<ConfigManager<PlatformaticComposerConfig>>(server.platformatic.configManager)
21
- }
22
-
23
- main().catch(console.error)