vike 0.4.150 → 0.4.151-commit-19bc995

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 (109) hide show
  1. package/dist/cjs/node/plugin/index.js +4 -4
  2. package/dist/cjs/node/plugin/plugins/assertFileEnv.js +107 -0
  3. package/dist/cjs/node/plugin/plugins/autoFullBuild.js +3 -2
  4. package/dist/cjs/node/plugin/plugins/baseUrls.js +2 -2
  5. package/dist/cjs/node/plugin/plugins/buildConfig.js +17 -36
  6. package/dist/cjs/node/plugin/plugins/commonConfig.js +1 -1
  7. package/dist/cjs/node/plugin/plugins/config/resolveExtensions.js +1 -1
  8. package/dist/cjs/node/plugin/plugins/config/stemUtils.js +1 -1
  9. package/dist/cjs/node/plugin/plugins/devConfig/determineFsAllowList.js +1 -1
  10. package/dist/cjs/node/plugin/plugins/importBuild/getVikeManifest.js +38 -0
  11. package/dist/cjs/node/plugin/plugins/importBuild/index.js +57 -19
  12. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +10 -0
  13. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +46 -28
  14. package/dist/cjs/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errSwc.js +5 -5
  15. package/dist/cjs/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errSwcBig.js +4 -4
  16. package/dist/cjs/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errVueCss.js +7 -7
  17. package/dist/cjs/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errVueHtml.js +2 -2
  18. package/dist/cjs/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errVueJavascript.js +3 -3
  19. package/dist/cjs/node/plugin/shared/loggerNotProd/errorWithCodeSnippet.js +1 -1
  20. package/dist/cjs/node/plugin/shared/loggerVite.js +1 -1
  21. package/dist/cjs/node/plugin/utils.js +1 -0
  22. package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +2 -0
  23. package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +2 -1
  24. package/dist/cjs/node/runtime/index-deprecated.js +3 -2
  25. package/dist/cjs/node/runtime/index.js +3 -2
  26. package/dist/cjs/node/runtime/renderPage/createHttpResponseObject/getCacheControl.js +20 -0
  27. package/dist/cjs/node/runtime/renderPage/createHttpResponseObject.js +8 -1
  28. package/dist/cjs/node/runtime/renderPage/executeOnBeforeRenderAndDataHooks.js +33 -0
  29. package/dist/cjs/node/runtime/renderPage/getPageAssets.js +1 -1
  30. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +5 -5
  31. package/dist/cjs/node/runtime/renderPage.js +21 -9
  32. package/dist/cjs/shared/getPageFiles/getExports.js +1 -1
  33. package/dist/cjs/shared/route/resolveRedirects.js +3 -11
  34. package/dist/cjs/shared/route/resolveUrlPathname.js +48 -0
  35. package/dist/cjs/utils/debug.js +35 -21
  36. package/dist/cjs/utils/getDependencyPackageJson.js +1 -1
  37. package/dist/cjs/utils/getFilePathAbsolute.js +1 -1
  38. package/dist/cjs/utils/getOutDirs.js +11 -1
  39. package/dist/cjs/utils/injectRollupInputs.js +29 -0
  40. package/dist/cjs/utils/isPlainObject.js +1 -1
  41. package/dist/cjs/utils/projectInfo.js +1 -1
  42. package/dist/cjs/utils/requireResolve.js +1 -1
  43. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +105 -66
  44. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +1 -1
  45. package/dist/esm/node/plugin/index.js +4 -4
  46. package/dist/esm/node/plugin/plugins/assertFileEnv.d.ts +3 -0
  47. package/dist/esm/node/plugin/plugins/assertFileEnv.js +101 -0
  48. package/dist/esm/node/plugin/plugins/autoFullBuild.js +3 -2
  49. package/dist/esm/node/plugin/plugins/baseUrls.js +2 -2
  50. package/dist/esm/node/plugin/plugins/buildConfig.js +17 -36
  51. package/dist/esm/node/plugin/plugins/commonConfig.js +1 -1
  52. package/dist/esm/node/plugin/plugins/config/resolveExtensions.js +1 -1
  53. package/dist/esm/node/plugin/plugins/config/stemUtils.js +1 -1
  54. package/dist/esm/node/plugin/plugins/devConfig/determineFsAllowList.js +1 -1
  55. package/dist/esm/node/plugin/plugins/importBuild/getVikeManifest.d.ts +5 -0
  56. package/dist/esm/node/plugin/plugins/importBuild/getVikeManifest.js +32 -0
  57. package/dist/esm/node/plugin/plugins/importBuild/index.js +59 -21
  58. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/debug.d.ts +1 -1
  59. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +10 -0
  60. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/crawlPlusFiles.js +47 -29
  61. package/dist/esm/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errSwc.js +5 -5
  62. package/dist/esm/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errSwcBig.js +4 -4
  63. package/dist/esm/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errVueCss.js +7 -7
  64. package/dist/esm/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errVueHtml.js +2 -2
  65. package/dist/esm/node/plugin/shared/loggerNotProd/errorWithCodeSnippet/fixture-errors/errVueJavascript.js +3 -3
  66. package/dist/esm/node/plugin/shared/loggerNotProd/errorWithCodeSnippet.js +1 -1
  67. package/dist/esm/node/plugin/shared/loggerVite.js +1 -1
  68. package/dist/esm/node/plugin/utils.d.ts +1 -0
  69. package/dist/esm/node/plugin/utils.js +1 -0
  70. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +2 -0
  71. package/dist/esm/node/runtime/html/serializePageContextClientSide.js +2 -1
  72. package/dist/esm/node/runtime/index-deprecated.js +3 -2
  73. package/dist/esm/node/runtime/index.js +3 -2
  74. package/dist/esm/node/runtime/renderPage/createHttpResponseObject/getCacheControl.d.ts +3 -0
  75. package/dist/esm/node/runtime/renderPage/createHttpResponseObject/getCacheControl.js +17 -0
  76. package/dist/esm/node/runtime/renderPage/createHttpResponseObject.js +8 -1
  77. package/dist/esm/node/runtime/renderPage/{executeOnBeforeRenderHook.d.ts → executeOnBeforeRenderAndDataHooks.d.ts} +2 -2
  78. package/dist/esm/node/runtime/renderPage/executeOnBeforeRenderAndDataHooks.js +30 -0
  79. package/dist/esm/node/runtime/renderPage/getPageAssets.js +1 -1
  80. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +5 -5
  81. package/dist/esm/node/runtime/renderPage.js +22 -10
  82. package/dist/esm/shared/VikeNamespace.d.ts +5 -1
  83. package/dist/esm/shared/getPageFiles/getExports.js +1 -1
  84. package/dist/esm/shared/page-configs/Config/PageContextConfig.d.ts +4 -4
  85. package/dist/esm/shared/page-configs/Config/helpers.d.ts +2 -2
  86. package/dist/esm/shared/page-configs/Config.d.ts +33 -7
  87. package/dist/esm/shared/route/resolveRedirects.js +3 -11
  88. package/dist/esm/shared/route/resolveUrlPathname.d.ts +12 -0
  89. package/dist/esm/shared/route/resolveUrlPathname.js +45 -0
  90. package/dist/esm/shared/types.d.ts +5 -0
  91. package/dist/esm/types/index.d.ts +1 -1
  92. package/dist/esm/utils/debug.d.ts +4 -4
  93. package/dist/esm/utils/debug.js +35 -21
  94. package/dist/esm/utils/debugGlob.d.ts +1 -1
  95. package/dist/esm/utils/getDependencyPackageJson.js +1 -1
  96. package/dist/esm/utils/getFilePathAbsolute.js +1 -1
  97. package/dist/esm/utils/getOutDirs.js +11 -1
  98. package/dist/esm/utils/injectRollupInputs.d.ts +7 -0
  99. package/dist/esm/utils/injectRollupInputs.js +26 -0
  100. package/dist/esm/utils/isPlainObject.js +1 -1
  101. package/dist/esm/utils/projectInfo.d.ts +2 -2
  102. package/dist/esm/utils/projectInfo.js +1 -1
  103. package/dist/esm/utils/requireResolve.js +1 -1
  104. package/package.json +38 -19
  105. package/dist/cjs/node/plugin/plugins/manifest.js +0 -59
  106. package/dist/cjs/node/runtime/renderPage/executeOnBeforeRenderHook.js +0 -23
  107. package/dist/esm/node/plugin/plugins/manifest.d.ts +0 -3
  108. package/dist/esm/node/plugin/plugins/manifest.js +0 -53
  109. package/dist/esm/node/runtime/renderPage/executeOnBeforeRenderHook.js +0 -20
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveUrlPathname = void 0;
4
+ const assertIsNotBrowser_js_1 = require("../../utils/assertIsNotBrowser.js");
5
+ const utils_js_1 = require("../utils.js");
6
+ (0, assertIsNotBrowser_js_1.assertIsNotBrowser)(); // Don't bloat the client
7
+ /** Given a `routeString` and `routeParams`, resolve `urlPathname`.
8
+ *
9
+ * Basically, the correct implementation of following:
10
+ * ```js
11
+ * let urlPathname = routeString
12
+ * Object.entries(routeParams).forEach(([key, val]) => {
13
+ * urlPathname = urlPathname.replaceAll(key, val)
14
+ * })
15
+ * ```
16
+ */
17
+ function resolveUrlPathname(routeString, routeParams) {
18
+ let parts = [{ val: routeString, type: 'ROUTE_STRING' }];
19
+ Object.entries(routeParams).forEach(([key, val]) => {
20
+ if (key.startsWith('*')) {
21
+ (0, utils_js_1.assert)(key === '*' || /\d+/.test(key.slice(1)));
22
+ (0, utils_js_1.assertUsage)(key === '*', "Resolving URL with multiple globs isn't implemented yet");
23
+ }
24
+ else {
25
+ key = `@${key}`;
26
+ }
27
+ parts = parts
28
+ .map((part) => {
29
+ if (part.type === 'URL') {
30
+ return part;
31
+ }
32
+ else {
33
+ return part.val
34
+ .split(key)
35
+ .map((rest, i) => {
36
+ const partURL = { val, type: 'URL' };
37
+ const partRouteString = { val: rest, type: 'ROUTE_STRING' };
38
+ return i === 0 ? [partRouteString] : [partURL, partRouteString];
39
+ })
40
+ .flat();
41
+ }
42
+ })
43
+ .flat();
44
+ });
45
+ const urlPathname = parts.map((p) => p.val).join('');
46
+ return urlPathname;
47
+ }
48
+ exports.resolveUrlPathname = resolveUrlPathname;
@@ -10,33 +10,47 @@ const getTerminWidth_js_1 = require("./getTerminWidth.js");
10
10
  // Avoid this to be loaded in the browser. For isomorphic code: instead of `import { createDebugger } from './utils.js'`, use `globalThis.createDebugger()`.
