@platformatic/basic 2.0.0-alpha.4 → 2.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/NOTICE +13 -0
- package/README.md +13 -0
- package/config.d.ts +1 -149
- package/index.js +78 -88
- package/lib/base.js +13 -9
- package/lib/schema.js +26 -33
- package/lib/utils.js +1 -5
- package/lib/worker/child-manager.js +21 -6
- package/lib/worker/child-process.js +66 -0
- package/package.json +6 -13
- package/schema.json +2 -512
- package/test/helper.js +43 -13
- package/lib/next.js +0 -105
- package/lib/server.js +0 -134
- package/lib/vite.js +0 -105
- package/lib/worker/next-loader.js +0 -137
- package/test/express.test.js +0 -34
- package/test/fastify.test.js +0 -34
- package/test/fixtures/express/no-build/index.js +0 -16
- package/test/fixtures/express/no-build/package.json +0 -7
- package/test/fixtures/express/no-build/platformatic.app.json +0 -3
- package/test/fixtures/express/no-build/platformatic.as-entrypoint.runtime.json +0 -19
- package/test/fixtures/express/no-build/platformatic.no-entrypoint.runtime.json +0 -16
- package/test/fixtures/express/with-build/index.js +0 -17
- package/test/fixtures/express/with-build/package.json +0 -7
- package/test/fixtures/express/with-build/platformatic.app.json +0 -3
- package/test/fixtures/express/with-build/platformatic.as-entrypoint.runtime.json +0 -19
- package/test/fixtures/express/with-build/platformatic.no-entrypoint.runtime.json +0 -16
- package/test/fixtures/fastify/no-build/index.js +0 -14
- package/test/fixtures/fastify/no-build/package.json +0 -7
- package/test/fixtures/fastify/no-build/platformatic.app.json +0 -3
- package/test/fixtures/fastify/no-build/platformatic.as-entrypoint.runtime.json +0 -19
- package/test/fixtures/fastify/no-build/platformatic.no-entrypoint.runtime.json +0 -16
- package/test/fixtures/fastify/with-build/index.js +0 -15
- package/test/fixtures/fastify/with-build/package.json +0 -7
- package/test/fixtures/fastify/with-build/platformatic.app.json +0 -3
- package/test/fixtures/fastify/with-build/platformatic.as-entrypoint.runtime.json +0 -19
- package/test/fixtures/fastify/with-build/platformatic.no-entrypoint.runtime.json +0 -16
- package/test/fixtures/next/composer-autodetect-prefix/next.config.mjs +0 -5
- package/test/fixtures/next/composer-autodetect-prefix/package.json +0 -15
- package/test/fixtures/next/composer-autodetect-prefix/platformatic.application.json +0 -8
- package/test/fixtures/next/composer-autodetect-prefix/platformatic.runtime.json +0 -21
- package/test/fixtures/next/composer-autodetect-prefix/src/app/layout.js +0 -7
- package/test/fixtures/next/composer-autodetect-prefix/src/app/page.js +0 -5
- package/test/fixtures/next/composer-with-prefix/next.config.js +0 -1
- package/test/fixtures/next/composer-with-prefix/package.json +0 -15
- package/test/fixtures/next/composer-with-prefix/platformatic.application.json +0 -11
- package/test/fixtures/next/composer-with-prefix/platformatic.runtime.json +0 -21
- package/test/fixtures/next/composer-with-prefix/src/app/layout.js +0 -7
- package/test/fixtures/next/composer-with-prefix/src/app/page.js +0 -5
- package/test/fixtures/next/composer-without-prefix/next.config.mjs +0 -3
- package/test/fixtures/next/composer-without-prefix/package.json +0 -15
- package/test/fixtures/next/composer-without-prefix/platformatic.application.json +0 -8
- package/test/fixtures/next/composer-without-prefix/platformatic.runtime.json +0 -21
- package/test/fixtures/next/composer-without-prefix/src/app/layout.js +0 -7
- package/test/fixtures/next/composer-without-prefix/src/app/page.js +0 -5
- package/test/fixtures/next/standalone/next.config.mjs +0 -3
- package/test/fixtures/next/standalone/package.json +0 -15
- package/test/fixtures/next/standalone/platformatic.runtime.json +0 -18
- package/test/fixtures/next/standalone/src/app/layout.js +0 -7
- package/test/fixtures/next/standalone/src/app/page.js +0 -5
- package/test/fixtures/nodejs/no-build/index.js +0 -21
- package/test/fixtures/nodejs/no-build/package.json +0 -7
- package/test/fixtures/nodejs/no-build/platformatic.app.json +0 -3
- package/test/fixtures/nodejs/no-build/platformatic.as-entrypoint.runtime.json +0 -19
- package/test/fixtures/nodejs/no-build/platformatic.no-entrypoint.runtime.json +0 -16
- package/test/fixtures/nodejs/no-configuration/index.js +0 -21
- package/test/fixtures/nodejs/no-configuration/platformatic.as-entrypoint.runtime.json +0 -18
- package/test/fixtures/nodejs/no-configuration/platformatic.no-entrypoint.runtime.json +0 -16
- package/test/fixtures/nodejs/with-build/index.js +0 -20
- package/test/fixtures/nodejs/with-build/package.json +0 -7
- package/test/fixtures/nodejs/with-build/platformatic.app.json +0 -3
- package/test/fixtures/nodejs/with-build/platformatic.as-entrypoint.runtime.json +0 -19
- package/test/fixtures/nodejs/with-build/platformatic.no-entrypoint.runtime.json +0 -16
- package/test/fixtures/platformatic-composer/platformatic.composer.json +0 -20
- package/test/fixtures/platformatic-composer/platformatic.no-prefix.composer.json +0 -23
- package/test/fixtures/platformatic-composer/plugin.js +0 -9
- package/test/fixtures/platformatic-service/platformatic.service.json +0 -15
- package/test/fixtures/platformatic-service/plugin.js +0 -12
- package/test/fixtures/vite/composer-autodetect-prefix/custom.vite.config.js +0 -3
- package/test/fixtures/vite/composer-autodetect-prefix/index.html +0 -13
- package/test/fixtures/vite/composer-autodetect-prefix/main.js +0 -3
- package/test/fixtures/vite/composer-autodetect-prefix/package.json +0 -14
- package/test/fixtures/vite/composer-autodetect-prefix/platformatic.application.json +0 -11
- package/test/fixtures/vite/composer-autodetect-prefix/platformatic.runtime.json +0 -21
- package/test/fixtures/vite/composer-with-prefix/index.html +0 -13
- package/test/fixtures/vite/composer-with-prefix/main.js +0 -3
- package/test/fixtures/vite/composer-with-prefix/package.json +0 -14
- package/test/fixtures/vite/composer-with-prefix/platformatic.application.json +0 -11
- package/test/fixtures/vite/composer-with-prefix/platformatic.runtime.json +0 -21
- package/test/fixtures/vite/composer-without-prefix/index.html +0 -13
- package/test/fixtures/vite/composer-without-prefix/main.js +0 -3
- package/test/fixtures/vite/composer-without-prefix/package.json +0 -14
- package/test/fixtures/vite/composer-without-prefix/platformatic.application.json +0 -8
- package/test/fixtures/vite/composer-without-prefix/platformatic.runtime.json +0 -21
- package/test/fixtures/vite/standalone/custom.vite.config.js +0 -3
- package/test/fixtures/vite/standalone/index.html +0 -13
- package/test/fixtures/vite/standalone/main.js +0 -3
- package/test/fixtures/vite/standalone/package.json +0 -14
- package/test/fixtures/vite/standalone/platformatic.runtime.json +0 -18
- package/test/next.test.js +0 -85
- package/test/node.test.js +0 -66
- package/test/vite.test.js +0 -89
package/NOTICE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright 2024 Platformatic
|
|
2
|
+
|
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
you may not use this file except in compliance with the License.
|
|
5
|
+
You may obtain a copy of the License at
|
|
6
|
+
|
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
|
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
See the License for the specific language governing permissions and
|
|
13
|
+
limitations under the License.
|
package/README.md
ADDED
package/config.d.ts
CHANGED
|
@@ -7,153 +7,5 @@
|
|
|
7
7
|
|
|
8
8
|
export interface PlatformaticStackable {
|
|
9
9
|
$schema?: string;
|
|
10
|
-
|
|
11
|
-
hostname?: string;
|
|
12
|
-
port?: number | string;
|
|
13
|
-
pluginTimeout?: number;
|
|
14
|
-
healthCheck?:
|
|
15
|
-
| boolean
|
|
16
|
-
| {
|
|
17
|
-
enabled?: boolean;
|
|
18
|
-
interval?: number;
|
|
19
|
-
[k: string]: unknown;
|
|
20
|
-
};
|
|
21
|
-
ignoreTrailingSlash?: boolean;
|
|
22
|
-
ignoreDuplicateSlashes?: boolean;
|
|
23
|
-
connectionTimeout?: number;
|
|
24
|
-
keepAliveTimeout?: number;
|
|
25
|
-
maxRequestsPerSocket?: number;
|
|
26
|
-
forceCloseConnections?: boolean | string;
|
|
27
|
-
requestTimeout?: number;
|
|
28
|
-
bodyLimit?: number;
|
|
29
|
-
maxParamLength?: number;
|
|
30
|
-
disableRequestLogging?: boolean;
|
|
31
|
-
exposeHeadRoutes?: boolean;
|
|
32
|
-
logger?:
|
|
33
|
-
| boolean
|
|
34
|
-
| {
|
|
35
|
-
level?: string;
|
|
36
|
-
transport?:
|
|
37
|
-
| {
|
|
38
|
-
target?: string;
|
|
39
|
-
options?: {
|
|
40
|
-
[k: string]: unknown;
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
| {
|
|
44
|
-
targets?: {
|
|
45
|
-
target?: string;
|
|
46
|
-
options?: {
|
|
47
|
-
[k: string]: unknown;
|
|
48
|
-
};
|
|
49
|
-
level?: string;
|
|
50
|
-
additionalProperties?: never;
|
|
51
|
-
[k: string]: unknown;
|
|
52
|
-
}[];
|
|
53
|
-
options?: {
|
|
54
|
-
[k: string]: unknown;
|
|
55
|
-
};
|
|
56
|
-
};
|
|
57
|
-
pipeline?: {
|
|
58
|
-
target?: string;
|
|
59
|
-
options?: {
|
|
60
|
-
[k: string]: unknown;
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
[k: string]: unknown;
|
|
64
|
-
};
|
|
65
|
-
serializerOpts?: {
|
|
66
|
-
schema?: {
|
|
67
|
-
[k: string]: unknown;
|
|
68
|
-
};
|
|
69
|
-
ajv?: {
|
|
70
|
-
[k: string]: unknown;
|
|
71
|
-
};
|
|
72
|
-
rounding?: "floor" | "ceil" | "round" | "trunc";
|
|
73
|
-
debugMode?: boolean;
|
|
74
|
-
mode?: "debug" | "standalone";
|
|
75
|
-
largeArraySize?: number | string;
|
|
76
|
-
largeArrayMechanism?: "default" | "json-stringify";
|
|
77
|
-
[k: string]: unknown;
|
|
78
|
-
};
|
|
79
|
-
caseSensitive?: boolean;
|
|
80
|
-
requestIdHeader?: string | false;
|
|
81
|
-
requestIdLogLabel?: string;
|
|
82
|
-
jsonShorthand?: boolean;
|
|
83
|
-
trustProxy?: boolean | string | string[] | number;
|
|
84
|
-
http2?: boolean;
|
|
85
|
-
https?: {
|
|
86
|
-
allowHTTP1?: boolean;
|
|
87
|
-
key:
|
|
88
|
-
| string
|
|
89
|
-
| {
|
|
90
|
-
path?: string;
|
|
91
|
-
}
|
|
92
|
-
| (
|
|
93
|
-
| string
|
|
94
|
-
| {
|
|
95
|
-
path?: string;
|
|
96
|
-
}
|
|
97
|
-
)[];
|
|
98
|
-
cert:
|
|
99
|
-
| string
|
|
100
|
-
| {
|
|
101
|
-
path?: string;
|
|
102
|
-
}
|
|
103
|
-
| (
|
|
104
|
-
| string
|
|
105
|
-
| {
|
|
106
|
-
path?: string;
|
|
107
|
-
}
|
|
108
|
-
)[];
|
|
109
|
-
requestCert?: boolean;
|
|
110
|
-
rejectUnauthorized?: boolean;
|
|
111
|
-
};
|
|
112
|
-
cors?: {
|
|
113
|
-
origin?:
|
|
114
|
-
| boolean
|
|
115
|
-
| string
|
|
116
|
-
| (
|
|
117
|
-
| string
|
|
118
|
-
| {
|
|
119
|
-
regexp: string;
|
|
120
|
-
[k: string]: unknown;
|
|
121
|
-
}
|
|
122
|
-
)[]
|
|
123
|
-
| {
|
|
124
|
-
regexp: string;
|
|
125
|
-
[k: string]: unknown;
|
|
126
|
-
};
|
|
127
|
-
methods?: string[];
|
|
128
|
-
/**
|
|
129
|
-
* Comma separated string of allowed headers.
|
|
130
|
-
*/
|
|
131
|
-
allowedHeaders?: string;
|
|
132
|
-
exposedHeaders?: string[] | string;
|
|
133
|
-
credentials?: boolean;
|
|
134
|
-
maxAge?: number;
|
|
135
|
-
preflightContinue?: boolean;
|
|
136
|
-
optionsSuccessStatus?: number;
|
|
137
|
-
preflight?: boolean;
|
|
138
|
-
strictPreflight?: boolean;
|
|
139
|
-
hideOptionsRoute?: boolean;
|
|
140
|
-
};
|
|
141
|
-
};
|
|
142
|
-
watch?:
|
|
143
|
-
| {
|
|
144
|
-
enabled?: boolean | string;
|
|
145
|
-
/**
|
|
146
|
-
* @minItems 1
|
|
147
|
-
*/
|
|
148
|
-
allow?: [string, ...string[]];
|
|
149
|
-
ignore?: string[];
|
|
150
|
-
}
|
|
151
|
-
| boolean
|
|
152
|
-
| string;
|
|
153
|
-
application?: {
|
|
154
|
-
base?: string;
|
|
155
|
-
};
|
|
156
|
-
vite?: {
|
|
157
|
-
configFile?: string | boolean;
|
|
158
|
-
};
|
|
10
|
+
[k: string]: unknown;
|
|
159
11
|
}
|
package/index.js
CHANGED
|
@@ -1,118 +1,108 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
1
|
import { existsSync } from 'node:fs'
|
|
4
2
|
import { readFile } from 'node:fs/promises'
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
import { NextStackable } from './lib/next.js'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { relative, resolve } from 'node:path'
|
|
5
|
+
import { workerData } from 'node:worker_threads'
|
|
6
|
+
import pino from 'pino'
|
|
10
7
|
import { packageJson, schema } from './lib/schema.js'
|
|
11
|
-
import {
|
|
12
|
-
import { ViteStackable } from './lib/vite.js'
|
|
13
|
-
|
|
14
|
-
const validFields = [
|
|
15
|
-
'main',
|
|
16
|
-
'exports',
|
|
17
|
-
'exports',
|
|
18
|
-
'exports#node',
|
|
19
|
-
'exports#import',
|
|
20
|
-
'exports#require',
|
|
21
|
-
'exports#default',
|
|
22
|
-
'exports#.#node',
|
|
23
|
-
'exports#.#import',
|
|
24
|
-
'exports#.#require',
|
|
25
|
-
'exports#.#default',
|
|
26
|
-
]
|
|
27
|
-
|
|
28
|
-
const validFilesBasenames = ['index', 'main', 'app', 'application', 'server', 'start', 'bundle', 'run', 'entrypoint']
|
|
29
|
-
|
|
30
|
-
async function parsePackageJson (root) {
|
|
31
|
-
let entrypoint
|
|
32
|
-
let packageJson
|
|
33
|
-
let hadEntrypointField = false
|
|
8
|
+
import { importFile } from './lib/utils.js'
|
|
34
9
|
|
|
10
|
+
async function importStackablePackage (opts, pkg, autodetectDescription) {
|
|
35
11
|
try {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
12
|
+
try {
|
|
13
|
+
// Try regular import
|
|
14
|
+
return await import(pkg)
|
|
15
|
+
} catch (e) {
|
|
16
|
+
// Scope to the service
|
|
17
|
+
const require = createRequire(resolve(opts.context.directory, 'index.js'))
|
|
18
|
+
const imported = require.resolve(pkg)
|
|
19
|
+
return await importFile(imported)
|
|
20
|
+
}
|
|
21
|
+
} catch (e) {
|
|
22
|
+
const rootFolder = relative(process.cwd(), workerData.dirname)
|
|
41
23
|
|
|
42
|
-
|
|
43
|
-
let current = packageJson
|
|
44
|
-
const sequence = field.split('#')
|
|
24
|
+
let errorMessage = `Unable to import package, "${pkg}". Please add it as a dependency `
|
|
45
25
|
|
|
46
|
-
|
|
47
|
-
|
|
26
|
+
if (rootFolder) {
|
|
27
|
+
errorMessage += `in the package.json file in the folder ${rootFolder}.`
|
|
28
|
+
} else {
|
|
29
|
+
errorMessage += 'in the root package.json file.'
|
|
48
30
|
}
|
|
49
31
|
|
|
50
|
-
|
|
51
|
-
entrypoint = current
|
|
52
|
-
hadEntrypointField = true
|
|
53
|
-
break
|
|
54
|
-
}
|
|
32
|
+
throw new Error(errorMessage)
|
|
55
33
|
}
|
|
34
|
+
}
|
|
56
35
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (existsSync(resolve(root, file))) {
|
|
63
|
-
entrypoint = file
|
|
64
|
-
break
|
|
65
|
-
}
|
|
66
|
-
}
|
|
36
|
+
async function buildStackable (opts) {
|
|
37
|
+
const root = opts.context.directory
|
|
38
|
+
let toImport = '@platformatic/node'
|
|
39
|
+
let autodetectDescription = 'is using a generic Node.js application'
|
|
67
40
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
41
|
+
let rootPackageJson
|
|
42
|
+
try {
|
|
43
|
+
rootPackageJson = JSON.parse(await readFile(resolve(root, 'package.json'), 'utf-8'))
|
|
44
|
+
} catch {
|
|
45
|
+
rootPackageJson = {}
|
|
72
46
|
}
|
|
73
47
|
|
|
74
|
-
|
|
75
|
-
}
|
|
48
|
+
const hadConfig = opts.config
|
|
76
49
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
this.current.watch = { enabled: false }
|
|
80
|
-
}
|
|
50
|
+
if (!hadConfig) {
|
|
51
|
+
const candidate = resolve(root, 'platformatic.application.json')
|
|
81
52
|
|
|
82
|
-
|
|
83
|
-
|
|
53
|
+
if (existsSync(candidate)) {
|
|
54
|
+
opts.config = candidate
|
|
55
|
+
}
|
|
84
56
|
}
|
|
85
|
-
}
|
|
86
57
|
|
|
87
|
-
|
|
88
|
-
const root = opts.context.directory
|
|
89
|
-
const {
|
|
90
|
-
entrypoint,
|
|
91
|
-
hadEntrypointField,
|
|
92
|
-
packageJson: { dependencies, devDependencies },
|
|
93
|
-
} = await parsePackageJson(root)
|
|
94
|
-
|
|
95
|
-
const configManager = new ConfigManager({ schema, source: opts.config ?? {} })
|
|
96
|
-
await configManager.parseAndValidate()
|
|
58
|
+
const { dependencies, devDependencies } = rootPackageJson
|
|
97
59
|
|
|
98
|
-
let stackable
|
|
99
60
|
if (dependencies?.next || devDependencies?.next) {
|
|
100
|
-
|
|
61
|
+
autodetectDescription = 'is using Next.js'
|
|
62
|
+
toImport = '@platformatic/next'
|
|
63
|
+
} else if (dependencies?.['@remix-run/dev'] || devDependencies?.['@remix-run/dev']) {
|
|
64
|
+
autodetectDescription = 'is using Remix'
|
|
65
|
+
toImport = '@platformatic/remix'
|
|
101
66
|
} else if (dependencies?.vite || devDependencies?.vite) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
67
|
+
autodetectDescription = 'is using Vite'
|
|
68
|
+
toImport = '@platformatic/vite'
|
|
69
|
+
} else if (dependencies?.astro || devDependencies?.astro) {
|
|
70
|
+
autodetectDescription = 'is using Astro'
|
|
71
|
+
toImport = '@platformatic/astro'
|
|
105
72
|
}
|
|
106
73
|
|
|
107
|
-
|
|
74
|
+
const imported = await importStackablePackage(opts, toImport, autodetectDescription)
|
|
75
|
+
|
|
76
|
+
if (!hadConfig) {
|
|
77
|
+
const serviceRoot = relative(process.cwd(), opts.context.directory)
|
|
78
|
+
const logger = pino({
|
|
79
|
+
level: opts.context.serverConfig?.logger?.level ?? 'warn',
|
|
80
|
+
name: opts.context.serviceId
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
logger.warn(
|
|
84
|
+
[
|
|
85
|
+
`Platformatic has auto-detected that service ${opts.context.serviceId} ${autodetectDescription}.\n`,
|
|
86
|
+
`We suggest you create a platformatic.application.json file in the folder ${serviceRoot} with the "$schema" `,
|
|
87
|
+
`property set to "https://schemas.platformatic.dev/${toImport}/${packageJson.version}.json".`
|
|
88
|
+
].join('')
|
|
89
|
+
)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return imported.buildStackable(opts)
|
|
108
93
|
}
|
|
109
94
|
|
|
110
95
|
export default {
|
|
111
96
|
configType: 'nodejs',
|
|
112
|
-
configManagerConfig: {
|
|
113
|
-
transformConfig,
|
|
114
|
-
},
|
|
97
|
+
configManagerConfig: {},
|
|
115
98
|
buildStackable,
|
|
116
99
|
schema,
|
|
117
|
-
version: packageJson.version
|
|
100
|
+
version: packageJson.version
|
|
118
101
|
}
|
|
102
|
+
|
|
103
|
+
export * from './lib/base.js'
|
|
104
|
+
export * as errors from './lib/errors.js'
|
|
105
|
+
export { schema, schemaComponents } from './lib/schema.js'
|
|
106
|
+
export * from './lib/utils.js'
|
|
107
|
+
export * from './lib/worker/child-manager.js'
|
|
108
|
+
export * from './lib/worker/server-listener.js'
|
package/lib/base.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import pino from 'pino'
|
|
2
|
-
import { packageJson } from './schema.js'
|
|
3
2
|
|
|
4
3
|
export class BaseStackable {
|
|
5
|
-
constructor (options, root, configManager) {
|
|
6
|
-
this.type =
|
|
4
|
+
constructor (type, version, options, root, configManager) {
|
|
5
|
+
this.type = type
|
|
6
|
+
this.version = version
|
|
7
7
|
this.id = options.context.serviceId
|
|
8
8
|
this.root = root
|
|
9
9
|
this.configManager = configManager
|
|
@@ -13,7 +13,7 @@ export class BaseStackable {
|
|
|
13
13
|
|
|
14
14
|
// Setup the logger
|
|
15
15
|
const pinoOptions = {
|
|
16
|
-
level: (this.configManager.current.server ?? this.serverConfig)?.logger?.level ?? 'trace'
|
|
16
|
+
level: (this.configManager.current.server ?? this.serverConfig)?.logger?.level ?? 'trace'
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
if (this.id) {
|
|
@@ -22,10 +22,10 @@ export class BaseStackable {
|
|
|
22
22
|
this.logger = pino(pinoOptions)
|
|
23
23
|
|
|
24
24
|
// Setup globals
|
|
25
|
-
|
|
25
|
+
this.registerGlobals({
|
|
26
26
|
setOpenapiSchema: this.setOpenapiSchema.bind(this),
|
|
27
|
-
setGraphqlSchema: this.setGraphqlSchema.bind(this)
|
|
28
|
-
}
|
|
27
|
+
setGraphqlSchema: this.setGraphqlSchema.bind(this)
|
|
28
|
+
})
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
getUrl () {
|
|
@@ -45,12 +45,12 @@ export class BaseStackable {
|
|
|
45
45
|
enabled,
|
|
46
46
|
path: this.root,
|
|
47
47
|
allow: config.watch?.allow,
|
|
48
|
-
ignore: config.watch?.ignore
|
|
48
|
+
ignore: config.watch?.ignore
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
async getInfo () {
|
|
53
|
-
return { type: this.type, version:
|
|
53
|
+
return { type: this.type, version: this.version }
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
getDispatchFunc () {
|
|
@@ -81,4 +81,8 @@ export class BaseStackable {
|
|
|
81
81
|
const logLevel = level ?? 'info'
|
|
82
82
|
this.logger[logLevel](message)
|
|
83
83
|
}
|
|
84
|
+
|
|
85
|
+
registerGlobals (globals) {
|
|
86
|
+
globalThis.platformatic = Object.assign(globalThis.platformatic ?? {}, globals)
|
|
87
|
+
}
|
|
84
88
|
}
|
package/lib/schema.js
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
import { schemas } from '@platformatic/utils'
|
|
2
2
|
import { readFileSync } from 'node:fs'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
3
|
|
|
5
|
-
export const packageJson = JSON.parse(readFileSync(
|
|
4
|
+
export const packageJson = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'))
|
|
5
|
+
|
|
6
|
+
const application = {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
basePath: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const watch = {
|
|
17
|
+
anyOf: [
|
|
18
|
+
schemas.watch,
|
|
19
|
+
{
|
|
20
|
+
type: 'boolean',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
type: 'string',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const schemaComponents = { application, watch }
|
|
6
29
|
|
|
7
30
|
export const schema = {
|
|
8
31
|
$id: `https://schemas.platformatic.dev/@platformatic/basic/${packageJson.version}.json`,
|
|
@@ -13,38 +36,8 @@ export const schema = {
|
|
|
13
36
|
$schema: {
|
|
14
37
|
type: 'string',
|
|
15
38
|
},
|
|
16
|
-
server: schemas.server,
|
|
17
|
-
watch: {
|
|
18
|
-
anyOf: [
|
|
19
|
-
schemas.watch,
|
|
20
|
-
{
|
|
21
|
-
type: 'boolean',
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
type: 'string',
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
},
|
|
28
|
-
application: {
|
|
29
|
-
type: 'object',
|
|
30
|
-
properties: {
|
|
31
|
-
base: {
|
|
32
|
-
type: 'string',
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
additionalProperties: false,
|
|
36
|
-
},
|
|
37
|
-
vite: {
|
|
38
|
-
type: 'object',
|
|
39
|
-
properties: {
|
|
40
|
-
configFile: {
|
|
41
|
-
oneOf: [{ type: 'string' }, { type: 'boolean' }],
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
additionalProperties: false,
|
|
45
|
-
},
|
|
46
39
|
},
|
|
47
|
-
additionalProperties:
|
|
40
|
+
additionalProperties: true,
|
|
48
41
|
}
|
|
49
42
|
|
|
50
43
|
/* c8 ignore next 3 */
|
package/lib/utils.js
CHANGED
|
@@ -7,11 +7,6 @@ export function getServerUrl (server) {
|
|
|
7
7
|
return new URL(family === 'IPv6' ? `http://[${address}]:${port}` : `http://${address}:${port}`).origin
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
// Paolo: This is kinda hackish but there is no better way. I apologize.
|
|
11
|
-
export function isFastify (app) {
|
|
12
|
-
return Object.getOwnPropertySymbols(app).some(s => s.description === 'fastify.state')
|
|
13
|
-
}
|
|
14
|
-
|
|
15
10
|
export async function injectViaRequest (baseUrl, injectParams, onInject) {
|
|
16
11
|
const url = new URL(injectParams.url, baseUrl).href
|
|
17
12
|
const requestParams = { method: injectParams.method, headers: injectParams.headers }
|
|
@@ -43,6 +38,7 @@ export async function injectViaRequest (baseUrl, injectParams, onInject) {
|
|
|
43
38
|
}
|
|
44
39
|
}
|
|
45
40
|
|
|
41
|
+
// This is to avoid common path/URL problems on Windows
|
|
46
42
|
export function importFile (path) {
|
|
47
43
|
return import(pathToFileURL(path))
|
|
48
44
|
}
|
|
@@ -2,6 +2,7 @@ import { ITC } from '@platformatic/itc'
|
|
|
2
2
|
import { subscribe, unsubscribe } from 'node:diagnostics_channel'
|
|
3
3
|
import { once } from 'node:events'
|
|
4
4
|
import { workerData } from 'node:worker_threads'
|
|
5
|
+
import { request } from 'undici'
|
|
5
6
|
|
|
6
7
|
export const childProcessWorkerFile = new URL('./child-process.js', import.meta.url)
|
|
7
8
|
|
|
@@ -12,7 +13,16 @@ export class ChildManager extends ITC {
|
|
|
12
13
|
#originalNodeOptions
|
|
13
14
|
|
|
14
15
|
constructor ({ loader, context }) {
|
|
15
|
-
super({
|
|
16
|
+
super({
|
|
17
|
+
handlers: {
|
|
18
|
+
log (message) {
|
|
19
|
+
workerData.loggingPort.postMessage(JSON.parse(message))
|
|
20
|
+
},
|
|
21
|
+
fetch: request => {
|
|
22
|
+
return this.#fetch(request)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
})
|
|
16
26
|
|
|
17
27
|
const childHandler = ({ process: child }) => {
|
|
18
28
|
unsubscribe('child_process', childHandler)
|
|
@@ -27,10 +37,6 @@ export class ChildManager extends ITC {
|
|
|
27
37
|
|
|
28
38
|
subscribe('child_process', childHandler)
|
|
29
39
|
|
|
30
|
-
this.handle('log', message => {
|
|
31
|
-
workerData.loggingPort.postMessage(JSON.parse(message))
|
|
32
|
-
})
|
|
33
|
-
|
|
34
40
|
this.#prepareChildEnvironment(loader, context)
|
|
35
41
|
}
|
|
36
42
|
|
|
@@ -72,7 +78,16 @@ export class ChildManager extends ITC {
|
|
|
72
78
|
this.#injectedNodeOptions = [
|
|
73
79
|
`--import="data:text/javascript,${loaderScript.replaceAll(/\n/g, '')}"`,
|
|
74
80
|
`--import=${childProcessWorkerFile}`,
|
|
75
|
-
process.env.NODE_OPTIONS ?? ''
|
|
81
|
+
process.env.NODE_OPTIONS ?? ''
|
|
76
82
|
].join(' ')
|
|
77
83
|
}
|
|
84
|
+
|
|
85
|
+
async #fetch (opts) {
|
|
86
|
+
const { statusCode, headers, body } = await request(opts)
|
|
87
|
+
|
|
88
|
+
const rawPayload = Buffer.from(await body.arrayBuffer())
|
|
89
|
+
const payload = rawPayload.toString()
|
|
90
|
+
|
|
91
|
+
return { statusCode, headers, body: payload, payload, rawPayload }
|
|
92
|
+
}
|
|
78
93
|
}
|
|
@@ -2,6 +2,67 @@ import { ITC } from '@platformatic/itc'
|
|
|
2
2
|
import { createPinoWritable, DestinationWritable, withResolvers } from '@platformatic/utils'
|
|
3
3
|
import { tracingChannel } from 'node:diagnostics_channel'
|
|
4
4
|
import pino from 'pino'
|
|
5
|
+
import { getGlobalDispatcher, setGlobalDispatcher } from 'undici'
|
|
6
|
+
|
|
7
|
+
function createInterceptor (itc) {
|
|
8
|
+
return function (dispatch) {
|
|
9
|
+
return async (opts, handler) => {
|
|
10
|
+
let url = opts.origin
|
|
11
|
+
if (!(url instanceof URL)) {
|
|
12
|
+
url = new URL(opts.path, url)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// Other URLs are handled normally
|
|
16
|
+
if (!url.hostname.endsWith('.plt.local')) {
|
|
17
|
+
return dispatch(opts, handler)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const headers = {
|
|
21
|
+
...opts?.headers,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
delete headers.connection
|
|
25
|
+
delete headers['transfer-encoding']
|
|
26
|
+
headers.host = url.host
|
|
27
|
+
|
|
28
|
+
const requestOpts = {
|
|
29
|
+
...opts,
|
|
30
|
+
headers,
|
|
31
|
+
}
|
|
32
|
+
delete requestOpts.dispatcher
|
|
33
|
+
|
|
34
|
+
itc
|
|
35
|
+
.send('fetch', requestOpts)
|
|
36
|
+
.then(res => {
|
|
37
|
+
if (res.rawPayload && !Buffer.isBuffer(res.rawPayload)) {
|
|
38
|
+
res.rawPayload = Buffer.from(res.rawPayload.data)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const headers = []
|
|
42
|
+
for (const [key, value] of Object.entries(res.headers)) {
|
|
43
|
+
if (Array.isArray(value)) {
|
|
44
|
+
for (const v of value) {
|
|
45
|
+
headers.push(key)
|
|
46
|
+
headers.push(v)
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
headers.push(key)
|
|
50
|
+
headers.push(value)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
handler.onHeaders(res.statusCode, headers, () => {}, res.statusMessage)
|
|
55
|
+
handler.onData(res.rawPayload)
|
|
56
|
+
handler.onComplete([])
|
|
57
|
+
})
|
|
58
|
+
.catch(e => {
|
|
59
|
+
handler.onError(new Error(e.message))
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
return true
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
5
66
|
|
|
6
67
|
class ChildProcessWritable extends DestinationWritable {
|
|
7
68
|
#itc
|
|
@@ -29,6 +90,7 @@ class ChildProcess extends ITC {
|
|
|
29
90
|
this.listen()
|
|
30
91
|
this.#setupLogger()
|
|
31
92
|
this.#setupServer()
|
|
93
|
+
this.#setupInterceptors()
|
|
32
94
|
}
|
|
33
95
|
|
|
34
96
|
_setupListener (listener) {
|
|
@@ -79,6 +141,10 @@ class ChildProcess extends ITC {
|
|
|
79
141
|
|
|
80
142
|
tracingChannel('net.server.listen').subscribe(subscribers)
|
|
81
143
|
}
|
|
144
|
+
|
|
145
|
+
#setupInterceptors () {
|
|
146
|
+
setGlobalDispatcher(getGlobalDispatcher().compose(createInterceptor(this)))
|
|
147
|
+
}
|
|
82
148
|
}
|
|
83
149
|
|
|
84
150
|
globalThis[Symbol.for('plt.children.itc')] = new ChildProcess()
|