vike
Version:
The Framework *You* Control - Next.js & Nuxt alternative for unprecedented flexibility and dependability.
131 lines (130 loc) • 7.7 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.execHookOnRenderHtml = execHookOnRenderHtml;
const renderHtml_js_1 = require("../html/renderHtml.js");
const getHook_js_1 = require("../../../shared/hooks/getHook.js");
const utils_js_1 = require("../utils.js");
const stream_js_1 = require("../html/stream.js");
const assertPageContextProvidedByUser_js_1 = require("../../../shared/assertPageContextProvidedByUser.js");
const preparePageContextForPublicUsageServer_js_1 = require("./preparePageContextForPublicUsageServer.js");
const assertHookReturnedObject_js_1 = require("../../../shared/assertHookReturnedObject.js");
const loggerRuntime_js_1 = require("../loggerRuntime.js");
const picocolors_1 = __importDefault(require("@brillout/picocolors"));
const execHook_js_1 = require("../../../shared/hooks/execHook.js");
async function execHookOnRenderHtml(pageContext) {
const hook = getRenderHook(pageContext);
(0, utils_js_1.objectAssign)(pageContext, { _renderHook: hook });
const { hookReturn } = await (0, execHook_js_1.execHookDirectSingleWithReturn)(hook, pageContext, preparePageContextForPublicUsageServer_js_1.preparePageContextForPublicUsageServer);
const { documentHtml, pageContextProvidedByRenderHook, pageContextPromise, injectFilter } = processHookReturnValue(hookReturn, hook);
Object.assign(pageContext, pageContextProvidedByRenderHook);
(0, utils_js_1.objectAssign)(pageContext, { _pageContextPromise: pageContextPromise });
const onErrorWhileStreaming = (err) => {
// Should the stream inject the following?
// ```
// <script>console.error("An error occurred on the server side while streaming the page to HTML, see server logs.")</script>
// ```
(0, loggerRuntime_js_1.logRuntimeError)(err, pageContext._httpRequestId);
if (!pageContext.errorWhileRendering) {
pageContext.errorWhileRendering = err;
}
};
const htmlRender = await (0, renderHtml_js_1.renderDocumentHtml)(documentHtml, pageContext, onErrorWhileStreaming, injectFilter);
(0, utils_js_1.assert)(typeof htmlRender === 'string' || (0, stream_js_1.isStream)(htmlRender));
return { htmlRender, renderHook: hook };
}
function getRenderHook(pageContext) {
let hookFound;
{
let hook;
let hookName = undefined;
hook = (0, getHook_js_1.getHookFromPageContext)(pageContext, 'onRenderHtml');
if (hook) {
hookName = 'onRenderHtml';
}
else {
hook = (0, getHook_js_1.getHookFromPageContext)(pageContext, 'render');
if (hook) {
hookName = 'render';
}
}
if (hook) {
(0, utils_js_1.assert)(hookName);
const { hookFilePath, hookFn, hookTimeout } = hook;
hookFound = { hookFn, hookFilePath, hookName, hookTimeout };
}
}
if (!hookFound) {
const hookName = pageContext._globalContext._pageConfigs.length > 0 ? 'onRenderHtml' : 'render';
(0, utils_js_1.assertUsage)(false, [
`No ${hookName}() hook found, see https://vike.dev/${hookName}`,
/*
'See https://vike.dev/render-modes for more information.',
[
// 'Loaded config files (none of them define the onRenderHtml() hook):',
'Loaded server-side page files (none of them `export { render }`):',
...pageContext._pageFilePathsLoaded.map((f, i) => ` (${i + 1}): ${f}`)
].join('\n')
*/
].join(' '));
}
return hookFound;
}
function processHookReturnValue(hookReturnValue, renderHook) {
let documentHtml;
let pageContextPromise = null;
let pageContextProvidedByRenderHook = null;
let injectFilter = null;
if ((0, renderHtml_js_1.isDocumentHtml)(hookReturnValue)) {
documentHtml = hookReturnValue;
return { documentHtml, pageContextProvidedByRenderHook, pageContextPromise, injectFilter };
}
const errPrefix = `The ${renderHook.hookName}() hook defined at ${renderHook.hookFilePath}`;
const errSuffix = `a string generated with ${picocolors_1.default.cyan('escapeInject`<html>...</html>`')} or the value returned by ${picocolors_1.default.cyan('dangerouslySkipEscape()')}, see https://vike.dev/escapeInject`;
if (typeof hookReturnValue === 'string') {
(0, utils_js_1.assertWarning)(false, [
errPrefix,
`returned a plain JavaScript string which is ${picocolors_1.default.red(picocolors_1.default.bold('dangerous'))}: it should instead return`,
errSuffix,
].join(' '), { onlyOnce: true });
hookReturnValue = (0, renderHtml_js_1.dangerouslySkipEscape)(hookReturnValue);
}
const wrongReturnValue = `should return the value ${picocolors_1.default.cyan('documentHtml')} or an object ${picocolors_1.default.cyan('{ documentHtml }')} where ${picocolors_1.default.cyan('documentHtml')} is ${errSuffix}`;
(0, utils_js_1.assertUsage)((0, utils_js_1.isObject)(hookReturnValue), `${errPrefix} ${wrongReturnValue}`);
(0, assertHookReturnedObject_js_1.assertHookReturnedObject)(hookReturnValue, ['documentHtml', 'pageContext', 'injectFilter'], errPrefix);
(0, utils_js_1.assertUsage)(hookReturnValue.documentHtml, `${errPrefix} returned an object that is missing the ${picocolors_1.default.code('documentHtml')} property: it ${wrongReturnValue}`);
if (hookReturnValue.injectFilter) {
(0, utils_js_1.assertUsage)((0, utils_js_1.isCallable)(hookReturnValue.injectFilter), 'injectFilter should be a function');
injectFilter = hookReturnValue.injectFilter;
}
{
let val = hookReturnValue.documentHtml;
const errBegin = `${errPrefix} returned ${picocolors_1.default.cyan('{ documentHtml }')}, but ${picocolors_1.default.cyan('documentHtml')}`;
if (typeof val === 'string') {
(0, utils_js_1.assertWarning)(false, [
errBegin,
`is a plain JavaScript string which is ${picocolors_1.default.bold(picocolors_1.default.red('dangerous'))}: ${picocolors_1.default.cyan('documentHtml')} should be`,
errSuffix,
].join(' '), { onlyOnce: true });
val = (0, renderHtml_js_1.dangerouslySkipEscape)(val);
}
(0, utils_js_1.assertUsage)((0, renderHtml_js_1.isDocumentHtml)(val), [errBegin, 'should be', errSuffix].join(' '));
documentHtml = val;
}
if (hookReturnValue.pageContext) {
const val = hookReturnValue.pageContext;
const errBegin = `${errPrefix} returned ${picocolors_1.default.cyan('{ pageContext }')}, but ${picocolors_1.default.cyan('pageContext')}`;
if ((0, utils_js_1.isPromise)(val) || (0, utils_js_1.isCallable)(val)) {
(0, utils_js_1.assertWarning)(!(0, utils_js_1.isPromise)(val), `${errBegin} is a promise which is deprecated in favor of async functions, see https://vike.dev/streaming#initial-data-after-stream-end`, { onlyOnce: true });
pageContextPromise = val;
}
else {
(0, utils_js_1.assertUsage)((0, utils_js_1.isObject)(val), `${errBegin} should be an object or an async function, see https://vike.dev/streaming#initial-data-after-stream-end`);
(0, assertPageContextProvidedByUser_js_1.assertPageContextProvidedByUser)(val, renderHook);
pageContextProvidedByRenderHook = val;
}
}
return { documentHtml, pageContextProvidedByRenderHook, pageContextPromise, injectFilter };
}