@platformatic/remix 3.4.1 → 3.5.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 +339 -3
- package/index.js +24 -241
- package/lib/capability.js +226 -0
- package/lib/schema.js +7 -4
- package/package.json +24 -21
- package/schema.json +1358 -7
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cleanBasePath,
|
|
3
|
+
ensureTrailingSlash,
|
|
4
|
+
errors,
|
|
5
|
+
getServerUrl,
|
|
6
|
+
importFile,
|
|
7
|
+
resolvePackage
|
|
8
|
+
} from '@platformatic/basic'
|
|
9
|
+
import { features } from '@platformatic/foundation'
|
|
10
|
+
import { ViteCapability } from '@platformatic/vite'
|
|
11
|
+
import { createRequestHandler } from '@remix-run/express'
|
|
12
|
+
import express from 'express'
|
|
13
|
+
import inject from 'light-my-request'
|
|
14
|
+
import { existsSync } from 'node:fs'
|
|
15
|
+
import { readFile } from 'node:fs/promises'
|
|
16
|
+
import { dirname, resolve } from 'node:path'
|
|
17
|
+
import { pinoHttp } from 'pino-http'
|
|
18
|
+
import { satisfies } from 'semver'
|
|
19
|
+
import { packageJson } from './schema.js'
|
|
20
|
+
|
|
21
|
+
const supportedVersions = '^2.0.0'
|
|
22
|
+
|
|
23
|
+
export class RemixCapability extends ViteCapability {
|
|
24
|
+
#app
|
|
25
|
+
#server
|
|
26
|
+
#remix
|
|
27
|
+
#basePath
|
|
28
|
+
|
|
29
|
+
constructor (root, config, context) {
|
|
30
|
+
super(root, config, context)
|
|
31
|
+
this.type = 'remix'
|
|
32
|
+
this.version = packageJson.version
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async init () {
|
|
36
|
+
await super.init()
|
|
37
|
+
|
|
38
|
+
if (!this.isProduction) {
|
|
39
|
+
this.#remix = resolve(dirname(resolvePackage(this.root, '@remix-run/dev')), '..')
|
|
40
|
+
const remixPackage = JSON.parse(await readFile(resolve(this.#remix, 'package.json'), 'utf-8'))
|
|
41
|
+
|
|
42
|
+
if (!satisfies(remixPackage.version, supportedVersions)) {
|
|
43
|
+
throw new errors.UnsupportedVersion('@remix-run/dev', remixPackage.version, supportedVersions)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const config = this.config
|
|
48
|
+
this.#basePath = config.application?.basePath
|
|
49
|
+
? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
|
|
50
|
+
: undefined
|
|
51
|
+
|
|
52
|
+
this.registerGlobals({ basePath: this.#basePath })
|
|
53
|
+
|
|
54
|
+
this.subprocessTerminationSignal = 'SIGKILL'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async start ({ listen }) {
|
|
58
|
+
// Make this idempotent
|
|
59
|
+
if (this.url) {
|
|
60
|
+
return this.url
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const config = this.config
|
|
64
|
+
const command = config.application.commands[this.isProduction ? 'production' : 'development']
|
|
65
|
+
|
|
66
|
+
if (command) {
|
|
67
|
+
return this.startWithCommand(command)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return this.isProduction ? this.#startProduction(listen) : this.#startDevelopment(listen)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async stop () {
|
|
74
|
+
await super.stop()
|
|
75
|
+
|
|
76
|
+
if (this.childManager) {
|
|
77
|
+
return this.stopCommand()
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (this.isProduction) {
|
|
81
|
+
return this.#stopProduction()
|
|
82
|
+
} else if (this.#app) {
|
|
83
|
+
return this.#app.close()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async build () {
|
|
88
|
+
const config = this.config
|
|
89
|
+
const command = config.application.commands.build
|
|
90
|
+
const basePath = config.application?.basePath
|
|
91
|
+
? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
|
|
92
|
+
: undefined
|
|
93
|
+
|
|
94
|
+
if (command) {
|
|
95
|
+
return this.buildWithCommand(command, basePath)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
await this.init()
|
|
99
|
+
const { viteBuild } = await importFile(resolve(this.#remix, 'dist/cli/commands.js'))
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
globalThis.platformatic.isBuilding = true
|
|
103
|
+
|
|
104
|
+
await viteBuild(this.root, {
|
|
105
|
+
emptyOutDir: true,
|
|
106
|
+
logLevel: this.logger.level,
|
|
107
|
+
mode: 'production',
|
|
108
|
+
profile: false
|
|
109
|
+
})
|
|
110
|
+
} finally {
|
|
111
|
+
globalThis.platformatic.isBuilding = false
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async inject (injectParams, onInject) {
|
|
116
|
+
if (!this.isProduction) {
|
|
117
|
+
return super.inject(injectParams, onInject)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const res = await inject(this.#app, injectParams, onInject)
|
|
121
|
+
|
|
122
|
+
/* c8 ignore next 3 */
|
|
123
|
+
if (onInject) {
|
|
124
|
+
return
|
|
125
|
+
} // Since inject might be called from the main thread directly via ITC, let's clean it up
|
|
126
|
+
|
|
127
|
+
const { statusCode, headers, body, payload, rawPayload } = res
|
|
128
|
+
return { statusCode, headers, body, payload, rawPayload }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
getMeta () {
|
|
132
|
+
if (!this.isProduction) {
|
|
133
|
+
return super.getMeta()
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
gateway: {
|
|
138
|
+
tcp: typeof this.url !== 'undefined',
|
|
139
|
+
url: this.url,
|
|
140
|
+
prefix: this.basePath ?? this.#basePath,
|
|
141
|
+
wantsAbsoluteUrls: true,
|
|
142
|
+
needsRootTrailingSlash: true
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async #startDevelopment (listen) {
|
|
148
|
+
const preloadViteEsmPath = resolve(this.#remix, './dist/vite/import-vite-esm-sync.js')
|
|
149
|
+
|
|
150
|
+
// Older versions
|
|
151
|
+
if (existsSync(preloadViteEsmPath)) {
|
|
152
|
+
const { preloadViteEsm } = await importFile(resolve(this.#remix, './dist/vite/import-vite-esm-sync.js'))
|
|
153
|
+
await preloadViteEsm()
|
|
154
|
+
} else {
|
|
155
|
+
const { preloadVite } = await importFile(resolve(this.#remix, './dist/vite/vite.js'))
|
|
156
|
+
await preloadVite()
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await super.start({ listen })
|
|
160
|
+
|
|
161
|
+
/* c8 ignore next 3 */
|
|
162
|
+
if (!this._getVite().config.plugins.some(p => p.name === 'remix')) {
|
|
163
|
+
this.logger.warn('Could not find Remix plugin in your Vite configuration. Continuing as plain Vite application.')
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
await this._collectMetrics()
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async #startProduction (listen) {
|
|
170
|
+
// Listen if entrypoint
|
|
171
|
+
if (this.#app && listen) {
|
|
172
|
+
const serverOptions = this.serverConfig
|
|
173
|
+
const listenOptions = { host: serverOptions?.hostname || '127.0.0.1', port: serverOptions?.port || 0 }
|
|
174
|
+
|
|
175
|
+
if (this.isProduction && features.node.reusePort) {
|
|
176
|
+
listenOptions.reusePort = true
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.#server = await new Promise((resolve, reject) => {
|
|
180
|
+
return this.#app
|
|
181
|
+
.listen(listenOptions, function () {
|
|
182
|
+
resolve(this)
|
|
183
|
+
})
|
|
184
|
+
.on('error', reject)
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
this.url = getServerUrl(this.#server)
|
|
188
|
+
|
|
189
|
+
return this.url
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const outputDirectory = this.config.remix.outputDirectory
|
|
193
|
+
this.verifyOutputDirectory(resolve(this.root, outputDirectory))
|
|
194
|
+
|
|
195
|
+
const build = await importFile(resolve(this.root, `${outputDirectory}/server/index.js`))
|
|
196
|
+
this.#basePath = ensureTrailingSlash(cleanBasePath(build.basename))
|
|
197
|
+
|
|
198
|
+
// Setup express app
|
|
199
|
+
this.#app = express()
|
|
200
|
+
this.#app.disable('x-powered-by')
|
|
201
|
+
this.#app.use(pinoHttp({ logger: this.logger }))
|
|
202
|
+
this.#app.use(this.#basePath, express.static(resolve(this.root, `${outputDirectory}/client`)))
|
|
203
|
+
this.#app.all(`${ensureTrailingSlash(cleanBasePath(this.#basePath))}*`, createRequestHandler({ build }))
|
|
204
|
+
|
|
205
|
+
await this._collectMetrics()
|
|
206
|
+
return this.url
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async #stopProduction () {
|
|
210
|
+
/* c8 ignore next 3 */
|
|
211
|
+
if (!this.#server?.listening) {
|
|
212
|
+
return
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
return new Promise((resolve, reject) => {
|
|
216
|
+
this.#server.close(error => {
|
|
217
|
+
/* c8 ignore next 3 */
|
|
218
|
+
if (error) {
|
|
219
|
+
return reject(error)
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
resolve()
|
|
223
|
+
})
|
|
224
|
+
})
|
|
225
|
+
}
|
|
226
|
+
}
|
package/lib/schema.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { schemaComponents as basicSchemaComponents } from '@platformatic/basic'
|
|
2
|
-
import { schemaComponents as utilsSchemaComponents } from '@platformatic/
|
|
2
|
+
import { schemaComponents as utilsSchemaComponents } from '@platformatic/foundation'
|
|
3
3
|
import { schemaComponents as viteSchemaComponents } from '@platformatic/vite'
|
|
4
4
|
import { readFileSync } from 'node:fs'
|
|
5
|
+
import { resolve } from 'node:path'
|
|
5
6
|
|
|
6
|
-
export const packageJson = JSON.parse(readFileSync(
|
|
7
|
+
export const packageJson = JSON.parse(readFileSync(resolve(import.meta.dirname, '../package.json'), 'utf8'))
|
|
8
|
+
export const version = packageJson.version
|
|
7
9
|
|
|
8
10
|
export const remix = {
|
|
9
11
|
type: 'object',
|
|
@@ -22,7 +24,7 @@ export const schemaComponents = { remix }
|
|
|
22
24
|
export const schema = {
|
|
23
25
|
$id: `https://schemas.platformatic.dev/@platformatic/remix/${packageJson.version}.json`,
|
|
24
26
|
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
25
|
-
title: 'Platformatic Remix
|
|
27
|
+
title: 'Platformatic Remix Config',
|
|
26
28
|
type: 'object',
|
|
27
29
|
properties: {
|
|
28
30
|
$schema: {
|
|
@@ -31,7 +33,8 @@ export const schema = {
|
|
|
31
33
|
logger: utilsSchemaComponents.logger,
|
|
32
34
|
server: utilsSchemaComponents.server,
|
|
33
35
|
watch: basicSchemaComponents.watch,
|
|
34
|
-
application: basicSchemaComponents.
|
|
36
|
+
application: basicSchemaComponents.buildableApplication,
|
|
37
|
+
runtime: utilsSchemaComponents.wrappedRuntime,
|
|
35
38
|
vite: viteSchemaComponents.vite,
|
|
36
39
|
remix
|
|
37
40
|
},
|
package/package.json
CHANGED
|
@@ -1,54 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/remix",
|
|
3
|
-
"version": "3.
|
|
4
|
-
"description": "Platformatic Remix
|
|
3
|
+
"version": "3.5.1",
|
|
4
|
+
"description": "Platformatic Remix Capability",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/platformatic/platformatic.git"
|
|
10
10
|
},
|
|
11
|
-
"author": "
|
|
11
|
+
"author": "Platformatic Inc. <oss@platformatic.dev> (https://platformatic.dev)",
|
|
12
12
|
"license": "Apache-2.0",
|
|
13
13
|
"bugs": {
|
|
14
14
|
"url": "https://github.com/platformatic/platformatic/issues"
|
|
15
15
|
},
|
|
16
16
|
"homepage": "https://github.com/platformatic/platformatic#readme",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@remix-run/express": "^2.
|
|
19
|
-
"light-my-request": "^6.0.0",
|
|
18
|
+
"@remix-run/express": "^2.16.8",
|
|
20
19
|
"express": "^4.19.2",
|
|
20
|
+
"light-my-request": "^6.0.0",
|
|
21
21
|
"pino-http": "^10.2.0",
|
|
22
22
|
"semver": "^7.6.3",
|
|
23
|
-
"@platformatic/basic": "3.
|
|
24
|
-
"@platformatic/
|
|
25
|
-
"@platformatic/
|
|
26
|
-
"@platformatic/utils": "3.4.1"
|
|
23
|
+
"@platformatic/basic": "3.5.1",
|
|
24
|
+
"@platformatic/foundation": "3.5.1",
|
|
25
|
+
"@platformatic/vite": "3.5.1"
|
|
27
26
|
},
|
|
28
27
|
"devDependencies": {
|
|
29
|
-
"@remix-run/dev": "^2.
|
|
30
|
-
"@remix-run/node": "^2.
|
|
31
|
-
"@remix-run/react": "^2.
|
|
32
|
-
"
|
|
28
|
+
"@remix-run/dev": "^2.16.8",
|
|
29
|
+
"@remix-run/node": "^2.16.8",
|
|
30
|
+
"@remix-run/react": "^2.16.8",
|
|
31
|
+
"@types/react": "^19.1.11",
|
|
32
|
+
"@types/react-dom": "^19.1.7",
|
|
33
|
+
"cleaner-spec-reporter": "^0.5.0",
|
|
33
34
|
"eslint": "9",
|
|
34
35
|
"fastify": "^5.0.0",
|
|
35
36
|
"isbot": "^5.1.17",
|
|
36
37
|
"json-schema-to-typescript": "^15.0.1",
|
|
37
|
-
"neostandard": "^0.
|
|
38
|
-
"react": "^
|
|
39
|
-
"react-dom": "^
|
|
38
|
+
"neostandard": "^0.12.0",
|
|
39
|
+
"react": "^19.1.0",
|
|
40
|
+
"react-dom": "^19.1.0",
|
|
40
41
|
"typescript": "^5.5.4",
|
|
41
42
|
"vite": "^5.4.2",
|
|
42
43
|
"ws": "^8.18.0",
|
|
43
|
-
"@platformatic/
|
|
44
|
-
"@platformatic/service": "3.
|
|
44
|
+
"@platformatic/gateway": "3.5.1",
|
|
45
|
+
"@platformatic/service": "3.5.1"
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=22.19.0"
|
|
45
49
|
},
|
|
46
50
|
"scripts": {
|
|
47
|
-
"test": "
|
|
48
|
-
"coverage": "npm run lint && borp -C -X test -X test/fixtures --concurrency=1 --no-timeout",
|
|
51
|
+
"test": "node --test --test-reporter=cleaner-spec-reporter --test-concurrency=1 --test-timeout=2000000 test/*.test.js test/**/*.test.js",
|
|
49
52
|
"gen-schema": "node lib/schema.js > schema.json",
|
|
50
53
|
"gen-types": "json2ts > config.d.ts < schema.json",
|
|
51
|
-
"build": "
|
|
54
|
+
"build": "npm run gen-schema && npm run gen-types",
|
|
52
55
|
"lint": "eslint"
|
|
53
56
|
}
|
|
54
57
|
}
|