@gracile/engine 0.0.4 → 0.1.1-next.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.
Files changed (70) hide show
  1. package/ambient.d.ts +6 -0
  2. package/dist/assertions.d.ts +1 -1
  3. package/dist/assertions.d.ts.map +1 -1
  4. package/dist/build/static.d.ts +12 -3
  5. package/dist/build/static.d.ts.map +1 -1
  6. package/dist/build/static.js +34 -19
  7. package/dist/dev/dev.d.ts +5 -2
  8. package/dist/dev/dev.d.ts.map +1 -1
  9. package/dist/dev/dev.js +14 -7
  10. package/dist/dev/server.d.ts +22 -2
  11. package/dist/dev/server.d.ts.map +1 -1
  12. package/dist/dev/server.js +51 -23
  13. package/dist/preview.d.ts +1 -1
  14. package/dist/preview.d.ts.map +1 -1
  15. package/dist/preview.js +3 -0
  16. package/dist/render/route-template.d.ts +14 -3
  17. package/dist/render/route-template.d.ts.map +1 -1
  18. package/dist/render/route-template.js +49 -11
  19. package/dist/render/utils.d.ts.map +1 -0
  20. package/dist/routes/collect.d.ts +2 -3
  21. package/dist/routes/collect.d.ts.map +1 -1
  22. package/dist/routes/collect.js +5 -2
  23. package/dist/routes/load-module.d.ts +5 -1
  24. package/dist/routes/load-module.d.ts.map +1 -1
  25. package/dist/routes/load-module.js +15 -6
  26. package/dist/routes/match.d.ts +4 -2
  27. package/dist/routes/match.d.ts.map +1 -1
  28. package/dist/routes/match.js +9 -6
  29. package/dist/routes/route.d.ts +19 -1
  30. package/dist/routes/route.d.ts.map +1 -1
  31. package/dist/routes/route.js +23 -1
  32. package/dist/server/env.d.ts +5 -0
  33. package/dist/server/env.d.ts.map +1 -0
  34. package/dist/server/env.js +6 -0
  35. package/dist/server/request.d.ts +21 -0
  36. package/dist/server/request.d.ts.map +1 -0
  37. package/dist/{dev → server}/request.js +64 -26
  38. package/dist/server/server.d.ts +4 -0
  39. package/dist/server/server.d.ts.map +1 -0
  40. package/dist/server/server.js +25 -0
  41. package/dist/server/utils.d.ts +4 -0
  42. package/dist/server/utils.d.ts.map +1 -0
  43. package/dist/server/utils.js +21 -0
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/dist/user-config.d.ts +11 -0
  46. package/dist/user-config.d.ts.map +1 -1
  47. package/dist/user-config.js +9 -0
  48. package/dist/vite/build.d.ts.map +1 -1
  49. package/dist/vite/build.js +123 -8
  50. package/dist/vite/config.d.ts +1 -0
  51. package/dist/vite/config.d.ts.map +1 -1
  52. package/dist/vite/config.js +6 -1
  53. package/dist/vite/plugins/build-routes.d.ts +28 -0
  54. package/dist/vite/plugins/build-routes.d.ts.map +1 -0
  55. package/dist/vite/plugins/build-routes.js +103 -0
  56. package/dist/vite/plugins/virtual-routes.d.ts +11 -0
  57. package/dist/vite/plugins/virtual-routes.d.ts.map +1 -0
  58. package/dist/vite/plugins/virtual-routes.js +51 -0
  59. package/dist/vite/server.d.ts +4 -1
  60. package/dist/vite/server.d.ts.map +1 -1
  61. package/dist/vite/server.js +5 -3
  62. package/package.json +10 -11
  63. package/dist/dev/request.d.ts +0 -4
  64. package/dist/dev/request.d.ts.map +0 -1
  65. package/dist/vite/plugins/html-static-pages.d.ts +0 -13
  66. package/dist/vite/plugins/html-static-pages.d.ts.map +0 -1
  67. package/dist/vite/plugins/html-static-pages.js +0 -58
  68. package/dist/vite/utils.d.ts.map +0 -1
  69. /package/dist/{vite → render}/utils.d.ts +0 -0
  70. /package/dist/{vite → render}/utils.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"match.d.ts","sourceRoot":"","sources":["../../src/routes/match.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAI1C,OAAO,KAAK,CAAC,MAAM,YAAY,CAAC;AAEhC,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AA+EjD,MAAM,MAAM,UAAU,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB,CAAC;AACF,wBAAsB,QAAQ,CAAC,OAAO,EAAE;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,aAAa,CAAC;CACpB,GAAG,OAAO,CAAC,UAAU,CAAC,CAqBtB"}
