vike 0.4.228-commit-90cfb1a → 0.4.228-commit-558224a

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 (115) hide show
  1. package/dist/cjs/__internal/index.js +2 -2
  2. package/dist/cjs/client/client-routing-runtime/globalContext.js +49 -0
  3. package/dist/cjs/client/server-routing-runtime/globalContext.js +41 -0
  4. package/dist/cjs/client/shared/createGetGlobalContext.js +31 -0
  5. package/dist/cjs/client/shared/getJsonSerializedInHtml.js +31 -0
  6. package/dist/cjs/client/shared/utils.js +21 -0
  7. package/dist/cjs/node/plugin/plugins/build/pluginModuleBanner.js +1 -0
  8. package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +6 -1
  9. package/dist/cjs/node/prerender/runPrerender.js +42 -40
  10. package/dist/cjs/node/prerender/utils.js +1 -1
  11. package/dist/cjs/node/runtime/globalContext.js +87 -119
  12. package/dist/cjs/node/runtime/html/injectAssets/getHtmlTags.js +18 -5
  13. package/dist/cjs/node/runtime/html/injectAssets/getViteDevScript.js +2 -2
  14. package/dist/cjs/node/runtime/html/propKeys.js +47 -0
  15. package/dist/cjs/node/runtime/html/renderHtml.js +1 -1
  16. package/dist/cjs/node/runtime/html/{serializePageContextClientSide.js → serializeContext.js} +37 -67
  17. package/dist/cjs/node/runtime/renderPage/analyzePage.js +1 -1
  18. package/dist/cjs/node/runtime/renderPage/createPageContextServerSide.js +14 -13
  19. package/dist/cjs/node/runtime/renderPage/getPageAssets.js +2 -2
  20. package/dist/cjs/node/runtime/renderPage/handleErrorWithoutErrorPage.js +1 -1
  21. package/dist/cjs/node/runtime/renderPage/loadUserFilesServerSide.js +1 -1
  22. package/dist/cjs/node/runtime/renderPage/log404/index.js +1 -1
  23. package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -3
  24. package/dist/cjs/node/runtime/renderPage.js +10 -10
  25. package/dist/cjs/node/runtime/utils.js +1 -1
  26. package/dist/cjs/shared/createGlobalContextShared.js +45 -0
  27. package/dist/cjs/shared/createPageContextShared.js +2 -2
  28. package/dist/cjs/{node/runtime/renderPage → shared/hooks}/executeHookGeneric.js +4 -4
  29. package/dist/cjs/shared/htmlElementIds.js +5 -0
  30. package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
  31. package/dist/cjs/utils/catchInfiniteLoop.js +3 -3
  32. package/dist/cjs/utils/getPublicProxy.js +27 -0
  33. package/dist/cjs/utils/objectAssign.js +5 -5
  34. package/dist/cjs/utils/objectReplace.js +4 -4
  35. package/dist/esm/__internal/index.js +2 -2
  36. package/dist/esm/client/client-routing-runtime/{createPageContextClientSide.d.ts → createPageContext.d.ts} +17 -8
  37. package/dist/esm/client/client-routing-runtime/{createPageContextClientSide.js → createPageContext.js} +14 -16
  38. package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +1 -1
  39. package/dist/esm/client/client-routing-runtime/globalContext.d.ts +16 -0
  40. package/dist/esm/client/client-routing-runtime/globalContext.js +13 -0
  41. package/dist/esm/client/client-routing-runtime/prefetch.js +1 -1
  42. package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +2 -3
  43. package/dist/esm/client/server-routing-runtime/createPageContextClientSide.d.ts +13 -4
  44. package/dist/esm/client/server-routing-runtime/createPageContextClientSide.js +16 -15
  45. package/dist/esm/client/server-routing-runtime/globalContext.d.ts +13 -0
  46. package/dist/esm/client/server-routing-runtime/globalContext.js +5 -0
  47. package/dist/esm/client/shared/createGetGlobalContext.d.ts +11 -0
  48. package/dist/esm/client/shared/createGetGlobalContext.js +29 -0
  49. package/dist/esm/client/shared/{getPageContextSerializedInHtml.d.ts → getJsonSerializedInHtml.d.ts} +2 -0
  50. package/dist/esm/client/shared/getJsonSerializedInHtml.js +29 -0
  51. package/dist/esm/client/shared/utils.d.ts +3 -0
  52. package/dist/esm/client/shared/utils.js +3 -0
  53. package/dist/esm/node/plugin/plugins/build/pluginModuleBanner.js +1 -0
  54. package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig/configDefinitionsBuiltIn.js +6 -1
  55. package/dist/esm/node/prerender/runPrerender.d.ts +300 -5
  56. package/dist/esm/node/prerender/runPrerender.js +43 -41
  57. package/dist/esm/node/prerender/utils.d.ts +1 -1
  58. package/dist/esm/node/prerender/utils.js +1 -1
  59. package/dist/esm/node/runtime/globalContext.d.ts +393 -46
  60. package/dist/esm/node/runtime/globalContext.js +88 -120
  61. package/dist/esm/node/runtime/html/injectAssets/getHtmlTags.js +18 -5
  62. package/dist/esm/node/runtime/html/injectAssets/getViteDevScript.js +2 -2
  63. package/dist/esm/node/runtime/html/injectAssets.d.ts +1 -1
  64. package/dist/esm/node/runtime/html/propKeys.d.ts +8 -0
  65. package/dist/esm/node/runtime/html/propKeys.js +45 -0
  66. package/dist/esm/node/runtime/html/renderHtml.js +1 -1
  67. package/dist/esm/node/runtime/html/{serializePageContextClientSide.d.ts → serializeContext.d.ts} +7 -6
  68. package/dist/esm/node/runtime/html/{serializePageContextClientSide.js → serializeContext.js} +36 -67
  69. package/dist/esm/node/runtime/renderPage/analyzePage.js +1 -1
  70. package/dist/esm/node/runtime/renderPage/createPageContextServerSide.d.ts +95 -35
  71. package/dist/esm/node/runtime/renderPage/createPageContextServerSide.js +14 -13
  72. package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.d.ts +1 -1
  73. package/dist/esm/node/runtime/renderPage/getPageAssets.js +2 -2
  74. package/dist/esm/node/runtime/renderPage/handleErrorWithoutErrorPage.js +1 -1
  75. package/dist/esm/node/runtime/renderPage/loadUserFilesServerSide.js +1 -1
  76. package/dist/esm/node/runtime/renderPage/log404/index.js +1 -1
  77. package/dist/esm/node/runtime/renderPage/preparePageContextForUserConsumptionServerSide.d.ts +2 -2
  78. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +186 -64
  79. package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +3 -3
  80. package/dist/esm/node/runtime/renderPage.d.ts +95 -34
  81. package/dist/esm/node/runtime/renderPage.js +10 -10
  82. package/dist/esm/node/runtime/utils.d.ts +1 -1
  83. package/dist/esm/node/runtime/utils.js +1 -1
  84. package/dist/esm/shared/VikeNamespace.d.ts +6 -0
  85. package/dist/esm/shared/createGlobalContextShared.d.ts +25 -0
  86. package/dist/esm/shared/createGlobalContextShared.js +43 -0
  87. package/dist/esm/shared/createPageContextShared.js +2 -2
  88. package/dist/esm/shared/hooks/executeHookGeneric.d.ts +8 -0
  89. package/dist/esm/{node/runtime/renderPage → shared/hooks}/executeHookGeneric.js +4 -4
  90. package/dist/esm/shared/htmlElementIds.d.ts +2 -0
  91. package/dist/esm/shared/htmlElementIds.js +2 -0
  92. package/dist/esm/shared/page-configs/Config.d.ts +8 -3
  93. package/dist/esm/shared/types.d.ts +20 -13
  94. package/dist/esm/types/index.d.ts +1 -5
  95. package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
  96. package/dist/esm/utils/PROJECT_VERSION.js +1 -1
  97. package/dist/esm/utils/catchInfiniteLoop.js +4 -4
  98. package/dist/esm/utils/getGlobalObject.d.ts +1 -1
  99. package/dist/esm/utils/getPublicProxy.d.ts +2 -0
  100. package/dist/esm/utils/getPublicProxy.js +25 -0
  101. package/dist/esm/utils/objectAssign.d.ts +1 -1
  102. package/dist/esm/utils/objectAssign.js +5 -5
  103. package/dist/esm/utils/objectReplace.d.ts +1 -1
  104. package/dist/esm/utils/objectReplace.js +4 -4
  105. package/package.json +2 -2
  106. package/dist/cjs/client/client-routing-runtime/globalContextClientSide.js +0 -10
  107. package/dist/cjs/client/client-routing-runtime/onLoad.js +0 -10
  108. package/dist/cjs/client/client-routing-runtime/utils.js +0 -43
  109. package/dist/cjs/utils/makePublicCopy.js +0 -32
  110. package/dist/esm/client/client-routing-runtime/globalContextClientSide.d.ts +0 -5
  111. package/dist/esm/client/client-routing-runtime/globalContextClientSide.js +0 -8
  112. package/dist/esm/client/shared/getPageContextSerializedInHtml.js +0 -20
  113. package/dist/esm/node/runtime/renderPage/executeHookGeneric.d.ts +0 -8
  114. package/dist/esm/utils/makePublicCopy.d.ts +0 -3
  115. package/dist/esm/utils/makePublicCopy.js +0 -30
