@platformatic/service 2.72.0 → 3.0.0-alpha.1
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 +1 -19
- package/eslint.config.js +4 -6
- package/index.d.ts +51 -47
- package/index.js +44 -199
- package/lib/application.js +57 -0
- package/lib/compile.js +1 -52
- package/lib/generator.js +154 -0
- package/lib/plugins/clients.js +9 -8
- package/lib/plugins/cors.js +5 -8
- package/lib/plugins/graphql.js +16 -14
- package/lib/plugins/health-check.js +6 -8
- package/lib/plugins/openapi.js +40 -31
- package/lib/plugins/plugins.js +15 -18
- package/lib/{root-endpoint/index.js → plugins/root.js} +9 -8
- package/lib/plugins/sandbox-wrapper.js +62 -55
- package/lib/plugins/typescript.js +10 -13
- package/lib/schema.js +1030 -132
- package/lib/stackable.js +180 -337
- package/lib/upgrade.js +6 -8
- package/lib/utils.js +39 -74
- package/lib/versions/0.16.0.js +14 -14
- package/lib/versions/{from-zero-twenty-eight-to-will-see.js → 0.28.0.js} +3 -5
- package/lib/versions/2.0.0.js +4 -6
- package/package.json +17 -22
- package/schema.json +3 -74
- package/tsconfig.json +16 -6
- package/.c8rc +0 -6
- package/help/compile.txt +0 -19
- package/help/create.txt +0 -11
- package/help/help.txt +0 -8
- package/help/schema.txt +0 -9
- package/help/start.txt +0 -23
- package/index.test-d.ts +0 -107
- package/lib/create.mjs +0 -85
- package/lib/gen-schema.js +0 -15
- package/lib/gen-types.mjs +0 -38
- package/lib/generator/README.md +0 -31
- package/lib/generator/service-generator.d.ts +0 -11
- package/lib/generator/service-generator.js +0 -126
- package/lib/openapi-schema-defs.js +0 -1108
- package/lib/plugins/metrics.js +0 -244
- package/lib/start.js +0 -190
- package/service.mjs +0 -71
- /package/{lib/root-endpoint/public → public}/images/dark_mode.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/favicon.ico +0 -0
- /package/{lib/root-endpoint/public → public}/images/light_mode.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/platformatic-logo-dark.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/platformatic-logo-light.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/triangle_dark.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/triangle_light.svg +0 -0
- /package/{lib/root-endpoint/public → public}/index.html +0 -0
package/lib/generator.js
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { BaseGenerator } from '@platformatic/generators'
|
|
2
|
+
|
|
3
|
+
export class Generator extends BaseGenerator {
|
|
4
|
+
constructor (opts = {}) {
|
|
5
|
+
super({
|
|
6
|
+
...opts,
|
|
7
|
+
module: '@platformatic/service'
|
|
8
|
+
})
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
getDefaultConfig () {
|
|
12
|
+
const config = super.getDefaultConfig()
|
|
13
|
+
config.plugin = true
|
|
14
|
+
config.tests = true
|
|
15
|
+
return config
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async _beforePrepare () {
|
|
19
|
+
// if we are NOT updating, create env and files, otherwise leave as it is
|
|
20
|
+
if (!this.config.isUpdating) {
|
|
21
|
+
if (!this.config.isRuntimeContext) {
|
|
22
|
+
this.addEnvVars(
|
|
23
|
+
{
|
|
24
|
+
PLT_SERVER_HOSTNAME: this.config.hostname,
|
|
25
|
+
PLT_SERVER_LOGGER_LEVEL: 'info',
|
|
26
|
+
PORT: 3042
|
|
27
|
+
},
|
|
28
|
+
{ overwrite: false }
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this.addEnvVars(
|
|
33
|
+
{
|
|
34
|
+
PLT_TYPESCRIPT: this.config.typescript
|
|
35
|
+
},
|
|
36
|
+
{ overwrite: false, default: true }
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
this.config.dependencies = {
|
|
40
|
+
'@platformatic/service': `^${this.platformaticVersion}`
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
getConfigFieldsDefinitions () {
|
|
46
|
+
if (this.config.isRuntimeContext) {
|
|
47
|
+
return []
|
|
48
|
+
}
|
|
49
|
+
return [
|
|
50
|
+
{
|
|
51
|
+
var: 'PLT_SERVER_HOSTNAME',
|
|
52
|
+
label: 'What is the hostname?',
|
|
53
|
+
default: '0.0.0.0',
|
|
54
|
+
type: 'string',
|
|
55
|
+
configValue: 'hostname'
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
var: 'PLT_SERVER_LOGGER_LEVEL',
|
|
59
|
+
label: 'What is the logger level?',
|
|
60
|
+
default: 'info',
|
|
61
|
+
type: 'string',
|
|
62
|
+
configValue: ''
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
label: 'Which port do you want to use?',
|
|
66
|
+
var: 'PORT',
|
|
67
|
+
default: 3042,
|
|
68
|
+
type: 'number',
|
|
69
|
+
configValue: 'port'
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async _afterPrepare () {
|
|
75
|
+
// if we are NOT updating, create env and files, otherwise leave as it is
|
|
76
|
+
if (!this.config.isUpdating) {
|
|
77
|
+
const PLT_ENVIRONMENT_TEMPLATE = `
|
|
78
|
+
import { FastifyInstance } from 'fastify'
|
|
79
|
+
import { PlatformaticApplication, PlatformaticServiceConfig } from '@platformatic/service'
|
|
80
|
+
|
|
81
|
+
declare module 'fastify' {
|
|
82
|
+
interface FastifyInstance {
|
|
83
|
+
platformatic: PlatformaticApplication<PlatformaticServiceConfig>
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
`
|
|
87
|
+
|
|
88
|
+
const README = `
|
|
89
|
+
# Platformatic Service API
|
|
90
|
+
|
|
91
|
+
This is a generated [Platformatic Service](https://docs.platformatic.dev/docs/service/overview) application.
|
|
92
|
+
|
|
93
|
+
## Requirements
|
|
94
|
+
|
|
95
|
+
Platformatic supports macOS, Linux and Windows ([WSL](https://docs.microsoft.com/windows/wsl/) recommended).
|
|
96
|
+
You'll need to have [Node.js](https://nodejs.org/) >= v18.8.0 or >= v20.6.0
|
|
97
|
+
|
|
98
|
+
## Setup
|
|
99
|
+
|
|
100
|
+
Install dependencies:
|
|
101
|
+
|
|
102
|
+
\`\`\`bash
|
|
103
|
+
npm install
|
|
104
|
+
\`\`\`
|
|
105
|
+
|
|
106
|
+
## Usage
|
|
107
|
+
|
|
108
|
+
Run the API with:
|
|
109
|
+
|
|
110
|
+
\`\`\`bash
|
|
111
|
+
npm start
|
|
112
|
+
\`\`\`
|
|
113
|
+
|
|
114
|
+
### Explore
|
|
115
|
+
- ⚡ The Platformatic DB server is running at http://localhost:3042/
|
|
116
|
+
- 📔 View the REST API's Swagger documentation at http://localhost:3042/documentation/
|
|
117
|
+
- 🔍 Try out the GraphiQL web UI at http://localhost:3042/graphiql
|
|
118
|
+
`
|
|
119
|
+
|
|
120
|
+
this.addFile({ path: '', file: 'plt-env.d.ts', contents: PLT_ENVIRONMENT_TEMPLATE })
|
|
121
|
+
this.addFile({ path: '', file: 'README.md', contents: README })
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async _getConfigFileContents () {
|
|
126
|
+
const { isRuntimeContext } = this.config
|
|
127
|
+
const version = this.platformaticVersion
|
|
128
|
+
const config = {
|
|
129
|
+
$schema: `https://schemas.platformatic.dev/@platformatic/service/${version}.json`,
|
|
130
|
+
service: {
|
|
131
|
+
openapi: true
|
|
132
|
+
},
|
|
133
|
+
watch: true
|
|
134
|
+
}
|
|
135
|
+
if (this.config.plugin) {
|
|
136
|
+
config.plugins = {
|
|
137
|
+
paths: [{ path: './plugins', encapsulate: false }, './routes'],
|
|
138
|
+
typescript: `{${this.getEnvVarName('PLT_TYPESCRIPT')}}`
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!isRuntimeContext) {
|
|
143
|
+
config.server = {
|
|
144
|
+
hostname: '{PLT_SERVER_HOSTNAME}',
|
|
145
|
+
port: '{PORT}',
|
|
146
|
+
logger: {
|
|
147
|
+
level: '{PLT_SERVER_LOGGER_LEVEL}'
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return config
|
|
153
|
+
}
|
|
154
|
+
}
|
package/lib/plugins/clients.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
async function
|
|
1
|
+
import client from '@platformatic/client'
|
|
2
|
+
import { kMetadata } from '@platformatic/utils'
|
|
3
|
+
import fp from 'fastify-plugin'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { resolve } from 'node:path'
|
|
6
|
+
async function setupClientsPlugin (app, opts) {
|
|
7
7
|
for (const { path, url, serviceId, name, schema, type, fullRequest, fullResponse, validateResponse } of opts) {
|
|
8
8
|
if (path) {
|
|
9
|
-
|
|
9
|
+
const require = createRequire(resolve(app.platformatic.config[kMetadata].root, 'noop.js'))
|
|
10
|
+
app.register(await require(path), { url, serviceId })
|
|
10
11
|
} else {
|
|
11
12
|
app.register(client, { url, serviceId, name, path: schema, type, fullRequest, fullResponse, validateResponse })
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
export const setupClients = fp(setupClientsPlugin)
|
package/lib/plugins/cors.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const fp = require('fastify-plugin')
|
|
1
|
+
import fastifyCors from '@fastify/cors'
|
|
2
|
+
import fp from 'fastify-plugin'
|
|
4
3
|
|
|
5
4
|
function originToRegexp (origin) {
|
|
6
5
|
if (typeof origin === 'object') {
|
|
@@ -12,9 +11,7 @@ function originToRegexp (origin) {
|
|
|
12
11
|
return origin
|
|
13
12
|
}
|
|
14
13
|
|
|
15
|
-
async function
|
|
16
|
-
const cors = opts
|
|
17
|
-
|
|
14
|
+
async function setupCorsPlugin (app, cors) {
|
|
18
15
|
let origin = cors.origin
|
|
19
16
|
if (Array.isArray(origin)) {
|
|
20
17
|
origin = origin.map(originToRegexp)
|
|
@@ -23,7 +20,7 @@ async function setupClients (app, opts) {
|
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
cors.origin = origin
|
|
26
|
-
app.register(
|
|
23
|
+
app.register(fastifyCors, cors)
|
|
27
24
|
}
|
|
28
25
|
|
|
29
|
-
|
|
26
|
+
export const setupCors = fp(setupCorsPlugin)
|
package/lib/plugins/graphql.js
CHANGED
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const deepmerge = require('@fastify/deepmerge')({ all: true })
|
|
5
|
-
const fp = require('fastify-plugin')
|
|
1
|
+
import { deepmerge } from '@platformatic/utils'
|
|
2
|
+
import fp from 'fastify-plugin'
|
|
3
|
+
import mercurius from 'mercurius'
|
|
6
4
|
|
|
7
5
|
// For some unknown reason, c8 is not detecting any of this
|
|
8
6
|
// despite being covered by test/graphql.test.js
|
|
9
7
|
/* c8 ignore next 12 */
|
|
10
|
-
async function
|
|
11
|
-
if (typeof
|
|
12
|
-
|
|
8
|
+
async function setupGraphQLPlugin (app, options) {
|
|
9
|
+
if (typeof options !== 'object') {
|
|
10
|
+
options = {}
|
|
13
11
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
|
|
13
|
+
const graphqlOptions = deepmerge(
|
|
14
|
+
{
|
|
15
|
+
graphiql: true,
|
|
16
|
+
additionalRouteOptions: {
|
|
17
|
+
schema: { hide: true }
|
|
18
|
+
}
|
|
18
19
|
},
|
|
19
|
-
|
|
20
|
+
options
|
|
21
|
+
)
|
|
20
22
|
|
|
21
23
|
app.register(mercurius, graphqlOptions)
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
export const setupGraphQL = fp(setupGraphQLPlugin)
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import underPressure from '@fastify/under-pressure'
|
|
2
|
+
import fp from 'fastify-plugin'
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
async function setupClients (app, opts) {
|
|
7
|
-
const healthCheck = opts
|
|
4
|
+
async function setupHealthCheckPlugin (app, options) {
|
|
5
|
+
const healthCheck = options
|
|
8
6
|
|
|
9
7
|
app.register(underPressure, {
|
|
10
8
|
exposeStatusRoute: '/status',
|
|
11
9
|
healthCheckInterval: healthCheck.interval !== undefined ? healthCheck.interval : 5000,
|
|
12
10
|
...healthCheck,
|
|
13
|
-
healthCheck: healthCheck.fn
|
|
11
|
+
healthCheck: healthCheck.fn
|
|
14
12
|
})
|
|
15
13
|
}
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
export const setupHealthCheck = fp(setupHealthCheckPlugin)
|
package/lib/plugins/openapi.js
CHANGED
|
@@ -1,43 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const deepmerge = require('@fastify/deepmerge')({ all: true })
|
|
5
|
-
const fp = require('fastify-plugin')
|
|
1
|
+
import Swagger from '@fastify/swagger'
|
|
2
|
+
import { deepmerge } from '@platformatic/utils'
|
|
3
|
+
import fp from 'fastify-plugin'
|
|
6
4
|
|
|
7
5
|
// For some unknown reason, c8 is not detecting any of this
|
|
8
6
|
// pf
|
|
9
7
|
// despite being covered by test/routes.test.js
|
|
10
8
|
/* c8 ignore next 33 */
|
|
11
|
-
async function
|
|
12
|
-
const { openapi } =
|
|
13
|
-
const openapiConfig = deepmerge(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
async function setupOpenAPIPlugin (app, options) {
|
|
10
|
+
const { openapi } = options
|
|
11
|
+
const openapiConfig = deepmerge(
|
|
12
|
+
{
|
|
13
|
+
exposeRoute: true,
|
|
14
|
+
info: {
|
|
15
|
+
title: 'Platformatic',
|
|
16
|
+
description: 'This is a service built on top of Platformatic',
|
|
17
|
+
version: '1.0.0'
|
|
18
|
+
},
|
|
19
|
+
servers: [{ url: globalThis.platformatic?.runtimeBasePath ?? '/' }]
|
|
19
20
|
},
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
typeof openapi === 'object' ? openapi : {}
|
|
22
|
+
)
|
|
22
23
|
app.log.trace({ openapi: openapiConfig })
|
|
23
24
|
const swaggerOptions = {
|
|
24
25
|
exposeRoute: openapiConfig.exposeRoute,
|
|
25
26
|
openapi: {
|
|
26
|
-
...openapiConfig
|
|
27
|
+
...openapiConfig
|
|
27
28
|
},
|
|
28
29
|
refResolver: {
|
|
29
30
|
buildLocalReference (json, baseUri, fragment, i) {
|
|
30
31
|
// TODO figure out if we need def-${i}
|
|
31
32
|
/* istanbul ignore next */
|
|
32
33
|
return json.$id || `def-${i}`
|
|
33
|
-
}
|
|
34
|
-
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
if (openapi.path) {
|
|
38
39
|
swaggerOptions.mode = 'static'
|
|
39
40
|
swaggerOptions.specification = {
|
|
40
|
-
path: openapi.path
|
|
41
|
+
path: openapi.path
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -49,24 +50,32 @@ async function setupOpenAPI (app, opts) {
|
|
|
49
50
|
const routePrefix = openapi.swaggerPrefix || '/documentation'
|
|
50
51
|
|
|
51
52
|
/** Serve spec file in yaml and json */
|
|
52
|
-
app.get(
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
app.get(
|
|
54
|
+
`${routePrefix}/json`,
|
|
55
|
+
{
|
|
56
|
+
schema: { hide: true },
|
|
57
|
+
logLevel: 'warn'
|
|
58
|
+
},
|
|
59
|
+
async () => app.swagger()
|
|
60
|
+
)
|
|
61
|
+
app.get(
|
|
62
|
+
`${routePrefix}/yaml`,
|
|
63
|
+
{
|
|
64
|
+
schema: { hide: true },
|
|
65
|
+
logLevel: 'warn'
|
|
66
|
+
},
|
|
67
|
+
async () => app.swagger({ yaml: true })
|
|
68
|
+
)
|
|
60
69
|
|
|
61
70
|
app.register(scalarApiReference, {
|
|
62
|
-
...
|
|
71
|
+
...options,
|
|
63
72
|
...openapi,
|
|
64
73
|
routePrefix,
|
|
65
74
|
publicPath: './',
|
|
66
75
|
configuration: {
|
|
67
|
-
customCss: scalarTheme.theme
|
|
68
|
-
}
|
|
76
|
+
customCss: scalarTheme.theme
|
|
77
|
+
}
|
|
69
78
|
})
|
|
70
79
|
}
|
|
71
80
|
|
|
72
|
-
|
|
81
|
+
export const setupOpenAPI = fp(setupOpenAPIPlugin)
|
package/lib/plugins/plugins.js
CHANGED
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import { kMetadata } from '@platformatic/utils'
|
|
2
|
+
import fp from 'fastify-plugin'
|
|
3
|
+
import { readFile } from 'node:fs/promises'
|
|
4
|
+
import { join, resolve } from 'node:path'
|
|
5
|
+
import { getJSPluginPath, isFileAccessible } from '../utils.js'
|
|
6
|
+
import { sandboxWrapper } from './sandbox-wrapper.js'
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const fp = require('fastify-plugin')
|
|
6
|
-
const wrapper = require('./sandbox-wrapper')
|
|
7
|
-
|
|
8
|
-
const { getJSPluginPath, isFileAccessible } = require('../utils')
|
|
9
|
-
|
|
10
|
-
async function loadPlugins (app, opts) {
|
|
11
|
-
const configManager = app.platformatic.configManager
|
|
12
|
-
const config = configManager.current
|
|
8
|
+
async function loadPluginsPlugin (app, context) {
|
|
9
|
+
const config = app.platformatic.config
|
|
13
10
|
|
|
14
11
|
let isOutDirAccessible = false
|
|
15
12
|
let outDir = null
|
|
16
13
|
|
|
17
|
-
const workingDir =
|
|
18
|
-
const tsConfigPath =
|
|
14
|
+
const workingDir = context?.directory ?? config[kMetadata].root
|
|
15
|
+
const tsConfigPath = config.plugins.typescript?.tsConfig || join(workingDir, 'tsconfig.json')
|
|
19
16
|
|
|
20
17
|
// If the tsconfig.json file exists, then we need to adjust the plugin paths
|
|
21
18
|
// to point to the compiled JS files.
|
|
@@ -26,14 +23,14 @@ async function loadPlugins (app, opts) {
|
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
/* c8 ignore next 3 */
|
|
29
|
-
if (
|
|
30
|
-
outDir =
|
|
26
|
+
if (config.plugins.typescript?.outDir) {
|
|
27
|
+
outDir = config.plugins.typescript.outDir
|
|
31
28
|
}
|
|
32
29
|
|
|
33
30
|
if (outDir) {
|
|
34
31
|
isOutDirAccessible = await isFileAccessible(outDir)
|
|
35
32
|
|
|
36
|
-
if (
|
|
33
|
+
if (context?.isProduction && !isOutDirAccessible) {
|
|
37
34
|
throw new Error(
|
|
38
35
|
`Cannot access directory '${outDir}'. Please run the 'build' command before running in production mode.`
|
|
39
36
|
)
|
|
@@ -51,7 +48,7 @@ async function loadPlugins (app, opts) {
|
|
|
51
48
|
})
|
|
52
49
|
}
|
|
53
50
|
|
|
54
|
-
await app.register(
|
|
51
|
+
await app.register(sandboxWrapper, { packages: config.plugins.packages, paths: config.plugins.paths })
|
|
55
52
|
}
|
|
56
53
|
|
|
57
|
-
|
|
54
|
+
export const loadPlugins = fp(loadPluginsPlugin)
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import fastifyStatic from '@fastify/static'
|
|
2
|
+
import fp from 'fastify-plugin'
|
|
3
|
+
import userAgentParser from 'my-ua-parser'
|
|
4
|
+
import { join } from 'node:path'
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
const fastifyStatic = require('@fastify/static')
|
|
5
|
-
const userAgentParser = require('my-ua-parser')
|
|
6
|
-
|
|
7
|
-
module.exports = async (app, opts) => {
|
|
6
|
+
async function setupRootPlugin (app) {
|
|
8
7
|
app.register(fastifyStatic, {
|
|
9
|
-
root:
|
|
8
|
+
root: join(import.meta.dirname, '../../public')
|
|
10
9
|
})
|
|
11
10
|
|
|
12
11
|
// root endpoint
|
|
@@ -23,6 +22,8 @@ module.exports = async (app, opts) => {
|
|
|
23
22
|
}
|
|
24
23
|
}
|
|
25
24
|
return { message: 'Welcome to Platformatic! Please visit https://docs.platformatic.dev' }
|
|
26
|
-
}
|
|
25
|
+
}
|
|
27
26
|
})
|
|
28
27
|
}
|
|
28
|
+
|
|
29
|
+
export const setupRoot = fp(setupRootPlugin)
|
|
@@ -1,26 +1,75 @@
|
|
|
1
|
-
|
|
1
|
+
import autoload from '@fastify/autoload'
|
|
2
|
+
import { kMetadata } from '@platformatic/utils'
|
|
3
|
+
import fp from 'fastify-plugin'
|
|
4
|
+
import { stat } from 'node:fs/promises'
|
|
5
|
+
import { createRequire } from 'node:module'
|
|
6
|
+
import { isAbsolute, resolve } from 'node:path'
|
|
7
|
+
import { pathToFileURL } from 'node:url'
|
|
2
8
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Creates an object for pattern specific options. This ensures that
|
|
11
|
+
* only configurations that have been provided are included in the
|
|
12
|
+
* final result. This prevents 'cannot read properties of undefined'
|
|
13
|
+
* errors when undefined configs are provided to the underlying
|
|
14
|
+
* @fastify/autoload plugin.
|
|
15
|
+
*/
|
|
16
|
+
function patternOptionsFromPlugin (plugin) {
|
|
17
|
+
const config = {}
|
|
18
|
+
|
|
19
|
+
// Expected keys for autoload plugin options that expect regexp patterns
|
|
20
|
+
const patternOptionKeys = ['ignorePattern', 'indexPattern', 'autoHooksPattern']
|
|
9
21
|
|
|
10
|
-
|
|
22
|
+
for (const key of patternOptionKeys) {
|
|
23
|
+
const pattern = plugin[key]
|
|
24
|
+
|
|
25
|
+
// If pattern key not found in plugin object, move on
|
|
26
|
+
if (!pattern) {
|
|
27
|
+
continue
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Build an instance of a RegExp. If this comes back undefined,
|
|
31
|
+
// then an invalid value was provided. Move on.
|
|
32
|
+
const regExpPattern = stringPatternToRegExp(pattern)
|
|
33
|
+
if (!regExpPattern) {
|
|
34
|
+
continue
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// We have a valid RegExp so add the option to the config to pass along to
|
|
38
|
+
// autoload.
|
|
39
|
+
config[key] = regExpPattern
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return config
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function stringPatternToRegExp (stringPattern) {
|
|
46
|
+
try {
|
|
47
|
+
return new RegExp(stringPattern)
|
|
48
|
+
} catch (err) {
|
|
49
|
+
return undefined
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function sandboxWrapperPlugin (app, options) {
|
|
11
54
|
// fake require next to the configManager dirname
|
|
12
|
-
const
|
|
13
|
-
|
|
55
|
+
const require = createRequire(resolve(app.platformatic.config[kMetadata].root, 'noop.js'))
|
|
56
|
+
|
|
57
|
+
for (const plugin of options.packages || []) {
|
|
14
58
|
const name = typeof plugin === 'string' ? plugin : plugin.name
|
|
15
|
-
const url = pathToFileURL(
|
|
59
|
+
const url = pathToFileURL(require.resolve(name))
|
|
16
60
|
const loaded = await import(url)
|
|
17
61
|
await app.register(loaded, plugin.options)
|
|
18
62
|
}
|
|
19
63
|
|
|
20
|
-
for (let plugin of
|
|
64
|
+
for (let plugin of options.paths || []) {
|
|
21
65
|
if (typeof plugin === 'string') {
|
|
22
66
|
plugin = { path: plugin, encapsulate: true }
|
|
23
67
|
}
|
|
68
|
+
|
|
69
|
+
if (plugin.path && !isAbsolute(plugin.path)) {
|
|
70
|
+
plugin.path = resolve(app.platformatic.config[kMetadata].root, plugin.path)
|
|
71
|
+
}
|
|
72
|
+
|
|
24
73
|
if (plugin.path && (await stat(plugin.path)).isDirectory()) {
|
|
25
74
|
const patternOptions = patternOptionsFromPlugin(plugin)
|
|
26
75
|
|
|
@@ -55,48 +104,6 @@ module.exports = fp(async function (app, opts) {
|
|
|
55
104
|
}
|
|
56
105
|
}
|
|
57
106
|
}
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Creates an object for pattern specific options. This ensures that
|
|
62
|
-
* only configurations that have been provided are included in the
|
|
63
|
-
* final result. This prevents 'cannot read properties of undefined'
|
|
64
|
-
* errors when undefined configs are provided to the underlying
|
|
65
|
-
* @fastify/autoload plugin.
|
|
66
|
-
*/
|
|
67
|
-
function patternOptionsFromPlugin (plugin) {
|
|
68
|
-
const config = {}
|
|
69
|
-
|
|
70
|
-
// Expected keys for autoload plugin options that expect regexp patterns
|
|
71
|
-
const patternOptionKeys = ['ignorePattern', 'indexPattern', 'autoHooksPattern']
|
|
72
|
-
|
|
73
|
-
for (const key of patternOptionKeys) {
|
|
74
|
-
const pattern = plugin[key]
|
|
75
|
-
|
|
76
|
-
// If pattern key not found in plugin object, move on
|
|
77
|
-
if (!pattern) {
|
|
78
|
-
continue
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Build an instance of a RegExp. If this comes back undefined,
|
|
82
|
-
// then an invalid value was provided. Move on.
|
|
83
|
-
const regExpPattern = stringPatternToRegExp(pattern)
|
|
84
|
-
if (!regExpPattern) {
|
|
85
|
-
continue
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// We have a valid RegExp so add the option to the config to pass along to
|
|
89
|
-
// autoload.
|
|
90
|
-
config[key] = regExpPattern
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return config
|
|
94
107
|
}
|
|
95
108
|
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
return new RegExp(stringPattern)
|
|
99
|
-
} catch (err) {
|
|
100
|
-
return undefined
|
|
101
|
-
}
|
|
102
|
-
}
|
|
109
|
+
export const sandboxWrapper = fp(sandboxWrapperPlugin)
|
|
@@ -1,20 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import compiler from '@platformatic/ts-compiler'
|
|
2
|
+
import { kMetadata } from '@platformatic/utils'
|
|
3
|
+
import fp from 'fastify-plugin'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const { extractTypeScriptCompileOptionsFromConfig } = require('../compile')
|
|
6
|
-
|
|
7
|
-
async function setupTsCompiler (app, opts) {
|
|
8
|
-
const configManager = app.platformatic.configManager
|
|
9
|
-
const config = configManager.current
|
|
10
|
-
const workingDir = opts?.context?.directory ?? configManager.dirname
|
|
5
|
+
async function setupTsCompilerPlugin (app, context) {
|
|
6
|
+
const config = app.platformatic.config
|
|
11
7
|
|
|
12
8
|
await compiler.compile({
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
tsConfig: config.plugins?.typescript?.tsConfig,
|
|
10
|
+
flags: config.plugins?.typescript?.flags,
|
|
11
|
+
cwd: context?.directory ?? config[kMetadata].root,
|
|
15
12
|
clean: false,
|
|
16
|
-
logger: app.log
|
|
13
|
+
logger: app.log
|
|
17
14
|
})
|
|
18
15
|
}
|
|
19
16
|
|
|
20
|
-
|
|
17
|
+
export const setupTsCompiler = fp(setupTsCompilerPlugin)
|