vike 0.4.171-commit-ea3808a → 0.4.171-commit-978d69d
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/node/plugin/plugins/extractAssetsPlugin.js +1 -1
- package/dist/cjs/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -1
- package/dist/cjs/node/prerender/runPrerender.js +2 -2
- package/dist/cjs/node/runtime/html/stream.js +9 -9
- package/dist/cjs/node/runtime/renderPage/executeOnBeforeRenderAndDataHooks.js +2 -2
- package/dist/cjs/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -1
- package/dist/cjs/node/runtime/renderPage/getHttpResponseBody.js +2 -2
- package/dist/cjs/shared/getPageContext.js +5 -0
- package/dist/cjs/shared/getPageFiles/getExports.js +10 -10
- package/dist/cjs/shared/hooks/executeHook.js +22 -3
- package/dist/cjs/shared/page-configs/serialize/parseConfigValuesImported.js +1 -1
- package/dist/cjs/shared/route/executeGuardHook.js +1 -1
- package/dist/cjs/shared/route/executeOnBeforeRouteHook.js +1 -1
- package/dist/cjs/utils/getPropAccessNotation.js +1 -4
- package/dist/cjs/utils/projectInfo.js +1 -1
- package/dist/esm/client/client-routing-runtime/getPageContextFromHooks.js +2 -2
- package/dist/esm/client/client-routing-runtime/renderPageClientSide.js +3 -3
- package/dist/esm/client/server-routing-runtime/utils.d.ts +1 -0
- package/dist/esm/client/server-routing-runtime/utils.js +1 -0
- package/dist/esm/client/shared/executeOnRenderClientHook.js +1 -1
- package/dist/esm/client/shared/getPageContextProxyForUser.d.ts +3 -2
- package/dist/esm/client/shared/getPageContextProxyForUser.js +35 -48
- package/dist/esm/node/plugin/plugins/extractAssetsPlugin.js +1 -1
- package/dist/esm/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.js +1 -1
- package/dist/esm/node/prerender/runPrerender.js +2 -2
- package/dist/esm/node/runtime/html/stream.d.ts +1 -1
- package/dist/esm/node/runtime/html/stream.js +9 -9
- package/dist/esm/node/runtime/renderPage/executeOnBeforeRenderAndDataHooks.js +2 -2
- package/dist/esm/node/runtime/renderPage/executeOnRenderHtmlHook.js +1 -1
- package/dist/esm/node/runtime/renderPage/getHttpResponseBody.js +2 -2
- package/dist/esm/shared/VikeNamespace.d.ts +9 -0
- package/dist/esm/shared/getPageContext.d.ts +1 -0
- package/dist/esm/shared/getPageContext.js +1 -0
- package/dist/esm/shared/getPageFiles/getExports.d.ts +5 -5
- package/dist/esm/shared/getPageFiles/getExports.js +10 -10
- package/dist/esm/shared/hooks/executeHook.d.ts +10 -1
- package/dist/esm/shared/hooks/executeHook.js +21 -2
- package/dist/esm/shared/page-configs/Config/PageContextConfig.d.ts +2 -2
- package/dist/esm/shared/page-configs/PageConfig.d.ts +4 -4
- package/dist/esm/shared/page-configs/serialize/PageConfigSerialized.d.ts +2 -2
- package/dist/esm/shared/page-configs/serialize/parseConfigValuesImported.js +1 -1
- package/dist/esm/shared/route/executeGuardHook.js +1 -1
- package/dist/esm/shared/route/executeOnBeforeRouteHook.js +1 -1
- package/dist/esm/utils/getPropAccessNotation.d.ts +1 -2
- package/dist/esm/utils/getPropAccessNotation.js +2 -6
- package/dist/esm/utils/projectInfo.d.ts +2 -2
- package/dist/esm/utils/projectInfo.js +1 -1
- package/package.json +10 -1
|
@@ -102,7 +102,7 @@ function extractAssetsPlugin() {
|
|
|
102
102
|
}
|
|
103
103
|
// If the import path resolves to a file in `node_modules/`, we ignore that file:
|
|
104
104
|
// - Direct CSS dependencies are included though, such as `import 'bootstrap/theme/dark.css'`. (Because the above if-branch for CSS files will add the file.)
|
|
105
|
-
// - Loading CSS from a library (living in `node_modules/`) in a non-direct way is
|
|
105
|
+
// - Loading CSS from a library (living in `node_modules/`) in a non-direct way is unconventional; we can safely not support this case. (I'm not aware of any library that does this.)
|
|
106
106
|
(0, utils_js_1.assertPosixPath)(file);
|
|
107
107
|
if (file.includes('/node_modules/')) {
|
|
108
108
|
return emptyModule(file, importer);
|
|
@@ -898,7 +898,7 @@ function getConfigValues(configValueSources, configValuesComputed, configDefinit
|
|
|
898
898
|
const configValueSource = sources[0];
|
|
899
899
|
if ('value' in configValueSource) {
|
|
900
900
|
configValues[configName] = {
|
|
901
|
-
type: '
|
|
901
|
+
type: 'standard',
|
|
902
902
|
value: configValueSource.value,
|
|
903
903
|
definedAtData: getDefinedAtFile(configValueSource)
|
|
904
904
|
};
|
|
@@ -245,7 +245,7 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, renderContext,
|
|
|
245
245
|
if (doNotPrerenderList.find((p) => p.pageId === pageId)) {
|
|
246
246
|
return;
|
|
247
247
|
}
|
|
248
|
-
const prerenderResult = await (0, executeHook_js_1.executeHook)(() => hookFn(), { hookName, hookFilePath, hookTimeout });
|
|
248
|
+
const prerenderResult = await (0, executeHook_js_1.executeHook)(() => hookFn(), { hookName, hookFilePath, hookTimeout }, null);
|
|
249
249
|
const result = normalizeOnPrerenderHookResult(prerenderResult, hookFilePath, hookName);
|
|
250
250
|
result.forEach(({ url, pageContext }) => {
|
|
251
251
|
{
|
|
@@ -420,7 +420,7 @@ async function callOnPrerenderStartHook(prerenderContext, renderContext) {
|
|
|
420
420
|
});
|
|
421
421
|
return prerenderContext.pageContexts;
|
|
422
422
|
}
|
|
423
|
-
}), onPrerenderStartHook);
|
|
423
|
+
}), onPrerenderStartHook, null);
|
|
424
424
|
if (result === null || result === undefined) {
|
|
425
425
|
return;
|
|
426
426
|
}
|
|
@@ -762,17 +762,17 @@ async function loadStreamNodeModule() {
|
|
|
762
762
|
const { Readable, Writable } = streamModule;
|
|
763
763
|
return { Readable, Writable };
|
|
764
764
|
}
|
|
765
|
-
function getStreamName(
|
|
766
|
-
let
|
|
767
|
-
if (
|
|
768
|
-
|
|
765
|
+
function getStreamName(kind, type) {
|
|
766
|
+
let typeName = (0, utils_js_1.capitalizeFirstLetter)(type);
|
|
767
|
+
if (typeName === 'Node') {
|
|
768
|
+
typeName = 'Node.js';
|
|
769
769
|
}
|
|
770
|
-
const
|
|
771
|
-
if (
|
|
772
|
-
return `a ${
|
|
770
|
+
const kindName = (0, utils_js_1.capitalizeFirstLetter)(kind);
|
|
771
|
+
if (kind !== 'pipe') {
|
|
772
|
+
return `a ${kindName} ${typeName} Stream`;
|
|
773
773
|
}
|
|
774
|
-
if (
|
|
775
|
-
return `a ${
|
|
774
|
+
if (kind === 'pipe') {
|
|
775
|
+
return `a ${typeName} Stream Pipe`;
|
|
776
776
|
}
|
|
777
777
|
(0, utils_js_1.assert)(false);
|
|
778
778
|
}
|
|
@@ -16,7 +16,7 @@ async function executeOnBeforeRenderAndDataHooks(pageContext) {
|
|
|
16
16
|
}
|
|
17
17
|
(0, preparePageContextForUserConsumptionServerSide_js_1.preparePageContextForUserConsumptionServerSide)(pageContext);
|
|
18
18
|
if (dataHook) {
|
|
19
|
-
const hookResult = await (0, executeHook_js_1.executeHook)(() => dataHook.hookFn(pageContext), dataHook);
|
|
19
|
+
const hookResult = await (0, executeHook_js_1.executeHook)(() => dataHook.hookFn(pageContext), dataHook, pageContext);
|
|
20
20
|
// Note: hookResult can be anything (e.g. an object) and is to be assigned to pageContext.data
|
|
21
21
|
const pageContextFromHook = {
|
|
22
22
|
data: hookResult
|
|
@@ -24,7 +24,7 @@ async function executeOnBeforeRenderAndDataHooks(pageContext) {
|
|
|
24
24
|
Object.assign(pageContext, pageContextFromHook);
|
|
25
25
|
}
|
|
26
26
|
if (onBeforeRenderHook) {
|
|
27
|
-
const hookResult = await (0, executeHook_js_1.executeHook)(() => onBeforeRenderHook.hookFn(pageContext), onBeforeRenderHook);
|
|
27
|
+
const hookResult = await (0, executeHook_js_1.executeHook)(() => onBeforeRenderHook.hookFn(pageContext), onBeforeRenderHook, pageContext);
|
|
28
28
|
(0, assertOnBeforeRenderHookReturn_js_1.assertOnBeforeRenderHookReturn)(hookResult, onBeforeRenderHook.hookFilePath);
|
|
29
29
|
const pageContextFromHook = hookResult?.pageContext;
|
|
30
30
|
Object.assign(pageContext, pageContextFromHook);
|
|
@@ -18,7 +18,7 @@ async function executeOnRenderHtmlHook(pageContext) {
|
|
|
18
18
|
const { renderHook, hookFn } = getRenderHook(pageContext);
|
|
19
19
|
(0, utils_js_1.objectAssign)(pageContext, { _renderHook: renderHook });
|
|
20
20
|
(0, preparePageContextForUserConsumptionServerSide_js_1.preparePageContextForUserConsumptionServerSide)(pageContext);
|
|
21
|
-
const hookReturnValue = await (0, executeHook_js_1.executeHook)(() => hookFn(pageContext), renderHook);
|
|
21
|
+
const hookReturnValue = await (0, executeHook_js_1.executeHook)(() => hookFn(pageContext), renderHook, pageContext);
|
|
22
22
|
const { documentHtml, pageContextProvidedByRenderHook, pageContextPromise, injectFilter } = processHookReturnValue(hookReturnValue, renderHook);
|
|
23
23
|
Object.assign(pageContext, pageContextProvidedByRenderHook);
|
|
24
24
|
(0, utils_js_1.objectAssign)(pageContext, { _pageContextPromise: pageContextPromise });
|
|
@@ -100,8 +100,8 @@ function getHttpResponseBodyStreamHandlers(htmlRender, renderHook) {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
|
-
function getFixMsg(
|
|
104
|
-
const streamName = (0, stream_js_1.getStreamName)(
|
|
103
|
+
function getFixMsg(kind, type) {
|
|
104
|
+
const streamName = (0, stream_js_1.getStreamName)(kind, type);
|
|
105
105
|
(0, utils_js_1.assert)(['a ', 'an ', 'the '].some((s) => streamName.startsWith(s)));
|
|
106
106
|
(0, utils_js_1.assert)(renderHook);
|
|
107
107
|
const { hookFilePath, hookName } = renderHook;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getPageContext = void 0;
|
|
4
|
+
var executeHook_js_1 = require("./hooks/executeHook.js");
|
|
5
|
+
Object.defineProperty(exports, "getPageContext", { enumerable: true, get: function () { return executeHook_js_1.getPageContext; } });
|
|
@@ -40,7 +40,7 @@ function getPageContextExports(pageFiles, pageConfig) {
|
|
|
40
40
|
sources[configName].push(src);
|
|
41
41
|
};
|
|
42
42
|
const from = {
|
|
43
|
-
|
|
43
|
+
configsStandard: {},
|
|
44
44
|
configsCumulative: {},
|
|
45
45
|
configsComputed: {}
|
|
46
46
|
};
|
|
@@ -58,6 +58,15 @@ function getPageContextExports(pageFiles, pageConfig) {
|
|
|
58
58
|
configDefinedAt,
|
|
59
59
|
configDefinedByFile: configValueFilePathToShowToUser
|
|
60
60
|
});
|
|
61
|
+
if (configValue.type === 'standard') {
|
|
62
|
+
const src = {
|
|
63
|
+
type: 'configsStandard',
|
|
64
|
+
value: configValue.value,
|
|
65
|
+
definedAt: (0, getConfigDefinedAt_js_1.getDefinedAtString)(configValue.definedAtData, configName)
|
|
66
|
+
};
|
|
67
|
+
addSrc(src, configName);
|
|
68
|
+
from.configsStandard[configName] = src;
|
|
69
|
+
}
|
|
61
70
|
if (configValue.type === 'cumulative') {
|
|
62
71
|
const src = {
|
|
63
72
|
type: 'configsCumulative',
|
|
@@ -74,15 +83,6 @@ function getPageContextExports(pageFiles, pageConfig) {
|
|
|
74
83
|
addSrc(src, configName);
|
|
75
84
|
from.configsCumulative[configName] = src;
|
|
76
85
|
}
|
|
77
|
-
if (configValue.type === 'classic') {
|
|
78
|
-
const src = {
|
|
79
|
-
type: 'configsOverridable',
|
|
80
|
-
value: configValue.value,
|
|
81
|
-
definedAt: (0, getConfigDefinedAt_js_1.getDefinedAtString)(configValue.definedAtData, configName)
|
|
82
|
-
};
|
|
83
|
-
addSrc(src, configName);
|
|
84
|
-
from.configsOverridable[configName] = src;
|
|
85
|
-
}
|
|
86
86
|
if (configValue.type === 'computed') {
|
|
87
87
|
const src = {
|
|
88
88
|
type: 'configsComputed',
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isUserHookError = exports.executeHook = void 0;
|
|
3
|
+
exports.isUserHookError = exports.getPageContext = exports.executeHook = void 0;
|
|
4
4
|
const assert_js_1 = require("../../utils/assert.js");
|
|
5
5
|
const getGlobalObject_js_1 = require("../../utils/getGlobalObject.js");
|
|
6
6
|
const humanizeTime_js_1 = require("../../utils/humanizeTime.js");
|
|
7
7
|
const isObject_js_1 = require("../../utils/isObject.js");
|
|
8
8
|
const globalObject = (0, getGlobalObject_js_1.getGlobalObject)('utils/executeHook.ts', {
|
|
9
|
-
userHookErrors: new WeakMap()
|
|
9
|
+
userHookErrors: new WeakMap(),
|
|
10
|
+
pageContext: null
|
|
10
11
|
});
|
|
11
12
|
function isUserHookError(err) {
|
|
12
13
|
if (!(0, isObject_js_1.isObject)(err))
|
|
@@ -14,7 +15,7 @@ function isUserHookError(err) {
|
|
|
14
15
|
return globalObject.userHookErrors.get(err) ?? false;
|
|
15
16
|
}
|
|
16
17
|
exports.isUserHookError = isUserHookError;
|
|
17
|
-
function executeHook(hookFnCaller, hook) {
|
|
18
|
+
function executeHook(hookFnCaller, hook, pageContext) {
|
|
18
19
|
const { hookName, hookFilePath, hookTimeout: { error: timeoutErr, warning: timeoutWarn } } = hook;
|
|
19
20
|
let resolve;
|
|
20
21
|
let reject;
|
|
@@ -45,6 +46,7 @@ function executeHook(hookFnCaller, hook) {
|
|
|
45
46
|
}, timeoutErr);
|
|
46
47
|
(async () => {
|
|
47
48
|
try {
|
|
49
|
+
providePageContext(pageContext);
|
|
48
50
|
const ret = await hookFnCaller();
|
|
49
51
|
resolve(ret);
|
|
50
52
|
}
|
|
@@ -61,3 +63,20 @@ exports.executeHook = executeHook;
|
|
|
61
63
|
function isNotDisabled(timeout) {
|
|
62
64
|
return !!timeout && timeout !== Infinity;
|
|
63
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Access `pageContext` object inside Vike hooks, in order to create universal hooks.
|
|
68
|
+
*
|
|
69
|
+
* https://vike.dev/getPageContext
|
|
70
|
+
*/
|
|
71
|
+
function getPageContext() {
|
|
72
|
+
return globalObject.pageContext;
|
|
73
|
+
}
|
|
74
|
+
exports.getPageContext = getPageContext;
|
|
75
|
+
function providePageContext(pageContext) {
|
|
76
|
+
globalObject.pageContext = pageContext;
|
|
77
|
+
// Promise.resolve() is quicker than process.nextTick() and setImmediate()
|
|
78
|
+
// https://stackoverflow.com/questions/67949576/process-nexttick-before-promise-resolve-then
|
|
79
|
+
Promise.resolve().then(() => {
|
|
80
|
+
globalObject.pageContext = null;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
@@ -53,7 +53,7 @@ function parseConfigValuesImported(configValuesImported) {
|
|
|
53
53
|
(0, utils_js_1.assert)(val);
|
|
54
54
|
const { value, importPath, exportName } = val;
|
|
55
55
|
configValues[configName] = {
|
|
56
|
-
type: '
|
|
56
|
+
type: 'standard',
|
|
57
57
|
value,
|
|
58
58
|
definedAtData: {
|
|
59
59
|
// importPath cannot be relative to the current file, since the current file is a virtual file
|
|
@@ -23,7 +23,7 @@ async function executeGuardHook(pageContext, prepareForUserConsumption) {
|
|
|
23
23
|
const res = prepareForUserConsumption(pageContext);
|
|
24
24
|
if (res)
|
|
25
25
|
pageContextForUserConsumption = res;
|
|
26
|
-
const hookResult = await (0, executeHook_js_1.executeHook)(() => guard(pageContextForUserConsumption), hook);
|
|
26
|
+
const hookResult = await (0, executeHook_js_1.executeHook)(() => guard(pageContextForUserConsumption), hook, pageContext);
|
|
27
27
|
(0, utils_js_1.assertUsage)(hookResult === undefined, `${errIntro} ${hook.hookFilePath} returns a value, but guard() shouldn't return any value`);
|
|
28
28
|
}
|
|
29
29
|
exports.executeGuardHook = executeGuardHook;
|
|
@@ -42,7 +42,7 @@ async function getPageContextFromHook(onBeforeRouteHook, pageContext) {
|
|
|
42
42
|
let hookReturn = onBeforeRouteHook.hookFn(pageContext);
|
|
43
43
|
(0, resolveRouteFunction_js_1.assertSyncRouting)(hookReturn, `The onBeforeRoute() hook ${onBeforeRouteHook.hookFilePath}`);
|
|
44
44
|
// TODO/v1-release: make executeOnBeforeRouteHook() and route() sync
|
|
45
|
-
hookReturn = await (0, executeHook_js_1.executeHook)(() => hookReturn, onBeforeRouteHook);
|
|
45
|
+
hookReturn = await (0, executeHook_js_1.executeHook)(() => hookReturn, onBeforeRouteHook, pageContext);
|
|
46
46
|
const errPrefix = `The onBeforeRoute() hook defined by ${onBeforeRouteHook.hookFilePath}`;
|
|
47
47
|
(0, utils_js_1.assertUsage)(hookReturn === null ||
|
|
48
48
|
hookReturn === undefined ||
|
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getPropAccessNotation = void 0;
|
|
4
4
|
function getPropAccessNotation(key) {
|
|
5
|
-
return
|
|
5
|
+
return typeof key === 'string' && /^[a-z0-9\$_]+$/i.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
|
|
6
6
|
}
|
|
7
7
|
exports.getPropAccessNotation = getPropAccessNotation;
|
|
8
|
-
function isKeyDotNotationCompatible(key) {
|
|
9
|
-
return /^[a-z0-9\$_]+$/i.test(key);
|
|
10
|
-
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PROJECT_VERSION = exports.projectInfo = void 0;
|
|
4
|
-
const PROJECT_VERSION = '0.4.171-commit-
|
|
4
|
+
const PROJECT_VERSION = '0.4.171-commit-978d69d';
|
|
5
5
|
exports.PROJECT_VERSION = PROJECT_VERSION;
|
|
6
6
|
const projectInfo = {
|
|
7
7
|
projectName: 'Vike',
|
|
@@ -108,7 +108,7 @@ async function executeHookClientSide(hookName, pageContext) {
|
|
|
108
108
|
return null;
|
|
109
109
|
}
|
|
110
110
|
const pageContextForUserConsumption = preparePageContextForUserConsumptionClientSide(pageContext, true);
|
|
111
|
-
const hookResult = await executeHook(() => hook.hookFn(pageContextForUserConsumption), hook);
|
|
111
|
+
const hookResult = await executeHook(() => hook.hookFn(pageContextForUserConsumption), hook, pageContext);
|
|
112
112
|
const pageContextFromHook = {};
|
|
113
113
|
if (hookName === 'onBeforeRender') {
|
|
114
114
|
assertOnBeforeRenderHookReturn(hookResult, hook.hookFilePath);
|
|
@@ -221,7 +221,7 @@ async function fetchPageContextFromServer(pageContext) {
|
|
|
221
221
|
}
|
|
222
222
|
// Is there a reason for having two different properties? Can't we use only one property? I guess/think the isServerSideError property was an attempt (a bad idea really) for rendering the error page even though an error occured on the server-side (which is a bad idea because the added complexity is non-negligible while the added value is minuscule since the error page usually doesn't have any (meaningful / server-side) hooks).
|
|
223
223
|
if ('serverSideError' in pageContextFromServer || isServerSideError in pageContextFromServer) {
|
|
224
|
-
throw getProjectError(`
|
|
224
|
+
throw getProjectError(`pageContext couldn't be fetched from server: an error occurred on the server-side (see your server logs)`);
|
|
225
225
|
}
|
|
226
226
|
assert(hasProp(pageContextFromServer, '_pageId', 'string'));
|
|
227
227
|
processPageContextFromServer(pageContextFromServer);
|
|
@@ -51,7 +51,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
51
51
|
const hook = onPageTransitionStartHook;
|
|
52
52
|
const { hookFn } = hook;
|
|
53
53
|
try {
|
|
54
|
-
await executeHook(() => hookFn(pageContext), hook);
|
|
54
|
+
await executeHook(() => hookFn(pageContext), hook, pageContext);
|
|
55
55
|
}
|
|
56
56
|
catch (err) {
|
|
57
57
|
await onError(err);
|
|
@@ -353,7 +353,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
353
353
|
if (hook) {
|
|
354
354
|
const { hookFn } = hook;
|
|
355
355
|
try {
|
|
356
|
-
await executeHook(() => hookFn(pageContext), hook);
|
|
356
|
+
await executeHook(() => hookFn(pageContext), hook, pageContext);
|
|
357
357
|
}
|
|
358
358
|
catch (err) {
|
|
359
359
|
await onError(err);
|
|
@@ -377,7 +377,7 @@ async function renderPageClientSide(renderArgs) {
|
|
|
377
377
|
if (hook) {
|
|
378
378
|
const { hookFn } = hook;
|
|
379
379
|
try {
|
|
380
|
-
await executeHook(() => hookFn(pageContext), hook);
|
|
380
|
+
await executeHook(() => hookFn(pageContext), hook, pageContext);
|
|
381
381
|
}
|
|
382
382
|
catch (err) {
|
|
383
383
|
await onError(err);
|
|
@@ -16,3 +16,4 @@ export * from '../../utils/parseUrl.js';
|
|
|
16
16
|
export * from '../../utils/projectInfo.js';
|
|
17
17
|
export * from '../../utils/slice.js';
|
|
18
18
|
export * from '../../utils/unique.js'; // Only used by Server Routing (not needed for Client Routing)
|
|
19
|
+
export * from '../../utils/getPropAccessNotation.js';
|
|
@@ -45,7 +45,7 @@ async function executeOnRenderClientHook(pageContext, isClientRouting) {
|
|
|
45
45
|
const renderHook = hook.hookFn;
|
|
46
46
|
assert(hookName);
|
|
47
47
|
// We don't use a try-catch wrapper because rendering errors are usually handled by the UI framework. (E.g. React's Error Boundaries.)
|
|
48
|
-
const hookResult = await executeHook(() => renderHook(pageContextForUserConsumption), hook);
|
|
48
|
+
const hookResult = await executeHook(() => renderHook(pageContextForUserConsumption), hook, pageContext);
|
|
49
49
|
assertUsage(hookResult === undefined, `The ${hookName}() hook defined by ${hook.hookFilePath} isn't allowed to return a value`);
|
|
50
50
|
}
|
|
51
51
|
function getUrlToShowToUser(pageContext) {
|
|
@@ -5,7 +5,8 @@ type PageContextForPassToClientWarning = {
|
|
|
5
5
|
_hasPageContextFromClient: boolean;
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
* -
|
|
8
|
+
* Throw error when pageContext value isn't:
|
|
9
|
+
* - serializable, or
|
|
10
|
+
* - defined.
|
|
10
11
|
*/
|
|
11
12
|
declare function getPageContextProxyForUser<PageContext extends Record<string, unknown> & PageContextForPassToClientWarning>(pageContext: PageContext): PageContext;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export { getPageContextProxyForUser };
|
|
2
|
-
import { assert, assertUsage, assertWarning, getGlobalObject } from '../server-routing-runtime/utils.js';
|
|
2
|
+
import { assert, assertUsage, assertWarning, getGlobalObject, getPropAccessNotation } from '../server-routing-runtime/utils.js';
|
|
3
3
|
import { notSerializable } from '../../shared/notSerializable.js';
|
|
4
4
|
const globalObject = getGlobalObject('getPageContextProxyForUser.ts', {});
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
6
|
+
* Throw error when pageContext value isn't:
|
|
7
|
+
* - serializable, or
|
|
8
|
+
* - defined.
|
|
8
9
|
*/
|
|
9
10
|
function getPageContextProxyForUser(pageContext) {
|
|
10
11
|
assert([true, false].includes(pageContext._hasPageContextFromServer));
|
|
@@ -12,66 +13,45 @@ function getPageContextProxyForUser(pageContext) {
|
|
|
12
13
|
return new Proxy(pageContext, {
|
|
13
14
|
get(_, prop) {
|
|
14
15
|
const val = pageContext[prop];
|
|
15
|
-
const propName =
|
|
16
|
-
assertUsage(val !== notSerializable, `pageContext
|
|
17
|
-
|
|
16
|
+
const propName = getPropAccessNotation(prop);
|
|
17
|
+
assertUsage(val !== notSerializable, `pageContext${propName} couldn't be serialized and, therefore, is missing on the client-side. Check the server logs for more information.`);
|
|
18
|
+
passToClientHint(pageContext, prop, propName);
|
|
18
19
|
return val;
|
|
19
20
|
}
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
|
-
function
|
|
23
|
-
|
|
24
|
-
// - Vue tries to read its old value first. This triggers a `assertIsDefined()` failure if e.g. `pageContextOldReactive.routeParams = pageContextNew.routeParams` and `pageContextOldReactive` has no `routeParams`.
|
|
25
|
-
// - Vue seems to read __v_raw before reading the property
|
|
26
|
-
if (globalObject.prev === prop || globalObject.prev === '__v_raw')
|
|
23
|
+
function passToClientHint(pageContext, prop, propName) {
|
|
24
|
+
if (handleVueReactivity(prop))
|
|
27
25
|
return;
|
|
28
|
-
|
|
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
|
+
// ```
|
|
29
30
|
if (prop in pageContext)
|
|
30
31
|
return;
|
|
31
|
-
if (
|
|
32
|
+
if (isWhitelisted(prop))
|
|
32
33
|
return;
|
|
33
|
-
//
|
|
34
|
-
// -
|
|
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.
|
|
35
36
|
if (!pageContext._hasPageContextFromServer)
|
|
36
37
|
return;
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
*/
|
|
44
|
-
if (!pageContext._hasPageContextFromClient) {
|
|
45
|
-
// We can safely assume that the property is missing in passToClient, because the server-side defines all passToClient properties even if they have an undefined value:
|
|
46
|
-
// ```
|
|
47
|
-
// <script id="vike_pageContext" type="application/json">{"_pageId":"/pages/admin","user":"!undefined","pageProps":"!undefined","title":"!undefined","abortReason":"!undefined","_urlRewrite":null}</script>
|
|
48
|
-
// ```
|
|
49
|
-
// Note how properties have "!undefined" values => we can tell whether an undefined pageContext value exists in passToClient.
|
|
50
|
-
assertUsage(false, `pageContext[${propName}] isn't available on the client-side because ${propName} is missing in passToClient, see https://vike.dev/passToClient`);
|
|
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 });
|
|
51
44
|
}
|
|
52
45
|
else {
|
|
53
|
-
|
|
54
|
-
// TODO/next-major-release make it an assertUsage()
|
|
55
|
-
assertWarning(false, [
|
|
56
|
-
`pageContext[${propName}] isn't defined on the client-side:`,
|
|
57
|
-
`1. if it's defined by the server-side then add ${propName} to passToClient (https://vike.dev/passToClient), or`,
|
|
58
|
-
`2. if it's expected that it may not be defined:`,
|
|
59
|
-
' ```js',
|
|
60
|
-
' // ❌ Replace code like this:',
|
|
61
|
-
` const val = pageContext[${propName}] ?? someDefaultValue`,
|
|
62
|
-
' // ✅ With that:',
|
|
63
|
-
` const val = ${propName} in pageContext ? pageContext[${propName}] : someDefaultValue`,
|
|
64
|
-
' ```',
|
|
65
|
-
`See stack track below to find where pageContext[${propName}] is being accessed.`
|
|
66
|
-
].join('\n'), { showStackTrace: true, onlyOnce: false });
|
|
46
|
+
assertUsage(false, errMsg);
|
|
67
47
|
}
|
|
68
48
|
}
|
|
69
|
-
const
|
|
49
|
+
const WHITELIST = [
|
|
70
50
|
'then',
|
|
71
|
-
'toJSON' // Vue
|
|
51
|
+
'toJSON' // Vue triggers `toJSON`
|
|
72
52
|
];
|
|
73
|
-
function
|
|
74
|
-
if (
|
|
53
|
+
function isWhitelisted(prop) {
|
|
54
|
+
if (WHITELIST.includes(prop))
|
|
75
55
|
return true;
|
|
76
56
|
if (typeof prop === 'symbol')
|
|
77
57
|
return true; // Vue tries to access some symbols
|
|
@@ -81,9 +61,16 @@ function isExpected(prop) {
|
|
|
81
61
|
return true; // Vue internals upon `reactive(pageContext)`
|
|
82
62
|
return false;
|
|
83
63
|
}
|
|
84
|
-
|
|
64
|
+
// Handle Vue's reactivity.
|
|
65
|
+
// When changing a reactive object:
|
|
66
|
+
// - 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`.
|
|
67
|
+
// - Vue seems to read __v_raw before reading the property.
|
|
68
|
+
function handleVueReactivity(prop) {
|
|
69
|
+
if (globalObject.prev === prop || globalObject.prev === '__v_raw')
|
|
70
|
+
return true;
|
|
85
71
|
globalObject.prev = prop;
|
|
86
72
|
window.setTimeout(() => {
|
|
87
73
|
globalObject.prev = undefined;
|
|
88
74
|
}, 0);
|
|
75
|
+
return false;
|
|
89
76
|
}
|
|
@@ -101,7 +101,7 @@ function extractAssetsPlugin() {
|
|
|
101
101
|
}
|
|
102
102
|
// If the import path resolves to a file in `node_modules/`, we ignore that file:
|
|
103
103
|
// - Direct CSS dependencies are included though, such as `import 'bootstrap/theme/dark.css'`. (Because the above if-branch for CSS files will add the file.)
|
|
104
|
-
// - Loading CSS from a library (living in `node_modules/`) in a non-direct way is
|
|
104
|
+
// - Loading CSS from a library (living in `node_modules/`) in a non-direct way is unconventional; we can safely not support this case. (I'm not aware of any library that does this.)
|
|
105
105
|
assertPosixPath(file);
|
|
106
106
|
if (file.includes('/node_modules/')) {
|
|
107
107
|
return emptyModule(file, importer);
|
|
@@ -892,7 +892,7 @@ function getConfigValues(configValueSources, configValuesComputed, configDefinit
|
|
|
892
892
|
const configValueSource = sources[0];
|
|
893
893
|
if ('value' in configValueSource) {
|
|
894
894
|
configValues[configName] = {
|
|
895
|
-
type: '
|
|
895
|
+
type: 'standard',
|
|
896
896
|
value: configValueSource.value,
|
|
897
897
|
definedAtData: getDefinedAtFile(configValueSource)
|
|
898
898
|
};
|
|
@@ -217,7 +217,7 @@ async function callOnBeforePrerenderStartHooks(prerenderContext, renderContext,
|
|
|
217
217
|
if (doNotPrerenderList.find((p) => p.pageId === pageId)) {
|
|
218
218
|
return;
|
|
219
219
|
}
|
|
220
|
-
const prerenderResult = await executeHook(() => hookFn(), { hookName, hookFilePath, hookTimeout });
|
|
220
|
+
const prerenderResult = await executeHook(() => hookFn(), { hookName, hookFilePath, hookTimeout }, null);
|
|
221
221
|
const result = normalizeOnPrerenderHookResult(prerenderResult, hookFilePath, hookName);
|
|
222
222
|
result.forEach(({ url, pageContext }) => {
|
|
223
223
|
{
|
|
@@ -392,7 +392,7 @@ async function callOnPrerenderStartHook(prerenderContext, renderContext) {
|
|
|
392
392
|
});
|
|
393
393
|
return prerenderContext.pageContexts;
|
|
394
394
|
}
|
|
395
|
-
}), onPrerenderStartHook);
|
|
395
|
+
}), onPrerenderStartHook, null);
|
|
396
396
|
if (result === null || result === undefined) {
|
|
397
397
|
return;
|
|
398
398
|
}
|
|
@@ -80,5 +80,5 @@ type StreamPipeWrapped = {
|
|
|
80
80
|
};
|
|
81
81
|
declare function pipeStream(pipe: StreamPipe): StreamPipeWrapped;
|
|
82
82
|
declare function streamToString(stream: StreamProviderAny): Promise<string>;
|
|
83
|
-
declare function getStreamName(
|
|
83
|
+
declare function getStreamName(kind: 'pipe' | 'readable' | 'writable', type: 'web' | 'node'): `a ${string} Stream` | `a ${string} Stream Pipe`;
|
|
84
84
|
declare function inferStreamName(stream: StreamProviderNormalized): `a ${string} Stream` | `a ${string} Stream Pipe`;
|
|
@@ -758,17 +758,17 @@ async function loadStreamNodeModule() {
|
|
|
758
758
|
const { Readable, Writable } = streamModule;
|
|
759
759
|
return { Readable, Writable };
|
|
760
760
|
}
|
|
761
|
-
function getStreamName(
|
|
762
|
-
let
|
|
763
|
-
if (
|
|
764
|
-
|
|
761
|
+
function getStreamName(kind, type) {
|
|
762
|
+
let typeName = capitalizeFirstLetter(type);
|
|
763
|
+
if (typeName === 'Node') {
|
|
764
|
+
typeName = 'Node.js';
|
|
765
765
|
}
|
|
766
|
-
const
|
|
767
|
-
if (
|
|
768
|
-
return `a ${
|
|
766
|
+
const kindName = capitalizeFirstLetter(kind);
|
|
767
|
+
if (kind !== 'pipe') {
|
|
768
|
+
return `a ${kindName} ${typeName} Stream`;
|
|
769
769
|
}
|
|
770
|
-
if (
|
|
771
|
-
return `a ${
|
|
770
|
+
if (kind === 'pipe') {
|
|
771
|
+
return `a ${typeName} Stream Pipe`;
|
|
772
772
|
}
|
|
773
773
|
assert(false);
|
|
774
774
|
}
|
|
@@ -14,7 +14,7 @@ async function executeOnBeforeRenderAndDataHooks(pageContext) {
|
|
|
14
14
|
}
|
|
15
15
|
preparePageContextForUserConsumptionServerSide(pageContext);
|
|
16
16
|
if (dataHook) {
|
|
17
|
-
const hookResult = await executeHook(() => dataHook.hookFn(pageContext), dataHook);
|
|
17
|
+
const hookResult = await executeHook(() => dataHook.hookFn(pageContext), dataHook, pageContext);
|
|
18
18
|
// Note: hookResult can be anything (e.g. an object) and is to be assigned to pageContext.data
|
|
19
19
|
const pageContextFromHook = {
|
|
20
20
|
data: hookResult
|
|
@@ -22,7 +22,7 @@ async function executeOnBeforeRenderAndDataHooks(pageContext) {
|
|
|
22
22
|
Object.assign(pageContext, pageContextFromHook);
|
|
23
23
|
}
|
|
24
24
|
if (onBeforeRenderHook) {
|
|
25
|
-
const hookResult = await executeHook(() => onBeforeRenderHook.hookFn(pageContext), onBeforeRenderHook);
|
|
25
|
+
const hookResult = await executeHook(() => onBeforeRenderHook.hookFn(pageContext), onBeforeRenderHook, pageContext);
|
|
26
26
|
assertOnBeforeRenderHookReturn(hookResult, onBeforeRenderHook.hookFilePath);
|
|
27
27
|
const pageContextFromHook = hookResult?.pageContext;
|
|
28
28
|
Object.assign(pageContext, pageContextFromHook);
|
|
@@ -13,7 +13,7 @@ async function executeOnRenderHtmlHook(pageContext) {
|
|
|
13
13
|
const { renderHook, hookFn } = getRenderHook(pageContext);
|
|
14
14
|
objectAssign(pageContext, { _renderHook: renderHook });
|
|
15
15
|
preparePageContextForUserConsumptionServerSide(pageContext);
|
|
16
|
-
const hookReturnValue = await executeHook(() => hookFn(pageContext), renderHook);
|
|
16
|
+
const hookReturnValue = await executeHook(() => hookFn(pageContext), renderHook, pageContext);
|
|
17
17
|
const { documentHtml, pageContextProvidedByRenderHook, pageContextPromise, injectFilter } = processHookReturnValue(hookReturnValue, renderHook);
|
|
18
18
|
Object.assign(pageContext, pageContextProvidedByRenderHook);
|
|
19
19
|
objectAssign(pageContext, { _pageContextPromise: pageContextPromise });
|
|
@@ -95,8 +95,8 @@ function getHttpResponseBodyStreamHandlers(htmlRender, renderHook) {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
};
|
|
98
|
-
function getFixMsg(
|
|
99
|
-
const streamName = getStreamName(
|
|
98
|
+
function getFixMsg(kind, type) {
|
|
99
|
+
const streamName = getStreamName(kind, type);
|
|
100
100
|
assert(['a ', 'an ', 'the '].some((s) => streamName.startsWith(s)));
|
|
101
101
|
assert(renderHook);
|
|
102
102
|
const { hookFilePath, hookName } = renderHook;
|
|
@@ -9,6 +9,7 @@ declare global {
|
|
|
9
9
|
* - You can refine the type of `Config['Page']`.
|
|
10
10
|
* - You can define the type of custom configurations created with `config.meta` (https://vike.dev/meta)
|
|
11
11
|
*
|
|
12
|
+
* https://vike.dev/meta#typescript
|
|
12
13
|
*/
|
|
13
14
|
interface Config {
|
|
14
15
|
}
|
|
@@ -22,6 +23,14 @@ declare global {
|
|
|
22
23
|
*/
|
|
23
24
|
interface PageContext {
|
|
24
25
|
}
|
|
26
|
+
/** Refine the `pageContext.config` type.
|
|
27
|
+
*
|
|
28
|
+
* It's used for cumulative configs: the `pageContext.config[configName]` type is an `array` whereas `Config[configName]` isn't.
|
|
29
|
+
*
|
|
30
|
+
* https://vike.dev/meta#typescript
|
|
31
|
+
*/
|
|
32
|
+
interface ConfigResolved {
|
|
33
|
+
}
|
|
25
34
|
}
|
|
26
35
|
/** This namespace is only used by:
|
|
27
36
|
* - `vike-react`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getPageContext } from './hooks/executeHook.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getPageContext } from './hooks/executeHook.js';
|
|
@@ -41,8 +41,8 @@ type PageContextExports = {
|
|
|
41
41
|
pageExports: Record<string, unknown>;
|
|
42
42
|
};
|
|
43
43
|
type From = {
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
configsStandard: Record<string, // configName
|
|
45
|
+
SourceConfigsStandard>;
|
|
46
46
|
configsCumulative: Record<string, // configName
|
|
47
47
|
SourceConfigsCumulative>;
|
|
48
48
|
configsComputed: Record<string, // configName
|
|
@@ -53,9 +53,9 @@ SourceAny>;
|
|
|
53
53
|
type Sources = Record<string, // configName
|
|
54
54
|
SourceAny[]>;
|
|
55
55
|
type SourceAny = SourceConfigs;
|
|
56
|
-
type SourceConfigs =
|
|
57
|
-
type
|
|
58
|
-
type: '
|
|
56
|
+
type SourceConfigs = SourceConfigsStandard | SourceConfigsCumulative | SourceConfigsComputed;
|
|
57
|
+
type SourceConfigsStandard = {
|
|
58
|
+
type: 'configsStandard';
|
|
59
59
|
value: unknown;
|
|
60
60
|
definedAt: string;
|
|
61
61
|
};
|
|
@@ -35,7 +35,7 @@ function getPageContextExports(pageFiles, pageConfig) {
|
|
|
35
35
|
sources[configName].push(src);
|
|
36
36
|
};
|
|
37
37
|
const from = {
|
|
38
|
-
|
|
38
|
+
configsStandard: {},
|
|
39
39
|
configsCumulative: {},
|
|
40
40
|
configsComputed: {}
|
|
41
41
|
};
|
|
@@ -53,6 +53,15 @@ function getPageContextExports(pageFiles, pageConfig) {
|
|
|
53
53
|
configDefinedAt,
|
|
54
54
|
configDefinedByFile: configValueFilePathToShowToUser
|
|
55
55
|
});
|
|
56
|
+
if (configValue.type === 'standard') {
|
|
57
|
+
const src = {
|
|
58
|
+
type: 'configsStandard',
|
|
59
|
+
value: configValue.value,
|
|
60
|
+
definedAt: getDefinedAtString(configValue.definedAtData, configName)
|
|
61
|
+
};
|
|
62
|
+
addSrc(src, configName);
|
|
63
|
+
from.configsStandard[configName] = src;
|
|
64
|
+
}
|
|
56
65
|
if (configValue.type === 'cumulative') {
|
|
57
66
|
const src = {
|
|
58
67
|
type: 'configsCumulative',
|
|
@@ -69,15 +78,6 @@ function getPageContextExports(pageFiles, pageConfig) {
|
|
|
69
78
|
addSrc(src, configName);
|
|
70
79
|
from.configsCumulative[configName] = src;
|
|
71
80
|
}
|
|
72
|
-
if (configValue.type === 'classic') {
|
|
73
|
-
const src = {
|
|
74
|
-
type: 'configsOverridable',
|
|
75
|
-
value: configValue.value,
|
|
76
|
-
definedAt: getDefinedAtString(configValue.definedAtData, configName)
|
|
77
|
-
};
|
|
78
|
-
addSrc(src, configName);
|
|
79
|
-
from.configsOverridable[configName] = src;
|
|
80
|
-
}
|
|
81
81
|
if (configValue.type === 'computed') {
|
|
82
82
|
const src = {
|
|
83
83
|
type: 'configsComputed',
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
export { executeHook };
|
|
2
|
+
export { getPageContext };
|
|
2
3
|
export { isUserHookError };
|
|
4
|
+
import type { PageContextClient, PageContextServer } from '../types.js';
|
|
3
5
|
import type { Hook, HookLoc } from './getHook.js';
|
|
6
|
+
type PageContextUnknown = null | Record<string, unknown>;
|
|
4
7
|
declare function isUserHookError(err: unknown): false | HookLoc;
|
|
5
|
-
declare function executeHook<T = unknown>(hookFnCaller: () => T, hook: Omit<Hook, 'hookFn'
|
|
8
|
+
declare function executeHook<T = unknown>(hookFnCaller: () => T, hook: Omit<Hook, 'hookFn'>, pageContext: PageContextUnknown): Promise<T>;
|
|
9
|
+
/**
|
|
10
|
+
* Access `pageContext` object inside Vike hooks, in order to create universal hooks.
|
|
11
|
+
*
|
|
12
|
+
* https://vike.dev/getPageContext
|
|
13
|
+
*/
|
|
14
|
+
declare function getPageContext<PageContext = PageContextClient | PageContextServer>(): null | PageContext;
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
export { executeHook };
|
|
2
|
+
export { getPageContext };
|
|
2
3
|
export { isUserHookError };
|
|
3
4
|
import { getProjectError, assertWarning } from '../../utils/assert.js';
|
|
4
5
|
import { getGlobalObject } from '../../utils/getGlobalObject.js';
|
|
5
6
|
import { humanizeTime } from '../../utils/humanizeTime.js';
|
|
6
7
|
import { isObject } from '../../utils/isObject.js';
|
|
7
8
|
const globalObject = getGlobalObject('utils/executeHook.ts', {
|
|
8
|
-
userHookErrors: new WeakMap()
|
|
9
|
+
userHookErrors: new WeakMap(),
|
|
10
|
+
pageContext: null
|
|
9
11
|
});
|
|
10
12
|
function isUserHookError(err) {
|
|
11
13
|
if (!isObject(err))
|
|
12
14
|
return false;
|
|
13
15
|
return globalObject.userHookErrors.get(err) ?? false;
|
|
14
16
|
}
|
|
15
|
-
function executeHook(hookFnCaller, hook) {
|
|
17
|
+
function executeHook(hookFnCaller, hook, pageContext) {
|
|
16
18
|
const { hookName, hookFilePath, hookTimeout: { error: timeoutErr, warning: timeoutWarn } } = hook;
|
|
17
19
|
let resolve;
|
|
18
20
|
let reject;
|
|
@@ -43,6 +45,7 @@ function executeHook(hookFnCaller, hook) {
|
|
|
43
45
|
}, timeoutErr);
|
|
44
46
|
(async () => {
|
|
45
47
|
try {
|
|
48
|
+
providePageContext(pageContext);
|
|
46
49
|
const ret = await hookFnCaller();
|
|
47
50
|
resolve(ret);
|
|
48
51
|
}
|
|
@@ -58,3 +61,19 @@ function executeHook(hookFnCaller, hook) {
|
|
|
58
61
|
function isNotDisabled(timeout) {
|
|
59
62
|
return !!timeout && timeout !== Infinity;
|
|
60
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Access `pageContext` object inside Vike hooks, in order to create universal hooks.
|
|
66
|
+
*
|
|
67
|
+
* https://vike.dev/getPageContext
|
|
68
|
+
*/
|
|
69
|
+
function getPageContext() {
|
|
70
|
+
return globalObject.pageContext;
|
|
71
|
+
}
|
|
72
|
+
function providePageContext(pageContext) {
|
|
73
|
+
globalObject.pageContext = pageContext;
|
|
74
|
+
// Promise.resolve() is quicker than process.nextTick() and setImmediate()
|
|
75
|
+
// https://stackoverflow.com/questions/67949576/process-nexttick-before-promise-resolve-then
|
|
76
|
+
Promise.resolve().then(() => {
|
|
77
|
+
globalObject.pageContext = null;
|
|
78
|
+
});
|
|
79
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export type { PageContextConfig };
|
|
2
2
|
import type { VikePackages } from '../../VikeNamespace.js';
|
|
3
3
|
import type { ConfigBuiltIn } from '../Config.js';
|
|
4
|
-
import type { Combine, IsNotEmpty, XOR5 } from './helpers.
|
|
5
|
-
type PageContextConfig = ConfigBuiltIn & Vike.Config & (ConfigVikePackagesNotEmptyXor extends true ? ConfigVikePackagesIntersection : ConfigVikePackagesCombined);
|
|
4
|
+
import type { Combine, IsNotEmpty, XOR5 } from './helpers.js';
|
|
5
|
+
type PageContextConfig = ConfigBuiltIn & Vike.ConfigResolved & Omit<Vike.Config, keyof Vike.ConfigResolved> & (ConfigVikePackagesNotEmptyXor extends true ? ConfigVikePackagesIntersection : ConfigVikePackagesCombined);
|
|
6
6
|
type ConfigVikePackagesIntersection = VikePackages.ConfigVikeReact & VikePackages.ConfigVikeVue & VikePackages.ConfigVikeSolid & VikePackages.ConfigVikeSvelte & VikePackages.ConfigVikeAngular;
|
|
7
7
|
type ConfigVikePackagesCombined = Combine<VikePackages.ConfigVikeReact, Combine<VikePackages.ConfigVikeVue, Combine<VikePackages.ConfigVikeSolid, Combine<VikePackages.ConfigVikeSvelte, VikePackages.ConfigVikeAngular>>>>;
|
|
8
8
|
type ConfigVikePackagesNotEmptyXor = XOR5<IsNotEmpty<VikePackages.ConfigVikeReact>, IsNotEmpty<VikePackages.ConfigVikeVue>, IsNotEmpty<VikePackages.ConfigVikeSolid>, IsNotEmpty<VikePackages.ConfigVikeSvelte>, IsNotEmpty<VikePackages.ConfigVikeAngular>>;
|
|
@@ -6,7 +6,7 @@ export type { ConfigEnvInternal };
|
|
|
6
6
|
export type { PageConfigGlobalRuntime };
|
|
7
7
|
export type { PageConfigGlobalBuildTime };
|
|
8
8
|
export type { ConfigValue };
|
|
9
|
-
export type {
|
|
9
|
+
export type { ConfigValueStandard };
|
|
10
10
|
export type { ConfigValueCumulative };
|
|
11
11
|
export type { ConfigValueComputed };
|
|
12
12
|
export type { ConfigValues };
|
|
@@ -86,10 +86,10 @@ type ConfigValuesComputed = Record<string, {
|
|
|
86
86
|
configEnv: ConfigEnvInternal;
|
|
87
87
|
value: unknown;
|
|
88
88
|
}>;
|
|
89
|
-
type ConfigValue =
|
|
89
|
+
type ConfigValue = ConfigValueStandard | ConfigValueCumulative | ConfigValueComputed;
|
|
90
90
|
/** Defined by a unique source (thus unique file path). */
|
|
91
|
-
type
|
|
92
|
-
type: '
|
|
91
|
+
type ConfigValueStandard = {
|
|
92
|
+
type: 'standard';
|
|
93
93
|
value: unknown;
|
|
94
94
|
definedAtData: DefinedAtFile;
|
|
95
95
|
};
|
|
@@ -2,7 +2,7 @@ export type { PageConfigRuntimeSerialized };
|
|
|
2
2
|
export type { PageConfigGlobalRuntimeSerialized };
|
|
3
3
|
export type { ConfigValueSerialized };
|
|
4
4
|
export type { ConfigValueImported };
|
|
5
|
-
import type {
|
|
5
|
+
import type { ConfigValueStandard, ConfigValueComputed, ConfigValueCumulative, PageConfigRuntime } from '../PageConfig.js';
|
|
6
6
|
/** Page config data structure serialized in virtual files: parsing it results in PageConfigRuntime */
|
|
7
7
|
type PageConfigRuntimeSerialized = Omit<PageConfigRuntime, 'configValues'> & {
|
|
8
8
|
/** Config values that are serializable and loaded eagerly such as config.passToClient */
|
|
@@ -14,7 +14,7 @@ type PageConfigGlobalRuntimeSerialized = {
|
|
|
14
14
|
configValuesImported: ConfigValueImported[];
|
|
15
15
|
};
|
|
16
16
|
/** Value is serialized */
|
|
17
|
-
type ConfigValueSerialized = (Omit<
|
|
17
|
+
type ConfigValueSerialized = (Omit<ConfigValueStandard, 'value'> & {
|
|
18
18
|
valueSerialized: string;
|
|
19
19
|
}) | (Omit<ConfigValueCumulative, 'value'> & {
|
|
20
20
|
valueSerialized: string;
|
|
@@ -51,7 +51,7 @@ function parseConfigValuesImported(configValuesImported) {
|
|
|
51
51
|
assert(val);
|
|
52
52
|
const { value, importPath, exportName } = val;
|
|
53
53
|
configValues[configName] = {
|
|
54
|
-
type: '
|
|
54
|
+
type: 'standard',
|
|
55
55
|
value,
|
|
56
56
|
definedAtData: {
|
|
57
57
|
// importPath cannot be relative to the current file, since the current file is a virtual file
|
|
@@ -21,7 +21,7 @@ async function executeGuardHook(pageContext, prepareForUserConsumption) {
|
|
|
21
21
|
const res = prepareForUserConsumption(pageContext);
|
|
22
22
|
if (res)
|
|
23
23
|
pageContextForUserConsumption = res;
|
|
24
|
-
const hookResult = await executeHook(() => guard(pageContextForUserConsumption), hook);
|
|
24
|
+
const hookResult = await executeHook(() => guard(pageContextForUserConsumption), hook, pageContext);
|
|
25
25
|
assertUsage(hookResult === undefined, `${errIntro} ${hook.hookFilePath} returns a value, but guard() shouldn't return any value`);
|
|
26
26
|
}
|
|
27
27
|
function findPageGuard(pageId, pageFilesAll) {
|
|
@@ -36,7 +36,7 @@ async function getPageContextFromHook(onBeforeRouteHook, pageContext) {
|
|
|
36
36
|
let hookReturn = onBeforeRouteHook.hookFn(pageContext);
|
|
37
37
|
assertSyncRouting(hookReturn, `The onBeforeRoute() hook ${onBeforeRouteHook.hookFilePath}`);
|
|
38
38
|
// TODO/v1-release: make executeOnBeforeRouteHook() and route() sync
|
|
39
|
-
hookReturn = await executeHook(() => hookReturn, onBeforeRouteHook);
|
|
39
|
+
hookReturn = await executeHook(() => hookReturn, onBeforeRouteHook, pageContext);
|
|
40
40
|
const errPrefix = `The onBeforeRoute() hook defined by ${onBeforeRouteHook.hookFilePath}`;
|
|
41
41
|
assertUsage(hookReturn === null ||
|
|
42
42
|
hookReturn === undefined ||
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
declare function getPropAccessNotation(key: string): `.${string}` | `[${string}]`;
|
|
1
|
+
export declare function getPropAccessNotation(key: unknown): `.${string}` | `[${string}]`;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
return isKeyDotNotationCompatible(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
|
|
4
|
-
}
|
|
5
|
-
function isKeyDotNotationCompatible(key) {
|
|
6
|
-
return /^[a-z0-9\$_]+$/i.test(key);
|
|
1
|
+
export function getPropAccessNotation(key) {
|
|
2
|
+
return typeof key === 'string' && /^[a-z0-9\$_]+$/i.test(key) ? `.${key}` : `[${JSON.stringify(key)}]`;
|
|
7
3
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { projectInfo };
|
|
2
2
|
export { PROJECT_VERSION };
|
|
3
|
-
declare const PROJECT_VERSION: "0.4.171-commit-
|
|
3
|
+
declare const PROJECT_VERSION: "0.4.171-commit-978d69d";
|
|
4
4
|
declare const projectInfo: {
|
|
5
5
|
projectName: "Vike";
|
|
6
|
-
projectVersion: "0.4.171-commit-
|
|
6
|
+
projectVersion: "0.4.171-commit-978d69d";
|
|
7
7
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vike",
|
|
3
|
-
"version": "0.4.171-commit-
|
|
3
|
+
"version": "0.4.171-commit-978d69d",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "tsc --watch",
|
|
6
6
|
"build": "rimraf dist/ && pnpm run build:esm && pnpm run build:cjs",
|
|
@@ -106,6 +106,15 @@
|
|
|
106
106
|
"types": "./dist/esm/shared/abort.d.ts",
|
|
107
107
|
"default": "./dist/esm/shared/abort.js"
|
|
108
108
|
},
|
|
109
|
+
"./getPageContext": {
|
|
110
|
+
"worker": "./dist/esm/shared/getPageContext.js",
|
|
111
|
+
"edge-light": "./dist/esm/shared/getPageContext.js",
|
|
112
|
+
"require": "./dist/cjs/shared/getPageContext.js",
|
|
113
|
+
"node": "./dist/esm/shared/getPageContext.js",
|
|
114
|
+
"browser": "./dist/esm/shared/getPageContext.js",
|
|
115
|
+
"types": "./dist/esm/shared/getPageContext.d.ts",
|
|
116
|
+
"default": "./dist/esm/shared/getPageContext.js"
|
|
117
|
+
},
|
|
109
118
|
"./__internal": {
|
|
110
119
|
"require": "./dist/cjs/__internal/index.js",
|
|
111
120
|
"node": "./dist/esm/__internal/index.js",
|