rari 0.5.10 → 0.5.12

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/client.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import { C as fetchWithTimeout, S as createNavigationError, _ as LayoutErrorBoundary, a as LoadingSpinner, b as NavigationErrorOverlay, c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, l as createLoadingBoundary, m as extractServerPropsWithCache, n as DefaultLoading, o as NotFound, p as extractServerProps, r as ErrorBoundary, s as createErrorBoundary, t as DefaultError, u as clearPropsCache, v as ClientRouter, w as LayoutManager, x as NavigationErrorHandler, y as StatePreserver } from "./runtime-client-CGCu6fmO.mjs";
1
+ import { C as fetchWithTimeout, S as createNavigationError, _ as LayoutErrorBoundary, a as LoadingSpinner, b as NavigationErrorOverlay, c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, l as createLoadingBoundary, m as extractServerPropsWithCache, n as DefaultLoading, o as NotFound, p as extractServerProps, r as ErrorBoundary, s as createErrorBoundary, t as DefaultError, u as clearPropsCache, v as ClientRouter, w as LayoutManager, x as NavigationErrorHandler, y as StatePreserver } from "./runtime-client-XDRmgAw-.mjs";
2
2
 
3
3
  export { ClientRouter, DefaultError, DefaultLoading, ErrorBoundary, HttpRuntimeClient, LayoutErrorBoundary, LayoutManager, LoadingSpinner, NavigationErrorHandler, NavigationErrorOverlay, NotFound, StatePreserver, clearPropsCache, clearPropsCacheForComponent, createErrorBoundary, createHttpRuntimeClient, createLoadingBoundary, createNavigationError, extractMetadata, extractServerProps, extractServerPropsWithCache, extractStaticParams, fetchWithTimeout, hasServerSideDataFetching };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-CT18_z0c.mjs";
1
+ import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-DckaZsam.mjs";
2
2
  import { i as writeManifest, n as generateAppRouteManifest, r as loadManifest, t as AppRouteGenerator } from "./app-routes-BjA_L5R4.mjs";
3
- import { c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, m as extractServerPropsWithCache, p as extractServerProps, u as clearPropsCache } from "./runtime-client-CGCu6fmO.mjs";
4
- import "./loading-component-map-UZ-MQYv0.mjs";
3
+ import { c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, m as extractServerPropsWithCache, p as extractServerProps, u as clearPropsCache } from "./runtime-client-XDRmgAw-.mjs";
4
+ import "./loading-component-map-vYjwg1Lq.mjs";
5
5
  import "./server-build-Cvj5EwXx.mjs";
6
6
 
7
7
  export { AppRouteGenerator, HttpRuntimeClient, RariResponse, clearPropsCache, clearPropsCacheForComponent, createHttpRuntimeClient, defineRariConfig, defineRariOptions, extractMetadata, extractServerProps, extractServerPropsWithCache, extractStaticParams, generateAppRouteManifest, hasServerSideDataFetching, headers, loadManifest, rari, rariRouter, writeManifest };
@@ -1,3 +1,3 @@
1
- import { n as getLoadingComponentMapPath, t as generateLoadingComponentMap } from "./loading-component-map-UZ-MQYv0.mjs";
1
+ import { n as getLoadingComponentMapPath, t as generateLoadingComponentMap } from "./loading-component-map-vYjwg1Lq.mjs";
2
2
 
3
3
  export { generateLoadingComponentMap, getLoadingComponentMapPath };
