vike 0.4.225-commit-37a36a5 → 0.4.225-commit-2b7971f
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.
- package/dist/cjs/client/shared/getPageContextProxyForUser.js +3 -66
- package/dist/cjs/node/api/prepareViteApiCall.js +22 -12
- package/dist/cjs/node/plugin/plugins/commonConfig.js +0 -6
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -1
- package/dist/cjs/node/prerender/resolvePrerenderConfig.js +3 -3
- package/dist/cjs/node/prerender/runPrerender.js +6 -10
- package/dist/cjs/node/runtime/html/serializePageContextClientSide.js +67 -14
- package/dist/cjs/node/runtime/renderPage/preparePageContextForUserConsumptionServerSide.js +3 -0
- package/dist/cjs/node/runtime/renderPage/renderPageAlreadyRouted.js +18 -12
- package/dist/cjs/node/runtime/renderPage.js +13 -28
- package/dist/cjs/shared/NOT_SERIALIZABLE.js +5 -0
- package/dist/cjs/utils/PROJECT_VERSION.js +1 -1
- package/dist/cjs/utils/assert.js +1 -1
- package/dist/cjs/utils/objectAssign.js +7 -2
- package/dist/esm/client/client-routing-runtime/createPageContext.d.ts +2 -0
- package/dist/esm/client/client-routing-runtime/createPageContext.js +2 -1
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +1 -1
- package/dist/esm/client/server-routing-runtime/getPageContext.d.ts +6 -3
- package/dist/esm/client/server-routing-runtime/getPageContext.js +6 -3
- package/dist/esm/client/shared/getPageContextProxyForUser.d.ts +1 -11
- package/dist/esm/client/shared/getPageContextProxyForUser.js +4 -67
- package/dist/esm/client/shared/preparePageContextForUserConsumptionClientSide.d.ts +2 -2
- package/dist/esm/node/api/prepareViteApiCall.js +22 -12
- package/dist/esm/node/plugin/plugins/commonConfig.js +0 -6
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -1
- package/dist/esm/node/prerender/resolvePrerenderConfig.js +3 -3
- package/dist/esm/node/prerender/runPrerender.js +6 -10
- package/dist/esm/node/runtime/html/serializePageContextClientSide.d.ts +2 -0
- package/dist/esm/node/runtime/html/serializePageContextClientSide.js +69 -15
- package/dist/esm/node/runtime/renderPage/preparePageContextForUserConsumptionServerSide.js +3 -0
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.d.ts +27 -1
- package/dist/esm/node/runtime/renderPage/renderPageAlreadyRouted.js +18 -12
- package/dist/esm/node/runtime/renderPage.js +14 -29
- package/dist/esm/shared/NOT_SERIALIZABLE.d.ts +1 -0
- package/dist/esm/shared/NOT_SERIALIZABLE.js +2 -0
- package/dist/esm/shared/page-configs/Config.d.ts +5 -3
- package/dist/esm/shared/page-configs/PageConfig.d.ts +1 -1
- package/dist/esm/shared/route/abort.d.ts +2 -2
- package/dist/esm/shared/types.d.ts +34 -2
- package/dist/esm/utils/PROJECT_VERSION.d.ts +1 -1
- package/dist/esm/utils/PROJECT_VERSION.js +1 -1
- package/dist/esm/utils/assert.js +1 -1
- package/dist/esm/utils/objectAssign.d.ts +1 -1
- package/dist/esm/utils/objectAssign.js +7 -2
- package/package.json +1 -1
- package/dist/cjs/shared/notSerializable.js +0 -5
- package/dist/esm/shared/notSerializable.d.ts +0 -1
- package/dist/esm/shared/notSerializable.js +0 -2
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
export { getPageContext };
|
|
2
2
|
declare function getPageContext(): Promise<{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
_isPageContextObject: boolean;
|
|
4
|
+
isPrerendering: boolean;
|
|
5
|
+
isClientSide: boolean;
|
|
6
6
|
isHydration: true;
|
|
7
7
|
isBackwardNavigation: null;
|
|
8
8
|
_hasPageContextFromServer: true;
|
|
9
9
|
_hasPageContextFromClient: false;
|
|
10
|
+
} & {
|
|
11
|
+
pageId: string;
|
|
12
|
+
routeParams: Record<string, string>;
|
|
10
13
|
} & {
|
|
11
14
|
_pageFilesAll: import("../../shared/getPageFiles.js").PageFile[];
|
|
12
15
|
_pageConfigs: import("../../__internal/index.js").PageConfig[];
|
|
@@ -9,13 +9,16 @@ import * as virtualFileExports from 'virtual:vike:importUserCode:client:server-r
|
|
|
9
9
|
const { pageFilesAll, pageConfigs, pageConfigGlobal } = getPageConfigsRuntime(virtualFileExports);
|
|
10
10
|
const urlFirst = getCurrentUrl({ withoutHash: true });
|
|
11
11
|
async function getPageContext() {
|
|
12
|
-
const pageContext =
|
|
13
|
-
|
|
12
|
+
const pageContext = {
|
|
13
|
+
_isPageContextObject: true,
|
|
14
|
+
isPrerendering: false,
|
|
15
|
+
isClientSide: true,
|
|
14
16
|
isHydration: true,
|
|
15
17
|
isBackwardNavigation: null,
|
|
16
18
|
_hasPageContextFromServer: true,
|
|
17
19
|
_hasPageContextFromClient: false
|
|
18
|
-
}
|
|
20
|
+
};
|
|
21
|
+
objectAssign(pageContext, getPageContextSerializedInHtml());
|
|
19
22
|
objectAssign(pageContext, await loadPageUserFiles(pageContext.pageId));
|
|
20
23
|
assertPristineUrl();
|
|
21
24
|
return pageContext;
|
|
@@ -1,12 +1,2 @@
|
|
|
1
1
|
export { getPageContextProxyForUser };
|
|
2
|
-
|
|
3
|
-
type PageContextForPassToClientWarning = {
|
|
4
|
-
_hasPageContextFromServer: boolean;
|
|
5
|
-
_hasPageContextFromClient: boolean;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* Throw error when pageContext value isn't:
|
|
9
|
-
* - serializable, or
|
|
10
|
-
* - defined.
|
|
11
|
-
*/
|
|
12
|
-
declare function getPageContextProxyForUser<PageContext extends Record<string, unknown> & PageContextForPassToClientWarning>(pageContext: PageContext): PageContext;
|
|
2
|
+
declare function getPageContextProxyForUser<PageContext extends Record<string, unknown>>(pageContext: PageContext): PageContext;
|
|
@@ -1,77 +1,14 @@
|
|
|
1
1
|
export { getPageContextProxyForUser };
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Throw error when pageContext value isn't:
|
|
7
|
-
* - serializable, or
|
|
8
|
-
* - defined.
|
|
9
|
-
*/
|
|
2
|
+
import { assertUsage, getPropAccessNotation } from '../server-routing-runtime/utils.js';
|
|
3
|
+
import { NOT_SERIALIZABLE } from '../../shared/NOT_SERIALIZABLE.js';
|
|
4
|
+
// Throw error when pageContext value isn't serializable
|
|
10
5
|
function getPageContextProxyForUser(pageContext) {
|
|
11
|
-
assert([true, false].includes(pageContext._hasPageContextFromServer));
|
|
12
|
-
assert([true, false].includes(pageContext._hasPageContextFromClient));
|
|
13
6
|
return new Proxy(pageContext, {
|
|
14
7
|
get(_, prop) {
|
|
15
8
|
const val = pageContext[prop];
|
|
16
9
|
const propName = getPropAccessNotation(prop);
|
|
17
|
-
assertUsage(val !==
|
|
18
|
-
passToClientHint(pageContext, prop, propName);
|
|
10
|
+
assertUsage(val !== NOT_SERIALIZABLE, `Can't access pageContext${propName} on the client side. Because it can't be serialized, see server logs.`);
|
|
19
11
|
return val;
|
|
20
12
|
}
|
|
21
13
|
});
|
|
22
14
|
}
|
|
23
|
-
function passToClientHint(pageContext, prop, propName) {
|
|
24
|
-
if (handleVueReactivity(prop))
|
|
25
|
-
return;
|
|
26
|
-
// `prop in pageContext` is the trick we use to know the passToClient value on the client-side, as we set a value to all passToClient props, even `undefined` ones:
|
|
27
|
-
// ```html
|
|
28
|
-
// <script id="vike_pageContext" type="application/json">{"pageProps":"!undefined"}</script>
|
|
29
|
-
// ```
|
|
30
|
-
if (prop in pageContext)
|
|
31
|
-
return;
|
|
32
|
-
if (isWhitelisted(prop))
|
|
33
|
-
return;
|
|
34
|
-
// The trick described above (`prop in pageContext`) doesn't work if Vike doesn't fetch any pageContext from the server.
|
|
35
|
-
// - There would still be some value to show a warning, but it isn't worth it because of the confusion that the first recommendation (adding `prop` to `passToClient`) wouldn't actually remove the warning, and only the second recommendation (using `prop in pageContext` instead of `pageContext[prop]`) would work.
|
|
36
|
-
if (!pageContext._hasPageContextFromServer)
|
|
37
|
-
return;
|
|
38
|
-
const errMsg = `pageContext${propName} isn't defined on the client-side, see https://vike.dev/passToClient#error`;
|
|
39
|
-
if (
|
|
40
|
-
// TODO/next-major-release always make it an error.
|
|
41
|
-
// - Remove pageContext._hasPageContextFromClient logic (IIRC this is its only use case).
|
|
42
|
-
pageContext._hasPageContextFromClient) {
|
|
43
|
-
assertWarning(false, errMsg, { onlyOnce: false, showStackTrace: true });
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
assertUsage(false, errMsg);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
const WHITELIST = [
|
|
50
|
-
'then',
|
|
51
|
-
// Vue calls toJSON()
|
|
52
|
-
'toJSON'
|
|
53
|
-
];
|
|
54
|
-
function isWhitelisted(prop) {
|
|
55
|
-
if (WHITELIST.includes(prop))
|
|
56
|
-
return true;
|
|
57
|
-
if (typeof prop === 'symbol')
|
|
58
|
-
return true; // Vue tries to access some symbols
|
|
59
|
-
if (typeof prop !== 'string')
|
|
60
|
-
return true;
|
|
61
|
-
if (prop.startsWith('__v_'))
|
|
62
|
-
return true; // Vue internals upon `reactive(pageContext)`
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
// Handle Vue's reactivity.
|
|
66
|
-
// When changing a reactive object:
|
|
67
|
-
// - Vue tries to read its old value first. This triggers a `assertIsDefined()` failure if e.g. `pageContextReactive.routeParams = pageContextNew.routeParams` and `pageContextReactive` has no `routeParams`.
|
|
68
|
-
// - Vue seems to read __v_raw before reading the property.
|
|
69
|
-
function handleVueReactivity(prop) {
|
|
70
|
-
if (globalObject.prev === prop || globalObject.prev === '__v_raw')
|
|
71
|
-
return true;
|
|
72
|
-
globalObject.prev = prop;
|
|
73
|
-
window.setTimeout(() => {
|
|
74
|
-
globalObject.prev = undefined;
|
|
75
|
-
}, 0);
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
@@ -2,9 +2,9 @@ export { preparePageContextForUserConsumptionClientSide };
|
|
|
2
2
|
export type { PageContextForUserConsumptionClientSide };
|
|
3
3
|
import type { PageConfigUserFriendlyOld } from '../../shared/getPageFiles.js';
|
|
4
4
|
import type { PageConfigRuntime } from '../../shared/page-configs/PageConfig.js';
|
|
5
|
-
|
|
6
|
-
type PageContextForUserConsumptionClientSide = PageConfigUserFriendlyOld & PageContextForPassToClientWarning & {
|
|
5
|
+
type PageContextForUserConsumptionClientSide = PageConfigUserFriendlyOld & {
|
|
7
6
|
pageId: string;
|
|
7
|
+
_hasPageContextFromServer: boolean;
|
|
8
8
|
_pageConfigs: PageConfigRuntime[];
|
|
9
9
|
};
|
|
10
10
|
declare function preparePageContextForUserConsumptionClientSide<T extends PageContextForUserConsumptionClientSide>(pageContext: T, isClientRouting: boolean): T & {
|
|
@@ -9,6 +9,7 @@ import path from 'path';
|
|
|
9
9
|
import { assert, assertUsage, getGlobalObject, isObject, toPosixPath } from './utils.js';
|
|
10
10
|
import pc from '@brillout/picocolors';
|
|
11
11
|
import { clearGlobalContext } from '../runtime/globalContext.js';
|
|
12
|
+
import { getEnvVarObject } from '../plugin/shared/getEnvVarObject.js';
|
|
12
13
|
const globalObject = getGlobalObject('api/prepareViteApiCall.ts', {});
|
|
13
14
|
async function prepareViteApiCall(options, operation) {
|
|
14
15
|
clear();
|
|
@@ -22,7 +23,7 @@ function clear() {
|
|
|
22
23
|
clearGlobalContext();
|
|
23
24
|
}
|
|
24
25
|
async function enhanceViteConfig(viteConfigFromOptions, operation) {
|
|
25
|
-
const viteInfo = await
|
|
26
|
+
const viteInfo = await getViteInfo(viteConfigFromOptions, operation);
|
|
26
27
|
await assertViteRoot2(viteInfo.root, viteInfo.viteConfigEnhanced, operation);
|
|
27
28
|
const vikeConfig = await getVikeConfig2(viteInfo.root, operation === 'dev', viteInfo.vikeVitePluginOptions);
|
|
28
29
|
const viteConfigEnhanced = addViteSettingsSetByVikeConfig(viteInfo.viteConfigEnhanced, vikeConfig);
|
|
@@ -44,21 +45,30 @@ function addViteSettingsSetByVikeConfig(viteConfigEnhanced, vikeConfig) {
|
|
|
44
45
|
}
|
|
45
46
|
async function getViteRoot(operation) {
|
|
46
47
|
if (!globalObject.root)
|
|
47
|
-
await
|
|
48
|
+
await getViteInfo(undefined, operation);
|
|
48
49
|
assert(globalObject.root);
|
|
49
50
|
return globalObject.root;
|
|
50
51
|
}
|
|
51
|
-
async function
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
//
|
|
52
|
+
async function getViteInfo(viteConfigFromOptions, operation) {
|
|
53
|
+
let viteConfigEnhanced = viteConfigFromOptions;
|
|
54
|
+
// Precedence:
|
|
55
|
+
// - viteConfigFromUserEnvVar (highest precendence)
|
|
56
|
+
// - viteConfigFromOptions
|
|
57
|
+
// - viteConfigFromUserViteFile (lowest precendence)
|
|
58
|
+
const viteConfigFromUserEnvVar = getEnvVarObject('VITE_CONFIG');
|
|
59
|
+
if (viteConfigFromUserEnvVar)
|
|
60
|
+
viteConfigEnhanced = mergeConfig(viteConfigEnhanced ?? {}, viteConfigFromUserEnvVar);
|
|
61
|
+
const viteConfigFromUserViteFile = await loadViteConfigFile(viteConfigEnhanced, operation);
|
|
62
|
+
// Correct precedence, replicates Vite:
|
|
55
63
|
// https://github.com/vitejs/vite/blob/4f5845a3182fc950eb9cd76d7161698383113b18/packages/vite/src/node/config.ts#L1001
|
|
56
|
-
|
|
64
|
+
const viteConfigResolved = mergeConfig(viteConfigFromUserViteFile ?? {}, viteConfigEnhanced ?? {});
|
|
65
|
+
const root = normalizeViteRoot(viteConfigResolved.root ?? process.cwd());
|
|
57
66
|
globalObject.root = root;
|
|
67
|
+
// - Find options `vike(options)` set in vite.config.js
|
|
68
|
+
// - TODO/next-major: remove
|
|
69
|
+
// - Add Vike's Vite plugin if missing
|
|
58
70
|
let vikeVitePluginOptions;
|
|
59
|
-
|
|
60
|
-
// If Vike's Vite plugin is found in both viteConfigFromOptions and viteConfigFromUserViteFile then Vike will later throw an error
|
|
61
|
-
const found = findVikeVitePlugin(viteConfigFromOptions) || findVikeVitePlugin(viteConfigFromUserViteFile);
|
|
71
|
+
const found = findVikeVitePlugin(viteConfigResolved);
|
|
62
72
|
if (found) {
|
|
63
73
|
vikeVitePluginOptions = found.vikeVitePluginOptions;
|
|
64
74
|
}
|
|
@@ -67,8 +77,8 @@ async function getInfoFromVite(viteConfigFromOptions, operation) {
|
|
|
67
77
|
// Using a dynamic import because the script calling the Vike API may not live in the same place as vite.config.js, thus vike/plugin may resolved to two different node_modules/vike directories.
|
|
68
78
|
const { plugin: vikePlugin } = await import('../plugin/index.js');
|
|
69
79
|
viteConfigEnhanced = {
|
|
70
|
-
...
|
|
71
|
-
plugins: [...(
|
|
80
|
+
...viteConfigEnhanced,
|
|
81
|
+
plugins: [...(viteConfigEnhanced?.plugins ?? []), vikePlugin()]
|
|
72
82
|
};
|
|
73
83
|
const res = findVikeVitePlugin(viteConfigEnhanced);
|
|
74
84
|
assert(res);
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
export { commonConfig };
|
|
2
2
|
export { getVikeConfigPublic };
|
|
3
|
-
import { mergeConfig } from 'vite';
|
|
4
3
|
import { assert, assertUsage, assertWarning, findPackageJson, hasProp, isDevCheck, isDocker, isObject } from '../utils.js';
|
|
5
4
|
import { assertRollupInput } from './build/pluginBuildConfig.js';
|
|
6
5
|
import { installRequireShim_setUserRootDir } from '@brillout/require-shim';
|
|
7
6
|
import pc from '@brillout/picocolors';
|
|
8
7
|
import path from 'path';
|
|
9
8
|
import { assertResolveAlias } from './commonConfig/assertResolveAlias.js';
|
|
10
|
-
import { getEnvVarObject } from '../shared/getEnvVarObject.js';
|
|
11
9
|
import { isViteCliCall } from '../shared/isViteCliCall.js';
|
|
12
10
|
import { isVikeCliOrApi } from '../../api/context.js';
|
|
13
11
|
import { getVikeConfig2 } from './importUserCode/v1-design/getVikeConfig.js';
|
|
@@ -91,10 +89,6 @@ function commonConfig(vikeVitePluginOptions) {
|
|
|
91
89
|
// Set `--host` for Docker/Podman
|
|
92
90
|
setDefault('host', true, configFromUser, configFromVike);
|
|
93
91
|
}
|
|
94
|
-
// VITE_CONFIG
|
|
95
|
-
const configFromEnvVar = getEnvVarObject('VITE_CONFIG');
|
|
96
|
-
if (configFromEnvVar)
|
|
97
|
-
configFromVike = mergeConfig(configFromVike, configFromEnvVar);
|
|
98
92
|
return configFromVike;
|
|
99
93
|
}
|
|
100
94
|
}
|
|
@@ -305,7 +305,7 @@ function assertGlobalConfigLocation(configName, sources, plusFilesAll, configDef
|
|
|
305
305
|
: 'to a value that is global';
|
|
306
306
|
const what = isConditionallyGlobal ? 'global values' : pc.cyan(configName);
|
|
307
307
|
const errEnd = configFilePathsGlobal.length > 0
|
|
308
|
-
? `define ${what} at a global config file such as ${joinEnglish(configFilePathsGlobal, 'or')} instead`
|
|
308
|
+
? `define ${what} at a global config file such as ${joinEnglish(configFilePathsGlobal.map(pc.bold), 'or')} instead`
|
|
309
309
|
: `create a global config file (e.g. /pages/+config.js) and define ${what} there instead`;
|
|
310
310
|
// When updating this error message => also update error message at https://vike.dev/warning/global-config
|
|
311
311
|
const errMsg = `${errBeg} ${errMid}: ${errEnd} (https://vike.dev/warning/global-config).`;
|
|
@@ -15,8 +15,8 @@ function resolvePrerenderConfigGlobal(vikeConfig) {
|
|
|
15
15
|
};
|
|
16
16
|
let defaultLocalValue = false;
|
|
17
17
|
{
|
|
18
|
-
const valueFirst = prerenderConfigs.filter((p) => !isObject(p) || p.
|
|
19
|
-
if (valueFirst === true || (isObject(valueFirst) && (valueFirst.
|
|
18
|
+
const valueFirst = prerenderConfigs.filter((p) => !isObject(p) || p.enable !== null)[0];
|
|
19
|
+
if (valueFirst === true || (isObject(valueFirst) && (valueFirst.enable ?? defaultValueForObject))) {
|
|
20
20
|
defaultLocalValue = true;
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -47,7 +47,7 @@ function resolvePrerenderConfigLocal(pageConfig) {
|
|
|
47
47
|
const values = configValue.value;
|
|
48
48
|
assert(isArray(values));
|
|
49
49
|
const value = values[0];
|
|
50
|
-
//
|
|
50
|
+
// If it's set to an object in a local config then Vike considers it a global config and it's skipped from local inheritance, thus we can assume the value to be a boolean.
|
|
51
51
|
assert(typeof value === 'boolean');
|
|
52
52
|
assert(isArray(configValue.definedAtData));
|
|
53
53
|
const prerenderConfigLocal = { value };
|
|
@@ -304,20 +304,16 @@ async function handlePagesWithStaticRoutes(prerenderContext, globalContext, doNo
|
|
|
304
304
|
})));
|
|
305
305
|
}
|
|
306
306
|
async function createPageContext(urlOriginal, prerenderContext, globalContext) {
|
|
307
|
-
const
|
|
307
|
+
const pageContextInit = { urlOriginal };
|
|
308
|
+
objectAssign(pageContextInit, prerenderContext.pageContextInit);
|
|
309
|
+
const pageContext = await getPageContextInitEnhanced(pageContextInit, globalContext, true, {});
|
|
310
|
+
assert(pageContext.isPrerendering === true);
|
|
311
|
+
objectAssign(pageContext, {
|
|
308
312
|
_urlHandler: null,
|
|
309
313
|
_urlRewrite: null,
|
|
310
314
|
_noExtraDir: prerenderContext.noExtraDir,
|
|
311
315
|
_prerenderContext: prerenderContext
|
|
312
|
-
};
|
|
313
|
-
const pageContextInit = {
|
|
314
|
-
urlOriginal
|
|
315
|
-
};
|
|
316
|
-
objectAssign(pageContextInit, prerenderContext.pageContextInit);
|
|
317
|
-
{
|
|
318
|
-
const pageContextInitEnhanced = await getPageContextInitEnhanced(pageContextInit, globalContext);
|
|
319
|
-
objectAssign(pageContext, pageContextInitEnhanced);
|
|
320
|
-
}
|
|
316
|
+
});
|
|
321
317
|
return pageContext;
|
|
322
318
|
}
|
|
323
319
|
async function callOnPrerenderStartHook(prerenderContext, globalContext) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { serializePageContextClientSide };
|
|
2
2
|
export { serializePageContextAbort };
|
|
3
3
|
export type { PageContextSerialization };
|
|
4
|
+
export { getPropKeys };
|
|
4
5
|
import type { PageConfigRuntime } from '../../../shared/page-configs/PageConfig.js';
|
|
5
6
|
import type { UrlRedirect } from '../../../shared/route/abort.js';
|
|
6
7
|
type PageContextSerialization = {
|
|
@@ -20,3 +21,4 @@ declare function serializePageContextAbort(pageContext: Record<string, unknown>
|
|
|
20
21
|
} | {
|
|
21
22
|
abortStatusCode: number;
|
|
22
23
|
})): string;
|
|
24
|
+
declare function getPropKeys(prop: string): string[];
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export { serializePageContextClientSide };
|
|
2
2
|
export { serializePageContextAbort };
|
|
3
|
+
// For ./serializePageContextClientSide.spec.ts
|
|
4
|
+
export { getPropKeys };
|
|
3
5
|
import { stringify, isJsonSerializerError } from '@brillout/json-serializer/stringify';
|
|
4
|
-
import { assert, assertUsage, assertWarning, getPropAccessNotation, hasProp, unique } from '../utils.js';
|
|
6
|
+
import { assert, assertUsage, assertWarning, getPropAccessNotation, hasProp, isObject, unique } from '../utils.js';
|
|
5
7
|
import { isErrorPage } from '../../../shared/error-page.js';
|
|
6
8
|
import { addIs404ToPageProps } from '../../../shared/addIs404ToPageProps.js';
|
|
7
9
|
import pc from '@brillout/picocolors';
|
|
8
|
-
import {
|
|
10
|
+
import { NOT_SERIALIZABLE } from '../../../shared/NOT_SERIALIZABLE.js';
|
|
9
11
|
import { pageContextInitIsPassedToClient } from '../../../shared/misc/pageContextInitIsPassedToClient.js';
|
|
10
12
|
import { isServerSideError } from '../../../shared/misc/isServerSideError.js';
|
|
11
13
|
const PASS_TO_CLIENT = [
|
|
@@ -25,12 +27,8 @@ const PASS_TO_CLIENT = [
|
|
|
25
27
|
const PASS_TO_CLIENT_ERROR_PAGE = ['pageProps', 'is404', isServerSideError];
|
|
26
28
|
function serializePageContextClientSide(pageContext) {
|
|
27
29
|
const passToClient = getPassToClient(pageContext);
|
|
28
|
-
const pageContextClient =
|
|
29
|
-
passToClient.
|
|
30
|
-
// We set non-existing props to `undefined`, in order to pass the list of passToClient values to the client-side
|
|
31
|
-
pageContextClient[prop] = pageContext[prop];
|
|
32
|
-
});
|
|
33
|
-
if (Object.keys(pageContext._pageContextInit).some((p) => passToClient.includes(p))) {
|
|
30
|
+
const pageContextClient = applyPassToClient(passToClient, pageContext);
|
|
31
|
+
if (passToClient.some((prop) => getPropVal(pageContext._pageContextInit, prop))) {
|
|
34
32
|
pageContextClient[pageContextInitIsPassedToClient] = true;
|
|
35
33
|
}
|
|
36
34
|
let pageContextSerialized;
|
|
@@ -42,14 +40,15 @@ function serializePageContextClientSide(pageContext) {
|
|
|
42
40
|
let hasWarned = false;
|
|
43
41
|
const propsNonSerializable = [];
|
|
44
42
|
passToClient.forEach((prop) => {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
const res = getPropVal(pageContext, prop);
|
|
44
|
+
if (!res)
|
|
45
|
+
return;
|
|
46
|
+
const { value } = res;
|
|
47
|
+
const varName = `pageContext${getPropKeys(prop).map(getPropAccessNotation).join('')}`;
|
|
48
48
|
try {
|
|
49
|
-
serialize(
|
|
49
|
+
serialize(value, varName);
|
|
50
50
|
}
|
|
51
51
|
catch (err) {
|
|
52
|
-
hasWarned = true;
|
|
53
52
|
propsNonSerializable.push(prop);
|
|
54
53
|
// useConfig() wrong usage
|
|
55
54
|
if (prop === '_configFromHook') {
|
|
@@ -62,7 +61,7 @@ function serializePageContextClientSide(pageContext) {
|
|
|
62
61
|
// Non-serializable pageContext set by the user
|
|
63
62
|
let msg = [
|
|
64
63
|
`${h(varName)} can't be serialized and, therefore, can't be passed to the client side.`,
|
|
65
|
-
`Make sure ${h(varName)} is serializable, or remove ${h(
|
|
64
|
+
`Make sure ${h(varName)} is serializable, or remove ${h(JSON.stringify(prop))} from ${h('passToClient')}.`
|
|
66
65
|
].join(' ');
|
|
67
66
|
if (isJsonSerializerError(err)) {
|
|
68
67
|
msg = `${msg} Serialization error: ${err.messageCore}.`;
|
|
@@ -75,11 +74,12 @@ function serializePageContextClientSide(pageContext) {
|
|
|
75
74
|
}
|
|
76
75
|
// We warn (instead of throwing an error) since Vike's client runtime throws an error (with `assertUsage()`) if the user's client code tries to access the property that cannot be serialized
|
|
77
76
|
assertWarning(false, msg, { onlyOnce: false });
|
|
77
|
+
hasWarned = true;
|
|
78
78
|
}
|
|
79
79
|
});
|
|
80
80
|
assert(hasWarned);
|
|
81
81
|
propsNonSerializable.forEach((prop) => {
|
|
82
|
-
pageContextClient[prop] =
|
|
82
|
+
pageContextClient[getPropKeys(prop)[0]] = NOT_SERIALIZABLE;
|
|
83
83
|
});
|
|
84
84
|
try {
|
|
85
85
|
pageContextSerialized = serialize(pageContextClient);
|
|
@@ -138,3 +138,57 @@ function serializePageContextAbort(pageContext) {
|
|
|
138
138
|
}
|
|
139
139
|
return serialize(pageContext);
|
|
140
140
|
}
|
|
141
|
+
function applyPassToClient(passToClient, pageContext) {
|
|
142
|
+
const pageContextClient = {};
|
|
143
|
+
passToClient.forEach((prop) => {
|
|
144
|
+
// Get value from pageContext
|
|
145
|
+
const res = getPropVal(pageContext, prop);
|
|
146
|
+
if (!res)
|
|
147
|
+
return;
|
|
148
|
+
const { value } = res;
|
|
149
|
+
// Set value to pageContextClient
|
|
150
|
+
setPropVal(pageContextClient, prop, value);
|
|
151
|
+
});
|
|
152
|
+
return pageContextClient;
|
|
153
|
+
}
|
|
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
|
+
}
|
|
@@ -7,5 +7,8 @@ function preparePageContextForUserConsumptionServerSide(pageContext) {
|
|
|
7
7
|
assert(isPlainObject(pageContext.routeParams));
|
|
8
8
|
assert('Page' in pageContext);
|
|
9
9
|
assert(typeof pageContext.isClientSideNavigation === 'boolean');
|
|
10
|
+
assert(pageContext._isPageContextObject);
|
|
11
|
+
assert(pageContext.isClientSide === false);
|
|
12
|
+
assert(typeof pageContext.isPrerendering === 'boolean');
|
|
10
13
|
preparePageContextForUserConsumption(pageContext);
|
|
11
14
|
}
|
|
@@ -2,6 +2,7 @@ export { renderPageAlreadyRouted };
|
|
|
2
2
|
export { prerenderPage };
|
|
3
3
|
export { prerender404Page };
|
|
4
4
|
export { getPageContextInitEnhanced };
|
|
5
|
+
export { createPageContext };
|
|
5
6
|
export type { PageContextAfterRender };
|
|
6
7
|
export type { PageContextInitEnhanced };
|
|
7
8
|
import { type PageContextUrlInternal } from '../../../shared/getPageContextUrlComputed.js';
|
|
@@ -32,6 +33,10 @@ declare function prerenderPage(pageContext: PageContextInitEnhanced & PageFiles
|
|
|
32
33
|
documentHtml: string;
|
|
33
34
|
pageContextSerialized: null;
|
|
34
35
|
pageContext: {
|
|
36
|
+
_isPageContextObject: boolean;
|
|
37
|
+
isClientSide: boolean;
|
|
38
|
+
isPrerendering: boolean;
|
|
39
|
+
} & Record<string, unknown> & {
|
|
35
40
|
urlOriginal: string;
|
|
36
41
|
headersOriginal?: unknown;
|
|
37
42
|
headers?: unknown;
|
|
@@ -118,6 +123,10 @@ declare function prerenderPage(pageContext: PageContextInitEnhanced & PageFiles
|
|
|
118
123
|
documentHtml: string;
|
|
119
124
|
pageContextSerialized: string;
|
|
120
125
|
pageContext: {
|
|
126
|
+
_isPageContextObject: boolean;
|
|
127
|
+
isClientSide: boolean;
|
|
128
|
+
isPrerendering: boolean;
|
|
129
|
+
} & Record<string, unknown> & {
|
|
121
130
|
urlOriginal: string;
|
|
122
131
|
headersOriginal?: unknown;
|
|
123
132
|
headers?: unknown;
|
|
@@ -205,6 +214,10 @@ declare function prerender404Page(pageContextInit_: Record<string, unknown> | nu
|
|
|
205
214
|
documentHtml: string;
|
|
206
215
|
pageContextSerialized: null;
|
|
207
216
|
pageContext: {
|
|
217
|
+
_isPageContextObject: boolean;
|
|
218
|
+
isClientSide: boolean;
|
|
219
|
+
isPrerendering: boolean;
|
|
220
|
+
} & Record<string, unknown> & {
|
|
208
221
|
urlOriginal: string;
|
|
209
222
|
headersOriginal?: unknown;
|
|
210
223
|
headers?: unknown;
|
|
@@ -291,6 +304,10 @@ declare function prerender404Page(pageContextInit_: Record<string, unknown> | nu
|
|
|
291
304
|
documentHtml: string;
|
|
292
305
|
pageContextSerialized: string;
|
|
293
306
|
pageContext: {
|
|
307
|
+
_isPageContextObject: boolean;
|
|
308
|
+
isClientSide: boolean;
|
|
309
|
+
isPrerendering: boolean;
|
|
310
|
+
} & Record<string, unknown> & {
|
|
294
311
|
urlOriginal: string;
|
|
295
312
|
headersOriginal?: unknown;
|
|
296
313
|
headers?: unknown;
|
|
@@ -379,13 +396,17 @@ declare function getPageContextInitEnhanced(pageContextInit: {
|
|
|
379
396
|
urlOriginal: string;
|
|
380
397
|
headersOriginal?: unknown;
|
|
381
398
|
headers?: unknown;
|
|
382
|
-
}, globalContext: GlobalContextInternal, { ssr: { urlRewrite, urlHandler, isClientSideNavigation } }?: {
|
|
399
|
+
}, globalContext: GlobalContextInternal, isPrerendering: boolean, { ssr: { urlRewrite, urlHandler, isClientSideNavigation } }?: {
|
|
383
400
|
ssr?: {
|
|
384
401
|
urlRewrite: null | string;
|
|
385
402
|
urlHandler: null | ((url: string) => string);
|
|
386
403
|
isClientSideNavigation: boolean;
|
|
387
404
|
};
|
|
388
405
|
}): Promise<{
|
|
406
|
+
_isPageContextObject: boolean;
|
|
407
|
+
isClientSide: boolean;
|
|
408
|
+
isPrerendering: boolean;
|
|
409
|
+
} & Record<string, unknown> & {
|
|
389
410
|
urlOriginal: string;
|
|
390
411
|
headersOriginal?: unknown;
|
|
391
412
|
headers?: unknown;
|
|
@@ -450,3 +471,8 @@ declare function getPageContextInitEnhanced(pageContextInit: {
|
|
|
450
471
|
} & {
|
|
451
472
|
headers: Record<string, string> | null;
|
|
452
473
|
}>;
|
|
474
|
+
declare function createPageContext(pageContextInit: Record<string, unknown>, isPrerendering: boolean): {
|
|
475
|
+
_isPageContextObject: boolean;
|
|
476
|
+
isClientSide: boolean;
|
|
477
|
+
isPrerendering: boolean;
|
|
478
|
+
} & Record<string, unknown>;
|
|
@@ -2,6 +2,7 @@ export { renderPageAlreadyRouted };
|
|
|
2
2
|
export { prerenderPage };
|
|
3
3
|
export { prerender404Page };
|
|
4
4
|
export { getPageContextInitEnhanced };
|
|
5
|
+
export { createPageContext };
|
|
5
6
|
import { getErrorPageId } from '../../../shared/error-page.js';
|
|
6
7
|
import { getHtmlString } from '../html/renderHtml.js';
|
|
7
8
|
import { assert, assertUsage, assertWarning, hasProp, normalizeHeaders, objectAssign } from '../utils.js';
|
|
@@ -84,7 +85,11 @@ async function prerender404Page(pageContextInit_, globalContext) {
|
|
|
84
85
|
if (!errorPageId) {
|
|
85
86
|
return null;
|
|
86
87
|
}
|
|
87
|
-
|
|
88
|
+
// A URL is required for `viteDevServer.transformIndexHtml(url,html)`
|
|
89
|
+
const pageContextInit = { urlOriginal: '/fake-404-url' };
|
|
90
|
+
objectAssign(pageContextInit, pageContextInit_);
|
|
91
|
+
const pageContext = await getPageContextInitEnhanced(pageContextInit, globalContext, true);
|
|
92
|
+
objectAssign(pageContext, {
|
|
88
93
|
pageId: errorPageId,
|
|
89
94
|
_httpRequestId: null,
|
|
90
95
|
_urlRewrite: null,
|
|
@@ -93,25 +98,17 @@ async function prerender404Page(pageContextInit_, globalContext) {
|
|
|
93
98
|
// `prerender404Page()` is about generating `dist/client/404.html` for static hosts; there is no Client Routing.
|
|
94
99
|
_usesClientRouter: false,
|
|
95
100
|
_debugRouteMatches: []
|
|
96
|
-
};
|
|
97
|
-
const pageContextInit = {
|
|
98
|
-
urlOriginal: '/fake-404-url' // A URL is needed for `applyViteHtmlTransform`
|
|
99
|
-
};
|
|
100
|
-
objectAssign(pageContextInit, pageContextInit_);
|
|
101
|
-
{
|
|
102
|
-
const pageContextInitEnhanced = await getPageContextInitEnhanced(pageContextInit, globalContext);
|
|
103
|
-
objectAssign(pageContext, pageContextInitEnhanced);
|
|
104
|
-
}
|
|
101
|
+
});
|
|
105
102
|
objectAssign(pageContext, await loadUserFilesServerSide(pageContext));
|
|
106
103
|
return prerenderPage(pageContext);
|
|
107
104
|
}
|
|
108
|
-
async function getPageContextInitEnhanced(pageContextInit, globalContext, { ssr: { urlRewrite, urlHandler, isClientSideNavigation } = {
|
|
105
|
+
async function getPageContextInitEnhanced(pageContextInit, globalContext, isPrerendering, { ssr: { urlRewrite, urlHandler, isClientSideNavigation } = {
|
|
109
106
|
urlRewrite: null,
|
|
110
107
|
urlHandler: null,
|
|
111
108
|
isClientSideNavigation: false
|
|
112
109
|
} } = {}) {
|
|
113
110
|
assert(pageContextInit.urlOriginal);
|
|
114
|
-
const pageContextInitEnhanced =
|
|
111
|
+
const pageContextInitEnhanced = createPageContext(pageContextInit, isPrerendering);
|
|
115
112
|
objectAssign(pageContextInitEnhanced, pageContextInit);
|
|
116
113
|
objectAssign(pageContextInitEnhanced, {
|
|
117
114
|
_objectCreatedByVike: true,
|
|
@@ -158,3 +155,12 @@ async function getPageContextInitEnhanced(pageContextInit, globalContext, { ssr:
|
|
|
158
155
|
}
|
|
159
156
|
return pageContextInitEnhanced;
|
|
160
157
|
}
|
|
158
|
+
function createPageContext(pageContextInit, isPrerendering) {
|
|
159
|
+
const pageContext = {
|
|
160
|
+
_isPageContextObject: true,
|
|
161
|
+
isClientSide: false,
|
|
162
|
+
isPrerendering
|
|
163
|
+
};
|
|
164
|
+
objectAssign(pageContext, pageContextInit);
|
|
165
|
+
return pageContext;
|
|
166
|
+
}
|