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.
Files changed (125) hide show
  1. package/dist/cjs/cli.cjs +5 -1
  2. package/dist/cjs/cli.js +5 -1
  3. package/dist/cjs/cli.js.map +1 -1
  4. package/dist/cjs/cli.native.js +5 -1
  5. package/dist/cjs/cli.native.js.map +2 -2
  6. package/dist/cjs/config.cjs +6 -6
  7. package/dist/cjs/config.js +3 -3
  8. package/dist/cjs/config.js.map +1 -1
  9. package/dist/cjs/config.native.js +3 -3
  10. package/dist/cjs/config.native.js.map +2 -2
  11. package/dist/cjs/serve-worker.cjs +34 -0
  12. package/dist/cjs/serve-worker.js +26 -0
  13. package/dist/cjs/serve-worker.js.map +6 -0
  14. package/dist/cjs/serve-worker.native.js +31 -0
  15. package/dist/cjs/serve-worker.native.js.map +6 -0
  16. package/dist/cjs/serve.cjs +17 -142
  17. package/dist/cjs/serve.js +9 -139
  18. package/dist/cjs/serve.js.map +2 -2
  19. package/dist/cjs/serve.native.js +8 -148
  20. package/dist/cjs/serve.native.js.map +2 -2
  21. package/dist/cjs/server/oneServe.cjs +173 -0
  22. package/dist/cjs/server/oneServe.js +160 -0
  23. package/dist/cjs/server/oneServe.js.map +6 -0
  24. package/dist/cjs/server/oneServe.native.js +174 -0
  25. package/dist/cjs/server/oneServe.native.js.map +6 -0
  26. package/dist/cjs/server/setupBuildOptions.cjs +28 -0
  27. package/dist/cjs/server/setupBuildOptions.js +23 -0
  28. package/dist/cjs/server/setupBuildOptions.js.map +6 -0
  29. package/dist/cjs/server/setupBuildOptions.native.js +29 -0
  30. package/dist/cjs/server/setupBuildOptions.native.js.map +6 -0
  31. package/dist/cjs/utils/ensureExists.cjs +28 -0
  32. package/dist/cjs/utils/ensureExists.js +24 -0
  33. package/dist/cjs/utils/ensureExists.js.map +6 -0
  34. package/dist/cjs/utils/ensureExists.native.js +29 -0
  35. package/dist/cjs/utils/ensureExists.native.js.map +6 -0
  36. package/dist/cjs/vite/build.cjs +38 -18
  37. package/dist/cjs/vite/build.js +38 -14
  38. package/dist/cjs/vite/build.js.map +1 -1
  39. package/dist/cjs/vite/build.native.js +29 -15
  40. package/dist/cjs/vite/build.native.js.map +2 -2
  41. package/dist/cjs/vite/one.cjs +4 -4
  42. package/dist/cjs/vite/one.js +3 -2
  43. package/dist/cjs/vite/one.js.map +1 -1
  44. package/dist/cjs/vite/one.native.js +3 -2
  45. package/dist/cjs/vite/one.native.js.map +2 -2
  46. package/dist/esm/cli.js +5 -1
  47. package/dist/esm/cli.js.map +1 -1
  48. package/dist/esm/cli.mjs +5 -1
  49. package/dist/esm/cli.mjs.map +1 -1
  50. package/dist/esm/cli.native.js +5 -1
  51. package/dist/esm/cli.native.js.map +2 -2
  52. package/dist/esm/config.js +3 -3
  53. package/dist/esm/config.js.map +1 -1
  54. package/dist/esm/config.mjs +6 -6
  55. package/dist/esm/config.mjs.map +1 -1
  56. package/dist/esm/config.native.js +3 -3
  57. package/dist/esm/config.native.js.map +2 -2
  58. package/dist/esm/serve-worker.js +13 -0
  59. package/dist/esm/serve-worker.js.map +6 -0
  60. package/dist/esm/serve-worker.mjs +11 -0
  61. package/dist/esm/serve-worker.mjs.map +1 -0
  62. package/dist/esm/serve-worker.native.js +13 -0
  63. package/dist/esm/serve-worker.native.js.map +6 -0
  64. package/dist/esm/serve.js +10 -140
  65. package/dist/esm/serve.js.map +2 -2
  66. package/dist/esm/serve.mjs +17 -142
  67. package/dist/esm/serve.mjs.map +1 -1
  68. package/dist/esm/serve.native.js +9 -149
  69. package/dist/esm/serve.native.js.map +2 -2
  70. package/dist/esm/server/oneServe.js +137 -0
  71. package/dist/esm/server/oneServe.js.map +6 -0
  72. package/dist/esm/server/oneServe.mjs +139 -0
  73. package/dist/esm/server/oneServe.mjs.map +1 -0
  74. package/dist/esm/server/oneServe.native.js +146 -0
  75. package/dist/esm/server/oneServe.native.js.map +6 -0
  76. package/dist/esm/server/setupBuildOptions.js +7 -0
  77. package/dist/esm/server/setupBuildOptions.js.map +6 -0
  78. package/dist/esm/server/setupBuildOptions.mjs +5 -0
  79. package/dist/esm/server/setupBuildOptions.mjs.map +1 -0
  80. package/dist/esm/server/setupBuildOptions.native.js +8 -0
  81. package/dist/esm/server/setupBuildOptions.native.js.map +6 -0
  82. package/dist/esm/utils/ensureExists.js +8 -0
  83. package/dist/esm/utils/ensureExists.js.map +6 -0
  84. package/dist/esm/utils/ensureExists.mjs +5 -0
  85. package/dist/esm/utils/ensureExists.mjs.map +1 -0
  86. package/dist/esm/utils/ensureExists.native.js +8 -0
  87. package/dist/esm/utils/ensureExists.native.js.map +6 -0
  88. package/dist/esm/vite/build.js +38 -14
  89. package/dist/esm/vite/build.js.map +1 -1
  90. package/dist/esm/vite/build.mjs +38 -18
  91. package/dist/esm/vite/build.mjs.map +1 -1
  92. package/dist/esm/vite/build.native.js +29 -15
  93. package/dist/esm/vite/build.native.js.map +2 -2
  94. package/dist/esm/vite/one.js +3 -2
  95. package/dist/esm/vite/one.js.map +1 -1
  96. package/dist/esm/vite/one.mjs +4 -4
  97. package/dist/esm/vite/one.mjs.map +1 -1
  98. package/dist/esm/vite/one.native.js +3 -2
  99. package/dist/esm/vite/one.native.js.map +2 -2
  100. package/package.json +14 -9
  101. package/src/cli.ts +4 -0
  102. package/src/config.ts +2 -3
  103. package/src/serve-worker.ts +19 -0
  104. package/src/serve.ts +13 -217
  105. package/src/server/oneServe.ts +216 -0
  106. package/src/server/setupBuildOptions.ts +7 -0
  107. package/src/utils/ensureExists.ts +5 -0
  108. package/src/vite/build.ts +43 -23
  109. package/src/vite/one.ts +2 -3
  110. package/src/vite/types.ts +2 -3
  111. package/types/config.d.ts.map +1 -1
  112. package/types/serve-worker.d.ts +3 -0
  113. package/types/serve-worker.d.ts.map +1 -0
  114. package/types/serve.d.ts +1 -1
  115. package/types/serve.d.ts.map +1 -1
  116. package/types/server/oneServe.d.ts +5 -0
  117. package/types/server/oneServe.d.ts.map +1 -0
  118. package/types/server/setupBuildOptions.d.ts +3 -0
  119. package/types/server/setupBuildOptions.d.ts.map +1 -0
  120. package/types/utils/ensureExists.d.ts +2 -0
  121. package/types/utils/ensureExists.d.ts.map +1 -0
  122. package/types/vite/build.d.ts.map +1 -1
  123. package/types/vite/one.d.ts.map +1 -1
  124. package/types/vite/types.d.ts +2 -2
  125. 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.345-1734464750388",
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.345-1734464750388",
111
- "@vxrn/tslib-lite": "1.1.345-1734464750388",
112
- "@vxrn/universal-color-scheme": "1.1.345-1734464750388",
113
- "@vxrn/use-isomorphic-layout-effect": "1.1.345-1734464750388",
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.345-1734464750388",
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.345-1734464750388",
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.1",
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.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 { getServerEntry, loadEnv, serve as vxrnServe } from 'vxrn/serve'
8
- import type { RenderAppProps } from './types'
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
- // ensure cache key matches build
19
- process.env.ONE_CACHE_KEY = buildInfo.constants.CACHE_KEY
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 { loadUserOneOptions } = await import('./vite/one')
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
- const oneOptions = await loadUserOneOptions('serve')
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
- ${err}
135
-
136
- If this is an import error, you can likely fix this by adding this dependency to
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
+ }
@@ -0,0 +1,5 @@
1
+ export function ensureExists<T>(value: T | undefined | null): asserts value is T {
2
+ if (value === undefined || value === null) {
3
+ throw new Error(`Missing value.`)
4
+ }
5
+ }