@@ -5,6 +5,10 @@ function generateLoadingComponentMap(options) {
5
5
  const { loadingComponents } = options;
6
6
  if (loadingComponents.length === 0) return `// No loading components found
7
7
  export const loadingComponentModules = {}
8
+
9
+ if (typeof globalThis !== 'undefined') {
10
+ globalThis.__rari_loading_components = new Map()
11
+ }
8
12
  `;
9
13
  const moduleEntries = [];
10
14
  for (const loading of loadingComponents) {
@@ -19,7 +23,7 @@ ${moduleEntries.join(",\n")}
19
23
  }
20
24
 
21
25
  if (typeof globalThis !== 'undefined') {
22
- globalThis.__rari_loading_components = loadingComponentModules
26
+ globalThis.__rari_loading_components = new Map(Object.entries(loadingComponentModules))
23
27
  }
24
28
  `;
25
29
  }
@@ -1050,7 +1050,7 @@ function ClientRouter({ children, manifest, initialRoute }) {
1050
1050
  if (loadingComponent) window.dispatchEvent(new CustomEvent("rari:show-loading", { detail: {
1051
1051
  route: targetPath,
1052
1052
  navigationId,
1053
- loadingComponent
1053
+ loadingEntry: loadingComponent
1054
1054
  } }));
1055
1055
  const navigationPromise = (async () => {
1056
1056
  const fromRoute = currentRouteRef.current;
@@ -1073,7 +1073,7 @@ function ClientRouter({ children, manifest, initialRoute }) {
1073
1073
  };
1074
1074
  if (options.replace) window.history.replaceState(historyState, "", targetPath);
1075
1075
  else window.history.pushState(historyState, "", targetPath);
1076
- const fetchUrl = window.location.origin + targetPath;
1076
+ const fetchUrl = (window.location.origin.includes(":5173") ? "http://localhost:3000" : window.location.origin) + targetPath;
1077
1077
  const response = await fetch(fetchUrl, {
1078
1078
  headers: { Accept: "text/x-component" },
1079
1079
  signal: abortController.signal
@@ -1751,7 +1751,7 @@ function rariRouter(options = {}) {
1751
1751
  const outDir = path.resolve(root, opts.outDir);
1752
1752
  await promises.mkdir(outDir, { recursive: true });
1753
1753
  await promises.writeFile(path.join(outDir, "app-routes.json"), manifestContent, "utf-8");
1754
- const { generateLoadingComponentMap, getLoadingComponentMapPath } = await import("./loading-component-map-Db2B5rLX.mjs");
1754
+ const { generateLoadingComponentMap, getLoadingComponentMapPath } = await import("./loading-component-map-DyMAME6V.mjs");
1755
1755
  const loadingMapCode = generateLoadingComponentMap({
1756
1756
  appDir: opts.appDir,
1757
1757
  loadingComponents: manifest.loading
@@ -1874,28 +1874,12 @@ function rariRouter(options = {}) {
1874
1874
  }
1875
1875
  },
1876
1876
  async generateBundle() {
1877
- if (cachedManifestContent) {
1878
- this.emitFile({
1879
- type: "asset",
1880
- fileName: "app-routes.json",
1881
- source: cachedManifestContent
1882
- });
1883
- try {
1884
- const manifest = JSON.parse(cachedManifestContent);
1885
- const { generateLoadingComponentMap } = await import("./loading-component-map-Db2B5rLX.mjs");
1886
- const loadingMapCode = generateLoadingComponentMap({
1887
- appDir: opts.appDir,
1888
- loadingComponents: manifest.loading
1889
- });
1890
- this.emitFile({
1891
- type: "asset",
1892
- fileName: "loading-component-map.js",
1893
- source: loadingMapCode
1894
- });
1895
- } catch (error) {
1896
- console.error("Failed to generate loading component map:", error);
1897
- }
1898
- } else console.warn("App router manifest not generated, skipping emission");
1877
+ if (cachedManifestContent) this.emitFile({
1878
+ type: "asset",
1879
+ fileName: "app-routes.json",
1880
+ source: cachedManifestContent
1881
+ });
1882
+ else console.warn("App router manifest not generated, skipping emission");
1899
1883
  },
1900
1884
  async closeBundle() {
1901
1885
  for (const timer of pendingHMRUpdates.values()) clearTimeout(timer);
@@ -2890,6 +2874,24 @@ const ${componentName$1} = registerClientReference(
2890
2874
  await handleServerComponentHMR(filePath);
2891
2875
  } else setTimeout(discoverAndRegisterComponents, 1e3);
2892
2876
  });
2877
+ server.middlewares.use("/app-routes.json", async (req, res) => {
2878
+ try {
2879
+ const manifestPath = path.join(server.config.root, "dist", "app-routes.json");
2880
+ if (fs.existsSync(manifestPath)) {
2881
+ const manifestContent = await fs.promises.readFile(manifestPath, "utf-8");
2882
+ res.statusCode = 200;
2883
+ res.setHeader("Content-Type", "application/json");
2884
+ res.setHeader("Cache-Control", "no-cache");
2885
+ res.end(manifestContent);
2886
+ } else {
2887
+ res.statusCode = 404;
2888
+ res.end("Manifest not found");
2889
+ }
2890
+ } catch (error) {
2891
+ res.statusCode = 500;
2892
+ res.end(`Error reading manifest: ${error instanceof Error ? error.message : String(error)}`);
2893
+ }
2894
+ });
2893
2895
  server.middlewares.use("/api/vite/hmr-transform", async (req, res) => {
2894
2896
  if (req.method !== "POST") {
2895
2897
  res.statusCode = 405;
package/dist/vite.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-CT18_z0c.mjs";
1
+ import { a as headers, i as rariRouter, n as defineRariOptions, o as RariResponse, r as rari, t as defineRariConfig } from "./vite-DckaZsam.mjs";
2
2
  import { i as writeManifest, n as generateAppRouteManifest, r as loadManifest, t as AppRouteGenerator } from "./app-routes-BjA_L5R4.mjs";
3
- import { c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, m as extractServerPropsWithCache, p as extractServerProps, u as clearPropsCache } from "./runtime-client-CGCu6fmO.mjs";
4
- import "./loading-component-map-UZ-MQYv0.mjs";
3
+ import { c as createHttpRuntimeClient, d as clearPropsCacheForComponent, f as extractMetadata, g as hasServerSideDataFetching, h as extractStaticParams, i as HttpRuntimeClient, m as extractServerPropsWithCache, p as extractServerProps, u as clearPropsCache } from "./runtime-client-XDRmgAw-.mjs";
4
+ import "./loading-component-map-vYjwg1Lq.mjs";
5
5
  import "./server-build-Cvj5EwXx.mjs";
6
6
 
7
7
  export { AppRouteGenerator, HttpRuntimeClient, RariResponse, clearPropsCache, clearPropsCacheForComponent, createHttpRuntimeClient, defineRariConfig, defineRariOptions, extractMetadata, extractServerProps, extractServerPropsWithCache, extractStaticParams, generateAppRouteManifest, hasServerSideDataFetching, headers, loadManifest, rari, rariRouter, writeManifest };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rari",
3
3
  "type": "module",
4
- "version": "0.5.10",
4
+ "version": "0.5.12",
5
5
  "description": "Runtime Accelerated Rendering Infrastructure (Rari)",
6
6
  "author": "Ryan Skinner",
7
7
  "license": "MIT",
@@ -236,7 +236,7 @@ export function ClientRouter({ children, manifest, initialRoute }: ClientRouterP
236
236
  detail: {
237
237
  route: targetPath,
238
238
  navigationId,
239
- loadingComponent,
239
+ loadingEntry: loadingComponent,
240
240
  },
241
241
  }))
242
242
  }
@@ -286,7 +286,10 @@ export function ClientRouter({ children, manifest, initialRoute }: ClientRouterP
286
286
  )
287
287
  }
288
288
 
289
- const fetchUrl = window.location.origin + targetPath
289
+ const rariServerUrl = window.location.origin.includes(':5173')
290
+ ? 'http://localhost:3000'
291
+ : window.location.origin
292
+ const fetchUrl = rariServerUrl + targetPath
290
293
 
291
294
  const response = await fetch(fetchUrl, {
292
295
  headers: { Accept: 'text/x-component' },
@@ -79,7 +79,10 @@ export class LoadingComponentRegistry {
79
79
  if (exactLoader) {
80
80
  try {
81
81
  const module = await exactLoader()
82
- return module.default
82
+ if (module && module.default && typeof module.default === 'function') {
83
+ return module.default
84
+ }
85
+ console.warn(`[LoadingRegistry] Invalid component for ${routePath}: module.default is not a function`)
83
86
  }
84
87
  catch (error) {
85
88
  console.warn(`[LoadingRegistry] Failed to load exact match for ${routePath}:`, error)
@@ -12,6 +12,10 @@ export function generateLoadingComponentMap(options: LoadingComponentMapOptions)
12
12
  if (loadingComponents.length === 0) {
13
13
  return `// No loading components found
14
14
  export const loadingComponentModules = {}
15
+
16
+ if (typeof globalThis !== 'undefined') {
17
+ globalThis.__rari_loading_components = new Map()
18
+ }
15
19
  `
16
20
  }
17
21
 
@@ -32,7 +36,7 @@ ${moduleEntries.join(',\n')}
32
36
  }
33
37
 
34
38
  if (typeof globalThis !== 'undefined') {
35
- globalThis.__rari_loading_components = loadingComponentModules
39
+ globalThis.__rari_loading_components = new Map(Object.entries(loadingComponentModules))
36
40
  }
37
41
  `
38
42
 
@@ -457,24 +457,6 @@ export function rariRouter(options: RariRouterPluginOptions = {}): Plugin {
457
457
  fileName: 'app-routes.json',
458
458
  source: cachedManifestContent,
459
459
  })
