vike 0.4.146-commit-701e2e5 → 0.4.147-commit-2fa53b2

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 (80) hide show
  1. package/dist/cjs/node/plugin/index.js +6 -4
  2. package/dist/cjs/node/plugin/plugins/devConfig/determineOptimizeDeps.js +3 -4
  3. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getConfigValuesSerialized.js +76 -0
  4. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +61 -40
  5. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +104 -0
  6. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +62 -75
  7. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +43 -17
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +12 -70
  9. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +11 -8
  10. package/dist/cjs/node/plugin/shared/{getConfigValueSourcesRelevant.js → getConfigValueSourcesNotOverriden.js} +3 -3
  11. package/dist/cjs/node/plugin/utils.js +2 -0
  12. package/dist/cjs/node/prerender/runPrerender.js +75 -67
  13. package/dist/cjs/node/runtime/html/injectAssets/injectAssets__public.js +1 -1
  14. package/dist/cjs/node/runtime/index-common.js +3 -1
  15. package/dist/cjs/node/runtime/renderPage/analyzePage.js +2 -2
  16. package/dist/cjs/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.js +12 -12
  17. package/dist/cjs/node/runtime/renderPage/createHttpResponseObject.js +3 -3
  18. package/dist/cjs/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -2
  19. package/dist/cjs/node/runtime/renderPage/getHttpResponseBody.js +1 -1
  20. package/dist/cjs/node/runtime/renderPage.js +8 -5
  21. package/dist/cjs/shared/getPageFiles/analyzePageClientSide/determineClientEntry.js +1 -0
  22. package/dist/cjs/shared/page-configs/loadConfigValues.js +12 -3
  23. package/dist/cjs/shared/page-configs/serialize/parseConfigValuesSerialized.js +19 -0
  24. package/dist/cjs/shared/page-configs/serialize/parsePageConfigs.js +3 -12
  25. package/dist/cjs/utils/assertKeys.js +28 -0
  26. package/dist/cjs/utils/joinEnglish.js +3 -3
  27. package/dist/cjs/utils/parseUrl.js +24 -16
  28. package/dist/cjs/utils/projectInfo.js +3 -2
  29. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +25 -11
  30. package/dist/esm/client/client-routing-runtime/index.d.ts +1 -0
  31. package/dist/esm/client/client-routing-runtime/index.js +1 -0
  32. package/dist/esm/client/client-routing-runtime/onBrowserHistoryNavigation.js +2 -2
  33. package/dist/esm/client/shared/getPageContextSerializedInHtml.js +1 -1
  34. package/dist/esm/node/plugin/index.d.ts +1 -0
  35. package/dist/esm/node/plugin/index.js +1 -0
  36. package/dist/esm/node/plugin/plugins/devConfig/determineOptimizeDeps.js +3 -4
  37. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigValuesSerialized.d.ts +5 -0
  38. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getConfigValuesSerialized.js +70 -0
  39. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +58 -37
  40. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.d.ts +5 -0
  41. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +98 -0
  42. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +63 -76
  43. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigValuesAll.js +43 -17
  44. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.d.ts +0 -3
  45. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVirtualFilePageConfigs.js +13 -68
  46. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/isRuntimeEnvMatch.js +11 -8
  47. package/dist/esm/node/plugin/shared/getConfigValueSourcesNotOverriden.d.ts +5 -0
  48. package/dist/esm/node/plugin/shared/{getConfigValueSourcesRelevant.js → getConfigValueSourcesNotOverriden.js} +2 -2
  49. package/dist/esm/node/plugin/utils.d.ts +2 -0
  50. package/dist/esm/node/plugin/utils.js +2 -0
  51. package/dist/esm/node/prerender/runPrerender.js +75 -67
  52. package/dist/esm/node/runtime/html/injectAssets/injectAssets__public.js +1 -1
  53. package/dist/esm/node/runtime/index-common.d.ts +1 -0
  54. package/dist/esm/node/runtime/index-common.js +1 -0
  55. package/dist/esm/node/runtime/renderPage/analyzePage.js +2 -2
  56. package/dist/esm/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.d.ts +1 -1
  57. package/dist/esm/node/runtime/renderPage/createHttpResponseObject/assertNoInfiniteHttpRedirect.js +12 -12
  58. package/dist/esm/node/runtime/renderPage/createHttpResponseObject.d.ts +1 -1
  59. package/dist/esm/node/runtime/renderPage/createHttpResponseObject.js +3 -3
  60. package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -2
  61. package/dist/esm/node/runtime/renderPage/getHttpResponseBody.js +1 -1
  62. package/dist/esm/node/runtime/renderPage.js +9 -6
  63. package/dist/esm/shared/getPageFiles/analyzePageClientSide/determineClientEntry.js +1 -0
  64. package/dist/esm/shared/page-configs/PageConfig.d.ts +14 -4
  65. package/dist/esm/shared/page-configs/loadConfigValues.js +12 -3
  66. package/dist/esm/shared/page-configs/serialize/parseConfigValuesSerialized.d.ts +4 -0
  67. package/dist/esm/shared/page-configs/serialize/parseConfigValuesSerialized.js +16 -0
  68. package/dist/esm/shared/page-configs/serialize/parsePageConfigs.js +4 -13
  69. package/dist/esm/utils/assertKeys.d.ts +4 -0
  70. package/dist/esm/utils/assertKeys.js +22 -0
  71. package/dist/esm/utils/joinEnglish.d.ts +1 -1
  72. package/dist/esm/utils/joinEnglish.js +3 -3
  73. package/dist/esm/utils/parseUrl.js +24 -16
  74. package/dist/esm/utils/projectInfo.d.ts +3 -1
  75. package/dist/esm/utils/projectInfo.js +2 -1
  76. package/package.json +3 -3
  77. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/helpers.js +0 -28
  78. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.d.ts +0 -5
  79. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/helpers.js +0 -25
  80. package/dist/esm/node/plugin/shared/getConfigValueSourcesRelevant.d.ts +0 -5
