vike 0.4.229-commit-2dbbc8d → 0.4.229-commit-845a4e0

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.
@@ -58,6 +58,12 @@ const configDefinitionsBuiltIn = {
58
58
  data: {
59
59
  env: { server: true }
60
60
  },
61
+ onData: {
62
+ env: { server: true, client: true }
63
+ /* TODO/now
64
+ cumulative: true
65
+ */
66
+ },
61
67
  iKnowThePerformanceRisksOfAsyncRouteFunctions: {
62
68
  env: { server: true, client: 'if-client-routing' },
63
69
  eager: true
@@ -5,7 +5,7 @@ exports.createHttpResponsePageContextJson = createHttpResponsePageContextJson;
5
5
  exports.createHttpResponseError = createHttpResponseError;
6
6
  exports.createHttpResponseErrorWithoutGlobalContext = createHttpResponseErrorWithoutGlobalContext;
7
7
  exports.createHttpResponseRedirect = createHttpResponseRedirect;
8
- exports.createHttpResponseFavicon404 = createHttpResponseFavicon404;
8
+ exports.createHttpResponse404 = createHttpResponse404;
9
9
  exports.createHttpResponseBaseIsMissing = createHttpResponseBaseIsMissing;
10
10
  const utils_js_1 = require("../utils.js");
11
11
  const error_page_js_1 = require("../../../shared/error-page.js");
@@ -38,8 +38,8 @@ async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
38
38
  }
39
39
  return createHttpResponse(statusCode, 'text/html;charset=utf-8', headers, htmlRender, earlyHints, renderHook);
40
40
  }