@@ -18,32 +18,36 @@ export { clearGlobalContext };
18
18
  export { assertBuildInfo };
19
19
  export { updateUserFiles };
20
20
  // The core logic revolves around:
21
- // - globalObject.userFiles which is the main requirement for resolveGlobalContext()
21
+ // - virtualFileExports is the main requirement
22
22
  // - In production: globalObject.buildEntry which is the production entry set by @brillout/vite-plugin-server-entry
23
- // - loadBuildEntry() sets globalObject.buildEntry and then sets globalObject.userFiles
23
+ // - loadBuildEntry() sets globalObject.buildEntry and then sets virtualFileExports
24
24
  // - With vike-server it's set at server start: @brillout/vite-plugin-server-entry injects `import './entry.mjs'` (the production entry generated by @brillout/vite-plugin-server-entry) as first line of code of dist/server/index.mjs while dist/server/entry.mjs calls setGlobalContext_buildEntry()
25
25
  // - Without vike-server it's manually loaded here using importServerProductionEntry() which uses @brillout/vite-plugin-server-entry's autoImporter or crawler
26
26
  // - In development: globalObject.viteDevServer which is Vite's development server
27
- // - globalObject.viteDevServer is used by updateUserFiles() which then sets globalConfig.userFiles
28
- import { assert, onSetupRuntime, assertUsage, assertWarning, isPlainObject, objectAssign, objectReplace, isObject, hasProp, debugGlob, getGlobalObject, genPromise, createDebugger, makePublicCopy, checkType, PROJECT_VERSION } from './utils.js';
27
+ // - globalObject.viteDevServer is used by updateUserFiles() which then sets virtualFileExports
28
+ import { assert, onSetupRuntime, assertUsage, assertWarning, isPlainObject, objectReplace, isObject, hasProp, debugGlob, getGlobalObject, genPromise, createDebugger, getPublicProxy, checkType, PROJECT_VERSION } from './utils.js';
29
29
  import { importServerProductionEntry } from '@brillout/vite-plugin-server-entry/runtime';
