vike 0.4.229-commit-a19745d → 0.4.229-commit-af508ef

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,10 @@ const configDefinitionsBuiltIn = {
58
58
  data: {
59
59
  env: { server: true }
60
60
  },
61
+ onData: {
62
+ env: { server: true, client: true },
63
+ cumulative: true
64
+ },
61
65
  iKnowThePerformanceRisksOfAsyncRouteFunctions: {
62
66
  env: { server: true, client: 'if-client-routing' },
63
67
  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-a19745d';
5
+ exports.PROJECT_VERSION = '0.4.229-commit-af508ef';
@@ -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,30 +32,30 @@ 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
- for (let context of contexts) {
43
+ for (const context of contexts) {
44
44
  (0, path_js_1.assertPosixPath)(context);
45
- context = ensureFilePrefix(context);
46
- const require_ = (0, node_module_1.createRequire)(context);
45
+ const contextNode = makeNodeFriendly(ensureFilePrefix(context));
46
+ let importPathNode = makeNodeFriendly(importPath);
47
+ const require_ = (0, node_module_1.createRequire)(contextNode);
47
48
  if (!doNotHandleFileExtension) {
48
49
  addFileExtensionsToRequireResolve(require_);
49
- importPath = removeFileExtention(importPath);
50
+ importPathNode = removeFileExtention(importPathNode);
50
51
  }
51
52
  try {
52
- importPathResolvedFilePath = require_.resolve(importPath);
53
+ importPathResolvedFilePath = require_.resolve(importPathNode);
53
54
  }
54
55
  catch (err) {
55
56
  if (debug.isActivated) {
56
- debug('err', err);
57
- debug('importPath', importPath);
58
- debug('context', context);
57
+ const stack = new Error().stack;
58
+ debug('ERROR', { err, importPath, context }, stack);
59
59
  }
60
60
  failure ?? (failure = { err });
61
61
  }
@@ -65,21 +65,23 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
65
65
  if (!importPathResolvedFilePath) {
66
66
  (0, assert_js_1.assert)(failure);
67
67
  if (debug.isActivated) {
68
- debug('FAILURE');
69
- debug('importPath', importPath);
70
- debug('importerFilePath', importerFilePath);
71
- debug('userRootDir', userRootDir);
72
- debug('doNotHandleFileExtension', doNotHandleFileExtension);
73
- debug('importMetaUrl', importMetaUrl);
74
- debug('contexts', contexts);
68
+ debug('FAILURE', {
69
+ importPath,
70
+ importerFilePath,
71
+ userRootDir,
72
+ doNotHandleFileExtension,
73
+ importMetaUrl,
74
+ contexts
75
+ });
75
76
  }
76
77
  return { importPathResolvedFilePath: undefined, err: failure.err, hasFailed: true };
77
78
  }
78
79
  else {
79
80
  if (failure && debug.isActivated) {
80
- debug('SUCCESS');
81
- debug('importPath', importPath);
82
- debug('contexts', contexts);
81
+ debug('SUCCESS', {
82
+ importPath,
83
+ contexts
84
+ });
83
85
  }
84
86
  (0, assert_js_1.assert)(importPathResolvedFilePath);
85
87
  importPathResolvedFilePath = (0, path_js_1.toPosixPath)(importPathResolvedFilePath);
@@ -87,14 +89,14 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
87
89
  }
88
90
  }
89
91
  function requireResolveOptional({ importPath, importerFilePath, userRootDir }) {
90
- const res = requireResolve_(importPath, importerFilePath, { userRootDir });
92
+ const res = requireResolve_(importPath, importerFilePath, userRootDir);
91
93
  if (res.hasFailed)
92
94
  return null;
93
95
  return res.importPathResolvedFilePath;
94
96
  }
95
97
  function requireResolveOptionalDir({ importPath, importerDir, userRootDir }) {
96
98
  const importerFilePath = getFakeImporterFile(importerDir);
97
- const res = requireResolve_(importPath, importerFilePath, { userRootDir });
99
+ const res = requireResolve_(importPath, importerFilePath, userRootDir);
98
100
  if (res.hasFailed)
99
101
  return null;
100
102
  return res.importPathResolvedFilePath;
@@ -102,7 +104,7 @@ function requireResolveOptionalDir({ importPath, importerDir, userRootDir }) {
102
104
  function requireResolveNpmPackage({ importPathNpmPackage, userRootDir }) {
103
105
  (0, parseNpmPackage_js_1.assertIsImportPathNpmPackage)(importPathNpmPackage);
104
106
  const importerFilePath = getFakeImporterFile(userRootDir);
105
- const res = requireResolve_(importPathNpmPackage, importerFilePath, { userRootDir });
107
+ const res = requireResolve_(importPathNpmPackage, importerFilePath, userRootDir);
106
108
  if (res.hasFailed)
107
109
  throw res.err;
108
110
  return res.importPathResolvedFilePath;
@@ -111,19 +113,19 @@ function requireResolveVikeDistFile(vikeDistFile) {
111
113
  const vikeNodeModulesRoot = getVikeNodeModulesRoot();
112
114
  (0, path_js_1.assertPosixPath)(vikeNodeModulesRoot);
113
115
  (0, path_js_1.assertPosixPath)(vikeDistFile);
114
- const importPathResolvedFilePath = node_path_1.default.posix.join(vikeNodeModulesRoot, vikeDistFile);
116
+ const importPathResolvedFilePath = makeNodeFriendly(node_path_1.default.posix.join(vikeNodeModulesRoot, vikeDistFile));
115
117
  // Double check
116
118
  {
117
119
  const res = requireResolve_(importPathResolvedFilePath,
118
120
  // No context needed: importPathResolvedFilePath is already resolved and absolute
119
- null, { doNotHandleFileExtension: true });
121
+ null, null, true);
120
122
  if (res.hasFailed)
121
123
  throw res.err;
122
124
  (0, assert_js_1.assert)(res.importPathResolvedFilePath === importPathResolvedFilePath);
123
125
  }
124
126
  return importPathResolvedFilePath;
125
127
  }
126
- function addExtraContextForNpmPackageImport(contexts, { importPath, userRootDir }) {
128
+ function addExtraContextForNpmPackageImport(contexts, importPath, userRootDir) {
127
129
  // We should add extra context only for npm packages, but unfortunately we cannot always disambiguate between npm package imports and path aliases.
128
130
  if (!(0, parseNpmPackage_js_1.isImportPathNpmPackageOrPathAlias)(importPath))
129
131
  return;
@@ -205,3 +207,7 @@ function getFilePrefix() {
205
207
  prefix += '/';
206
208
  return prefix;
207
209
  }
210
+ function makeNodeFriendly(filePath) {
211
+ // https://github.com/vikejs/vike/issues/2436#issuecomment-2849145340
212
+ return decodeURIComponent(filePath);
213
+ }
@@ -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
@@ -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,10 @@ const configDefinitionsBuiltIn = {
56
56
  data: {
57
57
  env: { server: true }
58
58
  },
59
+ onData: {
60
+ env: { server: true, client: true },
61
+ cumulative: true
62
+ },
59
63
  iKnowThePerformanceRisksOfAsyncRouteFunctions: {
60
64
  env: { server: true, client: 'if-client-routing' },
61
65
  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-a19745d";
1
+ export declare const PROJECT_VERSION: "0.4.229-commit-af508ef";
@@ -1,2 +1,2 @@
1
1
  // Automatically updated by @brillout/release-me
2
- export const PROJECT_VERSION = '0.4.229-commit-a19745d';
2
+ export const PROJECT_VERSION = '0.4.229-commit-af508ef';
@@ -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,30 +27,30 @@ 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
- for (let context of contexts) {
38
+ for (const context of contexts) {
39
39
  assertPosixPath(context);
40
- context = ensureFilePrefix(context);
41
- const require_ = createRequire(context);
40
+ const contextNode = makeNodeFriendly(ensureFilePrefix(context));
41
+ let importPathNode = makeNodeFriendly(importPath);
42
+ const require_ = createRequire(contextNode);
42
43
  if (!doNotHandleFileExtension) {
43
44
  addFileExtensionsToRequireResolve(require_);
44
- importPath = removeFileExtention(importPath);
45
+ importPathNode = removeFileExtention(importPathNode);
45
46
  }
46
47
  try {
47
- importPathResolvedFilePath = require_.resolve(importPath);
48
+ importPathResolvedFilePath = require_.resolve(importPathNode);
48
49
  }
49
50
  catch (err) {
50
51
  if (debug.isActivated) {
51
- debug('err', err);
52
- debug('importPath', importPath);
53
- debug('context', context);
52
+ const stack = new Error().stack;
53
+ debug('ERROR', { err, importPath, context }, stack);
54
54
  }
55
55
  failure ?? (failure = { err });
56
56
  }
@@ -60,21 +60,23 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
60
60
  if (!importPathResolvedFilePath) {
61
61
  assert(failure);
62
62
  if (debug.isActivated) {
63
- debug('FAILURE');
64
- debug('importPath', importPath);
65
- debug('importerFilePath', importerFilePath);
66
- debug('userRootDir', userRootDir);
67
- debug('doNotHandleFileExtension', doNotHandleFileExtension);
68
- debug('importMetaUrl', importMetaUrl);
69
- debug('contexts', contexts);
63
+ debug('FAILURE', {
64
+ importPath,
65
+ importerFilePath,
66
+ userRootDir,
67
+ doNotHandleFileExtension,
68
+ importMetaUrl,
69
+ contexts
70
+ });
70
71
  }
71
72
  return { importPathResolvedFilePath: undefined, err: failure.err, hasFailed: true };
72
73
  }
73
74
  else {
74
75
  if (failure && debug.isActivated) {
75
- debug('SUCCESS');
76
- debug('importPath', importPath);
77
- debug('contexts', contexts);
76
+ debug('SUCCESS', {
77
+ importPath,
78
+ contexts
79
+ });
78
80
  }
79
81
  assert(importPathResolvedFilePath);
80
82
  importPathResolvedFilePath = toPosixPath(importPathResolvedFilePath);
@@ -82,14 +84,14 @@ function requireResolve_(importPath, importerFilePath, { userRootDir, doNotHandl
82
84
  }
83
85
  }
84
86
  function requireResolveOptional({ importPath, importerFilePath, userRootDir }) {
85
- const res = requireResolve_(importPath, importerFilePath, { userRootDir });
87
+ const res = requireResolve_(importPath, importerFilePath, userRootDir);
86
88
  if (res.hasFailed)
87
89
  return null;
88
90
  return res.importPathResolvedFilePath;
89
91
  }
90
92
  function requireResolveOptionalDir({ importPath, importerDir, userRootDir }) {
91
93
  const importerFilePath = getFakeImporterFile(importerDir);
92
- const res = requireResolve_(importPath, importerFilePath, { userRootDir });
94
+ const res = requireResolve_(importPath, importerFilePath, userRootDir);
93
95
  if (res.hasFailed)
94
96
  return null;
95
97
  return res.importPathResolvedFilePath;
@@ -97,7 +99,7 @@ function requireResolveOptionalDir({ importPath, importerDir, userRootDir }) {
97
99
  function requireResolveNpmPackage({ importPathNpmPackage, userRootDir }) {
98
100
  assertIsImportPathNpmPackage(importPathNpmPackage);
99
101
  const importerFilePath = getFakeImporterFile(userRootDir);
100
- const res = requireResolve_(importPathNpmPackage, importerFilePath, { userRootDir });
102
+ const res = requireResolve_(importPathNpmPackage, importerFilePath, userRootDir);
101
103
  if (res.hasFailed)
102
104
  throw res.err;
103
105
  return res.importPathResolvedFilePath;
@@ -106,19 +108,19 @@ function requireResolveVikeDistFile(vikeDistFile) {
106
108
  const vikeNodeModulesRoot = getVikeNodeModulesRoot();
107
109
  assertPosixPath(vikeNodeModulesRoot);
108
110
  assertPosixPath(vikeDistFile);
109
- const importPathResolvedFilePath = path.posix.join(vikeNodeModulesRoot, vikeDistFile);
111
+ const importPathResolvedFilePath = makeNodeFriendly(path.posix.join(vikeNodeModulesRoot, vikeDistFile));
110
112
  // Double check
111
113
  {
112
114
  const res = requireResolve_(importPathResolvedFilePath,
113
115
  // No context needed: importPathResolvedFilePath is already resolved and absolute
114
- null, { doNotHandleFileExtension: true });
116
+ null, null, true);
115
117
  if (res.hasFailed)
116
118
  throw res.err;
117
119
  assert(res.importPathResolvedFilePath === importPathResolvedFilePath);
118
120
  }
119
121
  return importPathResolvedFilePath;
120
122
  }
121
- function addExtraContextForNpmPackageImport(contexts, { importPath, userRootDir }) {
123
+ function addExtraContextForNpmPackageImport(contexts, importPath, userRootDir) {
122
124
  // We should add extra context only for npm packages, but unfortunately we cannot always disambiguate between npm package imports and path aliases.
123
125
  if (!isImportPathNpmPackageOrPathAlias(importPath))
124
126
  return;
@@ -200,3 +202,7 @@ function getFilePrefix() {
200
202
  prefix += '/';
201
203
  return prefix;
202
204
  }
205
+ function makeNodeFriendly(filePath) {
206
+ // https://github.com/vikejs/vike/issues/2436#issuecomment-2849145340
207
+ return decodeURIComponent(filePath);
208
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike",
3
- "version": "0.4.229-commit-a19745d",
3
+ "version": "0.4.229-commit-af508ef",
4
4
  "repository": "https://github.com/vikejs/vike",
5
5
  "exports": {
6
6
  "./server": {