one 1.1.345-1734464750388 → 1.1.346
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/dist/cjs/cli.cjs +5 -1
- package/dist/cjs/cli.js +5 -1
- package/dist/cjs/cli.js.map +1 -1
- package/dist/cjs/cli.native.js +5 -1
- package/dist/cjs/cli.native.js.map +2 -2
- package/dist/cjs/config.cjs +6 -6
- package/dist/cjs/config.js +3 -3
- package/dist/cjs/config.js.map +1 -1
- package/dist/cjs/config.native.js +3 -3
- package/dist/cjs/config.native.js.map +2 -2
- package/dist/cjs/serve-worker.cjs +34 -0
- package/dist/cjs/serve-worker.js +26 -0
- package/dist/cjs/serve-worker.js.map +6 -0
- package/dist/cjs/serve-worker.native.js +31 -0
- package/dist/cjs/serve-worker.native.js.map +6 -0
- package/dist/cjs/serve.cjs +17 -142
- package/dist/cjs/serve.js +9 -139
- package/dist/cjs/serve.js.map +2 -2
- package/dist/cjs/serve.native.js +8 -148
- package/dist/cjs/serve.native.js.map +2 -2
- package/dist/cjs/server/oneServe.cjs +173 -0
- package/dist/cjs/server/oneServe.js +160 -0
- package/dist/cjs/server/oneServe.js.map +6 -0
- package/dist/cjs/server/oneServe.native.js +174 -0
- package/dist/cjs/server/oneServe.native.js.map +6 -0
- package/dist/cjs/server/setupBuildOptions.cjs +28 -0
- package/dist/cjs/server/setupBuildOptions.js +23 -0
- package/dist/cjs/server/setupBuildOptions.js.map +6 -0
- package/dist/cjs/server/setupBuildOptions.native.js +29 -0
- package/dist/cjs/server/setupBuildOptions.native.js.map +6 -0
- package/dist/cjs/utils/ensureExists.cjs +28 -0
- package/dist/cjs/utils/ensureExists.js +24 -0
- package/dist/cjs/utils/ensureExists.js.map +6 -0
- package/dist/cjs/utils/ensureExists.native.js +29 -0
- package/dist/cjs/utils/ensureExists.native.js.map +6 -0
- package/dist/cjs/vite/build.cjs +38 -18
- package/dist/cjs/vite/build.js +38 -14
- package/dist/cjs/vite/build.js.map +1 -1
- package/dist/cjs/vite/build.native.js +29 -15
- package/dist/cjs/vite/build.native.js.map +2 -2
- package/dist/cjs/vite/one.cjs +4 -4
- package/dist/cjs/vite/one.js +3 -2
- package/dist/cjs/vite/one.js.map +1 -1
- package/dist/cjs/vite/one.native.js +3 -2
- package/dist/cjs/vite/one.native.js.map +2 -2
- package/dist/esm/cli.js +5 -1
- package/dist/esm/cli.js.map +1 -1
- package/dist/esm/cli.mjs +5 -1
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/cli.native.js +5 -1
- package/dist/esm/cli.native.js.map +2 -2
- package/dist/esm/config.js +3 -3
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/config.mjs +6 -6
- package/dist/esm/config.mjs.map +1 -1
- package/dist/esm/config.native.js +3 -3
- package/dist/esm/config.native.js.map +2 -2
- package/dist/esm/serve-worker.js +13 -0
- package/dist/esm/serve-worker.js.map +6 -0
- package/dist/esm/serve-worker.mjs +11 -0
- package/dist/esm/serve-worker.mjs.map +1 -0
- package/dist/esm/serve-worker.native.js +13 -0
- package/dist/esm/serve-worker.native.js.map +6 -0
- package/dist/esm/serve.js +10 -140
- package/dist/esm/serve.js.map +2 -2
- package/dist/esm/serve.mjs +17 -142
- package/dist/esm/serve.mjs.map +1 -1
- package/dist/esm/serve.native.js +9 -149
- package/dist/esm/serve.native.js.map +2 -2
- package/dist/esm/server/oneServe.js +137 -0
- package/dist/esm/server/oneServe.js.map +6 -0
- package/dist/esm/server/oneServe.mjs +139 -0
- package/dist/esm/server/oneServe.mjs.map +1 -0
- package/dist/esm/server/oneServe.native.js +146 -0
- package/dist/esm/server/oneServe.native.js.map +6 -0
- package/dist/esm/server/setupBuildOptions.js +7 -0
- package/dist/esm/server/setupBuildOptions.js.map +6 -0
- package/dist/esm/server/setupBuildOptions.mjs +5 -0
- package/dist/esm/server/setupBuildOptions.mjs.map +1 -0
- package/dist/esm/server/setupBuildOptions.native.js +8 -0
- package/dist/esm/server/setupBuildOptions.native.js.map +6 -0
- package/dist/esm/utils/ensureExists.js +8 -0
- package/dist/esm/utils/ensureExists.js.map +6 -0
- package/dist/esm/utils/ensureExists.mjs +5 -0
- package/dist/esm/utils/ensureExists.mjs.map +1 -0
- package/dist/esm/utils/ensureExists.native.js +8 -0
- package/dist/esm/utils/ensureExists.native.js.map +6 -0
- package/dist/esm/vite/build.js +38 -14
- package/dist/esm/vite/build.js.map +1 -1
- package/dist/esm/vite/build.mjs +38 -18
- package/dist/esm/vite/build.mjs.map +1 -1
- package/dist/esm/vite/build.native.js +29 -15
- package/dist/esm/vite/build.native.js.map +2 -2
- package/dist/esm/vite/one.js +3 -2
- package/dist/esm/vite/one.js.map +1 -1
- package/dist/esm/vite/one.mjs +4 -4
- package/dist/esm/vite/one.mjs.map +1 -1
- package/dist/esm/vite/one.native.js +3 -2
- package/dist/esm/vite/one.native.js.map +2 -2
- package/package.json +14 -9
- package/src/cli.ts +4 -0
- package/src/config.ts +2 -3
- package/src/serve-worker.ts +19 -0
- package/src/serve.ts +13 -217
- package/src/server/oneServe.ts +216 -0
- package/src/server/setupBuildOptions.ts +7 -0
- package/src/utils/ensureExists.ts +5 -0
- package/src/vite/build.ts +43 -23
- package/src/vite/one.ts +2 -3
- package/src/vite/types.ts +2 -3
- package/types/config.d.ts.map +1 -1
- package/types/serve-worker.d.ts +3 -0
- package/types/serve-worker.d.ts.map +1 -0
- package/types/serve.d.ts +1 -1
- package/types/serve.d.ts.map +1 -1
- package/types/server/oneServe.d.ts +5 -0
- package/types/server/oneServe.d.ts.map +1 -0
- package/types/server/setupBuildOptions.d.ts +3 -0
- package/types/server/setupBuildOptions.d.ts.map +1 -0
- package/types/utils/ensureExists.d.ts +2 -0
- package/types/utils/ensureExists.d.ts.map +1 -0
- package/types/vite/build.d.ts.map +1 -1
- package/types/vite/one.d.ts.map +1 -1
- package/types/vite/types.d.ts +2 -2
- package/types/vite/types.d.ts.map +1 -1
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "one",
|
3
|
-
"version": "1.1.
|
3
|
+
"version": "1.1.346",
|
4
4
|
"source": "src/index.ts",
|
5
5
|
"types": "./types/index.d.ts",
|
6
6
|
"sideEffects": [
|
@@ -51,6 +51,11 @@
|
|
51
51
|
"import": "./dist/esm/serve.mjs",
|
52
52
|
"require": "./dist/cjs/serve.js"
|
53
53
|
},
|
54
|
+
"./serve-worker": {
|
55
|
+
"types": "./types/serve-worker.d.ts",
|
56
|
+
"import": "./dist/esm/serve-worker.mjs",
|
57
|
+
"require": "./dist/cjs/serve-worker.js"
|
58
|
+
},
|
54
59
|
"./setup": {
|
55
60
|
"types": "./types/setup.d.ts",
|
56
61
|
"import": "./dist/esm/setup.mjs",
|
@@ -107,15 +112,15 @@
|
|
107
112
|
"@react-navigation/routers": "~6.1.9",
|
108
113
|
"@swc/core": "^1.7.14",
|
109
114
|
"@ungap/structured-clone": "^1.2.0",
|
110
|
-
"@vxrn/resolve": "1.1.
|
111
|
-
"@vxrn/tslib-lite": "1.1.
|
112
|
-
"@vxrn/universal-color-scheme": "1.1.
|
113
|
-
"@vxrn/use-isomorphic-layout-effect": "1.1.
|
115
|
+
"@vxrn/resolve": "1.1.346",
|
116
|
+
"@vxrn/tslib-lite": "1.1.346",
|
117
|
+
"@vxrn/universal-color-scheme": "1.1.346",
|
118
|
+
"@vxrn/use-isomorphic-layout-effect": "1.1.346",
|
114
119
|
"babel-dead-code-elimination": "^1.0.6",
|
115
120
|
"babel-plugin-react-compiler": "^19.0.0-beta-201e55d-20241215",
|
116
121
|
"citty": "^0.1.6",
|
117
122
|
"core-js": "^3.38.1",
|
118
|
-
"create-vxrn": "1.1.
|
123
|
+
"create-vxrn": "1.1.346",
|
119
124
|
"escape-string-regexp": "^5.0.0",
|
120
125
|
"expo-linking": "~6.3.1",
|
121
126
|
"expo-modules-core": "^1.12.24",
|
@@ -138,7 +143,7 @@
|
|
138
143
|
"url-parse": "^1.5.10",
|
139
144
|
"vite": "^6.0.3",
|
140
145
|
"vite-tsconfig-paths": "^5.0.1",
|
141
|
-
"vxrn": "1.1.
|
146
|
+
"vxrn": "1.1.346",
|
142
147
|
"ws": "^8.18.0",
|
143
148
|
"xxhashjs": "^0.2.2"
|
144
149
|
},
|
@@ -146,7 +151,7 @@
|
|
146
151
|
"react-native": "*"
|
147
152
|
},
|
148
153
|
"devDependencies": {
|
149
|
-
"@tamagui/build": "^1.120.
|
154
|
+
"@tamagui/build": "^1.120.2",
|
150
155
|
"@types/node": "^22.1.0",
|
151
156
|
"@types/react-dom": "^18.2.25",
|
152
157
|
"@types/url-parse": "^1.4.11",
|
@@ -155,7 +160,7 @@
|
|
155
160
|
"get-port": "^7.1.0",
|
156
161
|
"react-native": "0.74.5",
|
157
162
|
"rollup": "^4.21.0",
|
158
|
-
"vitest": "^2.1.
|
163
|
+
"vitest": "^2.1.8"
|
159
164
|
},
|
160
165
|
"publishConfig": {
|
161
166
|
"access": "public"
|
package/src/cli.ts
CHANGED
@@ -118,6 +118,9 @@ const serveCommand = defineCommand({
|
|
118
118
|
cacheHeaders: {
|
119
119
|
type: 'boolean',
|
120
120
|
},
|
121
|
+
loadEnv: {
|
122
|
+
type: 'boolean',
|
123
|
+
},
|
121
124
|
},
|
122
125
|
async run({ args }) {
|
123
126
|
const { serve } = await import('./serve')
|
@@ -127,6 +130,7 @@ const serveCommand = defineCommand({
|
|
127
130
|
cacheHeaders: args.cacheHeaders === false ? 'off' : undefined,
|
128
131
|
compress: args.compress,
|
129
132
|
platform: args.platform === 'vercel' ? 'vercel' : 'node',
|
133
|
+
loadEnv: !!args.loadEnv,
|
130
134
|
})
|
131
135
|
},
|
132
136
|
})
|
package/src/config.ts
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
import { isWebServer } from './constants'
|
2
2
|
import type { One } from './vite/types'
|
3
3
|
|
4
|
-
const CLIENT_RENDER_MODE = process.env.ONE_DEFAULT_RENDER_MODE as One.RouteRenderMode | undefined
|
5
|
-
|
6
4
|
// works client or server
|
7
5
|
export const getDefaultRenderMode = () => {
|
6
|
+
const CLIENT_RENDER_MODE = process.env.ONE_DEFAULT_RENDER_MODE as One.RouteRenderMode | undefined
|
8
7
|
const serverConfig = globalThis['__vxrnPluginConfig__'] as One.PluginOptions | undefined
|
9
8
|
|
10
|
-
if (isWebServer && !serverConfig) {
|
9
|
+
if (!CLIENT_RENDER_MODE && isWebServer && !serverConfig) {
|
11
10
|
throw new Error(`Internal one error: should call setServerConfig before createManifest`)
|
12
11
|
}
|
13
12
|
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { createProdServer } from 'vxrn/serve'
|
2
|
+
import { oneServe } from './server/oneServe'
|
3
|
+
import type { One } from './vite/types'
|
4
|
+
import { setupBuildInfo } from './server/setupBuildOptions'
|
5
|
+
import { ensureExists } from './utils/ensureExists'
|
6
|
+
|
7
|
+
export async function serve(buildInfo: One.BuildInfo) {
|
8
|
+
setupBuildInfo(buildInfo)
|
9
|
+
ensureExists(buildInfo.oneOptions)
|
10
|
+
|
11
|
+
// TODO make this better, this ensures we get react 19
|
12
|
+
process.env.VXRN_REACT_19 = '1'
|
13
|
+
|
14
|
+
const app = await createProdServer(buildInfo.oneOptions)
|
15
|
+
|
16
|
+
await oneServe(buildInfo.oneOptions, buildInfo.oneOptions, buildInfo, app, false)
|
17
|
+
|
18
|
+
return app
|
19
|
+
}
|
package/src/serve.ts
CHANGED
@@ -1,11 +1,9 @@
|
|
1
1
|
import './polyfills-server'
|
2
2
|
|
3
3
|
import FSExtra from 'fs-extra'
|
4
|
-
import type { Hono } from 'hono'
|
5
|
-
import { join } from 'node:path'
|
6
4
|
import type { VXRNOptions } from 'vxrn'
|
7
|
-
import {
|
8
|
-
import
|
5
|
+
import { setupBuildInfo } from './server/setupBuildOptions'
|
6
|
+
import { ensureExists } from './utils/ensureExists'
|
9
7
|
import type { One } from './vite/types'
|
10
8
|
|
11
9
|
process.on('uncaughtException', (err) => {
|
@@ -14,19 +12,22 @@ process.on('uncaughtException', (err) => {
|
|
14
12
|
|
15
13
|
export async function serve(args: VXRNOptions['server'] = {}) {
|
16
14
|
const buildInfo = (await FSExtra.readJSON(`dist/buildInfo.json`)) as One.BuildInfo
|
15
|
+
const { oneOptions } = buildInfo
|
17
16
|
|
18
|
-
|
19
|
-
|
17
|
+
setupBuildInfo(buildInfo)
|
18
|
+
ensureExists(oneOptions)
|
20
19
|
|
21
20
|
// to avoid loading the CACHE_KEY before we set it use async imports:
|
22
21
|
const { labelProcess } = await import('./cli/label-process')
|
23
22
|
const { removeUndefined } = await import('./utils/removeUndefined')
|
24
|
-
const {
|
23
|
+
const { loadEnv, serve: vxrnServe } = await import('vxrn/serve')
|
24
|
+
const { oneServe } = await import('./server/oneServe')
|
25
25
|
|
26
26
|
labelProcess('serve')
|
27
|
-
loadEnv('production')
|
28
27
|
|
29
|
-
|
28
|
+
if (args.loadEnv) {
|
29
|
+
await loadEnv('production')
|
30
|
+
}
|
30
31
|
|
31
32
|
// TODO make this better, this ensures we get react 19
|
32
33
|
process.env.VXRN_REACT_19 = '1'
|
@@ -43,215 +44,10 @@ export async function serve(args: VXRNOptions['server'] = {}) {
|
|
43
44
|
platform: args.platform,
|
44
45
|
cacheHeaders: args.cacheHeaders,
|
45
46
|
}),
|
46
|
-
|
47
|
-
async beforeStart(options, app) {
|
48
|
-
await oneOptions.server?.beforeStart?.(options, app)
|
49
|
-
await oneServe(oneOptions, options, buildInfo, app)
|
50
|
-
},
|
51
47
|
},
|
52
|
-
})
|
53
|
-
}
|
54
|
-
|
55
|
-
async function oneServe(
|
56
|
-
options: One.PluginOptions,
|
57
|
-
vxrnOptions: VXRNOptions,
|
58
|
-
buildInfo: One.BuildInfo,
|
59
|
-
app: Hono
|
60
|
-
) {
|
61
|
-
const { createHandleRequest } = await import('./createHandleRequest')
|
62
|
-
const { isResponse } = await import('./utils/isResponse')
|
63
|
-
const { isStatusRedirect } = await import('./utils/isStatus')
|
64
|
-
const { resolveAPIRequest } = await import('./vite/resolveAPIRequest')
|
65
|
-
|
66
|
-
const isAPIRequest = new WeakMap<any, boolean>()
|
67
|
-
const root = vxrnOptions.root || '.'
|
68
|
-
|
69
|
-
// add redirects
|
70
|
-
const redirects = options.web?.redirects
|
71
|
-
if (redirects) {
|
72
|
-
for (const redirect of redirects) {
|
73
|
-
app.get(redirect.source, (context) => {
|
74
|
-
const destinationUrl = redirect.destination.replace(/:\w+/g, (param) => {
|
75
|
-
const paramName = param.substring(1)
|
76
|
-
return context.req.param(paramName) || ''
|
77
|
-
})
|
78
|
-
return context.redirect(destinationUrl, redirect.permanent ? 301 : 302)
|
79
|
-
})
|
80
|
-
}
|
81
|
-
}
|
82
|
-
|
83
|
-
if (!buildInfo) {
|
84
|
-
throw new Error(`No build info found, have you run build?`)
|
85
|
-
}
|
86
|
-
|
87
|
-
const { routeMap, builtRoutes } = buildInfo as One.BuildInfo
|
88
|
-
|
89
|
-
const routeToBuildInfo: Record<string, One.RouteBuildInfo> = {}
|
90
|
-
for (const route of builtRoutes) {
|
91
|
-
routeToBuildInfo[route.cleanPath] = route
|
92
|
-
|
93
|
-
// temp - make it back into brackets style
|
94
|
-
const bracketRoutePath = route.cleanPath
|
95
|
-
.split('/')
|
96
|
-
.map((part) => {
|
97
|
-
return part[0] === ':' ? `[${part.slice(1)}]` : part
|
98
|
-
})
|
99
|
-
.join('/')
|
100
|
-
routeToBuildInfo[bracketRoutePath] = route
|
101
|
-
}
|
102
|
-
|
103
|
-
const serverOptions = {
|
104
|
-
...options,
|
105
|
-
root,
|
106
|
-
}
|
107
|
-
|
108
|
-
const entryServer = getServerEntry(serverOptions)
|
109
|
-
const entry = await import(entryServer)
|
110
|
-
|
111
|
-
const render = entry.default.render as (props: RenderAppProps) => any
|
112
|
-
const apiCJS = options.build?.api?.outputFormat === 'cjs'
|
113
|
-
|
114
|
-
const handleRequest = createHandleRequest(
|
115
|
-
{},
|
116
|
-
{
|
117
|
-
async handleAPI({ route, request, loaderProps }) {
|
118
|
-
const apiFile = join(
|
119
|
-
process.cwd(),
|
120
|
-
'dist',
|
121
|
-
'api',
|
122
|
-
route.page.replace('[', '_').replace(']', '_') + (apiCJS ? '.cjs' : '.js')
|
123
|
-
)
|
124
|
-
|
125
|
-
isAPIRequest.set(request, true)
|
126
|
-
|
127
|
-
return resolveAPIRequest(
|
128
|
-
async () => {
|
129
|
-
try {
|
130
|
-
return await import(apiFile)
|
131
|
-
} catch (err) {
|
132
|
-
console.error(`\n [one] Error importing API route at ${apiFile}:
|
133
48
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
the "optimizeDeps.include" array in your vite.config.ts.
|
138
|
-
|
139
|
-
🐞 For a better error message run "node" and enter:
|
140
|
-
|
141
|
-
import('${apiFile}')\n\n`)
|
142
|
-
return {}
|
143
|
-
}
|
144
|
-
},
|
145
|
-
request,
|
146
|
-
loaderProps?.params || {}
|
147
|
-
)
|
148
|
-
},
|
149
|
-
|
150
|
-
async handleSSR({ route, url, loaderProps }) {
|
151
|
-
if (route.type === 'ssr') {
|
152
|
-
const buildInfo = routeToBuildInfo[route.page]
|
153
|
-
if (!buildInfo) {
|
154
|
-
throw new Error(
|
155
|
-
`No buildinfo found for ${url}, route: ${route.page}, in keys: ${Object.keys(routeToBuildInfo)}`
|
156
|
-
)
|
157
|
-
}
|
158
|
-
|
159
|
-
try {
|
160
|
-
const exported = await import(buildInfo.serverJsPath)
|
161
|
-
const loaderData = await exported.loader?.(loaderProps)
|
162
|
-
const preloads = buildInfo.preloads
|
163
|
-
|
164
|
-
const headers = new Headers()
|
165
|
-
headers.set('content-type', 'text/html')
|
166
|
-
|
167
|
-
return new Response(
|
168
|
-
await render({
|
169
|
-
loaderData,
|
170
|
-
loaderProps,
|
171
|
-
path: loaderProps?.path || '/',
|
172
|
-
preloads,
|
173
|
-
}),
|
174
|
-
{
|
175
|
-
headers,
|
176
|
-
}
|
177
|
-
)
|
178
|
-
} catch (err) {
|
179
|
-
console.error(`[one] Error rendering SSR route ${route.page}
|
180
|
-
|
181
|
-
${err?.['stack'] ?? err}
|
182
|
-
|
183
|
-
url: ${url}`)
|
184
|
-
}
|
185
|
-
}
|
186
|
-
},
|
187
|
-
}
|
188
|
-
)
|
189
|
-
|
190
|
-
// preload reading in all the files, for prod performance:
|
191
|
-
const htmlFiles: Record<string, string> = {}
|
192
|
-
for (const key in routeMap) {
|
193
|
-
const info = routeToBuildInfo[key]
|
194
|
-
|
195
|
-
if (info?.type === 'ssr') {
|
196
|
-
// we handle this on each request
|
197
|
-
continue
|
198
|
-
}
|
199
|
-
|
200
|
-
htmlFiles[key] = await FSExtra.readFile(join('dist/client', routeMap[key]), 'utf-8')
|
201
|
-
}
|
202
|
-
|
203
|
-
app.use(async (context, next) => {
|
204
|
-
// serve our generated html files
|
205
|
-
const html = htmlFiles[context.req.path]
|
206
|
-
if (html) {
|
207
|
-
return context.html(html)
|
208
|
-
}
|
209
|
-
|
210
|
-
try {
|
211
|
-
const request = context.req.raw
|
212
|
-
const response = await handleRequest.handler(request)
|
213
|
-
|
214
|
-
if (response) {
|
215
|
-
if (isResponse(response)) {
|
216
|
-
if (isStatusRedirect(response.status)) {
|
217
|
-
const location = `${response.headers.get('location') || ''}`
|
218
|
-
response.headers.forEach((value, key) => {
|
219
|
-
context.header(key, value)
|
220
|
-
})
|
221
|
-
return context.redirect(location, response.status)
|
222
|
-
}
|
223
|
-
|
224
|
-
if (isAPIRequest.get(request)) {
|
225
|
-
try {
|
226
|
-
// don't cache api requests by default
|
227
|
-
response.headers.set('Cache-Control', 'no-store')
|
228
|
-
} catch (err) {
|
229
|
-
console.info(
|
230
|
-
`Error udpating cache header on api route "${
|
231
|
-
context.req.path
|
232
|
-
}" to no-store, it is ${response.headers.get('cache-control')}, continue`,
|
233
|
-
err
|
234
|
-
)
|
235
|
-
}
|
236
|
-
}
|
237
|
-
|
238
|
-
return response as Response
|
239
|
-
}
|
240
|
-
|
241
|
-
return context.json(
|
242
|
-
response,
|
243
|
-
200,
|
244
|
-
isAPIRequest.get(request)
|
245
|
-
? {
|
246
|
-
'Cache-Control': 'no-store',
|
247
|
-
}
|
248
|
-
: undefined
|
249
|
-
)
|
250
|
-
}
|
251
|
-
} catch (err) {
|
252
|
-
console.error(` [one] Error handling request: ${(err as any)['stack']}`)
|
253
|
-
}
|
254
|
-
|
255
|
-
await next()
|
49
|
+
async beforeStart(options, app) {
|
50
|
+
await oneServe(oneOptions, options, buildInfo, app)
|
51
|
+
},
|
256
52
|
})
|
257
53
|
}
|
@@ -0,0 +1,216 @@
|
|
1
|
+
import type { Hono } from 'hono'
|
2
|
+
import { join } from 'node:path'
|
3
|
+
import type { VXRNOptions } from 'vxrn'
|
4
|
+
import { getServerEntry } from 'vxrn/serve'
|
5
|
+
import type { RenderAppProps } from '../types'
|
6
|
+
import type { One } from '../vite/types'
|
7
|
+
|
8
|
+
export async function oneServe(
|
9
|
+
oneOptions: One.PluginOptions,
|
10
|
+
vxrnOptions: VXRNOptions,
|
11
|
+
buildInfo: One.BuildInfo,
|
12
|
+
app: Hono,
|
13
|
+
serveStatic = true
|
14
|
+
) {
|
15
|
+
const { createHandleRequest } = await import('../createHandleRequest')
|
16
|
+
const { isResponse } = await import('../utils/isResponse')
|
17
|
+
const { isStatusRedirect } = await import('../utils/isStatus')
|
18
|
+
const { resolveAPIRequest } = await import('../vite/resolveAPIRequest')
|
19
|
+
|
20
|
+
const isAPIRequest = new WeakMap<any, boolean>()
|
21
|
+
const root = vxrnOptions.root || '.'
|
22
|
+
|
23
|
+
// add redirects
|
24
|
+
const redirects = oneOptions.web?.redirects
|
25
|
+
if (redirects) {
|
26
|
+
for (const redirect of redirects) {
|
27
|
+
app.get(redirect.source, (context) => {
|
28
|
+
const destinationUrl = redirect.destination.replace(/:\w+/g, (param) => {
|
29
|
+
const paramName = param.substring(1)
|
30
|
+
return context.req.param(paramName) || ''
|
31
|
+
})
|
32
|
+
return context.redirect(destinationUrl, redirect.permanent ? 301 : 302)
|
33
|
+
})
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
if (!buildInfo) {
|
38
|
+
throw new Error(`No build info found, have you run build?`)
|
39
|
+
}
|
40
|
+
|
41
|
+
const { routeMap, builtRoutes } = buildInfo as One.BuildInfo
|
42
|
+
|
43
|
+
const routeToBuildInfo: Record<string, One.RouteBuildInfo> = {}
|
44
|
+
for (const route of builtRoutes) {
|
45
|
+
routeToBuildInfo[route.cleanPath] = route
|
46
|
+
|
47
|
+
// temp - make it back into brackets style
|
48
|
+
const bracketRoutePath = route.cleanPath
|
49
|
+
.split('/')
|
50
|
+
.map((part) => {
|
51
|
+
return part[0] === ':' ? `[${part.slice(1)}]` : part
|
52
|
+
})
|
53
|
+
.join('/')
|
54
|
+
routeToBuildInfo[bracketRoutePath] = route
|
55
|
+
}
|
56
|
+
|
57
|
+
const serverOptions = {
|
58
|
+
...oneOptions,
|
59
|
+
root,
|
60
|
+
}
|
61
|
+
|
62
|
+
const entryServer = getServerEntry(serverOptions)
|
63
|
+
const entry = await import(entryServer)
|
64
|
+
|
65
|
+
const render = entry.default.render as (props: RenderAppProps) => any
|
66
|
+
const apiCJS = oneOptions.build?.api?.outputFormat === 'cjs'
|
67
|
+
|
68
|
+
const handleRequest = createHandleRequest(
|
69
|
+
{},
|
70
|
+
{
|
71
|
+
async handleAPI({ route, request, loaderProps }) {
|
72
|
+
const apiFile = join(
|
73
|
+
process.cwd(),
|
74
|
+
'dist',
|
75
|
+
'api',
|
76
|
+
route.page.replace('[', '_').replace(']', '_') + (apiCJS ? '.cjs' : '.js')
|
77
|
+
)
|
78
|
+
|
79
|
+
isAPIRequest.set(request, true)
|
80
|
+
|
81
|
+
return resolveAPIRequest(
|
82
|
+
async () => {
|
83
|
+
try {
|
84
|
+
return await import(apiFile)
|
85
|
+
} catch (err) {
|
86
|
+
console.error(`\n [one] Error importing API route at ${apiFile}:
|
87
|
+
|
88
|
+
${err}
|
89
|
+
|
90
|
+
If this is an import error, you can likely fix this by adding this dependency to
|
91
|
+
the "optimizeDeps.include" array in your vite.config.ts.
|
92
|
+
|
93
|
+
🐞 For a better error message run "node" and enter:
|
94
|
+
|
95
|
+
import('${apiFile}')\n\n`)
|
96
|
+
return {}
|
97
|
+
}
|
98
|
+
},
|
99
|
+
request,
|
100
|
+
loaderProps?.params || {}
|
101
|
+
)
|
102
|
+
},
|
103
|
+
|
104
|
+
async handleSSR({ route, url, loaderProps }) {
|
105
|
+
if (route.type === 'ssr') {
|
106
|
+
const buildInfo = routeToBuildInfo[route.page]
|
107
|
+
if (!buildInfo) {
|
108
|
+
throw new Error(
|
109
|
+
`No buildinfo found for ${url}, route: ${route.page}, in keys: ${Object.keys(routeToBuildInfo)}`
|
110
|
+
)
|
111
|
+
}
|
112
|
+
|
113
|
+
try {
|
114
|
+
const exported = await import(buildInfo.serverJsPath)
|
115
|
+
const loaderData = await exported.loader?.(loaderProps)
|
116
|
+
const preloads = buildInfo.preloads
|
117
|
+
|
118
|
+
const headers = new Headers()
|
119
|
+
headers.set('content-type', 'text/html')
|
120
|
+
|
121
|
+
return new Response(
|
122
|
+
await render({
|
123
|
+
loaderData,
|
124
|
+
loaderProps,
|
125
|
+
path: loaderProps?.path || '/',
|
126
|
+
preloads,
|
127
|
+
}),
|
128
|
+
{
|
129
|
+
headers,
|
130
|
+
}
|
131
|
+
)
|
132
|
+
} catch (err) {
|
133
|
+
console.error(`[one] Error rendering SSR route ${route.page}
|
134
|
+
|
135
|
+
${err?.['stack'] ?? err}
|
136
|
+
|
137
|
+
url: ${url}`)
|
138
|
+
}
|
139
|
+
}
|
140
|
+
},
|
141
|
+
}
|
142
|
+
)
|
143
|
+
|
144
|
+
// preload reading in all the files, for prod performance:
|
145
|
+
const htmlFiles: Record<string, string> = {}
|
146
|
+
|
147
|
+
if (serveStatic) {
|
148
|
+
const { readFile } = await import('node:fs/promises')
|
149
|
+
|
150
|
+
for (const key in routeMap) {
|
151
|
+
const info = routeToBuildInfo[key]
|
152
|
+
|
153
|
+
if (info?.type === 'ssr') {
|
154
|
+
// we handle this on each request
|
155
|
+
continue
|
156
|
+
}
|
157
|
+
|
158
|
+
htmlFiles[key] = await readFile(join('dist/client', routeMap[key]), 'utf-8')
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
app.use(async (context, next) => {
|
163
|
+
// serve our generated html files
|
164
|
+
const html = htmlFiles[context.req.path]
|
165
|
+
if (html) {
|
166
|
+
return context.html(html)
|
167
|
+
}
|
168
|
+
|
169
|
+
try {
|
170
|
+
const request = context.req.raw
|
171
|
+
const response = await handleRequest.handler(request)
|
172
|
+
|
173
|
+
if (response) {
|
174
|
+
if (isResponse(response)) {
|
175
|
+
if (isStatusRedirect(response.status)) {
|
176
|
+
const location = `${response.headers.get('location') || ''}`
|
177
|
+
response.headers.forEach((value, key) => {
|
178
|
+
context.header(key, value)
|
179
|
+
})
|
180
|
+
return context.redirect(location, response.status)
|
181
|
+
}
|
182
|
+
|
183
|
+
if (isAPIRequest.get(request)) {
|
184
|
+
try {
|
185
|
+
// don't cache api requests by default
|
186
|
+
response.headers.set('Cache-Control', 'no-store')
|
187
|
+
} catch (err) {
|
188
|
+
console.info(
|
189
|
+
`Error udpating cache header on api route "${
|
190
|
+
context.req.path
|
191
|
+
}" to no-store, it is ${response.headers.get('cache-control')}, continue`,
|
192
|
+
err
|
193
|
+
)
|
194
|
+
}
|
195
|
+
}
|
196
|
+
|
197
|
+
return response as Response
|
198
|
+
}
|
199
|
+
|
200
|
+
return context.json(
|
201
|
+
response,
|
202
|
+
200,
|
203
|
+
isAPIRequest.get(request)
|
204
|
+
? {
|
205
|
+
'Cache-Control': 'no-store',
|
206
|
+
}
|
207
|
+
: undefined
|
208
|
+
)
|
209
|
+
}
|
210
|
+
} catch (err) {
|
211
|
+
console.error(` [one] Error handling request: ${(err as any)['stack']}`)
|
212
|
+
}
|
213
|
+
|
214
|
+
await next()
|
215
|
+
})
|
216
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import type { One } from '../vite/types'
|
2
|
+
|
3
|
+
export function setupBuildInfo(buildInfo: One.BuildInfo) {
|
4
|
+
// ensure cache key matches build
|
5
|
+
process.env.ONE_CACHE_KEY ||= buildInfo.constants.CACHE_KEY
|
6
|
+
process.env.ONE_DEFAULT_RENDER_MODE ||= buildInfo.oneOptions?.web?.defaultRenderMode || 'ssg'
|
7
|
+
}
|