@@ -11,7 +11,7 @@ const picocolors_1 = __importDefault(require("@brillout/picocolors"));
11
11
  const streamDocs = 'See https://vike.dev/stream for more information.';
12
12
  function getHttpResponseBody(htmlRender, renderHook) {
13
13
  if (typeof htmlRender !== 'string') {
14
- (0, utils_js_1.assertUsage)(false, getErrMsg(htmlRender, renderHook, 'body', `Use ${picocolors_1.default.cyan('pageContext.httpResponse.pipe()')} or ${picocolors_1.default.cyan('pageContext.httpResponse.getBody()')} instead`));
14
+ (0, utils_js_1.assertUsage)(false, getErrMsg(htmlRender, renderHook, 'body', `Use ${picocolors_1.default.cyan('pageContext.httpResponse.pipe()')} instead`));
15
15
  }
16
16
  const body = htmlRender;
17
17
  return body;
@@ -333,10 +333,8 @@ function normalizeUrl(pageContextInit, httpRequestId) {
333
333
  function getPermanentRedirect(pageContextInit, httpRequestId) {
334
334
  const { redirects, baseServer } = (0, globalContext_js_1.getGlobalContext)();
335
335
  const urlWithoutBase = (0, utils_js_1.removeBaseServer)(pageContextInit.urlOriginal, baseServer);
336
- let urlOriginalPathnameWithouBase;
337
336
  let origin = null;
338
337
  let urlTarget = (0, utils_js_1.modifyUrlPathname)(urlWithoutBase, (urlPathname) => {
339
- urlOriginalPathnameWithouBase = urlPathname;
340
338
  const urlTargetWithOrigin = (0, resolveRedirects_js_1.resolveRedirects)(redirects, urlPathname);
341
339
  if (urlTargetWithOrigin === null)
342
340
  return null;
@@ -346,13 +344,12 @@ function getPermanentRedirect(pageContextInit, httpRequestId) {
346
344
  });
347
345
  if (origin)
348
346
  urlTarget = (0, utils_js_1.addUrlOrigin)(urlTarget, origin);
349
- (0, utils_js_1.assert)(urlOriginalPathnameWithouBase);
350
347
  if (urlTarget === urlWithoutBase)
351
348
  return null;
352
349
  (0, loggerRuntime_js_1.logRuntimeInfo)?.(`Permanent redirect defined by your config.redirects (https://vike.dev/redirects)`, httpRequestId, 'info');
353
350
  urlTarget = (0, utils_js_1.prependBase)(urlTarget, baseServer);
354
351
  (0, utils_js_1.assert)(urlTarget !== pageContextInit.urlOriginal);
355
- const httpResponse = (0, createHttpResponseObject_js_1.createHttpResponseObjectRedirect)({ url: urlTarget, statusCode: 301 }, urlOriginalPathnameWithouBase);
352
+ const httpResponse = (0, createHttpResponseObject_js_1.createHttpResponseObjectRedirect)({ url: urlTarget, statusCode: 301 }, urlWithoutBase);
356
353
  const pageContextHttpResponse = { ...pageContextInit, httpResponse };
357
354
  return pageContextHttpResponse;
358
355
  }
@@ -396,7 +393,13 @@ async function handleAbortError(errAbort, pageContextsFromRewrite, pageContextIn
396
393
  ...pageContextInit,
397
394
  ...pageContextAbort
398
395
  };
399
- const httpResponse = (0, createHttpResponseObject_js_1.createHttpResponseObjectRedirect)(pageContextAbort._urlRedirect, pageContextNominalPageInit.urlPathname);
396
+ const httpResponse = (0, createHttpResponseObject_js_1.createHttpResponseObjectRedirect)(pageContextAbort._urlRedirect, (() => {
397
+ const { pathname, searchOriginal } = pageContextNominalPageInit.urlParsed;
398
+ const urlLogical = (0, utils_js_1.createUrlFromComponents)(null, pathname, searchOriginal,
399
+ // The server-side doesn't have access to the hash
400
+ null);
401
+ return urlLogical;
402
+ })());
400
403
  (0, utils_js_1.objectAssign)(pageContextReturn, { httpResponse });
401
404
  return { pageContextReturn };
402
405
  }
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ // TODO/v1-release: remove
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.getVikeClientEntry = exports.determineClientEntry = void 0;
4
5
  function determineClientEntry({ pageFilesClientSide, pageFilesServerSide, isHtmlOnly, isClientRouting }) {
@@ -3,15 +3,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.loadConfigValues = void 0;
4
4
  const utils_js_1 = require("../utils.js");
5
5
  const parseConfigValuesImported_js_1 = require("./serialize/parseConfigValuesImported.js");
6
+ const parseConfigValuesSerialized_js_1 = require("./serialize/parseConfigValuesSerialized.js");
6
7
  async function loadConfigValues(pageConfig, isDev) {
7
8
  if ('isAllLoaded' in pageConfig &&
8
9
  // We don't need to cache in dev, since Vite already caches the virtual module
9
10
  !isDev) {
10
11
  return pageConfig;
11
12
  }
12
- const configValuesImported = await pageConfig.loadConfigValuesAll();
13
- const configValuesAddendum = (0, parseConfigValuesImported_js_1.parseConfigValuesImported)(configValuesImported);
14
- Object.assign(pageConfig.configValues, configValuesAddendum);
13
+ const configValuesLoaded = await pageConfig.loadConfigValuesAll();
14
+ {
15
+ const { configValuesImported } = configValuesLoaded;
16
+ const configValuesAddendum = (0, parseConfigValuesImported_js_1.parseConfigValuesImported)(configValuesImported);
17
+ Object.assign(pageConfig.configValues, configValuesAddendum);
18
+ }
19
+ {
20
+ const { configValuesSerialized } = configValuesLoaded;
21
+ const configValuesAddendum = (0, parseConfigValuesSerialized_js_1.parseConfigValuesSerialized)(configValuesSerialized);
22
+ Object.assign(pageConfig.configValues, configValuesAddendum);
23
+ }
15
24
  (0, utils_js_1.objectAssign)(pageConfig, { isAllLoaded: true });
16
25
  return pageConfig;
17
26
  }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseConfigValuesSerialized = void 0;
4
+ const utils_js_1 = require("../../utils.js");
5
+ const parse_1 = require("@brillout/json-serializer/parse");
6
+ function parseConfigValuesSerialized(configValuesSerialized) {
7
+ const configValues = {};
8
+ Object.entries(configValuesSerialized).forEach(([configName, configValueSeriliazed]) => {
9
+ const { valueSerialized, definedAt } = configValueSeriliazed;
10
+ (0, utils_js_1.assert)(valueSerialized);
11
+ (0, utils_js_1.assert)(!configValues[configName]);
12
+ configValues[configName] = {
13
+ value: (0, parse_1.parse)(valueSerialized),
14
+ definedAt
15
+ };
16
+ });
17
+ return configValues;
18
+ }
19
+ exports.parseConfigValuesSerialized = parseConfigValuesSerialized;
@@ -1,26 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.parsePageConfigs = void 0;
4
- const parse_1 = require("@brillout/json-serializer/parse");
5
4
  const parseConfigValuesImported_js_1 = require("./parseConfigValuesImported.js");
6
5
  const utils_js_1 = require("../../utils.js");
7
6
  const helpers_js_1 = require("../helpers.js");
7
+ const parseConfigValuesSerialized_js_1 = require("./parseConfigValuesSerialized.js");
8
8
  function parsePageConfigs(pageConfigsSerialized, pageConfigGlobalSerialized) {
9
9
  const pageConfigs = pageConfigsSerialized.map((pageConfigSerialized) => {
10
10
  const configValues = {};
11
11
  {
12
12
  const { configValuesSerialized } = pageConfigSerialized;
13
- Object.entries(configValuesSerialized).forEach(([configName, configValueSeriliazed]) => {
14
- {
15
- const { valueSerialized, definedAt } = configValueSeriliazed;
16
- (0, utils_js_1.assert)(valueSerialized);
17
- (0, utils_js_1.assert)(!configValues[configName]);
18
- configValues[configName] = {
19
- value: (0, parse_1.parse)(valueSerialized),
20
- definedAt
21
- };
22
- }
23
- });
13
+ const configValuesAddendum = (0, parseConfigValuesSerialized_js_1.parseConfigValuesSerialized)(configValuesSerialized);
14
+ Object.assign(configValues, configValuesAddendum);
24
15
  }
25
16
  {
26
17
  const { configValuesImported } = pageConfigSerialized;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.assertKeys = void 0;
7
+ const picocolors_1 = __importDefault(require("@brillout/picocolors"));
8
+ const assert_js_1 = require("./assert.js");
9
+ const joinEnglish_js_1 = require("./joinEnglish.js");
10
+ function assertKeys(obj, keysExpected, errPrefix) {
11
+ const keysUnknown = [];
12
+ const keys = Object.keys(obj);
13
+ for (const key of keys) {
14
+ if (!keysExpected.includes(key)) {
15
+ keysUnknown.push(key);
16
+ }
17
+ }
18
+ if (keysUnknown.length !== 0) {
19
+ (0, assert_js_1.assertUsage)(false, [
20
+ errPrefix,
21
+ `unknown key${keysUnknown.length === 1 ? '' : 's'}`,
22
+ (0, joinEnglish_js_1.joinEnglish)(keysUnknown, 'and', picocolors_1.default.cyan) + '.',
23
+ 'Only following keys are allowed:',
24
+ (0, joinEnglish_js_1.joinEnglish)(keysExpected, 'and', picocolors_1.default.cyan) + '.'
25
+ ].join(' '));
26
+ }
27
+ }
28
+ exports.assertKeys = assertKeys;
@@ -3,12 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.joinEnglish = void 0;
4
4
  const assert_js_1 = require("./assert.js");
5
5
  // https://stackoverflow.com/questions/53879088/join-an-array-by-commas-and-and/53879103#53879103
6
- function joinEnglish(arr, conjunction) {
6
+ function joinEnglish(arr, conjunction, colorizer = (s) => s) {
7
7
  (0, assert_js_1.assert)(arr.length > 0);
8
8
  if (arr.length === 1)
9
- return arr[0];
9
+ return colorizer(arr[0]);
10
10
  const firsts = arr.slice(0, arr.length - 1);
11
11
  const last = arr[arr.length - 1];
12
- return firsts.join(', ') + ` ${conjunction} ` + last;
12
+ return firsts.map(colorizer).join(', ') + ` ${conjunction} ` + colorizer(last);
13
13
  }
14
14
  exports.joinEnglish = joinEnglish;
@@ -55,7 +55,7 @@ function parseUrl(url, baseServer) {
55
55
  searchAll[key] = [...(searchAll.hasOwnProperty(key) ? searchAll[key] : []), val];
56
56
  });
57
57
  // Origin + pathname
58
- const { origin, pathname: pathnameResolved } = parsePathname(urlWithoutHashNorSearch, baseServer);
58
+ const { origin, pathname: pathnameResolved } = getPathname(urlWithoutHashNorSearch, baseServer);
59
59
  (0, assert_js_1.assert)(origin === null || origin === decodeSafe(origin)); // AFAICT decoding the origin is useless
60
60
  (0, assert_js_1.assert)(pathnameResolved.startsWith('/'));
61
61
  (0, assert_js_1.assert)(origin === null || url.startsWith(origin));
@@ -91,35 +91,43 @@ function decodeSafe(urlComponent) {
91
91
  return urlComponent;
92
92
  }
93
93
  function decodePathname(urlPathname) {
94
+ urlPathname = urlPathname.replace(/\s+$/, '');
94
95
  urlPathname = urlPathname
95
96
  .split('/')
96
97
  .map((dir) => decodeSafe(dir).split('/').join('%2F'))
97
98
  .join('/');
98
- urlPathname = urlPathname.replace(/\s/g, '');
99
99
  return urlPathname;
100
100
  }
101
- function parsePathname(urlWithoutHashNorSearch, baseServer) {
101
+ function getPathname(url, baseServer) {
102
+ // Search and hash already extracted
103
+ (0, assert_js_1.assert)(!url.includes('?') && !url.includes('#'));
104
+ // url has origin
102
105
  {
103
- const { origin, pathname } = parseOrigin(urlWithoutHashNorSearch);
106
+ const { origin, pathname } = parseOrigin(url);
104
107
  if (origin) {
105
108
  return { origin, pathname };
106
109
  }
107
- (0, assert_js_1.assert)(pathname === urlWithoutHashNorSearch);
110
+ (0, assert_js_1.assert)(pathname === url);
108
111
  }
109
- if (urlWithoutHashNorSearch.startsWith('/')) {
110
- return { origin: null, pathname: urlWithoutHashNorSearch };
112
+ // url doesn't have origin
113
+ if (url.startsWith('/')) {
114
+ return { origin: null, pathname: url };
111
115
  }
112
116
  else {
113
- // In the browser, this is the Base URL of the current URL
117
+ // url is a relative path
118
+ // In the browser, this is the Base URL of the current URL.
114
119
  // Safe access `window?.document?.baseURI` for users who shim `window` in Node.js
115
- let baseURI = typeof window !== 'undefined' && window?.document?.baseURI;
116
- if (baseURI)
117
- baseURI = parseOrigin(baseURI).pathname;
118
- const base = baseURI || baseServer;
119
- const pathname = resolveUrlPathnameRelative(urlWithoutHashNorSearch, base);
120
- // We need to parse the origin in case `base === window.document.baseURI`
121
- const parsed = parseOrigin(pathname);
122
- return parsed;
120
+ const baseURI = typeof window !== 'undefined' ? window?.document?.baseURI : undefined;
121
+ let base;
122
+ if (baseURI) {
123
+ const baseURIPathaname = parseOrigin(baseURI.split('?')[0]).pathname;
124
+ base = baseURIPathaname;
125
+ }
126
+ else {
127
+ base = baseServer;
128
+ }
129
+ const pathname = resolveUrlPathnameRelative(url, base);
130
+ return { origin: null, pathname };
123
131
  }
124
132
  }
125
133
  function parseOrigin(url) {
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.projectInfo = void 0;
3
+ exports.PROJECT_VERSION = exports.projectInfo = void 0;
4
4
  const assertSingleInstance_js_1 = require("./assertSingleInstance.js");
5
- const PROJECT_VERSION = '0.4.146-commit-701e2e5';
5
+ const PROJECT_VERSION = '0.4.147-commit-2fa53b2';
6
+ exports.PROJECT_VERSION = PROJECT_VERSION;
6
7
  const projectInfo = {
7
8
  projectName: 'Vike',
8
9
  projectVersion: PROJECT_VERSION,
@@ -27,7 +27,7 @@ async function getPageContextFromHooks_firstRender(pageContext) {
27
27
  objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
28
28
  {
29
29
  const pageContextForHook = { ...pageContext, ...pageContextFromHooks };
30
- if (await onBeforeRenderClientOnlyExists(pageContextForHook)) {
30
+ if (onBeforeRenderClientOnlyExists(pageContextForHook)) {
31
31
  const pageContextFromHook = await executeOnBeforeRenderHookClientSide(pageContextForHook);
32
32
  objectAssign(pageContextFromHooks, pageContextFromHook);
33
33
  }
@@ -57,13 +57,17 @@ async function getPageContextFromHooks_uponNavigation(pageContext) {
57
57
  }
58
58
  async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
59
59
  let pageContextFromHooks = {};
60
+ objectAssign(pageContextFromHooks, { _hasPageContextFromClient: false });
60
61
  objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContext._pageId, pageContext));
62
+ let pageContextFetchedFromServer = false;
61
63
  // Needs to be called before any client-side hook, because it may contain pageContextInit.user which is needed for guard() and onBeforeRender()
62
64
  if (
63
65
  // For the error page, we cannot fetch pageContext from the server because the pageContext JSON request is based on the URL
64
66
  !isErrorPage &&
67
+ // true if pageContextInit has some client data or the onBeforeRender hook is server-side only:
65
68
  (await hasPageContextServer({ ...pageContext, ...pageContextFromHooks }))) {
66
69
  const pageContextFromServer = await fetchPageContextFromServer(pageContext);
70
+ pageContextFetchedFromServer = true;
67
71
  if (!pageContextFromServer['_isError']) {
68
72
  objectAssign(pageContextFromHooks, pageContextFromServer);
69
73
  }
@@ -72,6 +76,7 @@ async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
72
76
  assert(errorPageId);
73
77
  pageContextFromHooks = {};
74
78
  objectAssign(pageContextFromHooks, {
79
+ _hasPageContextFromClient: false,
75
80
  isHydration: false,
76
81
  _pageId: errorPageId
77
82
  });
@@ -91,25 +96,29 @@ async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
91
96
  if (!isErrorPage) {
92
97
  // Should we really call the guard() hook on the client-side? Shouldn't we make the guard() hook a server-side only hook? Or maybe make its env configurable like onBeforeRender()?
93
98
  await executeGuardHook({
94
- _hasPageContextFromClient: false,
95
99
  ...pageContext,
96
100
  ...pageContextFromHooks
97
101
  }, (pageContext) => preparePageContextForUserConsumptionClientSide(pageContext, true));
98
102
  }
99
103
  }
104
+ // For the error page, we also execute the client-side onBeforeRender() hook, but maybe we shouldn't? The server-side does it as well (but maybe it shouldn't).
100
105
  {
101
- // For the error page, we also execute the client-side onBeforeRender() hook, but maybe we shouldn't? The server-side does it as well (but maybe it shouldn't).
102
- const pageContextFromOnBeforeRender = await executeOnBeforeRenderHookClientSide({
103
- ...pageContext,
104
- ...pageContextFromHooks
105
- });
106
- objectAssign(pageContextFromHooks, pageContextFromOnBeforeRender);
106
+ const pageContextForHook = { ...pageContext, ...pageContextFromHooks };
107
+ if (onBeforeRenderClientOnlyExists(pageContextForHook) || !pageContextFetchedFromServer) {
108
+ // This won't do anything if no hook has been defined or if the hook's env.client is false.
109
+ const pageContextFromHook = await executeOnBeforeRenderHookClientSide(pageContextForHook);
110
+ objectAssign(pageContextFromHooks, pageContextFromHook);
111
+ }
112
+ else {
113
+ assert(pageContextFetchedFromServer);
114
+ }
107
115
  }
108
116
  return pageContextFromHooks;
109
117
  }
110
118
  async function executeOnBeforeRenderHookClientSide(pageContext) {
111
119
  const hook = getHook(pageContext, 'onBeforeRender');
112
120
  if (!hook) {
121
+ // No hook defined or hook's env.client is false
113
122
  const pageContextFromOnBeforeRender = {
114
123
  _hasPageContextFromClient: false
115
124
  };
@@ -153,7 +162,9 @@ async function onBeforeRenderServerOnlyExists(pageContext) {
153
162
  if (pageContext._pageConfigs.length > 0) {
154
163
  // V1
155
164
  const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
156
- return getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value === 'server-only';
165
+ const onBeforeRenderEnv = getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value ?? {};
166
+ assert(isObject(onBeforeRenderEnv));
167
+ return !!onBeforeRenderEnv.server && !onBeforeRenderEnv.client;
157
168
  }
158
169
  else {
159
170
  // TODO/v1-release: remove
@@ -162,14 +173,17 @@ async function onBeforeRenderServerOnlyExists(pageContext) {
162
173
  return hasOnBeforeRenderServerSideOnlyHook;
163
174
  }
164
175
  }
165
- async function onBeforeRenderClientOnlyExists(pageContext) {
176
+ function onBeforeRenderClientOnlyExists(pageContext) {
166
177
  if (pageContext._pageConfigs.length > 0) {
167
178
  // V1
168
179
  const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
169
- return getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value === 'client-only';
180
+ const onBeforeRenderEnv = getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value ?? {};
181
+ assert(isObject(onBeforeRenderEnv));
182
+ return !!onBeforeRenderEnv.client && !onBeforeRenderEnv.server;
170
183
  }
171
184
  else {
172
185
  // TODO/v1-release: remove
186
+ // Client-only onBeforeRender() hooks were never supported for the V0.4 design
173
187
  return false;
174
188
  }
175
189
  }
@@ -1,5 +1,6 @@
1
1
  export { navigate, reload } from './navigate.js';
2
2
  export { prefetch } from './prefetch.js';
3
+ export { PROJECT_VERSION } from './utils.js';
3
4
  import type { PageContextBuiltInClientWithClientRouting } from '../../shared/types.js';
4
5
  /** @deprecated
5
6
  * Replace:
@@ -5,3 +5,4 @@
5
5
  // Use package.json#exports to make the imports isomorphic.
6
6
  export { navigate, reload } from './navigate.js';
7
7
  export { prefetch } from './prefetch.js';
8
+ export { PROJECT_VERSION } from './utils.js';
@@ -14,8 +14,8 @@ function onBrowserHistoryNavigation() {
14
14
  // - By user clicking on a hash link `<a href="#some-hash" />`
15
15
  // - The popstate event is *only* triggered if `href` starts with '#' (even if `href` is '/#some-hash' while the current URL's pathname is '/' then the popstate still isn't triggered)
16
16
  // - By JavaScript: `location.hash = 'some-hash'`
17
- // - The `event` of `window.addEventListener('popstate', (event) => /*...*/)` is useless: the History API doesn't provide the previous state (the popped state), see https://stackoverflow.com/questions/48055323/is-history-state-always-the-same-as-popstate-event-state
18
- window.addEventListener('popstate', () => {
17
+ // - The `event` argument of `window.addEventListener('popstate', (event) => /*...*/)` is useless: the History API doesn't provide the previous state (the popped state), see https://stackoverflow.com/questions/48055323/is-history-state-always-the-same-as-popstate-event-state
18
+ window.addEventListener('popstate', (ev) => {
19
19
  const currentState = getState();
20
20
  const scrollTarget = currentState.historyState.scrollPosition || 'scroll-to-top-or-hash';
21
21
  const isUserLandPushStateNavigation = currentState.historyState.triggedBy === 'user';
@@ -4,7 +4,7 @@ export { getPageContextSerializedInHtml };
4
4
  function getPageContextSerializedInHtml() {
5
5
  const id = 'vike_pageContext';
6
6
  const elem = document.getElementById(id);
7
- assertUsage(elem, `The element #${id} (which vike automatically injects into the HTML) is missing from the DOM. This may happen if your HTML is malformed. Make sure your HTML isn't malformed, and make sure you don't remove #${id} from the HTML nor from the DOM.`);
7
+ assertUsage(elem, `The element #${id} (which Vike automatically injects into the HTML) is missing from the DOM. This may happen if your HTML is malformed. Make sure your HTML isn't malformed, and make sure you don't remove #${id} from the HTML nor from the DOM.`);
8
8
  const pageContextJson = elem.textContent;
9
9
  assert(pageContextJson);
10
10
  const pageContextSerializedInHtml = parse(pageContextJson);
@@ -2,5 +2,6 @@ export default plugin;
2
2
  export { plugin };
3
3
  export { plugin as ssr };
4
4
  export type { ConfigVikeUserProvided as UserConfig };
5
+ export { PROJECT_VERSION as version } from './utils.js';
5
6
  import type { ConfigVikeUserProvided } from '../../shared/ConfigVike.js';
6
7
  declare function plugin(vikeConfig?: ConfigVikeUserProvided): any;
@@ -2,6 +2,7 @@ export default plugin;
2
2
  export { plugin };
3
3
  // TODO/v1-release: remove
4
4
  export { plugin as ssr };
5
+ export { PROJECT_VERSION as version } from './utils.js';
5
6
  import { assertUsage, markEnvAsVite } from './utils.js';
6
7
  import { buildConfig } from './plugins/buildConfig.js';
7
8
  import { previewConfig } from './plugins/previewConfig.js';
@@ -2,7 +2,7 @@ export { determineOptimizeDeps };
2
2
  import { findPageFiles } from '../../shared/findPageFiles.js';
3
3
  import { assert, getFilePathAbsolute, isNotNullish, isNpmPackageImport, unique } from '../../utils.js';
4
4
  import { getVikeConfig } from '../importUserCode/v1-design/getVikeConfig.js';
5
- import { getConfigValueSourcesRelevant } from '../../shared/getConfigValueSourcesRelevant.js';
5
+ import { getConfigValueSourcesNotOverriden } from '../../shared/getConfigValueSourcesNotOverriden.js';
6
6
  import { analyzeClientEntries } from '../buildConfig.js';
7
7
  import { virtualFileIdImportUserCodeClientCR, virtualFileIdImportUserCodeClientSR } from '../../../shared/virtual-files/virtualFileImportUserCode.js';
8
8
  async function determineOptimizeDeps(config, configVike, isDev) {
@@ -30,12 +30,11 @@ async function getPageDeps(config, pageConfigs, isDev) {
30
30
  // V1 design
31
31
  {
32
32
  pageConfigs.forEach((pageConfig) => {
33
- const configValueSourcesRelevant = getConfigValueSourcesRelevant(pageConfig);
34
- configValueSourcesRelevant.forEach((configValueSource) => {
33
+ getConfigValueSourcesNotOverriden(pageConfig).forEach((configValueSource) => {
35
34
  if (!configValueSource.valueIsImportedAtRuntime)
36
35
  return;
37
36
  const { definedAt, configEnv } = configValueSource;
38
- if (configEnv !== 'client-only' && configEnv !== 'server-and-client')
37
+ if (!configEnv.client)
39
38
  return;
40
39
  if (definedAt.filePathRelativeToUserRootDir !== null) {
41
40
  const { filePathAbsoluteFilesystem } = definedAt;
@@ -0,0 +1,5 @@
1
+ export { getConfigValuesSerialized };
2
+ export { assertConfigValueIsSerializable };
3
+ import type { ConfigEnvInternal, ConfigValueSource, DefinedAt, PageConfigBuildTime } from '../../../../../shared/page-configs/PageConfig.js';
4
+ declare function getConfigValuesSerialized(pageConfig: PageConfigBuildTime, isEnvMatch: (configEnv: ConfigEnvInternal, configValueSource?: ConfigValueSource) => boolean): string;
5
+ declare function assertConfigValueIsSerializable(value: unknown, configName: string, definedAt: DefinedAt): void;
@@ -0,0 +1,70 @@
1
+ export { getConfigValuesSerialized };
2
+ export { assertConfigValueIsSerializable };
3
+ import { assert, assertUsage, getPropAccessNotation } from '../../../utils.js';
4
+ import { isJsonSerializerError, stringify } from '@brillout/json-serializer/stringify';
5
+ import pc from '@brillout/picocolors';
6
+ import { getConfigValueFilePathToShowToUser } from '../../../../../shared/page-configs/helpers.js';
7
+ import { serializeConfigValue } from '../../../../../shared/page-configs/serialize/serializeConfigValue.js';
8
+ import { getConfigValueSourcesNotOverriden } from '../../../shared/getConfigValueSourcesNotOverriden.js';
9
+ function getConfigValuesSerialized(pageConfig, isEnvMatch) {
10
+ const lines = [];
11
+ Object.entries(pageConfig.configValuesComputed).forEach(([configName, configValuesComputed]) => {
12
+ const { value, configEnv } = configValuesComputed;
13
+ if (!isEnvMatch(configEnv))
14
+ return;
15
+ // configValeSources has higher precedence
16
+ if (pageConfig.configValueSources[configName])
17
+ return;
18
+ const configValue = pageConfig.configValues[configName];
19
+ assert(configValue);
20
+ const { definedAt } = configValue;
21
+ const valueSerialized = getConfigValueSerialized(value, configName, definedAt);
22
+ serializeConfigValue(lines, configName, { definedAt, valueSerialized });
23
+ });
24
+ getConfigValueSourcesNotOverriden(pageConfig).forEach((configValueSource) => {
25
+ const { configName, configEnv } = configValueSource;
26
+ const configValue = pageConfig.configValues[configName];
27
+ if (!configValue)
28
+ return;
29
+ if (!isEnvMatch(configEnv, configValueSource)) {
30
+ return;
31
+ }
32
+ const { value, definedAt } = configValue;
33
+ const valueSerialized = getConfigValueSerialized(value, configName, definedAt);
34
+ serializeConfigValue(lines, configName, { definedAt, valueSerialized });
35
+ });
36
+ const code = lines.join('\n');
37
+ return code;
38
+ }
39
+ function assertConfigValueIsSerializable(value, configName, definedAt) {
40
+ // Contains asserts
41
+ getConfigValueSerialized(value, configName, definedAt);
42
+ }
43
+ function getConfigValueSerialized(value, configName, definedAt) {
44
+ const valueName = `config${getPropAccessNotation(configName)}`;
45
+ let configValueSerialized;
46
+ try {
47
+ configValueSerialized = stringify(value, { valueName, forbidReactElements: true });
48
+ }
49
+ catch (err) {
50
+ let serializationErrMsg = '';
51
+ if (isJsonSerializerError(err)) {
52
+ serializationErrMsg = err.messageCore;
53
+ }
54
+ else {
55
+ // When a property getter throws an error
56
+ console.error('Serialization error:');
57
+ console.error(err);
58
+ serializationErrMsg = 'see serialization error printed above';
59
+ }
60
+ const configValueFilePathToShowToUser = getConfigValueFilePathToShowToUser({ definedAt });
61
+ assert(configValueFilePathToShowToUser);
62
+ assertUsage(false, [
63
+ `The value of the config ${pc.cyan(configName)} cannot be defined inside the file ${configValueFilePathToShowToUser}:`,
64
+ `its value must be defined in an another file and then imported by ${configValueFilePathToShowToUser}. (Because its value isn't serializable: ${serializationErrMsg}.)`,
65
+ `Only serializable config values can be defined inside +config.h.js files, see https://vike.dev/header-file.`
66
+ ].join(' '));
67
+ }
68
+ configValueSerialized = JSON.stringify(configValueSerialized);
69
+ return configValueSerialized;
70
+ }