460
-
461
- try {
462
- const manifest = JSON.parse(cachedManifestContent)
463
- const { generateLoadingComponentMap } = await import('./loading-component-map')
464
- const loadingMapCode = generateLoadingComponentMap({
465
- appDir: opts.appDir,
466
- loadingComponents: manifest.loading,
467
- })
468
-
469
- this.emitFile({
470
- type: 'asset',
471
- fileName: 'loading-component-map.js',
472
- source: loadingMapCode,
473
- })
474
- }
475
- catch (error) {
476
- console.error('Failed to generate loading component map:', error)
477
- }
478
460
  }
479
461
  else {
480
462
  console.warn('App router manifest not generated, skipping emission')
@@ -199,6 +199,11 @@ export function AppRouterProvider({ children, initialPayload, onNavigate }: AppR
199
199
  return null
200
200
  }
201
201
 
202
+ if (typeof Component !== 'function') {
203
+ console.warn('[AppRouterProvider] Component is not a function for module:', moduleInfo.id, '- skipping component')
204
+ return null
205
+ }
206
+
202
207
  const effectiveKey = serverKey || `fallback-${Math.random()}`
203
208
 
204
209
  const childProps = {
@@ -211,10 +216,31 @@ export function AppRouterProvider({ children, initialPayload, onNavigate }: AppR
211
216
  return element
212
217
  }
213
218
 
219
+ if (!type || (typeof type !== 'string' && typeof type !== 'function')) {
220
+ console.error('[AppRouterProvider] Invalid component type:', {
221
+ type,
222
+ typeOf: typeof type,
223
+ serverKey,
224
+ props,
225
+ rscData: rsc,
226
+ })
227
+ return null
228
+ }
229
+
214
230
  const processedProps = processProps(props, modules, layoutPath)
215
231
  return React.createElement(type, serverKey ? { ...processedProps, key: serverKey } : processedProps)
216
232
  }
217
- return rsc.map(child => rscToReact(child, modules, layoutPath))
233
+ return rsc.map((child, index) => {
234
+ const element = rscToReact(child, modules, layoutPath)
235
+ if (!element) {
236
+ return null
237
+ }
238
+ if (typeof element === 'object' && React.isValidElement(element) && !element.key) {
239
+ // eslint-disable-next-line react/no-clone-element
240
+ return React.cloneElement(element, { key: index })
241
+ }
242
+ return element
243
+ }).filter(Boolean)
218
244
  }
