vike 0.4.236-commit-eab75f6 → 0.4.237

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 (69) hide show
  1. package/dist/cjs/client/shared/createGetGlobalContextClient.js +2 -4
  2. package/dist/cjs/node/runtime/html/serializeContext.js +8 -47
  3. package/dist/cjs/node/runtime/html/stream.js +1 -1
  4. package/dist/cjs/node/runtime/renderPage/createPageContextServerSide.js +4 -7
  5. package/dist/cjs/node/runtime/renderPage/handlePageContextRequestUrl.js +50 -14
  6. package/dist/cjs/node/runtime/renderPage/loadPageConfigsLazyServerSide.js +19 -6
  7. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -3
  8. package/dist/cjs/node/runtime/renderPage.js +7 -6
  9. package/dist/cjs/node/vite/plugins/pluginDev/determineOptimizeDeps.js +45 -43
  10. package/dist/cjs/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.js +67 -0
  11. package/dist/cjs/node/vite/plugins/pluginVirtualFiles/getVirtualFilePageConfigLazy.js +1 -2
  12. package/dist/cjs/node/vite/plugins/pluginVirtualFiles/getVirtualFilePageConfigsEager.js +2 -3
  13. package/dist/cjs/node/vite/shared/resolveVikeConfigInternal/configDefinitionsBuiltIn.js +31 -3
  14. package/dist/cjs/node/vite/shared/resolveVikeConfigInternal.js +7 -18
  15. package/dist/cjs/shared/createGlobalContextShared.js +13 -0
  16. package/dist/cjs/shared/modifyUrlSameOrigin.js +9 -4
  17. package/dist/cjs/shared/page-configs/serialize/serializeConfigValues.js +12 -13
  18. package/dist/cjs/shared/utils.js +2 -0
  19. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  20. package/dist/cjs/utils/cast.js +1 -1
  21. package/dist/esm/client/runtime-client-routing/getPageContextFromHooks.js +35 -48
  22. package/dist/esm/client/runtime-client-routing/history.d.ts +3 -5
  23. package/dist/esm/client/runtime-client-routing/history.js +39 -22
  24. package/dist/esm/client/runtime-client-routing/initClientRouter.js +2 -3
  25. package/dist/esm/client/runtime-client-routing/utils.d.ts +2 -0
  26. package/dist/esm/client/runtime-client-routing/utils.js +2 -0
  27. package/dist/esm/client/shared/createGetGlobalContextClient.js +2 -4
  28. package/dist/esm/node/runtime/html/serializeContext.d.ts +8 -3
  29. package/dist/esm/node/runtime/html/serializeContext.js +8 -47
  30. package/dist/esm/node/runtime/html/stream.js +1 -1
  31. package/dist/esm/node/runtime/renderPage/createPageContextServerSide.d.ts +1 -1
  32. package/dist/esm/node/runtime/renderPage/createPageContextServerSide.js +4 -7
  33. package/dist/esm/node/runtime/renderPage/handleErrorWithoutErrorPage.d.ts +2 -2
  34. package/dist/esm/node/runtime/renderPage/handlePageContextRequestUrl.d.ts +1 -1
  35. package/dist/esm/node/runtime/renderPage/handlePageContextRequestUrl.js +51 -15
  36. package/dist/esm/node/runtime/renderPage/loadPageConfigsLazyServerSide.js +20 -7
  37. package/dist/esm/node/runtime/renderPage/log404/index.d.ts +2 -2
  38. package/dist/esm/node/runtime/renderPage/preparePageContextForPublicUsageServer.d.ts +0 -1
  39. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +4 -5
  40. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +1 -3
  41. package/dist/esm/node/runtime/renderPage.d.ts +1 -0
  42. package/dist/esm/node/runtime/renderPage.js +7 -6
  43. package/dist/esm/node/vite/plugins/pluginDev/determineOptimizeDeps.js +46 -44
  44. package/dist/esm/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.d.ts +14 -0
  45. package/dist/esm/node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.js +65 -0
  46. package/dist/esm/node/vite/plugins/pluginVirtualFiles/getVirtualFilePageConfigLazy.js +1 -2
  47. package/dist/esm/node/vite/plugins/pluginVirtualFiles/getVirtualFilePageConfigsEager.js +2 -3
  48. package/dist/esm/node/vite/shared/resolveVikeConfigInternal/configDefinitionsBuiltIn.d.ts +2 -2
  49. package/dist/esm/node/vite/shared/resolveVikeConfigInternal/configDefinitionsBuiltIn.js +31 -3
  50. package/dist/esm/node/vite/shared/resolveVikeConfigInternal.d.ts +1 -3
  51. package/dist/esm/node/vite/shared/resolveVikeConfigInternal.js +8 -19
  52. package/dist/esm/shared/createGlobalContextShared.js +14 -1
  53. package/dist/esm/shared/modifyUrlSameOrigin.d.ts +1 -1
  54. package/dist/esm/shared/modifyUrlSameOrigin.js +9 -4
  55. package/dist/esm/shared/page-configs/serialize/serializeConfigValues.d.ts +3 -2
  56. package/dist/esm/shared/page-configs/serialize/serializeConfigValues.js +12 -13
  57. package/dist/esm/shared/utils.d.ts +2 -0
  58. package/dist/esm/shared/utils.js +2 -0
  59. package/dist/esm/types/Config.d.ts +33 -98
  60. package/dist/esm/types/index.d.ts +3 -1
  61. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  62. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  63. package/dist/esm/utils/cast.d.ts +2 -2
  64. package/dist/esm/utils/cast.js +1 -1
  65. package/dist/esm/utils/objectFilter.d.ts +1 -1
  66. package/package.json +1 -1
  67. package/dist/cjs/node/vite/plugins/pluginVirtualFiles/isRuntimeEnvMatch.js +0 -23
  68. package/dist/esm/node/vite/plugins/pluginVirtualFiles/isRuntimeEnvMatch.d.ts +0 -7
  69. package/dist/esm/node/vite/plugins/pluginVirtualFiles/isRuntimeEnvMatch.js +0 -21
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.configDefinitionsBuiltIn = void 0;
4
4
  const utils_js_1 = require("../../utils.js");