30
30
  import { virtualFileIdImportUserCodeServer } from '../shared/virtual-files/virtualFileImportUserCode.js';
31
31
  import pc from '@brillout/picocolors';
32
32
  import { loadPageRoutes } from '../../shared/route/loadPageRoutes.js';
33
33
  import { assertV1Design } from '../shared/assertV1Design.js';
34
- import { getPageConfigsRuntime } from '../../shared/getPageConfigsRuntime.js';
35
34
  import { resolveBase } from '../shared/resolveBase.js';
35
+ import { createGlobalContextShared } from '../../shared/createGlobalContextShared.js';
36
36
  const debug = createDebugger('vike:globalContext');
37
37
  const globalObject = getGlobalObject('runtime/globalContext.ts', getInitialGlobalContext());
38
+ // Trick to break down TypeScript circular dependency
39
+ // https://chat.deepseek.com/a/chat/s/d7e9f90a-c7f3-4108-9cd5-4ad6caed3539
40
+ const globalObjectTyped = globalObject;
38
41
  async function getGlobalContextInternal() {
39
42
  // getGlobalContextInternal() should always be called after initGlobalContext()
40
43
  assert(globalObject.isInitialized);
41
44
  assertGlobalContextIsDefined();
42
45
  if (globalObject.isProduction !== true)
43
46
  await globalObject.waitForUserFilesUpdate;
44
- const { globalContext } = globalObject;
47
+ const { globalContext, globalContext_public } = globalObjectTyped;
45
48
  assertIsDefined(globalContext);
46
- return globalContext;
49
+ assert(globalContext_public);
50
+ return { globalContext, globalContext_public };
47
51
  }