219
245
 
220
246
  return rsc
@@ -457,31 +483,21 @@ export function AppRouterProvider({ children, initialPayload, onNavigate }: AppR
457
483
  return
458
484
 
459
485
  const handleShowLoading = async (event: Event) => {
460
- const customEvent = event as CustomEvent<{ route: string, navigationId: number, loadingComponent: any }>
461
- const { route, navigationId, loadingComponent: loadingEntry } = customEvent.detail
486
+ const customEvent = event as CustomEvent<{ route: string, navigationId: number, loadingEntry: any }>
487
+ const { route, navigationId, loadingEntry } = customEvent.detail
462
488
 
463
489
  currentNavigationIdRef.current = navigationId
464
490
 
465
- setLoadingState({
466
- isShowingLoading: true,
467
- loadingRoute: route,
468
- loadingComponent: null,
469
- })
470
-
471
- setRenderKey(prev => prev + 1)
472
-
473
491
  const loadingComponentPath = loadingEntry?.path || route
474
492
  const loadingComponent = await loadingRegistryRef.current.loadComponent(loadingComponentPath)
475
493
 
476
- if (currentNavigationIdRef.current === navigationId) {
477
- if (loadingComponent) {
478
- setLoadingState({
479
- isShowingLoading: true,
480
- loadingRoute: route,
481
- loadingComponent,
482
- })
483
- setRenderKey(prev => prev + 1)
484
- }
494
+ if (currentNavigationIdRef.current === navigationId && loadingComponent) {
495
+ setLoadingState({
496
+ isShowingLoading: true,
497
+ loadingRoute: route,
498
+ loadingComponent,
499
+ })
500
+ setRenderKey(prev => prev + 1)
485
501
  }
486
502
  }
487
503
 
@@ -670,7 +686,7 @@ export function AppRouterProvider({ children, initialPayload, onNavigate }: AppR
670
686
 
671
687
  const injectLoadingIntoLayout = (layoutElement: any, loadingComponent: React.ReactNode) => {
672
688
  if (!layoutElement || typeof layoutElement !== 'object') {
673
- return loadingComponent
689
+ return loadingComponent || null
674
690
  }
675
691
 
676
692
  const cloneWithLoadingInjected = (element: any): any => {
@@ -696,15 +712,36 @@ export function AppRouterProvider({ children, initialPayload, onNavigate }: AppR
696
712
  )
697
713
 
698
714
  if (hasMain) {
699
- newChildren = children.map((child: any) => cloneWithLoadingInjected(child))
715
+ newChildren = children.map((child: any, index: number) => {
716
+ const cloned = cloneWithLoadingInjected(child)
717
+ if (!cloned) {
718
+ return null
719
+ }
720
+
721
+ return cloned && typeof cloned === 'object' && !cloned.key && React.isValidElement(cloned)
722
+ // eslint-disable-next-line react/no-clone-element
723
+ ? React.cloneElement(cloned, { key: child?.key || index })
724
+ : cloned
725
+ }).filter(Boolean)
700
726
  }
701
727
  else {
702
- newChildren = children.map((child: any) => {
728
+ newChildren = children.map((child: any, index: number) => {
729
+ if (!child) {
730
+ return null
731
+ }
703
732
  if (child && typeof child === 'object') {
704
- return cloneWithLoadingInjected(child)
733
+ const cloned = cloneWithLoadingInjected(child)
734
+ if (!cloned) {
735
+ return null
736
+ }
737
+
738
+ return cloned && !cloned.key && React.isValidElement(cloned)
739
+ // eslint-disable-next-line react/no-clone-element
740
+ ? React.cloneElement(cloned, { key: child.key || index })
741
+ : cloned
705
742
  }
706
743
  return child
707
- })
744
+ }).filter(Boolean)
708
745
  }
709
746
  }
710
747
  else if (typeof children === 'object') {
@@ -714,6 +751,11 @@ export function AppRouterProvider({ children, initialPayload, onNavigate }: AppR
714
751
  newChildren = children
715
752
  }
716
753
 
754
+ if (!React.isValidElement(element)) {
755
+ console.warn('[AppRouterProvider] Attempting to clone invalid React element')
756
+ return element
757
+ }
758
+
717
759
  // eslint-disable-next-line react/no-clone-element
718
760
  return React.cloneElement(element, element.props, newChildren)
719
761
  }
@@ -728,18 +770,29 @@ export function AppRouterProvider({ children, initialPayload, onNavigate }: AppR
728
770
 
729
771
  if (loadingState.isShowingLoading) {
730
772
  let loadingComponentElement
731
- if (loadingState.loadingComponent) {
732
- loadingComponentElement = (
733
- <LoadingErrorBoundary>
734
- {React.createElement(loadingState.loadingComponent)}
735
- </LoadingErrorBoundary>
736
- )
773
+ if (loadingState.loadingComponent && typeof loadingState.loadingComponent === 'function') {
774
+ try {
775
+ const element = React.createElement(loadingState.loadingComponent)
776
+ if (element) {
777
+ loadingComponentElement = (
778
+ <LoadingErrorBoundary>
779
+ {element}
780
+ </LoadingErrorBoundary>
781
+ )
782
+ }
783
+ }
784
+ catch (error) {
785
+ console.error('[AppRouterProvider] Failed to create loading component:', error)
786
+ }
737
787
  }
738
788
 
739
789
  if (rscPayload?.element) {
740
- contentToRender = injectLoadingIntoLayout(rscPayload.element, loadingComponentElement)
790
+ const injected = injectLoadingIntoLayout(rscPayload.element, loadingComponentElement)
791
+ if (injected) {
792
+ contentToRender = injected
793
+ }
741
794
  }
742
- else {
795
+ else if (loadingComponentElement) {
743
796
  contentToRender = loadingComponentElement
744
797
  }
745
798
  }
@@ -748,6 +801,11 @@ export function AppRouterProvider({ children, initialPayload, onNavigate }: AppR
748
801
  contentToRender = extracted || rscPayload.element
749
802
  }
750
803
 
804
+ if (contentToRender && typeof contentToRender === 'object' && !React.isValidElement(contentToRender)) {
805
+ console.error('[AppRouterProvider] Invalid content to render:', contentToRender)
806
+ contentToRender = children
807
+ }
808
+
751
809
  return (
752
810
  <>
753
811
  {hmrError && (
@@ -62,7 +62,7 @@ export async function renderApp() {
62
62
  if (!manifest) {
63
63
  try {
64
64
  const manifestUrl = window.location.origin.includes(':5173')
65
- ? 'http://localhost:3000/app-routes.json'
65
+ ? '/app-routes.json'
66
66
  : '/app-routes.json'
67
67
 
68
68
  const manifestResponse = await fetch(manifestUrl, {
package/src/vite/index.ts CHANGED
@@ -1162,6 +1162,27 @@ const ${componentName} = registerClientReference(
1162
1162
  }
1163
1163
  })
1164
1164
 
1165
+ server.middlewares.use('/app-routes.json', async (req, res) => {
1166
+ try {
1167
+ const manifestPath = path.join(server.config.root, 'dist', 'app-routes.json')
1168
+ if (fs.existsSync(manifestPath)) {
1169
+ const manifestContent = await fs.promises.readFile(manifestPath, 'utf-8')
1170
+ res.statusCode = 200
1171
+ res.setHeader('Content-Type', 'application/json')
1172
+ res.setHeader('Cache-Control', 'no-cache')
1173
+ res.end(manifestContent)
1174
+ }
1175
+ else {
1176
+ res.statusCode = 404
1177
+ res.end('Manifest not found')
1178
+ }
1179
+ }
1180
+ catch (error) {
1181
+ res.statusCode = 500
1182
+ res.end(`Error reading manifest: ${error instanceof Error ? error.message : String(error)}`)
1183
+ }
1184
+ })
1185
+
1165
1186
  server.middlewares.use('/api/vite/hmr-transform', async (req, res) => {
1166
1187
  if (req.method !== 'POST') {
1167
1188
  res.statusCode = 405