5
5
  const getConfigDefinedAt_js_1 = require("../../../../shared/page-configs/getConfigDefinedAt.js");
6
+ const getConfigValueSourcesRelevant_js_1 = require("../../plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.js");
6
7
  const configDefinitionsBuiltIn = {
7
8
  onRenderHtml: {
8
9
  env: { server: true },
@@ -97,6 +98,22 @@ const configDefinitionsBuiltIn = {
97
98
  meta: {
98
99
  env: { config: true },
99
100
  },
101
+ serverOnlyHooks: {
102
+ env: { client: true },
103
+ eager: true,
104
+ _computed: (pageConfig) => {
105
+ const sources = ['data', 'onBeforeRender', 'onCreatePageContext']
106
+ .map((hookName) => (0, getConfigValueSourcesRelevant_js_1.getConfigValueSourcesRelevant)(hookName, {
107
+ isForClientSide: false,
108
+ // TO-DO/eventually/remove-server-router: let's eventually remove support for Server Routing
109
+ isClientRouting: true,
110
+ }, pageConfig))
111
+ .flat(1)
112
+ // Server-only
113
+ .filter((source) => !source.configEnv.client);
114
+ return sources.length > 0;
115
+ },
116
+ },
100
117
  // Whether the page loads:
101
118
  // - Vike's client runtime
102
119
  // - User's client hooks
@@ -104,7 +121,8 @@ const configDefinitionsBuiltIn = {
104
121
  isClientRuntimeLoaded: {
105
122
  env: { server: true, client: true },
106
123
  eager: true,
107
- _computed: (configValueSources) => {
124
+ _computed: (pageConfig) => {
125
+ const { configValueSources } = pageConfig;
108
126
  {
109
127
  const source = getConfigValueSource(configValueSources, 'clientHooks');
110
128
  if (source) {
@@ -122,15 +140,25 @@ const configDefinitionsBuiltIn = {
122
140
  !!getConfigEnv(configValueSources, 'Page')?.client);
123
141
  },
124
142
  },
143
+ // TO-DO/soon/cumulative-hooks: remove and replace with new computed prop `clientOnlyHooks: string[]` (see other TO-DO/soon/cumulative-hooks entries)
125
144
  onBeforeRenderEnv: {
126
145
  env: { client: true },
127
146
  eager: true,
128
- _computed: (configValueSources) => !isConfigSet(configValueSources, 'onBeforeRender') ? null : getConfigEnv(configValueSources, 'onBeforeRender'),
147
+ _computed: (pageConfig) => {
148
+ const { configValueSources } = pageConfig;
149
+ return !isConfigSet(configValueSources, 'onBeforeRender')
150
+ ? null
151
+ : getConfigEnv(configValueSources, 'onBeforeRender');
152
+ },
129
153
  },
154
+ // TO-DO/soon/cumulative-hooks: remove and replace with new computed prop `clientOnlyHooks: string[]` (see other TO-DO/soon/cumulative-hooks entries)
130
155
  dataEnv: {
131
156
  env: { client: true },
132
157
  eager: true,
133
- _computed: (configValueSources) => !isConfigSet(configValueSources, 'data') ? null : getConfigEnv(configValueSources, 'data'),
158
+ _computed: (pageConfig) => {
159
+ const { configValueSources } = pageConfig;
160
+ return !isConfigSet(configValueSources, 'data') ? null : getConfigEnv(configValueSources, 'data');
161
+ },
134
162
  },
135
163
  hooksTimeout: {
136
164
  env: { server: true, client: true },
@@ -12,7 +12,6 @@ exports.isV1Design = isV1Design;
12
12
  exports.getConfVal = getConfVal;
13
13
  exports.getConfigDefinitionOptional = getConfigDefinitionOptional;
14
14
  exports.getVikeConfigFromCliOrEnv = getVikeConfigFromCliOrEnv;
15
- exports.isOverridden = isOverridden;
16
15
  exports.getVikeConfig = getVikeConfig;
17
16
  const utils_js_1 = require("../utils.js");
18
17
  const configDefinitionsBuiltIn_js_1 = require("./resolveVikeConfigInternal/configDefinitionsBuiltIn.js");
@@ -290,15 +289,16 @@ function getPageConfigsBuildTime(configDefinitionsResolved, plusFilesAll, userRo
290
289
  applyEffectsMetaEnv(configValueSources, configDefinitionsLocal);
291
290
  applyEffectsConfVal(configValueSources, configDefinitionsLocal, plusFilesAll);
292
291
  sortConfigValueSources(configValueSources, locationId);
293
- const configValuesComputed = getComputed(configValueSources, configDefinitionsLocal);
294
292
  const pageConfig = {
295
293
  pageId: locationId,
296
294
  ...pageConfigRoute,
297
295
  configDefinitions: configDefinitionsLocal,
298
296
  plusFiles: plusFilesRelevant,
299
297
  configValueSources,
300
- configValuesComputed,
301
298
  };
299
+ const configValuesComputed = getComputed(pageConfig);
300
+ (0, utils_js_1.objectAssign)(pageConfig, { configValuesComputed });
301
+ (0, utils_js_1.checkType)(pageConfig);
302
302
  return pageConfig;
303
303
  });
304
304
  assertPageConfigs(pageConfigs);
@@ -365,7 +365,7 @@ function assertOnBeforeRenderEnv(pageConfig) {
365
365
  }
366
366
  function getConfigValues(pageConfig, tolerateMissingValue) {
367
367
  const configValues = {};
368
- (0, serializeConfigValues_js_1.getConfigValuesBase)(pageConfig, (configEnv) => !!configEnv.config, null).forEach((entry) => {
368
+ (0, serializeConfigValues_js_1.getConfigValuesBase)(pageConfig, { isForConfig: true }, null).forEach((entry) => {
369
369
  if (entry.configValueBase.type === 'computed') {
370
370
  (0, utils_js_1.assert)('value' in entry); // Help TS
371
371
  const { configValueBase, value, configName } = entry;
@@ -899,12 +899,12 @@ function applyEffectMetaEnv(configModFromEffect, configValueSources, configDefEf
899
899
  });
900
900
  });
901
901
  }
902
- function getComputed(configValueSources, configDefinitions) {
902
+ function getComputed(pageConfig) {
903
903
  const configValuesComputed = {};
904
- (0, utils_js_1.objectEntries)(configDefinitions).forEach(([configName, configDef]) => {
904
+ (0, utils_js_1.objectEntries)(pageConfig.configDefinitions).forEach(([configName, configDef]) => {
905
905
  if (!configDef._computed)
906
906
  return;
907
- const value = configDef._computed(configValueSources);
907
+ const value = configDef._computed(pageConfig);
908
908
  if (value === undefined)
909
909
  return;
910
910
  configValuesComputed[configName] = {
@@ -1100,17 +1100,6 @@ function isGlobalLocation(locationId, plusFilesAll) {
1100
1100
  .map(([locationId]) => locationId);
1101
1101
  return locationIdsPage.every((locId) => (0, filesystemRouting_js_1.isInherited)(locationId, locId));
1102
1102
  }
1103
- function isOverridden(source, configName, pageConfig) {
1104
- const configDef = pageConfig.configDefinitions[configName];
1105
- (0, utils_js_1.assert)(configDef);
1106
- if (configDef.cumulative)
1107
- return false;
1108
- const sources = pageConfig.configValueSources[configName];
1109
- (0, utils_js_1.assert)(sources);
1110
- const idx = sources.indexOf(source);
1111
- (0, utils_js_1.assert)(idx >= 0);
1112
- return idx > 0;
1113
- }
1114
1103
  function resolvePrerenderContext(vikeConfig) {
1115
1104
  const { isPrerenderingEnabled, isPrerenderingEnabledForAllPages } = (0, resolvePrerenderConfig_js_1.resolvePrerenderConfigGlobal)(vikeConfig);
1116
1105
  prerenderContext ?? (prerenderContext = {
@@ -10,9 +10,21 @@ const prepareGlobalContextForPublicUsage_js_1 = require("./prepareGlobalContextF
10
10
  const getHook_js_1 = require("./hooks/getHook.js");
11
11
  const getGlobalContextSyncErrMsg = "The global context isn't set yet, call getGlobalContextSync() later or use getGlobalContext() instead.";
12
12
  exports.getGlobalContextSyncErrMsg = getGlobalContextSyncErrMsg;
13
+ const globalObject_ = (0, utils_js_1.getGlobalObject)('shared/createGlobalContextShared.ts', {});
14
+ // TO-DO/eventually use flat globalContext — like flat pageContext
13
15
  async function createGlobalContextShared(virtualFileExports, globalObject, addGlobalContext,
14
16
  // TO-DO/next-major-release: we'll be able to remove addGlobalContextTmp after loadPageRoutes() is sync (it will be sync after we remove the old design)
15
17
  addGlobalContextTmp, addGlobalContextAsync) {
18
+ const { previousCallPromise } = globalObject_;
19
+ const { promise, resolve } = (0, utils_js_1.genPromise)({
20
+ // Avoid this Cloudflare Worker error:
21
+ // ```console
22
+ // Error: Disallowed operation called within global scope. Asynchronous I/O (ex: fetch() or connect()), setting a timeout, and generating random values are not allowed within global scope. To fix this error, perform this operation within a handler.
23
+ // ```
24
+ timeout: null,
25
+ });
26
+ globalObject_.previousCallPromise = promise;
27
+ await previousCallPromise;
16
28
  const globalContext = createGlobalContextBase(virtualFileExports);
17
29
  let isNewGlobalContext;
18
30
  if (!globalObject.globalContext) {
@@ -55,6 +67,7 @@ addGlobalContextTmp, addGlobalContextAsync) {
55
67
  (0, utils_js_1.objectAssign)(globalObject.globalContext, globalContext, true);
56
68
  }
57
69
  }
70
+ resolve();
58
71
  return globalObject.globalContext;
59
72
  }
60
73
  function createGlobalContextBase(virtualFileExports) {
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.modifyUrlSameOrigin = modifyUrlSameOrigin;
4
+ // We don't move modifyUrlSameOrigin() to the modifyUrl.ts file because we plan to use modifyUrlSameOrigin() on the client-side:
5
+ // https://github.com/vikejs/vike/blob/c5a2de5e85262771f97851767c00ac35da69c64b/packages/vike/client/runtime-client-routing/navigate.ts#L4
4
6
  const utils_js_1 = require("./utils.js");
5
7
  function modifyUrlSameOrigin(url, modify) {
6
8
  const urlParsed = (0, utils_js_1.parseUrl)(url, '/');
@@ -27,16 +29,19 @@ function modifyUrlSameOrigin(url, modify) {
27
29
  const urlModified = (0, utils_js_1.createUrlFromComponents)(urlParsed.origin, pathname, search, hash);
28
30
  return urlModified;
29
31
  }
30
- function resolveSearch(urlParsed, search) {
32
+ function resolveSearch(urlParsed, modifySearch) {
31
33
  let searchParams;
32
- if (search instanceof URLSearchParams) {
34
+ if (modifySearch instanceof URLSearchParams) {
33
35
  // Overwrite
34
- searchParams = search;
36
+ searchParams = modifySearch;
35
37
  }
36
38
  else {
37
39
  // Merge
38
- const searchMap = (0, utils_js_1.objectFilter)({ ...urlParsed.search, ...search }, (utils_js_1.isNotNullish_keyVal));
40
+ const searchMap = (0, utils_js_1.objectFilter)({ ...urlParsed.search, ...(0, utils_js_1.objectFilter)(modifySearch, isNotUndefined) }, (utils_js_1.isNotNullish_keyVal));
39
41
  searchParams = new URLSearchParams(searchMap);
40
42
  }
41
43
  return '?' + searchParams.toString();
42
44
  }
45
+ function isNotUndefined(arg) {
46
+ return arg[1] !== undefined;
47
+ }
@@ -12,7 +12,7 @@ const pointerImports_js_1 = require("../../../node/vite/shared/resolveVikeConfig
12
12
  const helpers_js_1 = require("../helpers.js");
13
13
  const stringify_1 = require("@brillout/json-serializer/stringify");
14
14
  const picocolors_1 = __importDefault(require("@brillout/picocolors"));
15
- const resolveVikeConfigInternal_js_1 = require("../../../node/vite/shared/resolveVikeConfigInternal.js");
15
+ const getConfigValueSourcesRelevant_js_1 = require("../../../node/vite/plugins/pluginVirtualFiles/getConfigValueSourcesRelevant.js");
16
16
  const stringifyOptions = { forbidReactElements: true };
17
17
  const REPLACE_ME_BEFORE = '__VIKE__REPLACE_ME_BEFORE__';
18
18
  const REPLACE_ME_AFTER = '__VIKE__REPLACE_ME_AFTER__';
@@ -21,10 +21,10 @@ const REPLACE_ME_AFTER = '__VIKE__REPLACE_ME_AFTER__';
21
21
  // - parsePageConfigs() is loaded on both the client- and server-side.
22
22
  (0, utils_js_1.assertIsNotBrowser)();
23
23
  (0, assertSetup_js_1.assertIsNotProductionRuntime)();
24
- function serializeConfigValues(pageConfig, importStatements, filesEnv, isEnvMatch, tabspace, isEager) {
24
+ function serializeConfigValues(pageConfig, importStatements, filesEnv, runtimeEnv, tabspace, isEager) {
25
25
  const lines = [];
26
26
  tabspace += ' ';
27
- getConfigValuesBase(pageConfig, isEnvMatch, isEager).forEach((entry) => {
27
+ getConfigValuesBase(pageConfig, runtimeEnv, isEager).forEach((entry) => {
28
28
  if (entry.configValueBase.type === 'computed') {
29
29
  (0, utils_js_1.assert)('value' in entry); // Help TS
30
30
  const { configValueBase, value, configName, configEnv } = entry;
@@ -181,12 +181,12 @@ function logJsonSerializeError(err, configName, definedAtData) {
181
181
  (0, utils_js_1.assert)(configValueFilePathToShowToUser);
182
182
  (0, utils_js_1.assertUsage)(false, `${picocolors_1.default.cyan(configName)} defined by ${configValueFilePathToShowToUser} must be defined using a separate file ${picocolors_1.default.bold(`+${configName}.js`)}, see https://vike.dev/error/runtime-in-config`);
183
183
  }
184
- function getConfigValuesBase(pageConfig, isEnvMatch, isEager) {
184
+ function getConfigValuesBase(pageConfig, runtimeEnv, isEager) {
185
185
  const fromComputed = Object.entries(pageConfig.configValuesComputed ?? {}).map(([configName, valueInfo]) => {
186
186
  const { configEnv, value } = valueInfo;
187
- if (!isEnvMatch(configEnv))
187
+ if (!(0, getConfigValueSourcesRelevant_js_1.isRuntimeEnvMatch)(configEnv, runtimeEnv))
188
188
  return 'SKIP';
189
- // Is there a use case for overriding computed values? If yes, then configValeSources has higher precedence
189
+ // AFAICT this should never happen: I ain't aware of a use case for overriding computed values. If there is a use case, then configValueSources has higher precedence.
190
190
  if (pageConfig.configValueSources[configName])
191
191
  return 'SKIP';
192
192
  const configValueBase = {
@@ -195,16 +195,17 @@ function getConfigValuesBase(pageConfig, isEnvMatch, isEager) {
195
195
  };
196
196
  return { configValueBase, value, configName, configEnv };
197
197
  });
198
- const fromSources = Object.entries(pageConfig.configValueSources).map(([configName, sources]) => {
198
+ const fromSources = Object.entries(pageConfig.configValueSources).map(([configName]) => {
199
199
  const configDef = pageConfig.configDefinitions[configName];
200
200
  (0, utils_js_1.assert)(configDef);
201
201
  if (isEager !== null && isEager !== !!configDef.eager)
202
202
  return 'SKIP';
203
203
  if (!configDef.cumulative) {
204
- const source = sources[0];
205
- (0, utils_js_1.assert)(source);
206
- if (!isEnvMatch(source.configEnv))
204
+ const sourcesRelevant = (0, getConfigValueSourcesRelevant_js_1.getConfigValueSourcesRelevant)(configName, runtimeEnv, pageConfig);
205
+ const source = sourcesRelevant[0];
206
+ if (!source)
207
207
  return 'SKIP';
208
+ (0, utils_js_1.assert)(sourcesRelevant.length === 1);
208
209
  const definedAtFile = getDefinedAtFileSource(source);
209
210
  const configValueBase = {
210
211
  type: 'standard',
@@ -213,9 +214,7 @@ function getConfigValuesBase(pageConfig, isEnvMatch, isEager) {
213
214
  return { configValueBase, sourceRelevant: source, configName };
214
215
  }
215
216
  else {
216
- const sourcesRelevant = sources
217
- .filter((source) => !(0, resolveVikeConfigInternal_js_1.isOverridden)(source, configName, pageConfig))
218
- .filter((source) => isEnvMatch(source.configEnv));
217
+ const sourcesRelevant = (0, getConfigValueSourcesRelevant_js_1.getConfigValueSourcesRelevant)(configName, runtimeEnv, pageConfig);
219
218
  if (sourcesRelevant.length === 0)
220
219
  return 'SKIP';
221
220
  const definedAtData = [];
@@ -45,3 +45,5 @@ __exportStar(require("../utils/objectDefineProperty.js"), exports);
45
45
  __exportStar(require("../utils/isScriptFile.js"), exports);
46
46
  __exportStar(require("../utils/objectFilter.js"), exports);
47
47
  __exportStar(require("../utils/getPropAccessNotation.js"), exports);
48
+ __exportStar(require("../utils/getGlobalObject.js"), exports);
49
+ __exportStar(require("../utils/genPromise.js"), exports);
@@ -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.236-commit-eab75f6';
5
+ exports.PROJECT_VERSION = '0.4.237';
@@ -3,4 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.cast = cast;
4
4
  exports.castProp = castProp;
5
5
  function cast(_thing) { }
6
- function castProp(_obj, _prop) { }
6
+ function castProp(_obj, prop) { }
@@ -23,7 +23,6 @@ const globalObject = getGlobalObject('runtime-client-routing/getPageContextFromH
23
23
  // TO-DO/eventually: rename
24
24
  function getPageContextFromHooks_serialized() {
25
25
  const pageContextSerialized = getPageContextSerializedInHtml();
26
- assertUsage(!('urlOriginal' in pageContextSerialized), "Adding 'urlOriginal' to passToClient is forbidden");
27
26
  processPageContextFromServer(pageContextSerialized);
28
27
  objectAssign(pageContextSerialized, {
29
28
  _hasPageContextFromServer: true,
@@ -33,6 +32,9 @@ function getPageContextFromHooks_serialized() {
33
32
  // TO-DO/eventually: rename
34
33
  async function getPageContextFromHooks_isHydration(pageContext) {
35
34
  for (const hookName of ['data', 'onBeforeRender']) {
35
+ // TO-DO/soon/cumulative-hooks: filter & execute all client-only hooks
36
+ // - The client-side needs to know what hooks are client-only
37
+ // - Possible implementation: new computed prop `clientOnlyHooks: string[]` (list of hook ids) and add `hookId` to serialized config values
36
38
  if (hookClientOnlyExists(hookName, pageContext)) {
37
39
  await execHookDataLike(hookName, pageContext);
38
40
  }
@@ -65,7 +67,7 @@ async function getPageContextFromServerHooks(pageContext, isErrorPage) {
65
67
  return { pageContextFromServerHooks };
66
68
  }
67
69
  async function getPageContextFromClientHooks(pageContext, isErrorPage) {
68
- let dataHookExec = false;
70
+ let dataHookExecuted = false;
69
71
  // At this point, we need to call the client-side guard(), data() and onBeforeRender() hooks, if they exist on client
70
72
  // env. However if we have fetched pageContext from the server, some of them might have run already on the
71
73
  // server-side, so we run only the client-only ones in this case.
@@ -82,9 +84,10 @@ async function getPageContextFromClientHooks(pageContext, isErrorPage) {
82
84
  }
83
85
  }
84
86
  else {
87
+ // TO-DO/soon/cumulative-hooks: filter & execute all client-only hooks (see other TO-DO/soon/cumulative-hooks entries)
85
88
  if (hookClientOnlyExists(hookName, pageContext) || !pageContext._hasPageContextFromServer) {
86
89
  if (hookName === 'data')
87
- dataHookExec = true;
90
+ dataHookExecuted = true;
88
91
  // This won't do anything if no hook has been defined or if the hook's env.client is false.
89
92
  await execHookDataLike(hookName, pageContext);
90
93
  }
@@ -92,7 +95,7 @@ async function getPageContextFromClientHooks(pageContext, isErrorPage) {
92
95
  }
93
96
  // Execute +onData
94
97
  const dataHookEnv = getHookEnv('data', pageContext);
95
- if ((dataHookExec && dataHookEnv.client) || (pageContext._hasPageContextFromServer && dataHookEnv.server)) {
98
+ if ((dataHookExecuted && dataHookEnv.client) || (pageContext._hasPageContextFromServer && dataHookEnv.server)) {
96
99
  await execHookClient('onData', pageContext);
97
100
  }
98
101
  const pageContextFromClientHooks = pageContext;
@@ -154,61 +157,40 @@ function setPageContextInitIsPassedToClient(pageContext) {
154
157
  }
155
158
  // TO-DO/next-major-release: make it sync
156
159
  async function hasPageContextServer(pageContext) {
157
- return (!!globalObject.pageContextInitIsPassedToClient ||
158
- (await hookServerOnlyExists('data', pageContext)) ||
159
- (await hookServerOnlyExists('onBeforeRender', pageContext)));
160
- }
161
- // TO-DO/next-major-release: make it sync
162
- /**
163
- * @param hookName
164
- * @param pageContext
165
- * @returns `true` if the given page has a `hookName` hook defined with a server-only env.
166
- */
167
- async function hookServerOnlyExists(hookName, pageContext) {
168
- if (pageContext._globalContext._pageConfigs.length > 0) {
169
- // V1
170
- const pageConfig = getPageConfig(pageContext.pageId, pageContext._globalContext._pageConfigs);
171
- const hookEnv = getConfigValueRuntime(pageConfig, `${hookName}Env`)?.value;
172
- if (hookEnv === null)
173
- return false;
174
- assert(isObject(hookEnv));
175
- const { client, server } = hookEnv;
176
- assert(client === true || client === undefined);
177
- assert(server === true || server === undefined);
178
- assert(client || server);
179
- return !!server && !client;
180
- }
181
- else {
182
- // TO-DO/next-major-release: remove
183
- // V0.4
184
- // data() hooks didn't exist in the V0.4 design
185
- if (hookName === 'data')
186
- return false;
187
- assert(hookName === 'onBeforeRender');
160
+ if (isOldDesign(pageContext)) {
188
161
  const { hasOnBeforeRenderServerSideOnlyHook } = await analyzePageServerSide(pageContext._pageFilesAll, pageContext.pageId);
162
+ // data() hooks didn't exist in the V0.4 design
189
163
  return hasOnBeforeRenderServerSideOnlyHook;
190
164
  }
165
+ return !!globalObject.pageContextInitIsPassedToClient || hasServerOnlyHook(pageContext);
166
+ }
167
+ function hasServerOnlyHook(pageContext) {
168
+ if (isOldDesign(pageContext))
169
+ return false;
170
+ const pageConfig = getPageConfig(pageContext.pageId, pageContext._globalContext._pageConfigs);
171
+ const val = getConfigValueRuntime(pageConfig, `serverOnlyHooks`)?.value;
172
+ assert(val === true || val === false);
173
+ return val;
191
174
  }
192
175
  function hookClientOnlyExists(hookName, pageContext) {
193
176
  const hookEnv = getHookEnv(hookName, pageContext);
194
177
  return !!hookEnv.client && !hookEnv.server;
195
178
  }
196
179
  function getHookEnv(hookName, pageContext) {
197
- if (pageContext._globalContext._pageConfigs.length > 0) {
198
- // V1
199
- const pageConfig = getPageConfig(pageContext.pageId, pageContext._globalContext._pageConfigs);
200
- // No runtime validation to save client-side KBs
201
- const hookEnv = (getConfigValueRuntime(pageConfig, `${hookName}Env`)?.value ?? {});
202
- return hookEnv;
203
- }
204
- else {
205
- // TO-DO/next-major-release: remove
180
+ if (isOldDesign(pageContext)) {
206
181
  // Client-only onBeforeRender() or data() hooks were never supported for the V0.4 design
207
182
  return { client: false, server: true };
208
183
  }
184
+ const pageConfig = getPageConfig(pageContext.pageId, pageContext._globalContext._pageConfigs);
185
+ // No runtime validation to save client-side KBs
186
+ const hookEnv = (getConfigValueRuntime(pageConfig, `${hookName}Env`)?.value ?? {});
187
+ return hookEnv;
209
188
  }
210
189
  async function fetchPageContextFromServer(pageContext) {
211
- const pageContextUrl = getPageContextRequestUrl(pageContext._urlRewrite ?? pageContext.urlOriginal);
190
+ let pageContextUrl = getPageContextRequestUrl(pageContext._urlRewrite ?? pageContext.urlOriginal);
191
+ /* TO-DO/soon/once: pass & use previousUrl
192
+ pageContextUrl = modifyUrlSameOrigin(pageContextUrl, { search: { _vike: JSON.stringify({ previousUrl: pageContext.previousPageContext.urlOriginal }) } })
193
+ */
212
194
  const response = await fetch(pageContextUrl);
213
195
  {
214
196
  const contentType = response.headers.get('content-type');
@@ -231,10 +213,15 @@ async function fetchPageContextFromServer(pageContext) {
231
213
  if ('serverSideError' in pageContextFromServer || isServerSideError in pageContextFromServer) {
232
214
  throw getProjectError(`pageContext couldn't be fetched because an error occurred on the server-side`);
233
215
  }
234
- assert(hasProp(pageContextFromServer, 'pageId', 'string'));
235
216
  processPageContextFromServer(pageContextFromServer);
236
217
  return { pageContextFromServer };
237
218
  }
238
- function processPageContextFromServer(pageContextFromServer) {
239
- removeBuiltInOverrides(pageContextFromServer);
219
+ function processPageContextFromServer(pageContext) {
220
+ assertUsage(!('urlOriginal' in pageContext), "Adding 'urlOriginal' to passToClient is forbidden");
221
+ assert(hasProp(pageContext, 'pageId', 'string'));
222
+ removeBuiltInOverrides(pageContext);
223
+ }
224
+ // TO-DO/next-major-release: remove
225
+ function isOldDesign(pageContext) {
226
+ return pageContext._globalContext._pageConfigs.length === 0;
240
227
  }
@@ -2,8 +2,7 @@ export { pushHistoryState };
2
2
  export { replaceHistoryStateOriginal };
3
3
  export { onPopStateBegin };
4
4
  export { saveScrollPosition };
5
- export { initHistoryState };
6
- export { monkeyPatchHistoryAPI };
5
+ export { initHistory };
7
6
  export type { HistoryInfo };
8
7
  export type { ScrollPosition };
9
8
  type StateEnhanced = {
@@ -18,8 +17,7 @@ type ScrollPosition = {
18
17
  };
19
18
  declare function saveScrollPosition(): void;
20
19
  declare function pushHistoryState(url: string, overwriteLastHistoryEntry: boolean): void;
21
- declare function replaceHistoryStateOriginal(state: unknown, url: string): void;
22
- declare function monkeyPatchHistoryAPI(): void;
20
+ declare function replaceHistoryStateOriginal(state: unknown, url: Parameters<typeof window.history.replaceState>[2]): void;
23
21
  type HistoryInfo = {
24
22
  url: `/${string}`;
25
23
  state: StateEnhanced;
@@ -29,4 +27,4 @@ declare function onPopStateBegin(): {
29
27
  previous: HistoryInfo;
30
28
  current: HistoryInfo;
31
29
  };
32
- declare function initHistoryState(): void;
30
+ declare function initHistory(): void;
@@ -2,21 +2,23 @@ export { pushHistoryState };
2
2
  export { replaceHistoryStateOriginal };
3
3
  export { onPopStateBegin };
4
4
  export { saveScrollPosition };
5
- export { initHistoryState };
6
- export { monkeyPatchHistoryAPI };
5
+ export { initHistory };
7
6
  import { getCurrentUrl } from '../shared/getCurrentUrl.js';
8
- import { assert, assertUsage, getGlobalObject, isObject } from './utils.js';
9
- initHistoryState(); // we redundantly call initHistoryState() to ensure it's called early
10
- const globalObject = getGlobalObject('runtime-client-routing/history.ts', { previous: getHistoryInfo() });
7
+ import { assert, assertUsage, getGlobalObject, isObject, deepEqual, cast } from './utils.js';
8
+ const globalObject = getGlobalObject('history.ts', {
9
+ monkeyPatched: false,
10
+ previous: undefined,
11
+ });
12
+ initHistory(); // we redundantly call initHistory() to ensure it's called early
13
+ globalObject.previous = getHistoryInfo();
11
14
  // `window.history.state === null` when:
12
15
  // - The very first render
13
16
  // - Click on `<a href="#some-hash" />`
14
17
  // - `location.hash = 'some-hash'`
15
18
  function enhanceHistoryState() {
16
- const stateNotEnhanced = getStateNotEnhanced();
17
- if (isVikeEnhanced(stateNotEnhanced))
19
+ if (isVikeEnhanced(window.history.state))
18
20
  return;
19
- const stateVikeEnhanced = enhance(stateNotEnhanced);
21
+ const stateVikeEnhanced = enhance(window.history.state);
20
22
  replaceHistoryState(stateVikeEnhanced);
21
23
  }
22
24
  function enhance(stateNotEnhanced) {
@@ -34,6 +36,7 @@ function enhance(stateNotEnhanced) {
34
36
  }
35
37
  else {
36
38
  // State information may be incomplete if `window.history.state` is set by an old Vike version. (E.g. `state.timestamp` was introduced for `pageContext.isBackwardNavigation` in `0.4.19`.)
39
+ cast(stateNotEnhanced);
37
40
  stateVikeEnhanced = {
38
41
  timestamp: stateNotEnhanced.timestamp ?? timestamp,
39
42
  scrollPosition: stateNotEnhanced.scrollPosition ?? scrollPosition,
@@ -41,21 +44,17 @@ function enhance(stateNotEnhanced) {
41
44
  _isVikeEnhanced: true,
42
45
  };
43
46
  }
44
- assert(isVikeEnhanced(stateVikeEnhanced));
47
+ assertIsVikeEnhanced(stateVikeEnhanced);
45
48
  return stateVikeEnhanced;
46
49
  }
47
50
  function getState() {
48
- const state = getStateNotEnhanced();
51
+ const state = window.history.state;
49
52
  // *Every* state added to the history needs to go through Vike.
50
53
  // - Otherwise Vike's `popstate` listener won't work. (Because, for example, if globalObject.previous is outdated => isHashNavigation faulty => client-side navigation is wrongfully skipped.)
51
54
  // - Therefore, we have to monkey patch history.pushState() and history.replaceState()
52
55
  // - Therefore, we need the assert() below to ensure history.state has been enhanced by Vike
53
56
  // - If users stumble upon this assert() then let's make it a assertUsage()
54
- assert(isVikeEnhanced(state), { state });
55
- return state;
56
- }
57
- function getStateNotEnhanced() {
58
- const state = window.history.state;
57
+ assertIsVikeEnhanced(state);
59
58
  return state;
60
59
  }
61
60
  function getScrollPosition() {
@@ -90,6 +89,7 @@ function pushHistoryState(url, overwriteLastHistoryEntry) {
90
89
  function replaceHistoryState(state, url) {
91
90
  const url_ = url ?? null; // Passing `undefined` chokes older Edge versions.
92
91
  window.history.replaceState(state, '', url_);
92
+ assertIsVikeEnhanced(window.history.state);
93
93
  }
94
94
  function replaceHistoryStateOriginal(state, url) {
95
95
  // Bypass all monkey patches.
@@ -100,7 +100,9 @@ function replaceHistoryStateOriginal(state, url) {
100
100
  // - history.pushState()
101
101
  // - history.replaceState()
102
102
  function monkeyPatchHistoryAPI() {
103
- ;
103
+ if (globalObject.monkeyPatched)
104
+ return;
105
+ globalObject.monkeyPatched = true;
104
106
  ['pushState', 'replaceState'].forEach((funcName) => {
105
107
  const funcOriginal = window.history[funcName].bind(window.history);
106
108
  window.history[funcName] = (stateOriginal = {}, ...rest) => {
@@ -114,10 +116,19 @@ function monkeyPatchHistoryAPI() {
114
116
  triggeredBy: 'user',
115
117
  ...stateOriginal,
116
118
  };
117
- assert(isVikeEnhanced(stateEnhanced));
118
- const ret = funcOriginal(stateEnhanced, ...rest);
119
+ assertIsVikeEnhanced(stateEnhanced);
120
+ funcOriginal(stateEnhanced, ...rest);
121
+ assert(deepEqual(stateEnhanced, window.history.state));
119
122
  globalObject.previous = getHistoryInfo();
120
- return ret;
123
+ // Workaround https://github.com/vikejs/vike/issues/2504#issuecomment-3149764736
124
+ queueMicrotask(() => {
125
+ if (deepEqual(stateEnhanced, window.history.state))
126
+ return;
127
+ Object.assign(stateEnhanced, window.history.state);
128
+ assertIsVikeEnhanced(stateEnhanced);
129
+ replaceHistoryStateOriginal(stateEnhanced, rest[1]);
130
+ assert(deepEqual(stateEnhanced, window.history.state));
131
+ });
121
132
  };
122
133
  });
123
134
  }
@@ -136,6 +147,11 @@ function isVikeEnhanced(state) {
136
147
  }
137
148
  return false;
138
149
  }
150
+ function assertIsVikeEnhanced(state) {
151
+ if (isVikeEnhanced(state))
152
+ return;
153
+ assert(false, { state });
154
+ }
139
155
  function getHistoryInfo() {
140
156
  return {
141
157
  url: getCurrentUrl(),
@@ -147,11 +163,12 @@ function onPopStateBegin() {
147
163
  const isHistoryStateEnhanced = window.history.state !== null;
148
164
  if (!isHistoryStateEnhanced)
149
165
  enhanceHistoryState();
150
- assert(isVikeEnhanced(window.history.state));
166
+ assertIsVikeEnhanced(window.history.state);
151
167
  const current = getHistoryInfo();
152
168
  globalObject.previous = current;
153
169
  return { isHistoryStateEnhanced, previous, current };
154
170
  }
155
- function initHistoryState() {
156
- enhanceHistoryState();
171
+ function initHistory() {
172
+ monkeyPatchHistoryAPI(); // the earlier we call it the better (Vike can workaround erroneous library monkey patches if Vike is the last one in the monkey patch chain)
173
+ enhanceHistoryState(); // enhance very first window.history.state which is `null`
157
174
  }
@@ -6,7 +6,7 @@ import { initOnLinkClick } from './initOnLinkClick.js';
6
6
  import { scrollRestoration_init } from './scrollRestoration.js';
7
7
  import { autoSaveScrollPosition } from './setScrollPosition.js';
8
8
  import { initLinkPrefetchHandlers } from './prefetch.js';
9
- import { initHistoryState, monkeyPatchHistoryAPI } from './history.js';
9
+ import { initHistory } from './history.js';
10
10
  async function initClientRouter() {
11
11
  // Init navigation history and scroll restoration
12
12
  initHistoryAndScroll();
@@ -29,8 +29,7 @@ async function renderFirstPage() {
29
29
  }
30
30
  function initHistoryAndScroll() {
31
31
  scrollRestoration_init();
32
- monkeyPatchHistoryAPI();
33
- initHistoryState(); // we redundantly call initHistoryState() to ensure it's called early
32
+ initHistory(); // we redundantly call initHistory() to ensure it's called early
34
33
  autoSaveScrollPosition();
35
34
  // Handle back-/forward navigation
36
35
  initOnPopState();
@@ -22,3 +22,5 @@ export * from '../../utils/PROJECT_VERSION.js';
22
22
  export * from '../../utils/genPromise.js';
23
23
  export * from '../../utils/catchInfiniteLoop.js';
24
24
  export * from '../../utils/changeEnumerable.js';
25
+ export * from '../../utils/deepEqual.js';
26
+ export * from '../../utils/cast.js';
@@ -26,3 +26,5 @@ export * from '../../utils/PROJECT_VERSION.js';
26
26
  export * from '../../utils/genPromise.js';
27
27
  export * from '../../utils/catchInfiniteLoop.js';
28
28
  export * from '../../utils/changeEnumerable.js';
29
+ export * from '../../utils/deepEqual.js';
30
+ export * from '../../utils/cast.js';
@@ -20,10 +20,8 @@ function createGetGlobalContextClient(virtualFileExports, isClientRouting, addGl
20
20
  getGlobalContext();
21
21
  return getGlobalContext;
22
22
  async function getGlobalContext() {
23
- // Cache
24
- if (globalObject.virtualFileExports &&
25
- // Don't break HMR
26
- globalObject.virtualFileExports === virtualFileExports) {
23
+ // HMR => virtualFileExports differ
24
+ if (globalObject.virtualFileExports === virtualFileExports) {
27
25
  const globalContext = await globalObject.globalContextPromise;
28
26
  return globalContext;
29
27
  }