@gracile/engine 0.7.1 → 0.8.0-next.1

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 (64) hide show
  1. package/ambient.d.ts +16 -1
  2. package/dist/dev/{dev.d.ts → development.d.ts} +2 -2
  3. package/dist/dev/development.d.ts.map +1 -0
  4. package/dist/dev/{dev.js → development.js} +6 -6
  5. package/dist/dev/route-typings.d.ts.map +1 -1
  6. package/dist/dev/route-typings.js +3 -8
  7. package/dist/errors/create-vite-better-error.d.ts.map +1 -1
  8. package/dist/errors/create-vite-better-error.js +1 -3
  9. package/dist/errors/errors-data.d.ts +2 -2
  10. package/dist/errors/errors-data.d.ts.map +1 -1
  11. package/dist/errors/errors.d.ts +3 -3
  12. package/dist/errors/errors.d.ts.map +1 -1
  13. package/dist/errors/errors.js +7 -8
  14. package/dist/errors/pages.d.ts +2 -2
  15. package/dist/errors/pages.d.ts.map +1 -1
  16. package/dist/errors/pages.js +4 -4
  17. package/dist/plugin.d.ts +1 -2
  18. package/dist/plugin.d.ts.map +1 -1
  19. package/dist/plugin.js +17 -16
  20. package/dist/render/route-template.d.ts.map +1 -1
  21. package/dist/render/route-template.js +54 -54
  22. package/dist/render/utils.d.ts +1 -1
  23. package/dist/render/utils.d.ts.map +1 -1
  24. package/dist/routes/collect.d.ts.map +1 -1
  25. package/dist/routes/collect.js +31 -34
  26. package/dist/routes/comparator.d.ts.map +1 -1
  27. package/dist/routes/comparator.js +5 -6
  28. package/dist/routes/load-module.d.ts.map +1 -1
  29. package/dist/routes/load-module.js +12 -12
  30. package/dist/routes/match.d.ts +2 -2
  31. package/dist/routes/match.d.ts.map +1 -1
  32. package/dist/routes/match.js +18 -21
  33. package/dist/{build/static.d.ts → routes/render.d.ts} +2 -2
  34. package/dist/routes/render.d.ts.map +1 -0
  35. package/dist/{build/static.js → routes/render.js} +34 -29
  36. package/dist/routes/route.d.ts +5 -5
  37. package/dist/routes/route.d.ts.map +1 -1
  38. package/dist/routes/route.js +1 -1
  39. package/dist/server/adapters/hono.d.ts +3 -3
  40. package/dist/server/adapters/hono.d.ts.map +1 -1
  41. package/dist/server/adapters/hono.js +3 -2
  42. package/dist/server/adapters/node.d.ts +5 -5
  43. package/dist/server/adapters/node.d.ts.map +1 -1
  44. package/dist/server/adapters/node.js +25 -21
  45. package/dist/server/request.d.ts.map +1 -1
  46. package/dist/server/request.js +25 -22
  47. package/dist/server/utils.d.ts +0 -1
  48. package/dist/server/utils.d.ts.map +1 -1
  49. package/dist/server/utils.js +14 -17
  50. package/dist/vite/{plugins/build-routes.d.ts → build-routes.d.ts} +3 -3
  51. package/dist/vite/build-routes.d.ts.map +1 -0
  52. package/dist/vite/{plugins/build-routes.js → build-routes.js} +24 -29
  53. package/dist/vite/html-routes.d.ts +10 -0
  54. package/dist/vite/html-routes.d.ts.map +1 -0
  55. package/dist/vite/html-routes.js +25 -0
  56. package/dist/vite/{plugins/virtual-routes.d.ts → virtual-routes.d.ts} +6 -3
  57. package/dist/vite/virtual-routes.d.ts.map +1 -0
  58. package/dist/vite/{plugins/virtual-routes.js → virtual-routes.js} +15 -17
  59. package/package.json +8 -9
  60. package/dist/build/static.d.ts.map +0 -1
  61. package/dist/dev/dev.d.ts.map +0 -1
  62. package/dist/tsconfig.tsbuildinfo +0 -1
  63. package/dist/vite/plugins/build-routes.d.ts.map +0 -1
  64. package/dist/vite/plugins/virtual-routes.d.ts.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { Writable } from 'node:stream';
2
2
  import { fileURLToPath } from 'node:url';
3
- import { env } from '@gracile/internal-utils/env';
3
+ import { nodeCondition } from '@gracile/internal-utils/node-condition/production-ssr';
4
4
  import { createLogger } from '@gracile/internal-utils/logger/helpers';
5
5
  import { createServerAdapter } from '@whatwg-node/server';