1
+ {"version":3,"file":"match.d.ts","sourceRoot":"","sources":["../../src/routes/match.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,KAAK,CAAC,MAAM,YAAY,CAAC;AAErC,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAoFjD,MAAM,MAAM,UAAU,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACrC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CACjB,CAAC;AACF,wBAAsB,QAAQ,CAAC,OAAO,EAAE;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACjC,MAAM,EAAE,CAAC,CAAC,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,CAAC,CAAC,aAAa,GAAG,SAAS,CAAC;CAC3C,GAAG,OAAO,CAAC,UAAU,CAAC,CA2BtB"}
@@ -1,7 +1,6 @@
1
- import { routes } from './collect.js';
2
1
  import { loadForeignRouteObject } from './load-module.js';
3
- import * as R from './route.js';
4
- function matchRouteFromUrl(url) {
2
+ // FIXME: proper DI for routes
3
+ function matchRouteFromUrl(url, routes) {
5
4
  let match;
6
5
  let foundRoute;
7
6
  const pathname = new URL(url).pathname;
@@ -44,9 +43,13 @@ function extractStaticPaths(options) {
44
43
  return { staticPaths, props };
45
44
  }
46
45
  export async function getRoute(options) {
47
- const { foundRoute, pathname, params } = matchRouteFromUrl(options.url);
48
- const routePath = foundRoute.filePath;
49
- const routeModule = await loadForeignRouteObject(options.vite, routePath);
46
+ const { foundRoute, pathname, params } = matchRouteFromUrl(options.url, options.routes);
47
+ // TODO: Simplify all the routes things
48
+ const routeModule = await loadForeignRouteObject({
49
+ vite: options.vite,
50
+ route: foundRoute,
51
+ routeImports: options.routeImports,
52
+ });
50
53
  const staticPaths = extractStaticPaths({
51
54
  routeModule,
52
55
  foundRoute,
@@ -3,17 +3,31 @@ import type { TemplateResult } from 'lit';
3
3
  export type MethodHtml = 'GET' | 'POST';
4
4
  export type MethodNonHtml = 'QUERY' | 'PUT' | 'PATCH' | 'DELETE';
5
5
  export type Method = MethodHtml & MethodNonHtml;
6
+ export declare const RequestMethod: {
7
+ readonly GET: "GET";
8
+ readonly QUERY: "QUERY";
9
+ readonly HEAD: "HEAD";
10
+ readonly POST: "POST";
11
+ readonly PUT: "PUT";
12
+ readonly DELETE: "DELETE";
13
+ readonly OPTIONS: "OPTIONS";
14
+ readonly PATCH: "PATCH";
15
+ };
6
16
  export type ModuleOptions = {
7
17
  staticPaths?: StaticPathsGeneric;
18
+ locals?: (locals: any) => any;
8
19
  handler?: HandlerGeneric;
9
- template?: (context: RouteContextGeneric) => RouteTemplateResult;
20
+ prerender?: boolean | undefined;
10
21
  document?: DocumentTemplate<RouteContextGeneric>;
22
+ template?: (context: RouteContextGeneric) => RouteTemplateResult;
11
23
  };
12
24
  export declare class RouteModule {
13
25
  #private;
14
26
  get staticPaths(): StaticPathsGeneric | undefined;
27
+ get locals(): ((locals: any) => any) | undefined;
15
28
  get handler(): Handler<object | Response | undefined> | Partial<Record<MethodHtml, Handler<object | Response | undefined>> & Record<MethodNonHtml, Handler<Response>>> | undefined;
16
29
  get document(): DocumentTemplate<RouteContextGeneric> | undefined;
30
+ get prerender(): boolean | undefined;
17
31
  get template(): ((context: RouteContextGeneric) => RouteTemplateResult) | undefined;
18
32
  constructor(options: ModuleOptions);
19
33
  }
@@ -27,6 +41,7 @@ export type Handler<Data extends HandlerData | HandlerDataHtml = never> = (conte
27
41
  */
28
42
  params: Params;
29
43
  request: Request;
44
+ locals: App.Locals;
30
45
  /**
31
46
  * Let you mutate the downstream **page** response.
32
47
  *
@@ -60,4 +75,7 @@ export interface Route {
60
75
  hasParams: boolean;
61
76
  pageAssets: string[];
62
77
  }
78
+ export type RoutesManifest = Map<string, Route>;
79
+ export type RoutesImports = Map<string, () => Record<string, unknown>>;
80
+ export type RoutesAssets = Map<string, string>;
63
81
  //# sourceMappingURL=route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/routes/route.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../../src/routes/route.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,25 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ // export type KnownMethod = typeof knownMethods[number];
3
+ export const RequestMethod = {
4
+ GET: 'GET',
5
+ QUERY: 'QUERY',
6
+ HEAD: 'HEAD',
7
+ POST: 'POST',
8
+ PUT: 'PUT',
9
+ DELETE: 'DELETE',
10
+ OPTIONS: 'OPTIONS',
11
+ PATCH: 'PATCH',
12
+ };
1
13
  // TODO: put in engine
2
14
  export class RouteModule {
3
15
  #staticPaths;
4
16
  get staticPaths() {
5
17
  return this.#staticPaths;
6
18
  }
19
+ #locals;
20
+ get locals() {
21
+ return this.#locals;
22
+ }
7
23
  #handler;
8
24
  get handler() {
9
25
  return this.#handler;
@@ -12,6 +28,10 @@ export class RouteModule {
12
28
  get document() {
13
29
  return this.#document;
14
30
  }
31
+ #prerender;
32
+ get prerender() {
33
+ return this.#prerender;
34
+ }
15
35
  #template;
16
36
  get template() {
17
37
  return this.#template;
@@ -23,10 +43,12 @@ export class RouteModule {
23
43
  typeof options.handler === 'function') &&
24
44
  options.handler)
25
45
  this.#handler = options.handler;
26
- // if (options.fragment) this.#fragment = options.fragment;
46
+ this.#locals = options.locals;
27
47
  if (typeof options.template === 'function')
28
48
  this.#template = options.template;
29
49
  if (typeof options.document === 'function')
30
50
  this.#document = options.document;
51
+ if (typeof options.prerender === 'boolean')
52
+ this.#prerender = options.prerender;
31
53
  }
32
54
  }
@@ -0,0 +1,5 @@
1
+ export declare const IP_LOCALHOST = "127.0.0.1";
2
+ export declare const IP_EXPOSED = "0.0.0.0";
3
+ export declare const RANDOM_PORT = 0;
4
+ export declare const PUBLIC_DIR: "public" | "./dist/client";
5
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/server/env.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY,cAAc,CAAC;AACxC,eAAO,MAAM,UAAU,YAAY,CAAC;AACpC,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B,eAAO,MAAM,UAAU,4BAEM,CAAC"}
@@ -0,0 +1,6 @@
1
+ export const IP_LOCALHOST = '127.0.0.1';
2
+ export const IP_EXPOSED = '0.0.0.0';
3
+ export const RANDOM_PORT = 0;
4
+ export const PUBLIC_DIR = import.meta.env?.DEV
5
+ ? 'public'
6
+ : './dist/client';
@@ -0,0 +1,21 @@
1
+ import type { IncomingMessage, ServerResponse } from 'node:http';
2
+ import type { ViteDevServer } from 'vite';
3
+ import type * as R from '../routes/route.js';
4
+ type NextFunction = (error?: unknown) => void | Promise<void>;
5
+ /**
6
+ * This is fully compatible with Express or bare Node HTTP
7
+ * What it adds on top of Connect-style middleware:
8
+ * 1. Async.
9
+ * 2. Can return a `ServerResponse`
10
+ */
11
+ export type ConnectLikeAsyncMiddleware = (req: IncomingMessage, res: ServerResponse, next: NextFunction) => Promise<void | NextFunction | ServerResponse> | (void | NextFunction | ServerResponse);
12
+ export declare function createGracileMiddleware({ vite, routes, routeImports, routeAssets, root, serverMode, }: {
13
+ vite?: ViteDevServer | undefined;
14
+ routes: R.RoutesManifest;
15
+ routeImports?: R.RoutesImports | undefined;
16
+ routeAssets?: R.RoutesAssets;
17
+ root: string;
18
+ serverMode?: boolean | undefined;
19
+ }): ConnectLikeAsyncMiddleware;
20
+ export {};
21
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/server/request.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAMjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAU1C,OAAO,KAAK,KAAK,CAAC,MAAM,oBAAoB,CAAC;AAE7C,KAAK,YAAY,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE9D;;;;;GAKG;AACH,MAAM,MAAM,0BAA0B,GAAG,CACxC,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,YAAY,KAEjB,OAAO,CAAC,IAAI,GAAG,YAAY,GAAG,cAAc,CAAC,GAE5C,CAAC,IAAI,GAAG,YAAY,GAAG,cAAc,CAAC,CAAC;AAM1C,wBAAgB,uBAAuB,CAAC,EACvC,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,UAAU,GACV,EAAE;IACF,IAAI,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACjC,MAAM,EAAE,CAAC,CAAC,cAAc,CAAC;IACzB,YAAY,CAAC,EAAE,CAAC,CAAC,aAAa,GAAG,SAAS,CAAC;IAC3C,WAAW,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACjC,8BAsOA"}
@@ -2,40 +2,60 @@ import { Writable } from 'node:stream';
2
2
  import { logger } from '@gracile/internal-utils/logger';
3
3
  import { createServerAdapter } from '@whatwg-node/server';
4
4
  import c from 'picocolors';
5
+ import { isUnknownObject } from '../assertions.js';
5
6
  import { /* errorInline, */ errorPage } from '../errors/templates.js';
6
7
  import { renderRouteTemplate, } from '../render/route-template.js';
8
+ import { renderSsrTemplate } from '../render/utils.js';
7
9
  import { getRoute } from '../routes/match.js';
8
- import { renderSsrTemplate } from '../vite/utils.js';
9
10
  // NOTE: Find a more canonical way to ponyfill the Node HTTP request to standard Request
10
11
  // @ts-expect-error Abusing this feature!
11
12
  const adapter = createServerAdapter((request) => request);
12
- export function createDevRequestHandler(vite) {
13
- return async (req, res, next) => {
14
- const url = req.originalUrl;
15
- logger.info(`[${c.yellow(req.method)}] ${c.yellow(url)}`, {
13
+ export function createGracileMiddleware({ vite, routes, routeImports, routeAssets, root, serverMode, }) {
14
+ const middleware = async (req, res, next) => {
15
+ // Typing workaround
16
+ if (!req.url)
17
+ throw Error('Incorrect url');
18
+ if (!req.method)
19
+ throw Error('Incorrect method');
20
+ logger.info(`[${c.yellow(req.method)}] ${c.yellow(req.url)}`, {
16
21
  timestamp: true,
17
22
  });
18
23
  // MARK: Skip unwanted requests
19
24
  if (
20
25
  //
21
- url.endsWith('favicon.ico') ||
22
- url.endsWith('favicon.svg'))
26
+ req.url.endsWith('favicon.ico') ||
27
+ req.url.endsWith('favicon.svg'))
23
28
  return next();
24
29
  const requestPonyfilled = (await Promise.resolve(adapter.handleNodeRequest(req)));
25
30
  async function renderPageFn(handlerInfos, routeInfos) {
26
- const { output } = await renderRouteTemplate(requestPonyfilled, vite, 'dev', routeInfos, handlerInfos);
27
- return output;
31
+ const { output } = await renderRouteTemplate({
32
+ request: requestPonyfilled,
33
+ vite,
34
+ mode: 'dev',
35
+ routeInfos,
36
+ handlerInfos,
37
+ routeAssets,
38
+ root,
39
+ serverMode,
40
+ });
41
+ return output || undefined;
28
42
  }
29
43
  try {
30
44
  // MARK: Get route infos
31
45
  const moduleInfos = await getRoute({
32
46
  url: requestPonyfilled.url,
33
47
  vite,
48
+ routes,
49
+ routeImports,
34
50
  });
35
51
  let output;
36
52
  // TODO: should move this to `special-file` so we don't recalculate on each request
37
53
  // + we would be able to do some route codegen.
38
54
  const response = {};
55
+ // NOTE: Only for Express for now.
56
+ let locals = {};
57
+ if ('locals' in res && isUnknownObject(res.locals))
58
+ locals = res.locals;
39
59
  // MARK: Server handler
40
60
  const handler = moduleInfos.routeModule.handler;
41
61
  if ('handler' in moduleInfos.routeModule &&
@@ -45,6 +65,7 @@ export function createDevRequestHandler(vite) {
45
65
  url: new URL(requestPonyfilled.url),
46
66
  response,
47
67
  params: moduleInfos.params,
68
+ locals,
48
69
  };
49
70
  // MARK: Top level handler
50
71
  if (typeof handler === 'function') {
@@ -52,13 +73,13 @@ export function createDevRequestHandler(vite) {
52
73
  if (handlerOutput instanceof Response)
53
74
  output = handlerOutput;
54
75
  else
55
- throw new Error('Catch-all handler must return a Response object.');
76
+ throw new TypeError('Catch-all handler must return a Response object.');
56
77
  // MARK: Handler with method
57
78
  }
58
79
  else if (requestPonyfilled.method in handler) {
59
80
  const handlerWithMethod = handler[requestPonyfilled.method];
60
81
  if (typeof handlerWithMethod !== 'function')
61
- throw Error('Handler must be a function.');
82
+ throw TypeError('Handler must be a function.');
62
83
  const handlerOutput = await Promise.resolve(handlerWithMethod(options));
63
84
  if (handlerOutput instanceof Response)
64
85
  output = handlerOutput;
@@ -85,10 +106,14 @@ export function createDevRequestHandler(vite) {
85
106
  if (output instanceof Response) {
86
107
  if (output.status >= 300 && output.status <= 303) {
87
108
  const location = output.headers.get('location');
88
- if (location)
89
- return res.redirect(location);
109
+ // if (location) return res.redirect(location);
110
+ if (location) {
111
+ res.statusCode = output.status;
112
+ res.setHeader('location', location);
113
+ return res.end(`Found. Redirecting to ${location}`);
114
+ }
90
115
  }
91
- output.headers?.forEach((content, header) => res.set(header, content));
116
+ output.headers?.forEach((content, header) => res.setHeader(header, content));
92
117
  if (output.status)
93
118
  res.statusCode = output.status;
94
119
  if (output.statusText)
@@ -100,17 +125,18 @@ export function createDevRequestHandler(vite) {
100
125
  output.body
101
126
  .pipeTo(Writable.toWeb(res))
102
127
  .catch((e) => logger.error(String(e)));
128
+ // else throw new Error('Missing body.');
103
129
  else
104
- throw new Error('Missing body.');
130
+ return res.end(output);
105
131
  // MARK: Stream page render
106
132
  }
107
133
  else {
108
- new Headers(response.headers)?.forEach((content, header) => res.set(header, content));
134
+ new Headers(response.headers)?.forEach((content, header) => res.setHeader(header, content));
109
135
  if (response.status)
110
136
  res.statusCode = response.status;
111
137
  if (response.statusText)
112
138
  res.statusMessage = response.statusText;
113
- res.set({ 'Content-Type': 'text/html' });
139
+ res.setHeader('Content-Type', 'text/html');
114
140
  // MARK: Page stream error
115
141
  output
116
142
  ?.on('error', (error) => {
@@ -124,11 +150,12 @@ export function createDevRequestHandler(vite) {
124
150
  // Maybe just returning nothing is better to not break the page?
125
151
  // Should send a overlay message anyway via WebSocket
126
152
  // vite.ws.send()
127
- setTimeout(() => {
128
- vite.hot.send('gracile:ssr-error', {
129
- message: errorMessage,
130
- });
131
- }, 500);
153
+ if (vite)
154
+ setTimeout(() => {
155
+ vite.hot.send('gracile:ssr-error', {
156
+ message: errorMessage,
157
+ });
158
+ }, 500);
132
159
  res.end('' /* errorInline(error) */);
133
160
  })
134
161
  .pipe(res);
@@ -137,15 +164,26 @@ export function createDevRequestHandler(vite) {
137
164
  }
138
165
  catch (e) {
139
166
  const error = e;
140
- vite.ssrFixStacktrace(error);
167
+ if (vite)
168
+ vite.ssrFixStacktrace(error);
169
+ // else
170
+ logger.error(error.message);
141
171
  if (error.cause === 404) {
142
- return res.status(404).end('404');
172
+ // TODO: Handle 404 with dedicated page
173
+ if (!vite)
174
+ return next();
175
+ res.statusCode = 404;
176
+ return res.end('404');
143
177
  // TODO: use a nice framework service page
144
178
  // .redirect(new URL('/__404/', requestPonyfilled.url).href)
145
179
  }
146
- const errorTemplate = await renderSsrTemplate(errorPage(error));
147
- res.status(500).end(await vite.transformIndexHtml(url, errorTemplate));
180
+ let errorTemplate = await renderSsrTemplate(errorPage(error));
181
+ if (vite)
182
+ errorTemplate = await vite.transformIndexHtml(req.url, errorTemplate);
183
+ res.statusCode = 500;
184
+ return res.end(errorTemplate);
148
185
  }
149
186
  return next();
150
187
  };
188
+ return middleware;
151
189
  }
@@ -0,0 +1,4 @@
1
+ import type { CreateMiddleware } from '../dev/server.js';
2
+ export declare const createHandlers: CreateMiddleware;
3
+ export { printNodeHttpServerAddressInfos as printAddressInfos } from './utils.js';
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAUzD,eAAO,MAAM,cAAc,EAAE,gBAiB5B,CAAC;AAEF,OAAO,EAAE,+BAA+B,IAAI,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { setCurrentWorkingDirectory } from '@gracile/internal-utils/paths';
2
+ import { routeAssets, routeImports, routes } from 'gracile:routes';
3
+ import { createGracileMiddleware } from './request.js';
4
+ routes.forEach((route, pattern) => {
5
+ routes.set(pattern, {
6
+ ...route,
7
+ pattern: new URLPattern(pattern, 'http://gracile'),
8
+ });
9
+ });
10
+ export const createHandlers = async ({ root = process.cwd(),
11
+ // hmrPort,
12
+ // NOTE: We need type parity with the dev. version of this function
13
+ // eslint-disable-next-line @typescript-eslint/require-await
14
+ } = {}) => {
15
+ setCurrentWorkingDirectory(root);
16
+ const gracileHandler = createGracileMiddleware({
17
+ root,
18
+ routes,
19
+ routeImports,
20
+ routeAssets,
21
+ serverMode: true,
22
+ });
23
+ return { handlers: [gracileHandler /* as RequestHandler */], vite: null };
24
+ };
25
+ export { printNodeHttpServerAddressInfos as printAddressInfos } from './utils.js';
@@ -0,0 +1,4 @@
1
+ import type { Server } from 'http';
2
+ import type { AddressInfo } from 'net';
3
+ export declare function printNodeHttpServerAddressInfos(instance: Server): AddressInfo;
4
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/server/utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAKvC,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,CAsB7E"}
@@ -0,0 +1,21 @@
1
+ // NOTE: Util. to pretty print for user provided server.
2
+ import { logger } from '@gracile/internal-utils/logger';
3
+ import { DEV } from 'esm-env';
4
+ import c from 'picocolors';
5
+ import { IP_EXPOSED } from './env.js';
6
+ export function printNodeHttpServerAddressInfos(instance) {
7
+ const infos = instance.address();
8
+ logger.info(c.green(`${DEV ? 'development' : 'production'} server started`), {
9
+ timestamp: true,
10
+ });
11
+ if (typeof infos === 'object' && infos && infos.port && infos.address) {
12
+ logger.info(`
13
+ ${c.dim('┃')} Local ${c.cyan(`http://localhost:${infos.port}/`)}` +
14
+ `${infos.address === IP_EXPOSED
15
+ ? `${c.dim('┃')} Network ${c.cyan(`http://${infos.address}:${infos.port}/`)}`
16
+ : ''}
17
+ `);
18
+ return infos;
19
+ }
20
+ throw Error('Invalid address/port.');
21
+ }