@platformatic/react-router 0.0.1 → 3.28.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.
- package/LICENSE +201 -0
- package/NOTICE +13 -0
- package/README.md +13 -0
- package/config.d.ts +613 -0
- package/eslint.config.js +5 -0
- package/index.js +31 -0
- package/lib/capability.js +203 -0
- package/lib/schema.js +47 -0
- package/package.json +53 -7
- package/schema.json +2315 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cleanBasePath,
|
|
3
|
+
createServerListener,
|
|
4
|
+
ensureTrailingSlash,
|
|
5
|
+
errors,
|
|
6
|
+
getServerUrl,
|
|
7
|
+
importFile,
|
|
8
|
+
resolvePackageViaCJS
|
|
9
|
+
} from '@platformatic/basic'
|
|
10
|
+
import { ViteCapability } from '@platformatic/vite'
|
|
11
|
+
import { createRequestHandler } from '@react-router/express'
|
|
12
|
+
import express from 'express'
|
|
13
|
+
import inject from 'light-my-request'
|
|
14
|
+
import { existsSync } from 'node:fs'
|
|
15
|
+
import { readFile, writeFile } 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 = '^7.0.0'
|
|
22
|
+
|
|
23
|
+
export class ReactRouterCapability extends ViteCapability {
|
|
24
|
+
#app
|
|
25
|
+
#server
|
|
26
|
+
#reactRouter
|
|
27
|
+
#basePath
|
|
28
|
+
|
|
29
|
+
constructor (root, config, context) {
|
|
30
|
+
super(root, config, context)
|
|
31
|
+
this.type = 'react-router'
|
|
32
|
+
this.version = packageJson.version
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async init () {
|
|
36
|
+
await super.init()
|
|
37
|
+
|
|
38
|
+
if (!this.isProduction) {
|
|
39
|
+
this.#reactRouter = resolve(dirname(await resolvePackageViaCJS(this.root, 'react-router')), '../..')
|
|
40
|
+
const reactRouterPackage = JSON.parse(await readFile(resolve(this.#reactRouter, 'package.json'), 'utf-8'))
|
|
41
|
+
|
|
42
|
+
if (!satisfies(reactRouterPackage.version, supportedVersions)) {
|
|
43
|
+
throw new errors.UnsupportedVersion('react-router', reactRouterPackage.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
|
+
const config = this.config
|
|
59
|
+
const reactRouterConfig = await this.#getReactRouterConfig()
|
|
60
|
+
|
|
61
|
+
if (this.isProduction) {
|
|
62
|
+
const command = this.config.application.commands.production
|
|
63
|
+
|
|
64
|
+
this.outputDirectory = resolve(this.root, config.reactRouter.outputDirectory, 'client')
|
|
65
|
+
this.buildInfoPath = resolve(this.root, config.reactRouter.outputDirectory, '.platformatic-build.json')
|
|
66
|
+
|
|
67
|
+
if (command) {
|
|
68
|
+
return this.startWithCommand(command)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (reactRouterConfig.ssr) {
|
|
72
|
+
return this.#startSSRProduction(listen)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return super.start({ listen })
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async stop () {
|
|
80
|
+
const reactRouterConfig = await this.#getReactRouterConfig()
|
|
81
|
+
|
|
82
|
+
if (reactRouterConfig.ssr) {
|
|
83
|
+
await this._stop()
|
|
84
|
+
|
|
85
|
+
if (this.#server?.listening) {
|
|
86
|
+
await this._closeServer(this.#server)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return super.stop()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async build () {
|
|
96
|
+
const config = this.config
|
|
97
|
+
const command = config.application.commands.build
|
|
98
|
+
const basePath = config.application?.basePath
|
|
99
|
+
? ensureTrailingSlash(cleanBasePath(config.application?.basePath))
|
|
100
|
+
: undefined
|
|
101
|
+
|
|
102
|
+
const reactRouterConfig = await this.#getReactRouterConfig()
|
|
103
|
+
|
|
104
|
+
if (command) {
|
|
105
|
+
return this.buildWithCommand(command, basePath)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
await this.buildWithCommand(`react-router build -m production ${this.root}`, basePath)
|
|
109
|
+
|
|
110
|
+
await writeFile(
|
|
111
|
+
resolve(this.root, config.reactRouter.outputDirectory, '.platformatic-build.json'),
|
|
112
|
+
JSON.stringify({ basePath: reactRouterConfig.basename ?? '/' }),
|
|
113
|
+
'utf-8'
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async getMeta () {
|
|
118
|
+
const reactRouterConfig = await this.#getReactRouterConfig()
|
|
119
|
+
return super.getMeta(reactRouterConfig.basename)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async inject (injectParams, onInject) {
|
|
123
|
+
const reactRouterConfig = await this.#getReactRouterConfig()
|
|
124
|
+
|
|
125
|
+
if (this.isProduction && reactRouterConfig.ssr) {
|
|
126
|
+
return this.#inject(injectParams, onInject)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return super.inject(injectParams, onInject)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async #getReactRouterConfig () {
|
|
133
|
+
const ext = ['ts', 'js'].find(ext => existsSync(resolve(this.root, `react-router.config.${ext}`)))
|
|
134
|
+
|
|
135
|
+
if (!ext) {
|
|
136
|
+
return {}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const { default: reactRouterConfig } = await importFile(resolve(this.root, `react-router.config.${ext}`))
|
|
140
|
+
return reactRouterConfig ?? {}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async #startSSRProduction (listen) {
|
|
144
|
+
// Listen if entrypoint
|
|
145
|
+
if (this.#app && listen) {
|
|
146
|
+
const serverOptions = this.serverConfig
|
|
147
|
+
const listenOptions = { host: serverOptions?.hostname || '127.0.0.1', port: serverOptions?.port || 0 }
|
|
148
|
+
|
|
149
|
+
if (typeof serverOptions?.backlog === 'number') {
|
|
150
|
+
createServerListener(false, false, { backlog: serverOptions.backlog })
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
this.#server = await new Promise((resolve, reject) => {
|
|
154
|
+
return this.#app
|
|
155
|
+
.listen(listenOptions, function () {
|
|
156
|
+
resolve(this)
|
|
157
|
+
})
|
|
158
|
+
.on('error', reject)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
this.url = getServerUrl(this.#server)
|
|
162
|
+
|
|
163
|
+
return this.url
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const config = this.config
|
|
167
|
+
|
|
168
|
+
const clientRoot = resolve(this.root, config.reactRouter.outputDirectory, 'client')
|
|
169
|
+
const serverRoot = resolve(this.root, config.reactRouter.outputDirectory, 'server')
|
|
170
|
+
this.verifyOutputDirectory(clientRoot)
|
|
171
|
+
this.verifyOutputDirectory(serverRoot)
|
|
172
|
+
this.#basePath = await this._getBasePathFromBuildInfo()
|
|
173
|
+
|
|
174
|
+
const { entrypoint } = await importFile(resolve(serverRoot, 'index.js'))
|
|
175
|
+
|
|
176
|
+
// Setup express app
|
|
177
|
+
this.#app = express()
|
|
178
|
+
this._setApp(this.#app)
|
|
179
|
+
this.#app.disable('x-powered-by')
|
|
180
|
+
this.#app.use(pinoHttp({ logger: this.logger }))
|
|
181
|
+
this.#app.use(this.#basePath, express.static(clientRoot))
|
|
182
|
+
this.#app.all(
|
|
183
|
+
`${ensureTrailingSlash(cleanBasePath(this.#basePath))}*`,
|
|
184
|
+
createRequestHandler({ build: () => entrypoint })
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
await this._collectMetrics()
|
|
188
|
+
return this.url
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async #inject (injectParams, onInject) {
|
|
192
|
+
const res = await inject(this.#app, injectParams, onInject)
|
|
193
|
+
|
|
194
|
+
/* c8 ignore next 3 */
|
|
195
|
+
if (onInject) {
|
|
196
|
+
return
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Since inject might be called from the main thread directly via ITC, let's clean it up
|
|
200
|
+
const { statusCode, headers, body, payload, rawPayload } = res
|
|
201
|
+
return { statusCode, headers, body, payload, rawPayload }
|
|
202
|
+
}
|
|
203
|
+
}
|
package/lib/schema.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { schemaComponents as basicSchemaComponents } from '@platformatic/basic'
|
|
2
|
+
import { schemaComponents as utilsSchemaComponents } from '@platformatic/foundation'
|
|
3
|
+
import { schemaComponents as viteSchemaComponents } from '@platformatic/vite'
|
|
4
|
+
import { readFileSync } from 'node:fs'
|
|
5
|
+
import { resolve } from 'node:path'
|
|
6
|
+
|
|
7
|
+
export const packageJson = JSON.parse(readFileSync(resolve(import.meta.dirname, '../package.json'), 'utf8'))
|
|
8
|
+
export const version = packageJson.version
|
|
9
|
+
|
|
10
|
+
export const reactRouter = {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
outputDirectory: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
default: 'build'
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
default: {},
|
|
19
|
+
additionalProperties: false
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const schemaComponents = { reactRouter }
|
|
23
|
+
|
|
24
|
+
export const schema = {
|
|
25
|
+
$id: `https://schemas.platformatic.dev/@platformatic/react-router/${packageJson.version}.json`,
|
|
26
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
27
|
+
title: 'Platformatic React Router Config',
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
$schema: {
|
|
31
|
+
type: 'string'
|
|
32
|
+
},
|
|
33
|
+
logger: utilsSchemaComponents.logger,
|
|
34
|
+
server: utilsSchemaComponents.server,
|
|
35
|
+
watch: basicSchemaComponents.watch,
|
|
36
|
+
application: basicSchemaComponents.buildableApplication,
|
|
37
|
+
runtime: utilsSchemaComponents.wrappedRuntime,
|
|
38
|
+
vite: viteSchemaComponents.vite,
|
|
39
|
+
reactRouter
|
|
40
|
+
},
|
|
41
|
+
additionalProperties: false
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* c8 ignore next 3 */
|
|
45
|
+
if (process.argv[1] === import.meta.filename) {
|
|
46
|
+
console.log(JSON.stringify(schema, null, 2))
|
|
47
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/react-router",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": "Matteo Collina <hello@matteocollina.com>",
|
|
7
|
-
"type": "commonjs",
|
|
3
|
+
"version": "3.28.2",
|
|
4
|
+
"description": "Platformatic React Router Capability",
|
|
8
5
|
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/platformatic/platformatic.git"
|
|
10
|
+
},
|
|
11
|
+
"author": "Platformatic Inc. <oss@platformatic.dev> (https://platformatic.dev)",
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/platformatic/platformatic/issues"
|
|
15
|
+
},
|
|
16
|
+
"homepage": "https://github.com/platformatic/platformatic#readme",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"express": "^4.19.2",
|
|
19
|
+
"light-my-request": "^6.0.0",
|
|
20
|
+
"pino-http": "^10.2.0",
|
|
21
|
+
"semver": "^7.6.3",
|
|
22
|
+
"@platformatic/basic": "3.28.2",
|
|
23
|
+
"@platformatic/vite": "3.28.2",
|
|
24
|
+
"@platformatic/foundation": "3.28.2"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@react-router/dev": "^7.10.0",
|
|
28
|
+
"@react-router/express": "^7.10.1",
|
|
29
|
+
"@react-router/node": "^7.10.0",
|
|
30
|
+
"@types/react": "^19.1.11",
|
|
31
|
+
"@types/react-dom": "^19.1.7",
|
|
32
|
+
"cleaner-spec-reporter": "^0.5.0",
|
|
33
|
+
"eslint": "9",
|
|
34
|
+
"fastify": "^5.0.0",
|
|
35
|
+
"isbot": "^5.1.17",
|
|
36
|
+
"json-schema-to-typescript": "^15.0.1",
|
|
37
|
+
"neostandard": "^0.12.0",
|
|
38
|
+
"react": "^19.1.0",
|
|
39
|
+
"react-dom": "^19.1.0",
|
|
40
|
+
"react-router": "^7.10.0",
|
|
41
|
+
"react-router-dom": "^7.10.0",
|
|
42
|
+
"typescript": "^5.5.4",
|
|
43
|
+
"vite": "^7.1.7",
|
|
44
|
+
"ws": "^8.18.0",
|
|
45
|
+
"@platformatic/gateway": "3.28.2",
|
|
46
|
+
"@platformatic/service": "3.28.2"
|
|
47
|
+
},
|
|
48
|
+
"engines": {
|
|
49
|
+
"node": ">=22.19.0"
|
|
50
|
+
},
|
|
9
51
|
"scripts": {
|
|
10
|
-
"test": "
|
|
52
|
+
"test": "node --test --test-reporter=cleaner-spec-reporter --test-concurrency=1 --test-timeout=2000000 test/*.test.js test/**/*.test.js",
|
|
53
|
+
"gen-schema": "node lib/schema.js > schema.json",
|
|
54
|
+
"gen-types": "json2ts > config.d.ts < schema.json",
|
|
55
|
+
"build": "npm run gen-schema && npm run gen-types",
|
|
56
|
+
"lint": "eslint"
|
|
11
57
|
}
|
|
12
|
-
}
|
|
58
|
+
}
|