6
6
  import { GracileError, GracileErrorData } from '../../errors/errors.js';
@@ -9,15 +9,16 @@ import { isRedirect, } from '../request.js';
9
9
  // NOTE: Find a more canonical way to ponyfill the Node HTTP request to standard Request
10
10
  // @ts-expect-error Abusing this feature!
11
11
  const nodeRequestToStandardRequest = createServerAdapter((request) => request);
12
- function standardResponseInitToNodeResponse(responseInit, res) {
12
+ function standardResponseInitToNodeResponse(responseInit, response) {
13
13
  const headers = responseInit instanceof Response
14
14
  ? responseInit.headers
15
15
  : new Headers(responseInit.headers);
16
- headers.forEach((content, header) => res.setHeader(header, content));
16
+ for (const [header, content] of headers.entries())
17
+ response.setHeader(header, content);
17
18
  if (responseInit.status)
18
- res.statusCode = responseInit.status;
19
+ response.statusCode = responseInit.status;
19
20
  if (responseInit.statusText)
20
- res.statusMessage = responseInit.statusText;
21
+ response.statusMessage = responseInit.statusText;
21
22
  }
22
23
  /**
23
24
  * @param handler - Takes a pre-built Gracile handler from `./dist/server/entrypoint.js`.
@@ -38,49 +39,51 @@ function standardResponseInitToNodeResponse(responseInit, res) {
38
39
  * ```
39
40
  */
40
41
  export function nodeAdapter(handler, options) {
41
- return async function nodeHandler(req, res, locals) {
42
+ return async function nodeHandler(request, response, locals) {
42
43
  const logger = createLogger(options?.logger);
43
44
  let webRequest;
44
45
  try {
45
46
  webRequest = (await Promise.resolve(nodeRequestToStandardRequest.handleNodeRequest(
46
47
  // HACK: Exact optional properties
47
- req)));
48
+ request)));
48
49
  }
49
- catch (e) {
50
+ catch (error) {
50
51
  throw new GracileError({
51
52
  ...GracileErrorData.InvalidRequestInAdapter,
52
53
  message: GracileErrorData.InvalidRequestInAdapter.message('Node'),
53
54
  }, {
54
- cause: e,
55
+ cause: error,
55
56
  });
56
57
  }
57
58
  const mergedLocals = {
58
- ...(locals ?? {}),
59
- ...('locals' in res && typeof res.locals === 'object' ? res.locals : {}),
59
+ ...(locals || null),
60
+ ...('locals' in response && typeof response.locals === 'object'
61
+ ? response.locals
62
+ : {}),
60
63
  };
61
64
  const result = await handler(webRequest, mergedLocals);
62
65
  if (result?.body) {
63
- standardResponseInitToNodeResponse(result.init, res);
66
+ standardResponseInitToNodeResponse(result.init, response);
64
67
  // NOTE: We can't do similar thing with Hono with just
65
68
  // a standard Response workflow, it seems
66
69
  result.body.addListener('error', (error) => {
67
- if (env.DEV)
70
+ if (nodeCondition.DEV)
68
71
  logger.error(String(error));
69
72
  // NOTE: res.writeHead doesn't seems to take effect, too (too late)
70
73
  // res.statusCode = 500;
71
- res.end(env.DEV ? '__SSR_ERROR__' : undefined);
74
+ response.end(nodeCondition.DEV ? '__SSR_ERROR__' : undefined);
72
75
  });
73
- return result.body.pipe(res);
76
+ return result.body.pipe(response);
74
77
  }
75
78
  if (result?.response) {
76
- standardResponseInitToNodeResponse(result.response, res);
79
+ standardResponseInitToNodeResponse(result.response, response);
77
80
  const redirect = isRedirect(result.response);
78
81
  if (redirect)
79
- return res.end(result.body);
82
+ return response.end(result.body);
80
83
  if (result.response.body) {
81
84
  const piped = await result.response.body
82
- .pipeTo(Writable.toWeb(res))
83
- .catch((e) => logger.error(String(e)));
85
+ .pipeTo(Writable.toWeb(response))
86
+ .catch((error) => logger.error(String(error)));
84
87
  return piped;
85
88
  }
86
89
  }
@@ -100,10 +103,11 @@ export function nodeAdapter(handler, options) {
100
103
  *
101
104
  * const app = express();
102
105
  *
103
- * app.use(express.static(gracile.getClientDistPath(import.meta.url)));
106
+ * app.use(express.static(gracile.getClientBuildPath(import.meta.url)));
104
107
  * ```
105
108
  */
106
- export function getClientDistPath(root) {
109
+ export function getClientBuildPath(root) {
107
110
  return fileURLToPath(new URL(constants.CLIENT_DIST_DIR, root));
108
111
  }
109
112
  export { printUrls } from '../utils.js';
113
+ export {} from '../request.js';
@@ -1 +1 @@
1
- {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/server/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAOvC,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAQlD,OAAO,KAAK,KAAK,CAAC,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,KAAK,gBAAgB,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAC3E,KAAK,wBAAwB,GAAG;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,YAAY,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,cAAc;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAC5B,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,OAAO,KACZ,OAAO,CAAC,gBAAgB,GAAG,wBAAwB,GAAG,IAAI,CAAC,CAAC;AAIjE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAO1E;AAED,wBAAgB,oBAAoB,CAAC,EACpC,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,UAAU,EACV,aAAa,GACb,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;IACjC,aAAa,EAAE,aAAa,CAAC;CAC7B,kBA4QA"}
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/server/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAOvC,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAQlD,OAAO,KAAK,KAAK,CAAC,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,KAAK,gBAAgB,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAC;IAAC,IAAI,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC;AAC3E,KAAK,wBAAwB,GAAG;IAC/B,QAAQ,CAAC,EAAE,KAAK,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,YAAY,CAAC;CACnB,CAAC;AAEF,MAAM,WAAW,cAAc;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,CAC5B,OAAO,EAAE,OAAO,EAChB,MAAM,CAAC,EAAE,OAAO,KACZ,OAAO,CAAC,gBAAgB,GAAG,wBAAwB,GAAG,IAAI,CAAC,CAAC;AASjE,wBAAgB,UAAU,CAAC,QAAQ,EAAE,QAAQ,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAO1E;AAED,wBAAgB,oBAAoB,CAAC,EACpC,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,WAAW,EACX,IAAI,EACJ,UAAU,EACV,aAAa,GACb,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;IACjC,aAAa,EAAE,aAAa,CAAC;CAC7B,kBA8QA"}
@@ -2,12 +2,16 @@ import { Readable } from 'node:stream';
2
2
  import * as assert from '@gracile/internal-utils/assertions';
3
3
  import { getLogger } from '@gracile/internal-utils/logger/helpers';
4
4
  import c from 'picocolors';
5
- import { GracileError } from '../errors/errors.js';
5
+ // import { GracileError } from '../errors/errors.js';
6
6
  import { builtIn404Page, builtInErrorPage } from '../errors/pages.js';
7
7
  import { renderRouteTemplate } from '../render/route-template.js';
8
8
  import { renderLitTemplate } from '../render/utils.js';
9
9
  import { getRoute } from '../routes/match.js';
10
10
  const CONTENT_TYPE_HTML = { 'Content-Type': 'text/html' };
11
+ const PREMISE_REGEXES = {
12
+ properties: /\/__(.*?)\.props\.json$/,
13
+ document: /\/__(.*?)\.doc\.html$/,
14
+ };
11
15
  export function isRedirect(response) {
12
16
  const location = response.headers.get('location');
13
17
  if (response.status >= 300 && response.status <= 303 && location) {
@@ -21,17 +25,18 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
21
25
  const { url: requestedUrl, method } = request;
22
26
  let emitViteBetterError = null;
23
27
  if (vite)
24
- emitViteBetterError = await import('../errors/create-vite-better-error.js').then(({ emitViteBetterError: e }) => e);
28
+ emitViteBetterError = await import('../errors/create-vite-better-error.js').then(({ emitViteBetterError: error }) => error);
25
29
  try {
26
30
  // MARK: Rewrite hidden route siblings
27
31
  const fullUrl = requestedUrl.replace(/\/__(.*)$/, '/');
32
+ // MARK: Setup premises
33
+ const propertiesOnly = PREMISE_REGEXES.properties.test(requestedUrl);
34
+ const documentOnly = PREMISE_REGEXES.document.test(requestedUrl);
35
+ const allowPremises = Boolean(gracileConfig.pages?.premises?.expose);
36
+ if (allowPremises === false && (propertiesOnly || documentOnly))
37
+ throw new Error('Accessed a page premise but they are not activated. You must enable `pages.premises.expose`.');
38
+ const premises = allowPremises ? { propertiesOnly, documentOnly } : null;
28
39
  // MARK: Get route infos
29
- const exposePremises = gracileConfig.pages?.premises?.expose
30
- ? {
31
- propsOnly: /\/__(.*?)\.props\.json$/.test(requestedUrl),
32
- docOnly: /\/__(.*?)\.doc\.html$/.test(requestedUrl),
33
- }
34
- : null;
35
40
  const routeOptions = {
36
41
  url: fullUrl,
37
42
  vite,
@@ -65,7 +70,7 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
65
70
  root,
66
71
  serverMode,
67
72
  routeInfos,
68
- docOnly: exposePremises?.docOnly,
73
+ docOnly: premises?.documentOnly,
69
74
  };
70
75
  logger.info(`[${c.yellow(method)}] ${c.yellow(fullUrl)}`, {
71
76
  timestamp: true,
@@ -76,8 +81,7 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
76
81
  providedLocals = locals;
77
82
  // MARK: Server handler
78
83
  const handler = routeInfos.routeModule.handler;
79
- if (('handler' in routeInfos.routeModule &&
80
- typeof handler !== 'undefined') ||
84
+ if (('handler' in routeInfos.routeModule && handler !== undefined) ||
81
85
  // TODO: Explain this condition
82
86
  (handler && 'GET' in handler === false && method !== 'GET')) {
83
87
  const routeContext = Object.freeze({
@@ -89,7 +93,7 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
89
93
  });
90
94
  // MARK: Run user middleware
91
95
  // NOTE: Experimental
92
- // eslint-disable-next-line no-inner-declarations
96
+ /// eslint-disable-next-line no-inner-declarations
93
97
  // async function useHandler() {}
94
98
  // if (vite) {
95
99
  // const middleware = await vite
@@ -115,7 +119,7 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
115
119
  ? handler
116
120
  : handler[method];
117
121
  if (typeof handlerWithMethod !== 'function')
118
- throw TypeError('Handler must be a function.');
122
+ throw new TypeError('Handler must be a function.');
119
123
  const handlerOutput = await Promise.resolve(handlerWithMethod(routeContext));
120
124
  if (assert.isResponseOrPatchedResponse(handlerOutput))
121
125
  output = handlerOutput;
@@ -123,7 +127,7 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
123
127
  routeTemplateOptions.routeInfos.props = hasTopLevelHandler
124
128
  ? handlerOutput
125
129
  : { [method]: handlerOutput };
126
- if (exposePremises?.docOnly) {
130
+ if (premises?.documentOnly) {
127
131
  const { document } = await renderRouteTemplate(routeTemplateOptions);
128
132
  return {
129
133
  response: new Response(document, {
@@ -131,7 +135,7 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
131
135
  }),
132
136
  };
133
137
  }
134
- if (exposePremises?.propsOnly)
138
+ if (premises?.propertiesOnly)
135
139
  return {
136
140
  response: Response.json(routeTemplateOptions.routeInfos.props),
137
141
  };
@@ -147,7 +151,7 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
147
151
  }
148
152
  }
149
153
  else {
150
- if (exposePremises?.docOnly) {
154
+ if (premises?.documentOnly) {
151
155
  const { document } = await renderRouteTemplate(routeTemplateOptions);
152
156
  return {
153
157
  response: new Response(document, {
@@ -155,7 +159,7 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
155
159
  }),
156
160
  };
157
161
  }
158
- if (exposePremises?.propsOnly)
162
+ if (premises?.propertiesOnly)
159
163
  return {
160
164
  response: Response.json(routeTemplateOptions.routeInfos.props || {}),
161
165
  };
@@ -188,16 +192,15 @@ export function createGracileHandler({ vite, routes, routeImports, routeAssets,
188
192
  const payload = {
189
193
  type: 'error',
190
194
  // FIXME: Use the emitViteBetterError instead (but flaky for now with streaming)
191
- // @ts-expect-error ...........
192
- err: new GracileError({
195
+ // err: new GracileError({}),
196
+ err: {
193
197
  name: 'StreamingError',
194
- title: 'An error occured during the page template streaming.',
195
198
  message: errorMessage,
199
+ stack: error.stack,
196
200
  hint: 'This is often caused by a wrong template location dynamic interpolation.',
197
- // @ts-expect-error ...........
198
201
  cause: error,
199
202
  // highlightedCode: error.message,
200
- }),
203
+ },
201
204
  };
202
205
  //
203
206
  setTimeout(() => {
@@ -2,7 +2,6 @@ import type { AddressInfo } from 'node:net';
2
2
  /**
3
3
  * Pretty print your server instance address as soon as it is listening.
4
4
  * Matches the dev. server CLI output style.
5
- *
6
5
  * @param server - Takes an `node:net` `AddressInfo` like object (address, family, port) or just a provided, pre-constructed string.
7
6
  * @example
8
7
  *
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/server/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAY5C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,QAwC5D"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/server/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAY5C;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,QA0C5D"}
@@ -1,5 +1,5 @@
1
1
  // NOTE: Util. to pretty print for user provided server.
2
- import { env as currentEnv } from '@gracile/internal-utils/env';
2
+ import { nodeCondition } from '@gracile/internal-utils/node-condition/production-ssr';
3
3
  import { getLogger } from '@gracile/internal-utils/logger/helpers';
4
4
  import c from 'picocolors';
5
5
  import { constants } from './constants.js';
@@ -9,7 +9,6 @@ import { constants } from './constants.js';
9
9
  /**
10
10
  * Pretty print your server instance address as soon as it is listening.
11
11
  * Matches the dev. server CLI output style.
12
- *
13
12
  * @param server - Takes an `node:net` `AddressInfo` like object (address, family, port) or just a provided, pre-constructed string.
14
13
  * @example
15
14
  *
@@ -30,27 +29,25 @@ export function printUrls(server) {
30
29
  let address = null;
31
30
  if (!server)
32
31
  throw new Error('Incorrect address infos');
33
- if (typeof server === 'string') {
34
- address = server;
35
- }
36
- else {
37
- address = `http://${server.address}${server.port ? `:${String(server.port)}` : ''}`;
38
- }
32
+ address =
33
+ typeof server === 'string'
34
+ ? server
35
+ : `http://${server.address}${server.port ? `:${String(server.port)}` : ''}`;
39
36
  // NOTE: Might move this to internal util env
40
- const envs = {
37
+ const environments = {
41
38
  PROD: 'production',
42
39
  DEV: 'development',
43
40
  PREVIEW: 'preview',
44
41
  TEST: 'testing',
45
42
  };
46
- let env = 'PROD';
47
- if (currentEnv.DEV)
48
- env = 'DEV';
49
- if (currentEnv.PREVIEW)
50
- env = 'PREVIEW';
51
- if (currentEnv.TEST)
52
- env = 'TEST';
53
- logger.info(c.green(`${envs[env]} ${c.yellow('server started')}`), {
43
+ let environment = 'PROD';
44
+ if (nodeCondition.DEV)
45
+ environment = 'DEV';
46
+ if (nodeCondition.PREVIEW)
47
+ environment = 'PREVIEW';
48
+ if (nodeCondition.TEST)
49
+ environment = 'TEST';
50
+ logger.info(c.green(`${environments[environment]} ${c.yellow('server started')}`), {
54
51
  timestamp: true,
55
52
  });
56
53
  if (address.includes(constants.IP_EXPOSED))
@@ -1,6 +1,6 @@
1
1
  import { type ViteDevServer } from 'vite';
2
- import type { RoutesManifest } from '../../routes/route.js';
3
- import type { GracileConfig } from '../../user-config.js';
2
+ import type { RoutesManifest } from '../routes/route.js';
3
+ import type { GracileConfig } from '../user-config.js';
4
4
  export declare const buildRoutes: ({ routes, viteServerForBuild, root, gracileConfig, serverMode, }: {
5
5
  routes: RoutesManifest;
6
6
  viteServerForBuild: ViteDevServer;
@@ -9,7 +9,7 @@ export declare const buildRoutes: ({ routes, viteServerForBuild, root, gracileCo
9
9
  serverMode?: boolean;
10
10
  }) => Promise<{
11
11
  routes: RoutesManifest;
12
- renderedRoutes: import("../../build/static.js").RenderedRouteDefinition[];
12
+ renderedRoutes: import("../routes/render.js").RenderedRouteDefinition[];
13
13
  inputList: string[];
14
14
  plugin: ({
15
15
  name: string;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-routes.d.ts","sourceRoot":"","sources":["../../src/vite/build-routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,aAAa,EAAE,MAAM,MAAM,CAAC;AAIrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AASvD,eAAO,MAAM,WAAW,qEAMrB;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,kBAAkB,EAAE,aAAa,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,aAAa,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;;;;;;;;;;;;;;;;;;;;;EA6JA,CAAC"}
@@ -1,7 +1,13 @@
1
1
  import { basename, extname, join } from 'node:path';
2
2
  import { createFilter } from 'vite';
3
- import { renderRoutes } from '../../build/static.js';
4
- import { REGEX_TAG_LINK, REGEX_TAG_SCRIPT, } from '../../render/route-template.js';
3
+ import { renderRoutes } from '../routes/render.js';
4
+ import { REGEX_TAG_LINK, REGEX_TAG_SCRIPT } from '../render/route-template.js';
5
+ function stripPremises(input) {
6
+ return input
7
+ .replace(/index\.html$/, '__index.doc.html')
8
+ .replace(/404\.html$/, '__404.doc.html')
9
+ .replace(/500\.html$/, '__500.doc.html');
10
+ }
5
11
  export const buildRoutes = async ({ routes, viteServerForBuild, root, gracileConfig, serverMode = false, }) => {
6
12
  // TODO: extract upstream, return just the plugins
7
13
  const { renderedRoutes } = await renderRoutes({
@@ -12,19 +18,17 @@ export const buildRoutes = async ({ routes, viteServerForBuild, root, gracileCon
12
18
  routes,
13
19
  });
14
20
  const inputList = renderedRoutes
15
- .filter((i) => i.html)
21
+ .filter((index) => index.html)
16
22
  .map((input) => input.name);
17
23
  const premisesFilter = gracileConfig.pages?.premises?.expose
18
24
  ? createFilter(gracileConfig.pages.premises.include, gracileConfig.pages.premises.exclude)
19
25
  : null;
20
26
  if (gracileConfig.pages?.premises?.expose && premisesFilter) {
27
+ // eslint-disable-next-line unicorn/no-array-for-each
21
28
  inputList.forEach((input) => {
22
29
  if (premisesFilter(input) === false)
23
30
  return;
24
- inputList.push(input
25
- .replace(/index\.html$/, '__index.doc.html')
26
- .replace(/404\.html$/, '__404.doc.html')
27
- .replace(/500\.html$/, '__500.doc.html'));
31
+ inputList.push(stripPremises(input));
28
32
  });
29
33
  }
30
34
  return {
@@ -37,31 +41,24 @@ export const buildRoutes = async ({ routes, viteServerForBuild, root, gracileCon
37
41
  apply: 'build',
38
42
  enforce: 'pre',
39
43
  resolveId(id) {
40
- if (extname(id) === '.html') {
41
- if (inputList.find((i) => i === id))
42
- return join(root, id);
43
- }
44
+ if (extname(id) === '.html' && inputList.includes(id))
45
+ return join(root, id);
44
46
  return null;
45
47
  },
46
48
  load(id) {
47
49
  if (extname(id) === '.html') {
48
50
  if (['index.html', '404.html', '500.html'].includes(basename(id))) {
49
- const content = renderedRoutes.find((i) => i.absoluteId === id)?.html;
51
+ const content = renderedRoutes.find((index) => index.absoluteId === id)?.html;
50
52
  if (content)
51
53
  return content;
52
54
  }
53
55
  if (gracileConfig.pages?.premises?.expose) {
54
56
  if (basename(id).endsWith('doc.html')) {
55
- const content = renderedRoutes.find((i) => {
56
- return (i.absoluteId
57
- .replace(/index\.html$/, '__index.doc.html')
58
- .replace(/404\.html$/, '__404.doc.html')
59
- .replace(/500\.html$/, '__500.doc.html') === id);
60
- })?.static.document;
57
+ const content = renderedRoutes.find((index) => stripPremises(index.absoluteId) === id)?.static.document;
61
58
  if (content)
62
59
  return content;
63
60
  }
64
- const content = renderedRoutes.find((i) => i.name === basename(id))?.html;
61
+ const content = renderedRoutes.find((index) => index.name === basename(id))?.html;
65
62
  if (content)
66
63
  return content;
67
64
  // return '';}
@@ -76,29 +73,28 @@ export const buildRoutes = async ({ routes, viteServerForBuild, root, gracileCon
76
73
  buildStart() {
77
74
  if (!gracileConfig.pages?.premises?.expose || !premisesFilter)
78
75
  return;
79
- renderedRoutes.forEach((route) => {
76
+ for (const route of renderedRoutes) {
80
77
  if (premisesFilter(route.name) === false)
81
- return;
78
+ continue;
82
79
  if (serverMode && route.savePrerender !== true)
83
- return;
80
+ continue;
84
81
  const fileNameParts = route.name.split('/');
85
82
  const last = fileNameParts.pop();
86
- const newName = last?.replace(/(.*)\.html$/, (_, r) => `__${r}.props.json`);
87
- if (!newName)
88
- throw new Error();
89
- fileNameParts.push(newName);
83
+ const properties = last?.replace(/(.*)\.html$/, (_, r) => `__${r}.props.json`);
84
+ if (!properties)
85
+ throw new Error('No props.');
86
+ fileNameParts.push(properties);
90
87
  const fileName = fileNameParts.join('/');
91
88
  this.emitFile({
92
89
  fileName,
93
90
  type: 'asset',
94
91
  source: JSON.stringify(route.static.props ?? {}),
95
92
  });
96
- });
93
+ }
97
94
  },
98
95
  generateBundle(_, bundle) {
99
96
  if (serverMode === false)
100
97
  return;
101
- // eslint-disable-next-line no-restricted-syntax, guard-for-in
102
98
  for (const fileKey in bundle) {
103
99
  const file = bundle[fileKey];
104
100
  if (fileKey.endsWith('.html') && file && 'source' in file) {
@@ -124,7 +120,6 @@ export const buildRoutes = async ({ routes, viteServerForBuild, root, gracileCon
124
120
  if (route)
125
121
  route.handlerAssets = collectedAssets;
126
122
  if (route?.savePrerender !== true) {
127
- // eslint-disable-next-line no-param-reassign, @typescript-eslint/no-dynamic-delete
128
123
  delete bundle[fileKey];
129
124
  // NOTE: Not sure if it's useful
130
125
  if (route?.html)
@@ -0,0 +1,10 @@
1
+ /**
2
+ * It make it possible to have HTML routes. It's funny,
3
+ * but not THAT useful.
4
+ * @todo Make tests and document this simple feature.
5
+ */
6
+ export declare function htmlRoutesLoader(): {
7
+ name: string;
8
+ load(this: import("rollup").PluginContext, id: string): Promise<string | null>;
9
+ }[];
10
+ //# sourceMappingURL=html-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"html-routes.d.ts","sourceRoot":"","sources":["../../src/vite/html-routes.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAgB,gBAAgB;;;IAoB/B"}
@@ -0,0 +1,25 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ /**
3
+ * It make it possible to have HTML routes. It's funny,
4
+ * but not THAT useful.
5
+ * @todo Make tests and document this simple feature.
6
+ */
7
+ export function htmlRoutesLoader() {
8
+ return [
9
+ {
10
+ name: 'gracile-html-route-loader',
11
+ async load(id) {
12
+ if (/\/src\/routes\/(.*?)\.html/.test(id) === false)
13
+ return null;
14
+ const htmlContent = await readFile(id, 'utf8');
15
+ return `import { defineRoute } from '@gracile/gracile/route';
16
+ import { html } from '@gracile/gracile/server-html';
17
+
18
+ export default defineRoute({
19
+ document: () => html\`${htmlContent.replaceAll('`', '\\`') /* Escape literal */}\`,
20
+ });
21
+ `;
22
+ },
23
+ },
24
+ ];
25
+ }
@@ -1,6 +1,9 @@
1
- import type { RenderedRouteDefinition } from '../../build/static.js';
2
- import type { RoutesManifest } from '../../routes/route.js';
3
- import type { GracileConfig } from '../../user-config.js';
1
+ import type { RenderedRouteDefinition } from '../routes/render.js';
2
+ import type { RoutesManifest } from '../routes/route.js';
3
+ import type { GracileConfig } from '../user-config.js';
4
+ /**
5
+ * @todo Client-side testing, docs.
6
+ */
4
7
  export declare function virtualRoutes({ routes, renderedRoutes, }: {
5
8
  routes: RoutesManifest;
6
9
  renderedRoutes: RenderedRouteDefinition[];
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-routes.d.ts","sourceRoot":"","sources":["../../src/vite/virtual-routes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;GAEG;AACH,wBAAgB,aAAa,CAAC,EAE7B,MAAM,EACN,cAAc,GACd,EAAE;IAEF,MAAM,EAAE,cAAc,CAAC;IACvB,cAAc,EAAE,uBAAuB,EAAE,CAAC;CAC1C;;;;IAyEA;AAKD,wBAAgB,mBAAmB,CAAC,EACnC,MAAM,EAAE,SAAS,EACjB,IAAe,EACf,aAAa,GACb,EAAE;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC1B,aAAa,EAAE,aAAa,CAAC;CAC7B;;;;IAsDA"}
@@ -1,5 +1,8 @@
1
1
  import { normalizeToPosix } from '@gracile/internal-utils/paths';
2
2
  import { createFilter } from 'vite';
3
+ /**
4
+ * @todo Client-side testing, docs.
5
+ */
3
6
  export function virtualRoutes({
4
7
  // root,
5
8
  routes, renderedRoutes, }) {
@@ -45,15 +48,13 @@ const routeImports = new Map(
45
48
  ]
46
49
  );
47
50
 
48
- const routeAssets = new Map(${JSON.stringify([
49
- ...renderedRoutesWithoutPrerender.map((r) => [
50
- `/${r.name
51
- //
52
- .replace(/index\.html$/, '')
53
- .replace(/* Error pages */ /\.html$/, '/')}`,
54
- r.handlerAssets,
55
- ]),
56
- ], null, 2)});
51
+ const routeAssets = new Map(${JSON.stringify(renderedRoutesWithoutPrerender.map((r) => [
52
+ `/${r.name
53
+ //
54
+ .replace(/index\.html$/, '')
55
+ .replace(/* Error pages */ /\.html$/, '/')}`,
56
+ r.handlerAssets,
57
+ ]), null, 2)});
57
58
 
58
59
  export { routes, routeImports, routeAssets };
59
60
  `;
@@ -69,7 +70,6 @@ export { routes, routeImports, routeAssets };
69
70
  export function virtualRoutesClient({ routes: routesMap, mode = 'server', gracileConfig, }) {
70
71
  const virtualModuleId = 'gracile:client:routes';
71
72
  const resolvedVirtualModuleId = `\0${virtualModuleId}`;
72
- const enabled = gracileConfig.pages?.premises?.expose;
73
73
  const premisesFilter = createFilter(gracileConfig.pages?.premises?.include, gracileConfig.pages?.premises?.exclude);
74
74
  return [
75
75
  {
@@ -83,21 +83,19 @@ export function virtualRoutesClient({ routes: routesMap, mode = 'server', gracil
83
83
  },
84
84
  load(id) {
85
85
  if (id === resolvedVirtualModuleId) {
86
- if (!routesMap || routesMap.size < 1)
86
+ if (!routesMap || routesMap.size === 0)
87
87
  return '';
88
88
  const routes = [...routesMap].filter((r) => premisesFilter(r[1].filePath));
89
89
  return `
90
90
  const routeImports = new Map(
91
91
  [
92
- ${enabled
93
- ? routes
94
- .map(([pattern, route]) => `['${pattern}', () => import('/${normalizeToPosix(route.filePath)}')],`)
95
- .join('\n ')
96
- : '/* DISABLED */'}
92
+ ${routes
93
+ .map(([pattern, route]) => `['${pattern}', () => import('/${normalizeToPosix(route.filePath)}')],`)
94
+ .join('\n ')}
97
95
  ]
98
96
  );
99
97
 
100
- export const enabled = ${enabled};
98
+ export const enabled = true;
101
99
 
102
100
  export const mode = '${mode}';
103
101
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gracile/engine",
3
- "version": "0.7.1",
3
+ "version": "0.8.0-next.1",
4
4
  "description": "A thin, full-stack, web framework",
5
5
  "keywords": [
6
6
  "custom-elements",
@@ -43,14 +43,13 @@
43
43
  "!/dist/typedoc-entrypoint.*"
44
44
  ],
45
45
  "dependencies": {
46
- "@gracile-labs/better-errors": "^0.1.1",
47
- "@gracile/client": "^0.3.1",
48
- "@gracile/internal-utils": "^0.4.0",
49
- "@whatwg-node/server": "^0.9.25",
50
- "fdir": "^6.2.0",
51
- "picocolors": "^1.0.1",
46
+ "@gracile-labs/better-errors": "^0.1.2-next.1",
47
+ "@gracile/internal-utils": "^0.5.0-next.1",
48
+ "@whatwg-node/server": "^0.9.50",
49
+ "fdir": "^6.4.2",
50
+ "picocolors": "^1.1.1",
52
51
  "urlpattern-polyfill": "^10.0.0",
53
- "vite": "^5.3.5"
52
+ "vite": "^5.4.10"
54
53
  },
55
54
  "peerDependencies": {
56
55
  "@lit-labs/ssr": "^3.2.2",
@@ -61,5 +60,5 @@
61
60
  "access": "public",
62
61
  "provenance": true
63
62
  },
64
- "gitHead": "7ff4d62a5ed8385220bc24742c55aae713f9b085"
63
+ "gitHead": "918ea2107304571493be80ada5e07496fae472f5"
65
64
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../../src/build/static.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAK1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,uBAAuB;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,MAAM,EAAE;QACP,KAAK,EAAE,OAAO,CAAC;QACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;KACxB,CAAC;IAEF,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAeD,wBAAsB,YAAY,CAAC,EAClC,MAAM,EACN,IAAI,EACJ,UAAU,EACV,IAAoB,EACpB,aAAa,GACb,EAAE;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,aAAa,CAAC;CAC7B;;;GAwJA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/dev/dev.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAEN,KAAK,cAAc,EACnB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,wBAAsB,gBAAgB,CAAC,EACtC,MAAM,EACN,IAAI,EACJ,aAAa,GACb,EAAE;IACF,MAAM,EAAE,cAAc,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;CAC7B,GAAG,OAAO,CAAC;IACX,OAAO,EAAE,cAAc,CAAC;IACxB,MAAM,EAAE,cAAc,CAAC;CACvB,CAAC,CAgDD"}