41
- function createHttpResponseFavicon404() {
42
- const httpResponse = createHttpResponse(404, 'text/html;charset=utf-8', [], "<p>No favicon.ico found.</p><script>console.log('This HTTP response was generated by Vike.')</script>");
41
+ function createHttpResponse404(errMsg404) {
42
+ const httpResponse = createHttpResponse(404, 'text/html;charset=utf-8', [], `<p>${errMsg404}.</p><script>console.log('This HTTP response was generated by Vike.')</script>`);
43
43
  return httpResponse;
44
44
  }
45
45
  function createHttpResponseBaseIsMissing(urlOriginal, baseServer) {
@@ -22,6 +22,13 @@ async function executeOnBeforeRenderAndDataHooks(pageContext) {
22
22
  data: hookResult
23
23
  };
24
24
  Object.assign(pageContext, pageContextFromHook);
25
+ // Execute +onData
26
+ if (!pageContext.isClientSideNavigation) {
27
+ const onDataHook = (0, getHook_js_1.getHookFromPageContext)(pageContext, 'onData');
28
+ if (onDataHook) {
29
+ await (0, executeHook_js_1.executeHook)(() => onDataHook.hookFn(pageContext), dataHook, pageContext);
30
+ }
31
+ }
25
32
  }
26
33
  if (onBeforeRenderHook) {
27
34
  const hookResult = await (0, executeHook_js_1.executeHook)(() => onBeforeRenderHook.hookFn(pageContext), onBeforeRenderHook, pageContext);
@@ -33,9 +33,9 @@ async function renderPage(pageContextInit) {
33
33
  (0, utils_js_1.assert)((0, utils_js_1.hasProp)(pageContextInit, 'urlOriginal', 'string')); // assertUsage() already implemented at assertArguments()
34
34
  assertIsUrl(pageContextInit.urlOriginal);
35
35
  (0, utils_js_1.onSetupRuntime)();
36
- const pageContextInvalidRequest = getPageContextInvalidRequest(pageContextInit);
37
- if (pageContextInvalidRequest)
38
- return pageContextInvalidRequest;
36
+ const pageContextSkipRequest = getPageContextSkipRequest(pageContextInit);
37
+ if (pageContextSkipRequest)
38
+ return pageContextSkipRequest;
39
39
  const httpRequestId = getRequestId();
40
40
  const urlOriginalPretty = (0, utils_js_1.getUrlPretty)(pageContextInit.urlOriginal);
41
41
  logHttpRequest(urlOriginalPretty, httpRequestId);
@@ -459,13 +459,22 @@ async function checkBaseUrl(pageContextBegin, globalContext) {
459
459
  (0, utils_js_1.checkType)(pageContext);
460
460
  return pageContext;
461
461
  }
462
- function getPageContextInvalidRequest(pageContextInit) {
462
+ function getPageContextSkipRequest(pageContextInit) {
463
463
  const urlPathnameWithBase = (0, utils_js_1.parseUrl)(pageContextInit.urlOriginal, '/').pathname;
464
464
  assertIsNotViteRequest(urlPathnameWithBase, pageContextInit.urlOriginal);
465
- if (!urlPathnameWithBase.endsWith('/favicon.ico'))
465
+ let errMsg404;
466
+ if (urlPathnameWithBase.endsWith('/favicon.ico')) {
467
+ errMsg404 = 'No favicon.ico found';
468
+ }
469
+ if (urlPathnameWithBase.endsWith('.well-known/appspecific/com.chrome.devtools.json')) {
470
+ // https://chromium.googlesource.com/devtools/devtools-frontend/+/main/docs/ecosystem/automatic_workspace_folders.md
471
+ // https://www.reddit.com/r/node/comments/1kcr0wh/odd_request_coming_into_my_localhost_server_from/
472
+ errMsg404 = 'Not spported';
473
+ }
474
+ if (!errMsg404)
466
475
  return;
467
476
  const pageContext = (0, createPageContextServerSide_js_1.createPageContextServerSideWithoutGlobalContext)(pageContextInit);
468
- const httpResponse = (0, createHttpResponse_js_1.createHttpResponseFavicon404)();
477
+ const httpResponse = (0, createHttpResponse_js_1.createHttpResponse404)(errMsg404);
469
478
  (0, utils_js_1.objectAssign)(pageContext, { httpResponse });
470
479
  (0, utils_js_1.checkType)(pageContext);
471
480
  return pageContext;
@@ -1,13 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.debug = debug;
4
- var _debug;
4
+ exports.setCreateDebugger = setCreateDebugger;
5
+ // Using createDebugger() for isomorphic code without bloating the client-side.
6
+ // On the server-side, this is just a transparent proxy.
7
+ // On the client-side, this is an emtpy shell.
8
+ const getGlobalObject_js_1 = require("../../utils/getGlobalObject.js");
9
+ const globalObject = (0, getGlobalObject_js_1.getGlobalObject)('route/debug.ts', {});
5
10
  function debug(...args) {
6
- if (!_debug) {
7
- // We use this trick instead of `import { createDebugger } from '../../utils/debug` in order to ensure that the `debug` mechanism is only loaded on the server-side
8
- _debug = globalThis.__brillout_debug_createDebugger?.('vike:routing');
9
- }
10
- if (_debug) {
11
- _debug(...args);
11
+ // Client-side => does nothing
12
+ if (!globalObject.createDebugger)
13
+ return;
14
+ // Server-side => just a proxy
15
+ if (!globalObject.debug) {
16
+ globalObject.debug = globalObject.createDebugger('vike:routing');
12
17
  }
18
+ globalObject.debug(...args);
19
+ }
20
+ // Called only on the server-side
21
+ function setCreateDebugger(createDebugger) {
22
+ globalObject.createDebugger = createDebugger;
13
23
  }
@@ -2,4 +2,4 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PROJECT_VERSION = void 0;
4
4
  // Automatically updated by @brillout/release-me
5
- exports.PROJECT_VERSION = '0.4.229-commit-2dbbc8d';
5
+ exports.PROJECT_VERSION = '0.4.229-commit-845a4e0';
@@ -13,11 +13,10 @@ const checkType_js_1 = require("./checkType.js");
13
13
  const getTerminWidth_js_1 = require("./getTerminWidth.js");
14
14
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
15
15
  const isArray_js_1 = require("./isArray.js");
16
- // Avoid this to be loaded in the browser. For isomorphic code: instead of `import { createDebugger } from './utils.js'`, use `globalThis.createDebugger()`.
16
+ const isObject_js_1 = require("./isObject.js");
17
+ const debug_js_1 = require("../shared/route/debug.js");
17
18
  (0, assert_js_1.assert)(!(0, isBrowser_js_1.isBrowser)());
18
- globalThis.__brillout_debug_createDebugger = createDebugger;
19
- // We purposely read process.env.DEBUG early, in order to avoid users from the temptation to set process.env.DEBUG with JavaScript, since reading & writing process.env.DEBUG dynamically leads to inconsistencies: for example https://github.com/vikejs/vike/issues/2239
20
- const DEBUG = getDEBUG() ?? '';
19
+ (0, debug_js_1.setCreateDebugger)(createDebugger); // for isomorphic code
21
20
  const flags = [
22
21
  'vike:crawl',
23
22
  'vike:error',
@@ -39,6 +38,10 @@ const flags = [
39
38
  ];
40
39
  const flagsSkipWildcard = ['vike:log'];
41
40
  const flagRegex = /\bvike:[a-zA-Z-]+/g;
41
+ // We purposely read process.env.DEBUG early, in order to avoid users from the temptation to set process.env.DEBUG with JavaScript, since reading & writing process.env.DEBUG dynamically leads to inconsistencies such as https://github.com/vikejs/vike/issues/2239
42
+ const DEBUG = getDEBUG() ?? '';
43
+ if (isDebug())
44
+ Error.stackTraceLimit = Infinity;
42
45
  assertFlagsActivated();
43
46
  function createDebugger(flag, optionsGlobal) {
44
47
  (0, checkType_js_1.checkType)(flag);
@@ -65,9 +68,10 @@ function debug_(flag, options, ...msgs) {
65
68
  });
66
69
  let logFirst;
67
70
  let logsRest;
68
- const noNewLine = msgsRest.length <= 1 && [msgFirst, ...msgsRest].every((m) => typeof m === 'string' && !m.includes('\n'));
71
+ const noNewLine = msgsRest.length <= 1 &&
72
+ [msgFirst, ...msgsRest].every((m) => (typeof m === 'string' ? !m.includes('\n') : !(0, isObject_js_1.isObject)(m)));
69
73
  if (noNewLine) {
70
- logFirst = [msgFirst, ...msgsRest].map((m) => String(m).trim());
74
+ logFirst = [msgFirst, ...msgsRest].map((m) => (typeof m !== 'string' ? m : m.trim()));
71
75
  logsRest = [];
72
76
  }
73
77
  else {
@@ -157,6 +161,10 @@ function getFlagsActivated() {
157
161
  const all = DEBUG.includes('vike:*');
158
162
  return { flagsActivated, all };
159
163
  }
164
+ function isDebug() {
165
+ const { flagsActivated, all } = getFlagsActivated();
166
+ return all || flagsActivated.length > 0;
167
+ }
160
168
  function getDEBUG() {
161
169
  let DEBUG;
162
170
  // - `process` can be undefined in edge workers
@@ -32,12 +32,12 @@ const debug = (0, debug_js_1.createDebugger)('vike:resolve');
32
32
  // - The argument createRequire(argument) seems to be overriden by the `paths` argument require.resolve()
33
33
  // - For example, passing an empty array to `paths` kills the argument passed to `createRequire()`
34
34
  // - Thus, when `paths` is defined, then the context needs to be passed to both createRequire() as well as the `paths` argument of require.resolve()
35
- function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandleFileExtension } = {}) {
35
+ function requireResolve_(importPath, importerFilePath, userRootDir, doNotHandleFileExtension = false) {
36
36
  (0, path_js_1.assertPosixPath)(importPath);
37
37
  const contexts = importerFilePath
38
38
  ? [importerFilePath]
39
39
  : [userRootDir ? getFakeImporterFile(userRootDir) : importMetaUrl];
40
- addExtraContextForNpmPackageImport(contexts, { importPath, userRootDir });
40
+ addExtraContextForNpmPackageImport(contexts, importPath, userRootDir);
41
41
  let importPathResolvedFilePath;
42
42
  let failure;
43
43
  for (const context of contexts) {
@@ -54,9 +54,8 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
54
54
  }
55
55
  catch (err) {
56
56
  if (debug.isActivated) {
57
- debug('err', err);
58
- debug('importPath', importPath);
59
- debug('context', context);
57
+ const stack = new Error().stack;
58
+ debug('ERROR', { err, importPath, context }, stack);
60
59
  }
61
60
  failure ?? (failure = { err });
62
61
  }
@@ -66,21 +65,23 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
66
65
  if (!importPathResolvedFilePath) {
67
66
  (0, assert_js_1.assert)(failure);
68
67
  if (debug.isActivated) {
69
- debug('FAILURE');
70
- debug('importPath', importPath);
71
- debug('importerFilePath', importerFilePath);
72
- debug('userRootDir', userRootDir);
73
- debug('doNotHandleFileExtension', doNotHandleFileExtension);
74
- debug('importMetaUrl', importMetaUrl);
75
- debug('contexts', contexts);
68
+ debug('FAILURE', {
69
+ importPath,
70
+ importerFilePath,
71
+ userRootDir,
72
+ doNotHandleFileExtension,
73
+ importMetaUrl,
74
+ contexts
75
+ });
76
76
  }
77
77
  return { importPathResolvedFilePath: undefined, err: failure.err, hasFailed: true };
78
78
  }
79
79
  else {
80
80
  if (failure && debug.isActivated) {
81
- debug('SUCCESS');
82
- debug('importPath', importPath);
83
- debug('contexts', contexts);
81
+ debug('SUCCESS', {
82
+ importPath,
83
+ contexts
84
+ });
84
85
  }
85
86
  (0, assert_js_1.assert)(importPathResolvedFilePath);
86
87
  importPathResolvedFilePath = (0, path_js_1.toPosixPath)(importPathResolvedFilePath);
@@ -88,14 +89,14 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
88
89
  }
89
90
  }
90
91
  function requireResolveOptional({ importPath, importerFilePath, userRootDir }) {
91
- const res = requireResolve_(importPath, importerFilePath, { userRootDir });
92
+ const res = requireResolve_(importPath, importerFilePath, userRootDir);
92
93
  if (res.hasFailed)
93
94
  return null;
94
95
  return res.importPathResolvedFilePath;
95
96
  }
96
97
  function requireResolveOptionalDir({ importPath, importerDir, userRootDir }) {
97
98
  const importerFilePath = getFakeImporterFile(importerDir);
98
- const res = requireResolve_(importPath, importerFilePath, { userRootDir });
99
+ const res = requireResolve_(importPath, importerFilePath, userRootDir);
99
100
  if (res.hasFailed)
100
101
  return null;
101
102
  return res.importPathResolvedFilePath;
@@ -103,7 +104,7 @@ function requireResolveOptionalDir({ importPath, importerDir, userRootDir }) {
103
104
  function requireResolveNpmPackage({ importPathNpmPackage, userRootDir }) {
104
105
  (0, parseNpmPackage_js_1.assertIsImportPathNpmPackage)(importPathNpmPackage);
105
106
  const importerFilePath = getFakeImporterFile(userRootDir);
106
- const res = requireResolve_(importPathNpmPackage, importerFilePath, { userRootDir });
107
+ const res = requireResolve_(importPathNpmPackage, importerFilePath, userRootDir);
107
108
  if (res.hasFailed)
108
109
  throw res.err;
109
110
  return res.importPathResolvedFilePath;
@@ -117,14 +118,14 @@ function requireResolveVikeDistFile(vikeDistFile) {
117
118
  {
118
119
  const res = requireResolve_(importPathResolvedFilePath,
119
120
  // No context needed: importPathResolvedFilePath is already resolved and absolute
120
- null, { doNotHandleFileExtension: true });
121
+ null, null, true);
121
122
  if (res.hasFailed)
122
123
  throw res.err;
123
124
  (0, assert_js_1.assert)(res.importPathResolvedFilePath === importPathResolvedFilePath);
124
125
  }
125
126
  return importPathResolvedFilePath;
126
127
  }
127
- function addExtraContextForNpmPackageImport(contexts, { importPath, userRootDir }) {
128
+ function addExtraContextForNpmPackageImport(contexts, importPath, userRootDir) {
128
129
  // We should add extra context only for npm packages, but unfortunately we cannot always disambiguate between npm package imports and path aliases.
129
130
  if (!(0, parseNpmPackage_js_1.isImportPathNpmPackageOrPathAlias)(importPath))
130
131
  return;
@@ -30,7 +30,7 @@ function getPageContextFromHooks_serialized() {
30
30
  });
31
31
  return pageContextSerialized;
32
32
  }
33
- // TODO/eventually: rename
33
+ // TO-DO/eventually: rename
34
34
  async function getPageContextFromHooks_isHydration(pageContext) {
35
35
  objectAssign(pageContext, {
36
36
  _hasPageContextFromClient: false
@@ -73,6 +73,7 @@ async function getPageContextFromClientHooks(pageContext, isErrorPage) {
73
73
  objectAssign(pageContext, {
74
74
  _hasPageContextFromClient: false
75
75
  });
76
+ let dataHookExists = false;
76
77
  // At this point, we need to call the client-side guard(), data() and onBeforeRender() hooks, if they exist on client
77
78
  // env. However if we have fetched pageContext from the server, some of them might have run already on the
78
79
  // server-side, so we run only the client-only ones in this case.
@@ -89,7 +90,8 @@ async function getPageContextFromClientHooks(pageContext, isErrorPage) {
89
90
  }
90
91
  }
91
92
  else {
92
- assert(hookName === 'data' || hookName === 'onBeforeRender');
93
+ if (hookName === 'data')
94
+ dataHookExists = true;
93
95
  if (hookClientOnlyExists(hookName, pageContext) || !pageContext._hasPageContextFromServer) {
94
96
  // This won't do anything if no hook has been defined or if the hook's env.client is false.
95
97
  const pageContextFromHook = await executeHookClientSide(hookName, pageContext);
@@ -98,6 +100,14 @@ async function getPageContextFromClientHooks(pageContext, isErrorPage) {
98
100
  }
99
101
  }
100
102
  }
103
+ // Execute +onData
104
+ if (dataHookExists) {
105
+ const hook = getHookFromPageContext(pageContext, 'onData');
106
+ if (hook) {
107
+ const pageContextForUserConsumption = preparePageContextForUserConsumptionClientSide(pageContext, true);
108
+ await executeHook(() => hook.hookFn(pageContextForUserConsumption), hook, pageContext);
109
+ }
110
+ }
101
111
  const pageContextFromClientHooks = pageContext;
102
112
  return pageContextFromClientHooks;
103
113
  }
@@ -82,7 +82,7 @@ async function renderPageClientSide(renderArgs) {
82
82
  // Route
83
83
  if (isFirstRender) {
84
84
  const pageContextSerialized = getPageContextFromHooks_serialized();
85
- // TODO/eventually: create helper assertPageContextFromHook()
85
+ // TO-DO/eventually: create helper assertPageContextFromHook()
86
86
  assert(!('urlOriginal' in pageContextSerialized));
87
87
  objectAssign(pageContext, pageContextSerialized);
88
88
  // TODO/pageContext-prefetch: remove or change, because this only makes sense for a pre-rendered page
@@ -127,7 +127,7 @@ async function renderPageClientSide(renderArgs) {
127
127
  // Skip's Vike's rendering; let the user handle the navigation
128
128
  return;
129
129
  }
130
- // TODO/eventually: create helper assertPageContextFromHook()
130
+ // TO-DO/eventually: create helper assertPageContextFromHook()
131
131
  assert(!('urlOriginal' in pageContextFromRoute));
132
132
  objectAssign(pageContext, pageContextFromRoute);
133
133
  }
@@ -197,9 +197,24 @@ async function renderPageClientSide(renderArgs) {
197
197
  }
198
198
  if (isRenderOutdated())
199
199
  return;
200
- // TODO/eventually: create helper assertPageContextFromHook()
200
+ // TO-DO/eventually: create helper assertPageContextFromHook()
201
201
  assert(!('urlOriginal' in pageContextFromServerHooks));
202
202
  objectAssign(pageContext, pageContextFromServerHooks);
203
+ // Execute +onData
204
+ assertHook(pageContext, 'onData');
205
+ const hook = getHookFromPageContext(pageContext, 'onData');
206
+ if (hook) {
207
+ const { hookFn } = hook;
208
+ try {
209
+ await executeHook(() => hookFn(pageContext), hook, pageContext);
210
+ }
211
+ catch (err) {
212
+ await onError(err);
213
+ return;
214
+ }
215
+ if (isRenderOutdated())
216
+ return;
217
+ }
203
218
  // Get pageContext from client-side hooks
204
219
  let pageContextFromClientHooks;
205
220
  try {
@@ -365,7 +380,7 @@ async function renderPageClientSide(renderArgs) {
365
380
  }
366
381
  if (isRenderOutdated())
367
382
  return;
368
- // TODO/eventually: create helper assertPageContextFromHook()
383
+ // TO-DO/eventually: create helper assertPageContextFromHook()
369
384
  assert(!('urlOriginal' in pageContextFromServerHooks));
370
385
  objectAssign(pageContext, pageContextFromServerHooks);
371
386
  let pageContextFromClientHooks;
@@ -56,6 +56,12 @@ const configDefinitionsBuiltIn = {
56
56
  data: {
57
57
  env: { server: true }
58
58
  },
59
+ onData: {
60
+ env: { server: true, client: true }
61
+ /* TODO/now
62
+ cumulative: true
63
+ */
64
+ },
59
65
  iKnowThePerformanceRisksOfAsyncRouteFunctions: {
60
66
  env: { server: true, client: 'if-client-routing' },
61
67
  eager: true
@@ -3,7 +3,7 @@ export { createHttpResponsePageContextJson };
3
3
  export { createHttpResponseError };
4
4
  export { createHttpResponseErrorWithoutGlobalContext };
5
5
  export { createHttpResponseRedirect };
6
- export { createHttpResponseFavicon404 };
6
+ export { createHttpResponse404 };
7
7
  export { createHttpResponseBaseIsMissing };
8
8
  export type { HttpResponse };
9
9
  import type { GetPageAssets } from './getPageAssets.js';
@@ -30,7 +30,7 @@ declare function createHttpResponsePage(htmlRender: HtmlRender, renderHook: null
30
30
  _pageConfigs: PageConfigRuntime[];
31
31
  abortStatusCode?: AbortStatusCode;
32
32
  }): Promise<HttpResponse>;
33
- declare function createHttpResponseFavicon404(): HttpResponse;
33
+ declare function createHttpResponse404(errMsg404: string): HttpResponse;
34
34
  declare function createHttpResponseBaseIsMissing(urlOriginal: string, baseServer: string): HttpResponse;
35
35
  declare function createHttpResponseError(pageContext: {
36
36
  _pageFilesAll: PageFile[];
@@ -3,7 +3,7 @@ export { createHttpResponsePageContextJson };
3
3
  export { createHttpResponseError };
4
4
  export { createHttpResponseErrorWithoutGlobalContext };
5
5
  export { createHttpResponseRedirect };
6
- export { createHttpResponseFavicon404 };
6
+ export { createHttpResponse404 };
7
7
  export { createHttpResponseBaseIsMissing };
8
8
  import { assert, assertWarning, escapeHtml } from '../utils.js';
9
9
  import { getErrorPageId, isErrorPage } from '../../../shared/error-page.js';
@@ -36,8 +36,8 @@ async function createHttpResponsePage(htmlRender, renderHook, pageContext) {
36
36
  }
37
37
  return createHttpResponse(statusCode, 'text/html;charset=utf-8', headers, htmlRender, earlyHints, renderHook);
38
38
  }
39
- function createHttpResponseFavicon404() {
40
- const httpResponse = createHttpResponse(404, 'text/html;charset=utf-8', [], "<p>No favicon.ico found.</p><script>console.log('This HTTP response was generated by Vike.')</script>");
39
+ function createHttpResponse404(errMsg404) {
40
+ const httpResponse = createHttpResponse(404, 'text/html;charset=utf-8', [], `<p>${errMsg404}.</p><script>console.log('This HTTP response was generated by Vike.')</script>`);
41
41
  return httpResponse;
42
42
  }
43
43
  function createHttpResponseBaseIsMissing(urlOriginal, baseServer) {
@@ -20,6 +20,13 @@ async function executeOnBeforeRenderAndDataHooks(pageContext) {
20
20
  data: hookResult
21
21
  };
22
22
  Object.assign(pageContext, pageContextFromHook);
23
+ // Execute +onData
24
+ if (!pageContext.isClientSideNavigation) {
25
+ const onDataHook = getHookFromPageContext(pageContext, 'onData');
26
+ if (onDataHook) {
27
+ await executeHook(() => onDataHook.hookFn(pageContext), dataHook, pageContext);
28
+ }
29
+ }
23
30
  }
24
31
  if (onBeforeRenderHook) {
25
32
  const hookResult = await executeHook(() => onBeforeRenderHook.hookFn(pageContext), onBeforeRenderHook, pageContext);
@@ -7,7 +7,7 @@ import { assert, hasProp, objectAssign, isUrl, parseUrl, onSetupRuntime, assertW
7
7
  import { assertNoInfiniteAbortLoop, getPageContextFromAllRewrites, isAbortError, logAbortErrorHandled } from '../../shared/route/abort.js';
8
8
  import { getGlobalContextServerInternal, initGlobalContext_renderPage } from './globalContext.js';
9
9
  import { handlePageContextRequestUrl } from './renderPage/handlePageContextRequestUrl.js';
10
- import { createHttpResponseFavicon404, createHttpResponseRedirect, createHttpResponsePageContextJson, createHttpResponseError, createHttpResponseErrorWithoutGlobalContext, createHttpResponseBaseIsMissing } from './renderPage/createHttpResponse.js';
10
+ import { createHttpResponse404, createHttpResponseRedirect, createHttpResponsePageContextJson, createHttpResponseError, createHttpResponseErrorWithoutGlobalContext, createHttpResponseBaseIsMissing } from './renderPage/createHttpResponse.js';
11
11
  import { logRuntimeError, logRuntimeInfo } from './renderPage/loggerRuntime.js';
12
12
  import { isNewError } from './renderPage/isNewError.js';
13
13
  import { assertArguments } from './renderPage/assertArguments.js';
@@ -28,9 +28,9 @@ async function renderPage(pageContextInit) {
28
28
  assert(hasProp(pageContextInit, 'urlOriginal', 'string')); // assertUsage() already implemented at assertArguments()
29
29
  assertIsUrl(pageContextInit.urlOriginal);
30
30
  onSetupRuntime();
31
- const pageContextInvalidRequest = getPageContextInvalidRequest(pageContextInit);
32
- if (pageContextInvalidRequest)
33
- return pageContextInvalidRequest;
31
+ const pageContextSkipRequest = getPageContextSkipRequest(pageContextInit);
32
+ if (pageContextSkipRequest)
33
+ return pageContextSkipRequest;
34
34
  const httpRequestId = getRequestId();
35
35
  const urlOriginalPretty = getUrlPretty(pageContextInit.urlOriginal);
36
36
  logHttpRequest(urlOriginalPretty, httpRequestId);
@@ -454,13 +454,22 @@ async function checkBaseUrl(pageContextBegin, globalContext) {
454
454
  checkType(pageContext);
455
455
  return pageContext;
456
456
  }
457
- function getPageContextInvalidRequest(pageContextInit) {
457
+ function getPageContextSkipRequest(pageContextInit) {
458
458
  const urlPathnameWithBase = parseUrl(pageContextInit.urlOriginal, '/').pathname;
459
459
  assertIsNotViteRequest(urlPathnameWithBase, pageContextInit.urlOriginal);
460
- if (!urlPathnameWithBase.endsWith('/favicon.ico'))
460
+ let errMsg404;
461
+ if (urlPathnameWithBase.endsWith('/favicon.ico')) {
462
+ errMsg404 = 'No favicon.ico found';
463
+ }
464
+ if (urlPathnameWithBase.endsWith('.well-known/appspecific/com.chrome.devtools.json')) {
465
+ // https://chromium.googlesource.com/devtools/devtools-frontend/+/main/docs/ecosystem/automatic_workspace_folders.md
466
+ // https://www.reddit.com/r/node/comments/1kcr0wh/odd_request_coming_into_my_localhost_server_from/
467
+ errMsg404 = 'Not spported';
468
+ }
469
+ if (!errMsg404)
461
470
  return;
462
471
  const pageContext = createPageContextServerSideWithoutGlobalContext(pageContextInit);
463
- const httpResponse = createHttpResponseFavicon404();
472
+ const httpResponse = createHttpResponse404(errMsg404);
464
473
  objectAssign(pageContext, { httpResponse });
465
474
  checkType(pageContext);
466
475
  return pageContext;
@@ -44,7 +44,7 @@ import type { HooksTimeoutProvidedByUser } from '../hooks/getHook.js';
44
44
  import type { GlobalContext, PageContextClient, PageContextServer } from '../types.js';
45
45
  import type { InlineConfig } from 'vite';
46
46
  type HookName = HookNamePage | HookNameGlobal | HookNameOldDesign;
47
- type HookNamePage = 'onHydrationEnd' | 'onBeforePrerenderStart' | 'onBeforeRender' | 'onPageTransitionStart' | 'onPageTransitionEnd' | 'onRenderHtml' | 'onRenderClient' | 'guard' | 'data';
47
+ type HookNamePage = 'onHydrationEnd' | 'onBeforePrerenderStart' | 'onBeforeRender' | 'onPageTransitionStart' | 'onPageTransitionEnd' | 'onRenderHtml' | 'onRenderClient' | 'guard' | 'data' | 'onData';
48
48
  type HookNameGlobal = 'onBeforePrerender' | 'onBeforeRoute' | 'onPrerenderStart' | 'onCreatePageContext' | 'onCreateGlobalContext';
49
49
  type HookNameOldDesign = 'render' | 'prerender';
50
50
  type ConfigNameBuiltIn = Exclude<keyof Config, keyof VikeVitePluginOptions | 'onBeforeRoute' | 'onPrerenderStart' | 'vite' | 'redirects'> | 'prerender' | 'isClientRuntimeLoaded' | 'onBeforeRenderEnv' | 'dataEnv' | 'hooksTimeout' | 'clientHooks' | 'middleware';
@@ -345,6 +345,11 @@ type ConfigBuiltIn = {
345
345
  * https://vike.dev/data
346
346
  */
347
347
  data?: DataAsync<unknown> | DataSync<unknown> | ImportString | null;
348
+ /** TODO/now
349
+ *
350
+ * https://vike.dev/onData
351
+ */
352
+ onData?: Function;
348
353
  /** Determines what pageContext properties are sent to the client-side.
349
354
  *
350
355
  * https://vike.dev/passToClient
@@ -1,3 +1,6 @@
1
1
  export { debug };
2
- import type { Debug } from '../../utils/debug.js';
2
+ export { setCreateDebugger };
3
+ import type { createDebugger, Debug } from '../../utils/debug.js';
4
+ type CreateDebugger = typeof createDebugger;
3
5
  declare function debug(...args: Parameters<Debug>): void;
6
+ declare function setCreateDebugger(createDebugger: CreateDebugger): void;
@@ -1,11 +1,21 @@
1
1
  export { debug };
2
- var _debug;
2
+ export { setCreateDebugger };
3
+ // Using createDebugger() for isomorphic code without bloating the client-side.
4
+ // On the server-side, this is just a transparent proxy.
5
+ // On the client-side, this is an emtpy shell.
6
+ import { getGlobalObject } from '../../utils/getGlobalObject.js';
7
+ const globalObject = getGlobalObject('route/debug.ts', {});
3
8
  function debug(...args) {
4
- if (!_debug) {
5
- // We use this trick instead of `import { createDebugger } from '../../utils/debug` in order to ensure that the `debug` mechanism is only loaded on the server-side
6
- _debug = globalThis.__brillout_debug_createDebugger?.('vike:routing');
7
- }
8
- if (_debug) {
9
- _debug(...args);
9
+ // Client-side => does nothing
10
+ if (!globalObject.createDebugger)
11
+ return;
12
+ // Server-side => just a proxy
13
+ if (!globalObject.debug) {
14
+ globalObject.debug = globalObject.createDebugger('vike:routing');
10
15
  }
16
+ globalObject.debug(...args);
17
+ }
18
+ // Called only on the server-side
19
+ function setCreateDebugger(createDebugger) {
20
+ globalObject.createDebugger = createDebugger;
11
21
  }
@@ -1 +1 @@
1
- export declare const PROJECT_VERSION: "0.4.229-commit-2dbbc8d";
1
+ export declare const PROJECT_VERSION: "0.4.229-commit-845a4e0";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.229-commit-2dbbc8d';
2
+ export const PROJECT_VERSION = '0.4.229-commit-845a4e0';
@@ -8,11 +8,10 @@ import { checkType } from './checkType.js';
8
8
  import { getTerminalWidth } from './getTerminWidth.js';
9
9
  import pc from '@brillout/picocolors';
10
10
  import { isArray } from './isArray.js';
11
- // Avoid this to be loaded in the browser. For isomorphic code: instead of `import { createDebugger } from './utils.js'`, use `globalThis.createDebugger()`.
11
+ import { isObject } from './isObject.js';
12
+ import { setCreateDebugger } from '../shared/route/debug.js';
12
13
  assert(!isBrowser());
13
- globalThis.__brillout_debug_createDebugger = createDebugger;
14
- // We purposely read process.env.DEBUG early, in order to avoid users from the temptation to set process.env.DEBUG with JavaScript, since reading & writing process.env.DEBUG dynamically leads to inconsistencies: for example https://github.com/vikejs/vike/issues/2239
15
- const DEBUG = getDEBUG() ?? '';
14
+ setCreateDebugger(createDebugger); // for isomorphic code
16
15
  const flags = [
17
16
  'vike:crawl',
18
17
  'vike:error',
@@ -34,6 +33,10 @@ const flags = [
34
33
  ];
35
34
  const flagsSkipWildcard = ['vike:log'];
36
35
  const flagRegex = /\bvike:[a-zA-Z-]+/g;
36
+ // We purposely read process.env.DEBUG early, in order to avoid users from the temptation to set process.env.DEBUG with JavaScript, since reading & writing process.env.DEBUG dynamically leads to inconsistencies such as https://github.com/vikejs/vike/issues/2239
37
+ const DEBUG = getDEBUG() ?? '';
38
+ if (isDebug())
39
+ Error.stackTraceLimit = Infinity;
37
40
  assertFlagsActivated();
38
41
  function createDebugger(flag, optionsGlobal) {
39
42
  checkType(flag);
@@ -60,9 +63,10 @@ function debug_(flag, options, ...msgs) {
60
63
  });
61
64
  let logFirst;
62
65
  let logsRest;
63
- const noNewLine = msgsRest.length <= 1 && [msgFirst, ...msgsRest].every((m) => typeof m === 'string' && !m.includes('\n'));
66
+ const noNewLine = msgsRest.length <= 1 &&
67
+ [msgFirst, ...msgsRest].every((m) => (typeof m === 'string' ? !m.includes('\n') : !isObject(m)));
64
68
  if (noNewLine) {
65
- logFirst = [msgFirst, ...msgsRest].map((m) => String(m).trim());
69
+ logFirst = [msgFirst, ...msgsRest].map((m) => (typeof m !== 'string' ? m : m.trim()));
66
70
  logsRest = [];
67
71
  }
68
72
  else {
@@ -152,6 +156,10 @@ function getFlagsActivated() {
152
156
  const all = DEBUG.includes('vike:*');
153
157
  return { flagsActivated, all };
154
158
  }
159
+ function isDebug() {
160
+ const { flagsActivated, all } = getFlagsActivated();
161
+ return all || flagsActivated.length > 0;
162
+ }
155
163
  function getDEBUG() {
156
164
  let DEBUG;
157
165
  // - `process` can be undefined in edge workers
@@ -27,12 +27,12 @@ const debug = createDebugger('vike:resolve');
27
27
  // - The argument createRequire(argument) seems to be overriden by the `paths` argument require.resolve()
28
28
  // - For example, passing an empty array to `paths` kills the argument passed to `createRequire()`
29
29
  // - Thus, when `paths` is defined, then the context needs to be passed to both createRequire() as well as the `paths` argument of require.resolve()
30
- function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandleFileExtension } = {}) {
30
+ function requireResolve_(importPath, importerFilePath, userRootDir, doNotHandleFileExtension = false) {
31
31
  assertPosixPath(importPath);
32
32
  const contexts = importerFilePath
33
33
  ? [importerFilePath]
34
34
  : [userRootDir ? getFakeImporterFile(userRootDir) : importMetaUrl];
35
- addExtraContextForNpmPackageImport(contexts, { importPath, userRootDir });
35
+ addExtraContextForNpmPackageImport(contexts, importPath, userRootDir);
36
36
  let importPathResolvedFilePath;
37
37
  let failure;
38
38
  for (const context of contexts) {
@@ -49,9 +49,8 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
49
49
  }
50
50
  catch (err) {
51
51
  if (debug.isActivated) {
52
- debug('err', err);
53
- debug('importPath', importPath);
54
- debug('context', context);
52
+ const stack = new Error().stack;
53
+ debug('ERROR', { err, importPath, context }, stack);
55
54
  }
56
55
  failure ?? (failure = { err });
57
56
  }
@@ -61,21 +60,23 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
61
60
  if (!importPathResolvedFilePath) {
62
61
  assert(failure);
63
62
  if (debug.isActivated) {
64
- debug('FAILURE');
65
- debug('importPath', importPath);
66
- debug('importerFilePath', importerFilePath);
67
- debug('userRootDir', userRootDir);
68
- debug('doNotHandleFileExtension', doNotHandleFileExtension);
69
- debug('importMetaUrl', importMetaUrl);
70
- debug('contexts', contexts);
63
+ debug('FAILURE', {
64
+ importPath,
65
+ importerFilePath,
66
+ userRootDir,
67
+ doNotHandleFileExtension,
68
+ importMetaUrl,
69
+ contexts
70
+ });
71
71
  }
72
72
  return { importPathResolvedFilePath: undefined, err: failure.err, hasFailed: true };
73
73
  }
74
74
  else {
75
75
  if (failure && debug.isActivated) {
76
- debug('SUCCESS');
77
- debug('importPath', importPath);
78
- debug('contexts', contexts);
76
+ debug('SUCCESS', {
77
+ importPath,
78
+ contexts
79
+ });
79
80
  }
80
81
  assert(importPathResolvedFilePath);
81
82
  importPathResolvedFilePath = toPosixPath(importPathResolvedFilePath);
@@ -83,14 +84,14 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
83
84
  }
84
85
  }
85
86
  function requireResolveOptional({ importPath, importerFilePath, userRootDir }) {
86
- const res = requireResolve_(importPath, importerFilePath, { userRootDir });
87
+ const res = requireResolve_(importPath, importerFilePath, userRootDir);
87
88
  if (res.hasFailed)
88
89
  return null;
89
90
  return res.importPathResolvedFilePath;
90
91
  }
91
92
  function requireResolveOptionalDir({ importPath, importerDir, userRootDir }) {
92
93
  const importerFilePath = getFakeImporterFile(importerDir);
93
- const res = requireResolve_(importPath, importerFilePath, { userRootDir });
94
+ const res = requireResolve_(importPath, importerFilePath, userRootDir);
94
95
  if (res.hasFailed)
95
96
  return null;
96
97
  return res.importPathResolvedFilePath;
@@ -98,7 +99,7 @@ function requireResolveOptionalDir({ importPath, importerDir, userRootDir }) {
98
99
  function requireResolveNpmPackage({ importPathNpmPackage, userRootDir }) {
99
100
  assertIsImportPathNpmPackage(importPathNpmPackage);
100
101
  const importerFilePath = getFakeImporterFile(userRootDir);
101
- const res = requireResolve_(importPathNpmPackage, importerFilePath, { userRootDir });
102
+ const res = requireResolve_(importPathNpmPackage, importerFilePath, userRootDir);
102
103
  if (res.hasFailed)
103
104
  throw res.err;
104
105
  return res.importPathResolvedFilePath;
@@ -112,14 +113,14 @@ function requireResolveVikeDistFile(vikeDistFile) {
112
113
  {
113
114
  const res = requireResolve_(importPathResolvedFilePath,
114
115
  // No context needed: importPathResolvedFilePath is already resolved and absolute
115
- null, { doNotHandleFileExtension: true });
116
+ null, null, true);
116
117
  if (res.hasFailed)
117
118
  throw res.err;
118
119
  assert(res.importPathResolvedFilePath === importPathResolvedFilePath);
119
120
  }
120
121
  return importPathResolvedFilePath;
121
122
  }
122
- function addExtraContextForNpmPackageImport(contexts, { importPath, userRootDir }) {
123
+ function addExtraContextForNpmPackageImport(contexts, importPath, userRootDir) {
123
124
  // We should add extra context only for npm packages, but unfortunately we cannot always disambiguate between npm package imports and path aliases.
124
125
  if (!isImportPathNpmPackageOrPathAlias(importPath))
125
126
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.229-commit-2dbbc8d",
3
+ "version": "0.4.229-commit-845a4e0",
4
4
  "repository": "https://github.com/vikejs/vike",
5
5
  "exports": {
6
6
  "./server": {