11
11
  (0, assert_js_1.assert)(!(0, isBrowser_js_1.isBrowser)());
12
12
  globalThis.__brillout_debug_createDebugger = createDebugger;
13
- function createDebugger(namespace, optionsGlobal) {
14
- (0, checkType_js_1.checkType)(namespace);
15
- const debugWithOptions = (options) => {
13
+ function createDebugger(flag, optionsGlobal) {
14
+ (0, checkType_js_1.checkType)(flag);
15
+ const debugWithOptions = (optionsLocal) => {
16
16
  return (...msgs) => {
17
- if (!isDebugEnabled(namespace))
18
- return;
19
- let [msgFirst, ...msgsRest] = msgs;
20
- const padding = ' '.repeat(namespace.length + 1);
21
- const optionsResolved = { ...optionsGlobal, ...options };
22
- msgFirst = formatMsg(msgFirst, optionsResolved, padding, 'FIRST');
23
- msgsRest = msgsRest.map((msg, i) => {
24
- const position = i === msgsRest.length - 1 ? 'LAST' : 'MIDDLE';
25
- return formatMsg(msg, optionsResolved, padding, position);
26
- });
27
- console.log('\x1b[1m%s\x1b[0m', namespace, msgFirst);
28
- msgsRest.forEach((msg) => {
29
- console.log(msg);
30
- });
17
+ const options = { ...optionsGlobal, ...optionsLocal };
18
+ debug_(flag, options, ...msgs);
31
19
  };
32
20
  };
33
21
  const debug = (...msgs) => debugWithOptions({})(...msgs);
34
- (0, objectAssign_js_1.objectAssign)(debug, { options: debugWithOptions, isEnabled: isDebugEnabled(namespace) });
22
+ (0, objectAssign_js_1.objectAssign)(debug, { options: debugWithOptions, isEnabled: isDebugEnabled(flag) });
35
23
  return debug;
36
24
  }
37
25
  exports.createDebugger = createDebugger;
38
- function isDebugEnabled(namespace) {
39
- (0, checkType_js_1.checkType)(namespace);
26
+ function debug_(flag, options, ...msgs) {
27
+ if (!isDebugEnabled(flag))
28
+ return;
29
+ let [msgFirst, ...msgsRest] = msgs;
30
+ const padding = ' '.repeat(flag.length + 1);
31
+ msgFirst = formatMsg(msgFirst, options, padding, 'FIRST');
32
+ msgsRest = msgsRest.map((msg, i) => {
33
+ const position = i === msgsRest.length - 1 ? 'LAST' : 'MIDDLE';
34
+ return formatMsg(msg, options, padding, position);
35
+ });
36
+ let logFirst;
37
+ let logsRest;
38
+ const noNewLine = msgsRest.length <= 1 && [msgFirst, ...msgsRest].every((m) => typeof m === 'string' && !m.includes('\n'));
39
+ if (noNewLine) {
40
+ logFirst = [msgFirst, ...msgsRest].map((m) => String(m).trim());
41
+ logsRest = [];
42
+ }
43
+ else {
44
+ logFirst = [msgFirst];
45
+ logsRest = msgsRest;
46
+ }
47
+ console.log('\x1b[1m%s\x1b[0m', flag, ...logFirst);
48
+ logsRest.forEach((msg) => {
49
+ console.log(msg);
50
+ });
51
+ }
52
+ function isDebugEnabled(flag) {
53
+ (0, checkType_js_1.checkType)(flag);
40
54
  let DEBUG;
41
55
  // - `process` can be undefined in edge workers
42
56
  // - We want bundlers to be able to statically replace `process.env.*`
@@ -44,7 +58,7 @@ function isDebugEnabled(namespace) {
44
58
  DEBUG = process.env.DEBUG;
45
59
  }
46
60
  catch { }
47
- return DEBUG?.includes(namespace) ?? false;
61
+ return DEBUG?.includes(flag) ?? false;
48
62
  }
49
63
  exports.isDebugEnabled = isDebugEnabled;
50
64
  function formatMsg(info, options, padding, position) {
@@ -17,7 +17,7 @@ const path_1 = __importDefault(require("path"));
17
17
  const fs_1 = __importDefault(require("fs"));
18
18
  const assertIsNotProductionRuntime_js_1 = require("./assertIsNotProductionRuntime.js");
19
19
  const module_1 = require("module");
20
- // @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
20
+ // @ts-ignore Shimmed by dist-cjs-fixup.js for CJS build.
21
21
  const importMetaUrl = `file://${__filename}`;
22
22
  const require_ = (0, module_1.createRequire)(importMetaUrl);
23
23
  (0, assertIsNotProductionRuntime_js_1.assertIsNotProductionRuntime)();
@@ -11,7 +11,7 @@ const assertIsNotProductionRuntime_js_1 = require("./assertIsNotProductionRuntim
11
11
  const isNpmPackage_js_1 = require("./isNpmPackage.js");
12
12
  const assertPathIsFilesystemAbsolute_js_1 = require("./assertPathIsFilesystemAbsolute.js");
13
13
  const module_1 = require("module");
14
- // @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
14
+ // @ts-ignore Shimmed by dist-cjs-fixup.js for CJS build.
15
15
  const importMetaUrl = `file://${__filename}`;
16
16
  const require_ = (0, module_1.createRequire)(importMetaUrl);
17
17
  (0, assertIsNotProductionRuntime_js_1.assertIsNotProductionRuntime)();
@@ -9,7 +9,10 @@ const assert_js_1 = require("./assert.js");
9
9
  const path_shim_js_1 = require("./path-shim.js");
10
10
  const filesystemPathHandling_js_1 = require("./filesystemPathHandling.js");
11
11
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
12
+ const debug_js_1 = require("./debug.js");
13
+ const debug = (0, debug_js_1.createDebugger)('vike:outDir');
12
14
  function getOutDirs(config) {
15
+ debug('getOutDirs()', new Error().stack);
13
16
  let outDirRoot;
14
17
  {
15
18
  const outDir = getOutDirFromViteResolvedConfig(config);
@@ -23,12 +26,17 @@ function getOutDirs(config) {
23
26
  outDirRoot = outDir.slice(0, -1 * '/client'.length);
24
27
  }
25
28
  }
26
- return getOutDirsAll(outDirRoot, config.root);
29
+ const outDirs = getOutDirsAll(outDirRoot, config.root);
30
+ debug('outDirRoot', outDirRoot);
31
+ debug('outDirs', outDirs);
32
+ return outDirs;
27
33
  }
28
34
  exports.getOutDirs = getOutDirs;
29
35
  /** Appends `client/` or `server/` to `config.build.outDir` */
30
36
  function resolveOutDir(config) {
37
+ debug('resolveOutDir()', new Error().stack);
31
38
  const outDir = getOutDirFromViteUserConfig(config) || 'dist';
39
+ debug('outDir', 'outDir');
32
40
  // outDir may already be resolved when using Telefunc + vike (because both Telefunc and vike use this logic)
33
41
  if (!isOutDirRoot(outDir)) {
34
42
  assertOutDirResolved(outDir, config);
@@ -37,9 +45,11 @@ function resolveOutDir(config) {
37
45
  else {
38
46
  const { outDirClient, outDirServer } = determineOutDirs(outDir);
39
47
  if ((0, viteIsSSR_js_1.viteIsSSR)(config)) {
48
+ debug('outDirServer', 'outDirServer');
40
49
  return outDirServer;
41
50
  }
42
51
  else {
52
+ debug('outDirClient', 'outDirClient');
43
53
  return outDirClient;
44
54
  }
45
55
  }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeRollupInput = exports.injectRollupInputs = void 0;
4
+ const assert_js_1 = require("./assert.js");
5
+ const isObject_js_1 = require("./isObject.js");
6
+ function injectRollupInputs(inputsNew, config) {
7
+ const inputsCurrent = normalizeRollupInput(config.build.rollupOptions.input);
8
+ const input = {
9
+ ...inputsNew,
10
+ ...inputsCurrent
11
+ };
12
+ return input;
13
+ }
14
+ exports.injectRollupInputs = injectRollupInputs;
15
+ function normalizeRollupInput(input) {
16
+ if (!input) {
17
+ return {};
18
+ }
19
+ // Usually `input` is an oject, but the user can set it as a `string` or `string[]`
20
+ if (typeof input === 'string') {
21
+ input = [input];
22
+ }
23
+ if (Array.isArray(input)) {
24
+ return Object.fromEntries(input.map((input) => [input, input]));
25
+ }
26
+ (0, assert_js_1.assert)((0, isObject_js_1.isObject)(input));
27
+ return input;
28
+ }
29
+ exports.normalizeRollupInput = normalizeRollupInput;
@@ -10,7 +10,7 @@ function isPlainObject(value) {
10
10
  return true;
11
11
  }
12
12
  return (
13
- /* Doesn't work in Cloudlfare Pages workers
13
+ /* Doesn't work in Cloudflare Pages workers
14
14
  value.constructor === Object
15
15
  */
16
16
  value.constructor.name === 'Object');
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PROJECT_VERSION = exports.projectInfo = void 0;
4
4
  const assertSingleInstance_js_1 = require("./assertSingleInstance.js");
5
- const PROJECT_VERSION = '0.4.150';
5
+ const PROJECT_VERSION = '0.4.151-commit-19bc995';
6
6
  exports.PROJECT_VERSION = PROJECT_VERSION;
7
7
  const projectInfo = {
8
8
  projectName: 'Vike',
@@ -7,7 +7,7 @@ const assertIsNotProductionRuntime_js_1 = require("./assertIsNotProductionRuntim
7
7
  const filesystemPathHandling_js_1 = require("./filesystemPathHandling.js");
8
8
  const isScriptFile_js_1 = require("./isScriptFile.js");
9
9
  const module_1 = require("module");
10
- // @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
10
+ // @ts-ignore Shimmed by dist-cjs-fixup.js for CJS build.
11
11
  const importMetaUrl = `file://${__filename}`;
12
12
  const require_ = (0, module_1.createRequire)(importMetaUrl);
13
13
  (0, assertIsNotBrowser_js_1.assertIsNotBrowser)();
@@ -25,10 +25,10 @@ async function getPageContextFromHooks_firstRender(pageContext) {
25
25
  _hasPageContextFromClient: false
26
26
  });
27
27
  objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
28
- {
28
+ for (const hookName of ['data', 'onBeforeRender']) {
29
29
  const pageContextForHook = { ...pageContext, ...pageContextFromHooks };
30
- if (onBeforeRenderClientOnlyExists(pageContextForHook)) {
31
- const pageContextFromHook = await executeOnBeforeRenderHookClientSide(pageContextForHook);
30
+ if (hookClientOnlyExists(hookName, pageContextForHook)) {
31
+ const pageContextFromHook = await executeHookClientSide(hookName, pageContextForHook);
32
32
  objectAssign(pageContextFromHooks, pageContextFromHook);
33
33
  }
34
34
  }
@@ -56,31 +56,34 @@ async function getPageContextFromHooks_uponNavigation(pageContext) {
56
56
  return pageContextFromHooks;
57
57
  }
58
58
  async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
59
- let pageContextFromHooks = {};
60
- objectAssign(pageContextFromHooks, { _hasPageContextFromClient: false });
61
- objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContext._pageId, pageContext));
62
- let pageContextFetchedFromServer = false;
63
- // Needs to be called before any client-side hook, because it may contain pageContextInit.user which is needed for guard() and onBeforeRender()
59
+ const getPageContextFromHooksInit = async (pageId) => {
60
+ const pageContextFromHooks = {
61
+ _hasPageContextFromClient: false,
62
+ _pageId: pageId
63
+ };
64
+ const pageContextFromPageFiles = await loadPageFilesClientSide(pageId, pageContext);
65
+ objectAssign(pageContextFromHooks, pageContextFromPageFiles);
66
+ return pageContextFromHooks;
67
+ };
68
+ let pageContextFromHooks = await getPageContextFromHooksInit(pageContext._pageId);
69
+ let hasPageContextFromServer = false;
70
+ // If pageContextInit has some client data or if one of the hooks guard(), data() or onBeforeRender() is server-side
71
+ // only, then we need to fetch pageContext from the server.
72
+ // We do it before executing any client-side hook, because it contains pageContextInit which may be needed for guard() / data() / onBeforeRender(), for example pageContextInit.user is crucial for guard()
64
73
  if (
65
74
  // For the error page, we cannot fetch pageContext from the server because the pageContext JSON request is based on the URL
66
75
  !isErrorPage &&
67
- // true if pageContextInit has some client data or the onBeforeRender hook is server-side only:
76
+ // true if pageContextInit has some client data or at least one of the data() and onBeforeRender() hooks is server-side only:
68
77
  (await hasPageContextServer({ ...pageContext, ...pageContextFromHooks }))) {
69
78
  const pageContextFromServer = await fetchPageContextFromServer(pageContext);
70
- pageContextFetchedFromServer = true;
79
+ hasPageContextFromServer = true;
71
80
  if (!pageContextFromServer['_isError']) {
72
81
  objectAssign(pageContextFromHooks, pageContextFromServer);
73
82
  }
74
83
  else {
75
84
  const errorPageId = getErrorPageId(pageContext._pageFilesAll, pageContext._pageConfigs);
76
85
  assert(errorPageId);
77
- pageContextFromHooks = {};
78
- objectAssign(pageContextFromHooks, {
79
- _hasPageContextFromClient: false,
80
- isHydration: false,
81
- _pageId: errorPageId
82
- });
83
- objectAssign(pageContextFromHooks, await loadPageFilesClientSide(pageContextFromHooks._pageId, pageContext));
86
+ pageContextFromHooks = await getPageContextFromHooksInit(errorPageId);
84
87
  assert(hasProp(pageContextFromServer, 'is404', 'boolean'));
85
88
  assert(hasProp(pageContextFromServer, 'pageProps', 'object'));
86
89
  assert(hasProp(pageContextFromServer.pageProps, 'is404', 'boolean'));
@@ -89,54 +92,73 @@ async function getPageContextAlreadyRouted(pageContext, isErrorPage) {
89
92
  objectAssign(pageContextFromHooks, pageContextFromServer);
90
93
  }
91
94
  }
92
- else {
93
- objectAssign(pageContextFromHooks, { _hasPageContextFromServer: false });
94
- // We don't need to call guard() on the client-side if we fetch pageContext from the server side. (Because the `${url}.pageContext.json` HTTP request will already trigger the routing and guard() hook on the serve-side.)
95
- // We cannot call guard() before retrieving pageContext from server, since the server-side may define pageContextInit.user which is paramount for guard() hooks
96
- if (!isErrorPage) {
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()?
98
- await executeGuardHook({
99
- ...pageContext,
100
- ...pageContextFromHooks
101
- }, (pageContext) => preparePageContextForUserConsumptionClientSide(pageContext, true));
102
- }
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).
105
- {
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);
95
+ // At this point, we need to call the client-side guard(), data() and onBeforeRender() hooks, if they exist on client
96
+ // env. However if we have fetched pageContext from the server, some of them might have run already on the
97
+ // server-side, so we run only the client-only ones in this case.
98
+ // Note: for the error page, we also execute the client-side data() and onBeforeRender() hooks, but maybe we
99
+ // shouldn't? The server-side does it as well (but maybe it shouldn't).
100
+ for (const hookName of ['guard', 'data', 'onBeforeRender']) {
101
+ const pageContextForHook = {
102
+ _hasPageContextFromServer: hasPageContextFromServer,
103
+ ...pageContext,
104
+ ...pageContextFromHooks
105
+ };
106
+ if (hookName === 'guard') {
107
+ if (!isErrorPage &&
108
+ // We don't need to call guard() on the client-side if we fetch pageContext from the server side. (Because the `${url}.pageContext.json` HTTP request will already trigger the routing and guard() hook on the server-side.)
109
+ !hasPageContextFromServer) {
110
+ // Should we really call the guard() hook on the client-side? Shouldn't we make the guard() hook a server-side
111
+ // only hook? Or maybe make its env configurable like data() and onBeforeRender()?
112
+ await executeGuardHook(pageContextForHook, (pageContext) => preparePageContextForUserConsumptionClientSide(pageContext, true));
113
+ }
111
114
  }
112
115
  else {
113
- assert(pageContextFetchedFromServer);
116
+ assert(hookName === 'data' || hookName === 'onBeforeRender');
117
+ if (hookClientOnlyExists(hookName, pageContextForHook) || !hasPageContextFromServer) {
118
+ // This won't do anything if no hook has been defined or if the hook's env.client is false.
119
+ const pageContextFromHook = await executeHookClientSide(hookName, pageContextForHook);
120
+ objectAssign(pageContextFromHooks, pageContextFromHook);
121
+ }
122
+ else {
123
+ assert(hasPageContextFromServer);
124
+ }
114
125
  }
115
126
  }
127
+ objectAssign(pageContextFromHooks, {
128
+ _hasPageContextFromServer: hasPageContextFromServer
129
+ });
116
130
  return pageContextFromHooks;
117
131
  }
118
- async function executeOnBeforeRenderHookClientSide(pageContext) {
119
- const hook = getHook(pageContext, 'onBeforeRender');
132
+ async function executeHookClientSide(hookName, pageContext) {
133
+ const hook = getHook(pageContext, hookName);
120
134
  if (!hook) {
121
135
  // No hook defined or hook's env.client is false
122
- const pageContextFromOnBeforeRender = {
123
- _hasPageContextFromClient: false
136
+ return null;
137
+ }
138
+ const pageContextForUserConsumption = preparePageContextForUserConsumptionClientSide(pageContext, true);
139
+ const hookResult = await executeHook(() => hook.hookFn(pageContextForUserConsumption), hook);
140
+ const pageContextFromHook = {};
141
+ if (hookName === 'onBeforeRender') {
142
+ assertOnBeforeRenderHookReturn(hookResult, hook.hookFilePath);
143
+ // Note: hookResult looks like { pageContext: { ... } }
144
+ const pageContextFromOnBeforeRender = hookResult?.pageContext;
145
+ if (pageContextFromOnBeforeRender) {
146
+ objectAssign(pageContextFromHook, { _hasPageContextFromClient: true });
147
+ objectAssign(pageContextFromHook, pageContextFromOnBeforeRender);
148
+ }
149
+ }
150
+ else {
151
+ assert(hookName === 'data');
152
+ // Note: hookResult can be anything (e.g. an object) and is to be assigned to pageContext.data
153
+ const pageContextFromData = {
154
+ data: hookResult
124
155
  };
125
- return pageContextFromOnBeforeRender;
156
+ if (hookResult) {
157
+ objectAssign(pageContextFromHook, { _hasPageContextFromClient: true });
158
+ }
159
+ objectAssign(pageContextFromHook, pageContextFromData);
126
160
  }
127
- const onBeforeRender = hook.hookFn;
128
- const pageContextFromOnBeforeRender = {
129
- _hasPageContextFromClient: true
130
- };
131
- const pageContextForUserConsumption = preparePageContextForUserConsumptionClientSide({
132
- ...pageContext,
133
- ...pageContextFromOnBeforeRender
134
- }, true);
135
- const hookResult = await executeHook(() => onBeforeRender(pageContextForUserConsumption), hook);
136
- assertOnBeforeRenderHookReturn(hookResult, hook.hookFilePath);
137
- const pageContextFromHook = hookResult?.pageContext;
138
- objectAssign(pageContextFromOnBeforeRender, pageContextFromHook);
139
- return pageContextFromOnBeforeRender;
161
+ return pageContextFromHook;
140
162
  }
141
163
  // Workaround for the fact that the client-side cannot known whether a pageContext JSON request is needed in order to fetch pageContextInit data passed to the client.
142
164
  // - The workaround is reliable as long as the user sets additional pageContextInit to undefined instead of not defining the property:
@@ -155,35 +177,53 @@ function setPageContextInitHasClientData(pageContext) {
155
177
  globalObject.pageContextInitHasClientData = true;
156
178
  }
157
179
  }
180
+ // TODO/v1-release: make it sync
158
181
  async function hasPageContextServer(pageContext) {
159
- return !!globalObject.pageContextInitHasClientData || (await onBeforeRenderServerOnlyExists(pageContext));
182
+ return (!!globalObject.pageContextInitHasClientData ||
183
+ (await hookServerOnlyExists('data', pageContext)) ||
184
+ (await hookServerOnlyExists('onBeforeRender', pageContext)));
160
185
  }
161
- async function onBeforeRenderServerOnlyExists(pageContext) {
186
+ // TODO/v1-release: make it sync
187
+ /**
188
+ * @param hookName
189
+ * @param pageContext
190
+ * @returns `true` if the given page has a `hookName` hook defined with a server-only env.
191
+ */
192
+ async function hookServerOnlyExists(hookName, pageContext) {
162
193
  if (pageContext._pageConfigs.length > 0) {
163
194
  // V1
164
195
  const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
165
- const onBeforeRenderEnv = getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value ?? {};
166
- assert(isObject(onBeforeRenderEnv));
167
- return !!onBeforeRenderEnv.server && !onBeforeRenderEnv.client;
196
+ const hookEnv = getConfigValue(pageConfig, `${hookName}Env`)?.value ?? {};
197
+ assert(isObject(hookEnv));
198
+ return !!hookEnv.server && !hookEnv.client;
168
199
  }
169
200
  else {
170
201
  // TODO/v1-release: remove
171
202
  // V0.4
203
+ // data() hooks didn't exist in the V0.4 design
204
+ if (hookName === 'data')
205
+ return false;
206
+ assert(hookName === 'onBeforeRender');
172
207
  const { hasOnBeforeRenderServerSideOnlyHook } = await analyzePageServerSide(pageContext._pageFilesAll, pageContext._pageId);
173
208
  return hasOnBeforeRenderServerSideOnlyHook;
174
209
  }
175
210
  }
176
- function onBeforeRenderClientOnlyExists(pageContext) {
211
+ /**
212
+ * @param hookName
213
+ * @param pageContext
214
+ * @returns `true` if the given page has a `hookName` hook defined with a client-only env.
215
+ */
216
+ function hookClientOnlyExists(hookName, pageContext) {
177
217
  if (pageContext._pageConfigs.length > 0) {
178
218
  // V1
179
219
  const pageConfig = getPageConfig(pageContext._pageId, pageContext._pageConfigs);
180
- const onBeforeRenderEnv = getConfigValue(pageConfig, 'onBeforeRenderEnv')?.value ?? {};
181
- assert(isObject(onBeforeRenderEnv));
182
- return !!onBeforeRenderEnv.client && !onBeforeRenderEnv.server;
220
+ const hookEnv = getConfigValue(pageConfig, `${hookName}Env`)?.value ?? {};
221
+ assert(isObject(hookEnv));
222
+ return !!hookEnv.client && !hookEnv.server;
183
223
  }
184
224
  else {
185
225
  // TODO/v1-release: remove
186
- // Client-only onBeforeRender() hooks were never supported for the V0.4 design
226
+ // Client-only onBeforeRender() or data() hooks were never supported for the V0.4 design
187
227
  return false;
188
228
  }
189
229
  }
@@ -212,7 +252,6 @@ async function fetchPageContextFromServer(pageContext) {
212
252
  }
213
253
  assert(hasProp(pageContextFromServer, '_pageId', 'string'));
214
254
  removeBuiltInOverrides(pageContextFromServer);
215
- objectAssign(pageContextFromServer, { _hasPageContextFromServer: true });
216
255
  return pageContextFromServer;
217
256
  }
218
257
  function isAlreadyServerSideRouted(err) {
@@ -133,7 +133,7 @@ async function renderPageClientSide(renderArgs) {
133
133
  console.error(err);
134
134
  }
135
135
  else {
136
- // We swallow throw redirect()/render() called by client-side hooks onBeforeRender() and guard()
136
+ // We swallow throw redirect()/render() called by client-side hooks onBeforeRender(), data() and guard()
137
137
  // We handle the abort error down below.
138
138
  }
139
139
  if (shouldSwallowAndInterrupt(err, pageContext, isFirstRender))
@@ -8,7 +8,6 @@ import { buildConfig } from './plugins/buildConfig.js';
8
8
  import { previewConfig } from './plugins/previewConfig.js';
9
9
  import { autoFullBuild } from './plugins/autoFullBuild.js';
10
10
  import { devConfig } from './plugins/devConfig/index.js';
11
- import { manifest } from './plugins/manifest.js';
12
11
  import { packageJsonFile } from './plugins/packageJsonFile.js';
13
12
  import { removeRequireHookPlugin } from './plugins/removeRequireHookPlugin.js';
14
13
  import { importUserCode } from './plugins/importUserCode/index.js';
@@ -24,18 +23,18 @@ import { extensionsAssets } from './plugins/extensionsAssets.js';
24
23
  import { baseUrls } from './plugins/baseUrls.js';
25
24
  import { envVarsPlugin } from './plugins/envVars.js';
26
25
  import pc from '@brillout/picocolors';
26
+ import { assertFileEnv } from './plugins/assertFileEnv.js';
27
27
  markEnvAsVite();
28
28
  // Return as `any` to avoid Plugin type mismatches when there are multiple Vite versions installed
29
29
  function plugin(vikeConfig) {
30
30
  const plugins = [
31
- resolveVikeConfig(vikeConfig),
31
+ resolveVikeConfig(vikeConfig), // The configResolved() hook of resolveVikeConfig() should be the first called
32
32
  ...commonConfig(),
33
33
  importUserCode(),
34
34
  ...devConfig(),
35
35
  buildConfig(),
36
36
  previewConfig(),
37
37
  ...autoFullBuild(),
38
- ...manifest(),
39
38
  packageJsonFile(),
40
39
  removeRequireHookPlugin(),
41
40
  distFileNames(),
@@ -46,7 +45,8 @@ function plugin(vikeConfig) {
46
45
  ...importBuild(),
47
46
  extensionsAssets(),
48
47
  baseUrls(vikeConfig),
49
- envVarsPlugin()
48
+ envVarsPlugin(),
49
+ assertFileEnv()
50
50
  ];
51
51
  return plugins;
52
52
  }
@@ -0,0 +1,3 @@
1
+ export { assertFileEnv };
2
+ import type { Plugin } from 'vite';
3
+ declare function assertFileEnv(): Plugin;