48
52
  function assertIsDefined(globalContext) {
49
53
  if (!globalContext) {
@@ -53,7 +57,8 @@ function assertIsDefined(globalContext) {
53
57
  }
54
58
  }
55
59
  function assertGlobalContextIsDefined() {
56
- assertIsDefined(globalObject.globalContext);
60
+ assertIsDefined(globalObjectTyped.globalContext);
61
+ assert(globalObject.globalContext);
57
62
  assert(globalObject.globalContext_public);
58
63
  }
59
64
  /**
@@ -83,7 +88,7 @@ async function getGlobalContextAsync(isProduction) {
83
88
  if (!isProduction)
84
89
  await globalObject.waitForUserFilesUpdate;
85
90
  assertGlobalContextIsDefined();
86
- const { globalContext_public } = globalObject;
91
+ const { globalContext_public } = globalObjectTyped;
87
92
  assert(globalContext_public);
88
93
  return globalContext_public;
89
94
  }
@@ -96,7 +101,7 @@ async function getGlobalContextAsync(isProduction) {
96
101
  */
97
102
  function getGlobalContextSync() {
98
103
  debug('getGlobalContextSync()');
99
- const { globalContext_public } = globalObject;
104
+ const { globalContext_public } = globalObjectTyped;
100
105
  assertUsage(globalContext_public, "The global context isn't set yet, call getGlobalContextSync() later or use getGlobalContext() instead.");
101
106
  assertWarning(false,
102
107
  // We discourage users from using it because using `pageContext.globalContext` is better: it doesn't have the race condition issue that `getGlobalContextSync()` would have when called inside React/Vue components.
@@ -105,15 +110,7 @@ function getGlobalContextSync() {
105
110
  return globalContext_public;
106
111
  }
107
112
  function makePublic(globalContext) {
108
- const globalContextPublic = makePublicCopy(globalContext, 'globalContext', [
109
- 'assetsManifest',
110
- 'config',
111
- 'viteConfig',
112
- 'viteConfigRuntime',
113
- 'pages',
114
- 'baseServer',
115
- 'baseAssets'
116
- ]);
113
+ const globalContextPublic = getPublicProxy(globalContext, 'globalContext', ['assetsManifest', 'config', 'viteConfig', 'viteConfigRuntime', 'pages', 'baseServer', 'baseAssets'], true);
117
114
  return globalContextPublic;
118
115
  }
119
116
  async function setGlobalContext_viteDevServer(viteDevServer) {
@@ -221,96 +218,6 @@ function setIsProduction(isProduction) {
221
218
  assert(globalObject.isProduction === isProduction);
222
219
  globalObject.isProduction = isProduction;
223
220
  }
224
- function defineGlobalContext() {
225
- const globalContext = resolveGlobalContext();
226
- assertIsDefined(globalContext);
227
- const globalContext_public = makePublic(globalContext);
228
- objectAssign(globalContext, { globalContext_public });
229
- globalObject.globalContext = globalContext;
230
- globalObject.globalContext_public = globalContext_public;
231
- assertGlobalContextIsDefined();
232
- onSetupRuntime();
233
- }
234
- function resolveGlobalContext() {
235
- const { viteDevServer, viteConfig, viteConfigRuntime, isPrerendering, isProduction, userFiles } = globalObject;
236
- assert(typeof isProduction === 'boolean');
237
- let globalContext;
238
- if (!isProduction) {
239
- // Requires globalObject.viteDevServer
240
- if (!viteDevServer)
241
- return null;
242
- assert(userFiles); // main common requiement
243
- assert(viteConfig);
244
- assert(viteConfigRuntime);
245
- assert(!isPrerendering);
246
- globalContext = {
247
- isProduction: false,
248
- isPrerendering: false,
249
- assetsManifest: null,
250
- viteDevServer,
251
- viteConfig,
252
- ...userFiles,
253
- viteConfigRuntime,
254
- ...resolveBaseRuntime(viteConfigRuntime, userFiles.config)
255
- };
256
- }
257
- else {
258
- // Requires globalObject.buildEntry
259
- if (!globalObject.buildEntry)
260
- return null;
261
- assert(userFiles); // main common requiement
262
- const { buildInfo, assetsManifest } = globalObject;
263
- assert(buildInfo);
264
- assert(assetsManifest);
265
- const globalContext_ = {
266
- isProduction: true,
267
- assetsManifest,
268
- ...userFiles,
269
- viteDevServer: null,
270
- viteConfigRuntime: buildInfo.viteConfigRuntime,
271
- usesClientRouter: buildInfo.usesClientRouter,
272
- ...resolveBaseRuntime(buildInfo.viteConfigRuntime, userFiles.config)
273
- };
274
- if (isPrerendering) {
275
- assert(viteConfig);
276
- objectAssign(globalContext_, {
277
- isPrerendering: true,
278
- viteConfig
279
- });
280
- globalContext = globalContext_;
281
- }
282
- else {
283
- objectAssign(globalContext_, {
284
- isPrerendering: false,
285
- viteConfig: null
286
- });
287
- globalContext = globalContext_;
288
- }
289
- }
290
- return globalContext;
291
- }
292
- async function getUserFiles() {
293
- // Help TypeScript resolve what TypeScript (wrongfully) believes to be cyclic dependency
294
- const globalObject_ = globalObject;
295
- const { pageConfigsRuntime } = globalObject_;
296
- assert(pageConfigsRuntime);
297
- const { pageFilesAll, allPageIds, pageConfigs, pageConfigGlobal, globalConfig, pageConfigsUserFriendly } = pageConfigsRuntime;
298
- const { pageRoutes, onBeforeRouteHook } = await loadPageRoutes(pageFilesAll, pageConfigs, pageConfigGlobal, allPageIds);
299
- const userFiles = {
300
- pageFilesAll,
301
- pageConfigs,
302
- pageConfigGlobal,
303
- allPageIds,
304
- pageRoutes,
305
- onBeforeRouteHook,
306
- pages: pageConfigsUserFriendly,
307
- config: globalConfig.config
308
- };
309
- assertV1Design(
310
- // pageConfigs is PageConfigRuntime[] but assertV1Design() requires PageConfigBuildTime[]
311
- pageConfigs.length > 0, pageFilesAll);
312
- return userFiles;
313
- }
314
221
  function assertViteManifest(manifest) {
315
222
  assert(isPlainObject(manifest));
316
223
  /* We should include these assertions but we don't as a workaround for PWA manifests: https://github.com/vikejs/vike/issues/769
@@ -326,10 +233,7 @@ function assertViteManifest(manifest) {
326
233
  }
327
234
  async function loadBuildEntry(outDir) {
328
235
  debug('loadBuildEntry()');
329
- if (globalObject.userFiles) {
330
- assert(globalObject.buildInfo);
331
- assert(globalObject.assetsManifest);
332
- assert(globalObject.buildEntry);
236
+ if (globalObject.globalContext) {
333
237
  return;
334
238
  }
335
239
  if (!globalObject.buildEntry) {
@@ -353,7 +257,7 @@ async function loadBuildEntry(outDir) {
353
257
  assertBuildEntry(buildEntry);
354
258
  globalObject.assetsManifest = buildEntry.assetsManifest;
355
259
  globalObject.buildInfo = buildEntry.buildInfo;
356
- await setUserFiles(buildEntry.virtualFileExports);
260
+ await setGlobalContext(buildEntry.virtualFileExports);
357
261
  }
358
262
  async function setGlobalContext_buildEntry(buildEntry) {
359
263
  debug('setGlobalContext_buildEntry()');
@@ -413,15 +317,79 @@ async function updateUserFiles() {
413
317
  // Avoid race condition: abort if there is a new globalObject.viteDevServer (happens when vite.config.js is modified => Vite's dev server is fully reloaded).
414
318
  if (viteDevServer !== globalObject.viteDevServer)
415
319
  return;
416
- await setUserFiles(virtualFileExports);
320
+ await setGlobalContext(virtualFileExports);
417
321
  resolve();
418
322
  }
419
- async function setUserFiles(virtualFileExports) {
420
- globalObject.pageConfigsRuntime = getPageConfigsRuntime(virtualFileExports);
421
- const userFiles = await getUserFiles();
422
- globalObject.userFiles = userFiles;
423
- defineGlobalContext();
323
+ async function setGlobalContext(virtualFileExports) {
324
+ const globalContext = await createGlobalContextShared(virtualFileExports, globalObject, addGlobalContext);
325
+ assertV1Design(
326
+ // pageConfigs is PageConfigRuntime[] but assertV1Design() requires PageConfigBuildTime[]
327
+ globalContext._pageConfigs.length > 0, globalContext._pageFilesAll);
328
+ // Public usage
329
+ globalObject.globalContext_public = makePublic(globalContext);
424
330
  assertGlobalContextIsDefined();
331
+ onSetupRuntime();
332
+ // Never actually used, only used for TypeScript `ReturnType<typeof setGlobalContext>`
333
+ return globalContext;
334
+ }
335
+ async function addGlobalContext(globalContext) {
336
+ const { pageRoutes, onBeforeRouteHook } = await loadPageRoutes(globalContext._pageFilesAll, globalContext._pageConfigs, globalContext._pageConfigGlobal, globalContext._allPageIds);
337
+ const globalContextBase = {
338
+ _pageRoutes: pageRoutes,
339
+ _onBeforeRouteHook: onBeforeRouteHook
340
+ };
341
+ const { viteDevServer, viteConfig, viteConfigRuntime, isPrerendering, isProduction } = globalObject;
342
+ assert(typeof isProduction === 'boolean');
343
+ if (!isProduction) {
344
+ assert(viteDevServer);
345
+ assert(globalContext); // main common requirement
346
+ assert(viteConfig);
347
+ assert(viteConfigRuntime);
348
+ assert(!isPrerendering);
349
+ return {
350
+ ...globalContext,
351
+ ...globalContextBase,
352
+ ...resolveBaseRuntime(viteConfigRuntime, globalContext.config),
353
+ _isProduction: false,
354
+ _isPrerendering: false,
355
+ assetsManifest: null,
356
+ _viteDevServer: viteDevServer,
357
+ viteConfig,
358
+ viteConfigRuntime
359
+ };
360
+ }
361
+ else {
362
+ assert(globalObject.buildEntry);
363
+ assert(globalContext); // main common requiement
364
+ const { buildInfo, assetsManifest } = globalObject;
365
+ assert(buildInfo);
366
+ assert(assetsManifest);
367
+ const globalContextBase2 = {
368
+ ...globalContext,
369
+ ...globalContextBase,
370
+ ...resolveBaseRuntime(buildInfo.viteConfigRuntime, globalContext.config),
371
+ _isProduction: true,
372
+ assetsManifest,
373
+ _viteDevServer: null,
374
+ viteConfigRuntime: buildInfo.viteConfigRuntime,
375
+ _usesClientRouter: buildInfo.usesClientRouter
376
+ };
377
+ if (isPrerendering) {
378
+ assert(viteConfig);
379
+ return {
380
+ ...globalContextBase2,
381
+ _isPrerendering: true,
382
+ viteConfig
383
+ };
384
+ }
385
+ else {
386
+ return {
387
+ ...globalContextBase2,
388
+ _isPrerendering: false,
389
+ viteConfig: null
390
+ };
391
+ }
392
+ }
425
393
  }
426
394
  function clearGlobalContext() {
427
395
  debug('clearGlobalContext()');
@@ -1,7 +1,7 @@
1
1
  import { isFontFallback } from '../../renderPage/isFontFallback.js';
2
2
  export { getHtmlTags };
3
3
  import { assert, assertWarning, assertUsage, isObject, freezePartial } from '../../utils.js';
4
- import { serializePageContextClientSide } from '../serializePageContextClientSide.js';
4
+ import { getGlobalContextClientSerialized, getPageContextClientSerialized } from '../serializeContext.js';
5
5
  import { sanitizeJson } from './sanitizeJson.js';
6
6
  import { inferAssetTag, inferPreloadTag } from './inferHtmlTags.js';
7
7
  import { mergeScriptTags } from './mergeScriptTags.js';
@@ -9,11 +9,12 @@ import { getPageConfig } from '../../../../shared/page-configs/helpers.js';
9
9
  import { getConfigValueRuntime } from '../../../../shared/page-configs/getConfigValueRuntime.js';
10
10
  import pc from '@brillout/picocolors';
11
11
  import { getConfigDefinedAt } from '../../../../shared/page-configs/getConfigDefinedAt.js';
12
+ import { htmlElementId_globalContext, htmlElementId_pageContext } from '../../../../shared/htmlElementIds.js';
12
13
  const stamp = '__injectFilterEntry';
13
14
  async function getHtmlTags(pageContext, streamFromReactStreamingPackage, injectFilter, pageAssets, viteDevScript, isStream) {
14
15
  assert([true, false].includes(pageContext._isHtmlOnly));
15
16
  const isHtmlOnly = pageContext._isHtmlOnly;
16
- const { isProduction } = pageContext._globalContext;
17
+ const { _isProduction: isProduction } = pageContext._globalContext;
17
18
  const injectScriptsAt = getInjectScriptsAt(pageContext.pageId, pageContext._pageConfigs);
18
19
  const injectFilterEntries = [];
19
20
  pageAssets
@@ -119,14 +120,21 @@ async function getHtmlTags(pageContext, streamFromReactStreamingPackage, injectF
119
120
  // - https://github.com/vikejs/vike-vue/issues/85
120
121
  assertWarning(false, "We recommend against using HTML streaming and a pageContext promise (https://vike.dev/streaming#initial-data-after-stream-end) at the same time, because progressive hydration (https://vike.dev/streaming#progressive-rendering) won't work.", { onlyOnce: true });
121
122
  }
122
- // <script id="vike_pageContext" type="application/json">
123
123
  if (!isHtmlOnly) {
124
+ // <script id="vike_pageContext" type="application/json">
124
125
  htmlTags.push({
125
126
  htmlTag: () =>
126
127
  // Needs to be called after resolvePageContextPromise()
127
128
  getPageContextJsonScriptTag(pageContext),
128
129
  position: positionJavaScriptEntry
129
130
  });
131
+ // <script id="vike_globalContext" type="application/json">
132
+ htmlTags.push({
133
+ htmlTag: () =>
134
+ // Needs to be called after resolvePageContextPromise()
135
+ getGlobalContextJsonScriptTag(pageContext),
136
+ position: positionJavaScriptEntry
137
+ });
130
138
  }
131
139
  // The JavaScript entry <script> tag
132
140
  const scriptEntry = mergeScriptEntries(pageAssets, viteDevScript);
@@ -157,13 +165,18 @@ function mergeScriptEntries(pageAssets, viteDevScript) {
157
165
  return scriptTag;
158
166
  }
159
167
  function getPageContextJsonScriptTag(pageContext) {
160
- const pageContextSerialized = sanitizeJson(serializePageContextClientSide(pageContext));
161
- const htmlTag = `<script id="vike_pageContext" type="application/json">${pageContextSerialized}</script>`;
168
+ const pageContextClientSerialized = sanitizeJson(getPageContextClientSerialized(pageContext));
169
+ const htmlTag = `<script id="${htmlElementId_pageContext}" type="application/json">${pageContextClientSerialized}</script>`;
162
170
  // Used by contra.com https://github.com/gajus
163
171
  // @ts-expect-error
164
172
  pageContext._pageContextHtmlTag = htmlTag;
165
173
  return htmlTag;
166
174
  }
175
+ function getGlobalContextJsonScriptTag(pageContext) {
176
+ const globalContextClientSerialized = sanitizeJson(getGlobalContextClientSerialized(pageContext));
177
+ const htmlTag = `<script id="${htmlElementId_globalContext}" type="application/json">${globalContextClientSerialized}</script>`;
178
+ return htmlTag;
179
+ }
167
180
  function assertInjectFilterEntries(injectFilterEntries) {
168
181
  try {
169
182
  checkForWrongUsage(injectFilterEntries);
@@ -4,10 +4,10 @@ import pc from '@brillout/picocolors';
4
4
  const reachOutCTA = 'Create a new GitHub issue to discuss a solution.';
5
5
  async function getViteDevScript(pageContext) {
6
6
  const globalContext = pageContext._globalContext;
7
- if (globalContext.isProduction) {
7
+ if (globalContext._isProduction) {
8
8
  return '';
9
9
  }
10
- const { viteDevServer } = globalContext;
10
+ const { _viteDevServer: viteDevServer } = globalContext;
11
11
  const fakeHtmlBegin = '<html> <head>'; // White space to test whether user is using a minifier
12
12
  const fakeHtmlEnd = '</head><body></body></html>';
13
13
  let fakeHtml = fakeHtmlBegin + fakeHtmlEnd;
@@ -7,7 +7,7 @@ import type { HtmlPart } from './renderHtml.js';
7
7
  import { type PreloadFilter } from './injectAssets/getHtmlTags.js';
8
8
  import type { StreamFromReactStreamingPackage } from './stream/react-streaming.js';
9
9
  import type { PageConfigRuntime } from '../../../shared/page-configs/PageConfig.js';
10
- import type { PageContextSerialization } from './serializePageContextClientSide.js';
10
+ import type { PageContextSerialization } from './serializeContext.js';
11
11
  import type { GlobalContextInternal } from '../globalContext.js';
12
12
  type PageContextInjectAssets = {
13
13
  urlPathname: string;
@@ -0,0 +1,8 @@
1
+ export { getPropVal };
2
+ export { setPropVal };
3
+ export { getPropKeys };
4
+ declare function getPropVal(obj: Record<string, unknown>, prop: string): null | {
5
+ value: unknown;
6
+ };
7
+ declare function setPropVal(obj: Record<string, unknown>, prop: string, val: unknown): void;
8
+ declare function getPropKeys(prop: string): string[];
@@ -0,0 +1,45 @@
1
+ export { getPropVal };
2
+ export { setPropVal };
3
+ export { getPropKeys };
4
+ import { isObject } from '../utils.js';
5
+ // Get a nested property from an object using a dot-separated path such as 'user.id'
6
+ function getPropVal(obj, prop) {
7
+ const keys = getPropKeys(prop);
8
+ let value = obj;
9
+ for (const key of keys) {
10
+ if (isObject(value) && key in value) {
11
+ value = value[key];
12
+ }
13
+ else {
14
+ return null; // Property or intermediate property doesn't exist
15
+ }
16
+ }
17
+ return { value };
18
+ }
19
+ // Set a nested property in an object using a dot-separated path such as 'user.id'
20
+ function setPropVal(obj, prop, val) {
21
+ const keys = getPropKeys(prop);
22
+ let currentObj = obj;
23
+ // Creating intermediate objects if necessary
24
+ for (let i = 0; i <= keys.length - 2; i++) {
25
+ const key = keys[i];
26
+ if (!(key in currentObj)) {
27
+ // Create intermediate object
28
+ currentObj[key] = {};
29
+ }
30
+ if (!isObject(currentObj[key])) {
31
+ // Skip value upon data structure conflict
32
+ return;
33
+ }
34
+ currentObj = currentObj[key];
35
+ }
36
+ // Set the final key to the value
37
+ const finalKey = keys[keys.length - 1];
38
+ currentObj[finalKey] = val;
39
+ }
40
+ function getPropKeys(prop) {
41
+ // Like `prop.split('.')` but with added support for `\` escaping, see getPageContextClientSerialized.spec.ts
42
+ return prop
43
+ .split(/(?<!\\)\./) // Split on unescaped dots
44
+ .map((key) => key.replace(/\\\./g, '.')); // Replace escaped dots with literal dots
45
+ }
@@ -192,7 +192,7 @@ function renderTemplate(templateContent, pageContext) {
192
192
  }
193
193
  }
194
194
  {
195
- const { isProduction } = pageContext._globalContext;
195
+ const { _isProduction: isProduction } = pageContext._globalContext;
196
196
  if (isHtml(templateVar) &&
197
197
  // We don't show this warning in production because it's expected that some users may (un)willingly do some XSS injection: we avoid flooding the production logs.
198
198
  !isProduction) {
@@ -1,7 +1,7 @@
1
- export { serializePageContextClientSide };
2
- export { serializePageContextAbort };
1
+ export { getPageContextClientSerialized };
2
+ export { getPageContextClientSerializedAbort };
3
+ export { getGlobalContextClientSerialized };
3
4
  export type { PageContextSerialization };
4
- export { getPropKeys };
5
5
  import type { PageConfigRuntime } from '../../../shared/page-configs/PageConfig.js';
6
6
  import type { UrlRedirect } from '../../../shared/route/abort.js';
7
7
  type PageContextSerialization = {
@@ -12,13 +12,14 @@ type PageContextSerialization = {
12
12
  is404: null | boolean;
13
13
  pageProps?: Record<string, unknown>;
14
14
  _pageContextInit: Record<string, unknown>;
15
+ globalContext: Record<string, any>;
15
16
  };
16
- declare function serializePageContextClientSide(pageContext: PageContextSerialization): string;
17
- declare function serializePageContextAbort(pageContext: Record<string, unknown> & ({
17
+ declare function getPageContextClientSerialized(pageContext: PageContextSerialization): string;
18
+ declare function getGlobalContextClientSerialized(pageContext: PageContextSerialization): string;
19
+ declare function getPageContextClientSerializedAbort(pageContext: Record<string, unknown> & ({
18
20
  _urlRedirect: UrlRedirect;
19
21
  } | {
20
22
  _urlRewrite: string;
21
23
  } | {
22
24
  abortStatusCode: number;
23
25
  })): string;
24
- declare function getPropKeys(prop: string): string[];
@@ -1,16 +1,16 @@
1
- export { serializePageContextClientSide };
2
- export { serializePageContextAbort };
3
- // For ./serializePageContextClientSide.spec.ts
4
- export { getPropKeys };
1
+ export { getPageContextClientSerialized };
2
+ export { getPageContextClientSerializedAbort };
3
+ export { getGlobalContextClientSerialized };
5
4
  import { stringify, isJsonSerializerError } from '@brillout/json-serializer/stringify';
6
- import { assert, assertUsage, assertWarning, getPropAccessNotation, hasProp, isObject, unique } from '../utils.js';
5
+ import { assert, assertUsage, assertWarning, getPropAccessNotation, hasProp, unique } from '../utils.js';
7
6
  import { isErrorPage } from '../../../shared/error-page.js';
8
7
  import { addIs404ToPageProps } from '../../../shared/addIs404ToPageProps.js';
9
8
  import pc from '@brillout/picocolors';
10
9
  import { NOT_SERIALIZABLE } from '../../../shared/NOT_SERIALIZABLE.js';
11
10
  import { pageContextInitIsPassedToClient } from '../../../shared/misc/pageContextInitIsPassedToClient.js';
12
11
  import { isServerSideError } from '../../../shared/misc/isServerSideError.js';
13
- const PASS_TO_CLIENT = [
12
+ import { getPropKeys, getPropVal, setPropVal } from './propKeys.js';
13
+ const passToClientBuiltInPageContext = [
14
14
  'abortReason',
15
15
  '_urlRewrite',
16
16
  '_urlRedirect',
@@ -24,29 +24,39 @@ const PASS_TO_CLIENT = [
24
24
  'routeParams',
25
25
  'data' // for data() hook
26
26
  ];
27
- const PASS_TO_CLIENT_ERROR_PAGE = ['pageProps', 'is404', isServerSideError];
28
- function serializePageContextClientSide(pageContext) {
29
- const passToClient = getPassToClient(pageContext);
30
- const pageContextClient = applyPassToClient(passToClient, pageContext);
31
- if (passToClient.some((prop) => getPropVal(pageContext._pageContextInit, prop))) {
27
+ const pageToClientBuiltInPageContextError = ['pageProps', 'is404', isServerSideError];
28
+ function getPageContextClientSerialized(pageContext) {
29
+ const passToClientPageContext = getPassToClientPageContext(pageContext);
30
+ const pageContextClient = applyPassToClient(passToClientPageContext, pageContext);
31
+ if (passToClientPageContext.some((prop) => getPropVal(pageContext._pageContextInit, prop))) {
32
32
  pageContextClient[pageContextInitIsPassedToClient] = true;
33
33
  }
34
- let pageContextSerialized;
34
+ const pageContextClientSerialized = serializeObject(pageContextClient, 'pageContext', passToClientPageContext);
35
+ return pageContextClientSerialized;
36
+ }
37
+ function getGlobalContextClientSerialized(pageContext) {
38
+ const passToClient = pageContext._passToClient;
39
+ const globalContextClient = applyPassToClient(passToClient, pageContext.globalContext);
40
+ const globalContextClientSerialized = serializeObject(globalContextClient, 'globalContext', passToClient);
41
+ return globalContextClientSerialized;
42
+ }
43
+ function serializeObject(obj, objName, passToClient) {
44
+ let serialized;
35
45
  try {
36
- pageContextSerialized = serialize(pageContextClient);
46
+ serialized = serializeValue(obj);
37
47
  }
38
48
  catch (err) {
39
49
  const h = (s) => pc.cyan(s);
40
50
  let hasWarned = false;
41
51
  const propsNonSerializable = [];
42
52
  passToClient.forEach((prop) => {
43
- const res = getPropVal(pageContext, prop);
53
+ const res = getPropVal(obj, prop);
44
54
  if (!res)
45
55
  return;
46
56
  const { value } = res;
47
- const varName = `pageContext${getPropKeys(prop).map(getPropAccessNotation).join('')}`;
57
+ const varName = `${objName}${getPropKeys(prop).map(getPropAccessNotation).join('')}`;
48
58
  try {
49
- serialize(value, varName);
59
+ serializeValue(value, varName);
50
60
  }
51
61
  catch (err) {
52
62
  propsNonSerializable.push(prop);
@@ -58,7 +68,7 @@ function serializePageContextClientSide(pageContext) {
58
68
  }
59
69
  assertUsage(false, `Cannot serialize config ${h(pathString)} set by useConfig(), see https://vike.dev/useConfig#serialization-error`);
60
70
  }
61
- // Non-serializable pageContext set by the user
71
+ // Non-serializable property set by the user
62
72
  let msg = [
63
73
  `${h(varName)} can't be serialized and, therefore, can't be passed to the client side.`,
64
74
  `Make sure ${h(varName)} is serializable, or remove ${h(JSON.stringify(prop))} from ${h('passToClient')}.`
@@ -79,31 +89,31 @@ function serializePageContextClientSide(pageContext) {
79
89
  });
80
90
  assert(hasWarned);
81
91
  propsNonSerializable.forEach((prop) => {
82
- pageContextClient[getPropKeys(prop)[0]] = NOT_SERIALIZABLE;
92
+ obj[getPropKeys(prop)[0]] = NOT_SERIALIZABLE;
83
93
  });
84
94
  try {
85
- pageContextSerialized = serialize(pageContextClient);
95
+ serialized = serializeValue(obj);
86
96
  }
87
97
  catch (err) {
88
98
  assert(false);
89
99
  }
90
100
  }
91
- return pageContextSerialized;
101
+ return serialized;
92
102
  }
93
- function serialize(value, varName) {
103
+ function serializeValue(value, varName) {
94
104
  return stringify(value, { forbidReactElements: true, valueName: varName });
95
105
  }
96
- function getPassToClient(pageContext) {
97
- let passToClient = [...pageContext._passToClient, ...PASS_TO_CLIENT];
106
+ function getPassToClientPageContext(pageContext) {
107
+ let passToClient = [...pageContext._passToClient, ...passToClientBuiltInPageContext];
98
108
  if (isErrorPage(pageContext.pageId, pageContext._pageConfigs)) {
99
109
  assert(hasProp(pageContext, 'is404', 'boolean'));
100
110
  addIs404ToPageProps(pageContext);
101
- passToClient.push(...PASS_TO_CLIENT_ERROR_PAGE);
111
+ passToClient.push(...pageToClientBuiltInPageContextError);
102
112
  }
103
113
  passToClient = unique(passToClient);
104
114
  return passToClient;
105
115
  }
106
- function serializePageContextAbort(pageContext) {
116
+ function getPageContextClientSerializedAbort(pageContext) {
107
117
  assert(pageContext._urlRedirect || pageContext._urlRewrite || pageContext.abortStatusCode);
108
118
  assert(pageContext._abortCall);
109
119
  assert(pageContext._abortCaller);
@@ -136,7 +146,7 @@ function serializePageContextAbort(pageContext) {
136
146
  onlyOnce: false
137
147
  });
138
148
  }
139
- return serialize(pageContext);
149
+ return serializeValue(pageContext);
140
150
  }
141
151
  function applyPassToClient(passToClient, pageContext) {
142
152
  const pageContextClient = {};
@@ -151,44 +161,3 @@ function applyPassToClient(passToClient, pageContext) {
151
161
  });
152
162
  return pageContextClient;
153
163
  }
154
- // Get a nested property from an object using a dot-separated path such as 'user.id'
155
- function getPropVal(obj, prop) {
156
- const keys = getPropKeys(prop);
157
- let value = obj;
158
- for (const key of keys) {
159
- if (isObject(value) && key in value) {
160
- value = value[key];
161
- }
162
- else {
163
- return null; // Property or intermediate property doesn't exist
164
- }
165
- }
166
- return { value };
167
- }
168
- // Set a nested property in an object using a dot-separated path such as 'user.id'
169
- function setPropVal(obj, prop, val) {
170
- const keys = getPropKeys(prop);
171
- let currentObj = obj;
172
- // Creating intermediate objects if necessary
173
- for (let i = 0; i <= keys.length - 2; i++) {
174
- const key = keys[i];
175
- if (!(key in currentObj)) {
176
- // Create intermediate object
177
- currentObj[key] = {};
178
- }
179
- if (!isObject(currentObj[key])) {
180
- // Skip value upon data structure conflict
181
- return;
182
- }
183
- currentObj = currentObj[key];
184
- }
185
- // Set the final key to the value
186
- const finalKey = keys[keys.length - 1];
187
- currentObj[finalKey] = val;
188
- }
189
- function getPropKeys(prop) {
190
- // Like `prop.split('.')` but with added support for `\` escaping, see serializePageContextClientSide.spec.ts
191
- return prop
192
- .split(/(?<!\\)\./) // Split on unescaped dots
193
- .map((key) => key.replace(/\\\./g, '.')); // Replace escaped dots with literal dots
194
- }
@@ -20,7 +20,7 @@ async function analyzePage(pageFilesAll, pageConfig, pageId, globalContext) {
20
20
  eagerlyImported: false
21
21
  });
22
22
  // In production we inject the import of the server virtual module with ?extractAssets inside the client virtual module
23
- if (!globalContext.isProduction) {
23
+ if (!globalContext._isProduction) {
24
24
  clientDependencies.push({
25
25
  id: getVirtualFileIdPageConfigValuesAll(pageConfig.pageId, false),
26
26
  onlyAssets: true,