@modern-js/server-core
Version:
A Progressive React Framework for modern web development.
364 lines (363 loc) • 12.9 kB
JavaScript
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
import { _ as _class_call_check } from "@swc/helpers/_/_class_call_check";
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
import { time } from "@modern-js/runtime-utils/time";
import { isArray, isFunction } from "@modern-js/utils";
import { ServerTimings } from "../../constants";
import { getLoaderCtx } from "../../helper";
import { transformResponse } from "../../utils";
import { createBaseHookContext } from "./base";
import { createAfterStreamingRenderContext, createCustomMiddlewaresCtx, getAfterMatchCtx, getAfterRenderCtx } from "./context";
var noop = function() {
};
var isHtmlResponse = function(response) {
var contentType = response.headers.get("content-type");
return contentType === null || contentType === void 0 ? void 0 : contentType.includes("text/html");
};
var CustomServer = /* @__PURE__ */ function() {
"use strict";
function CustomServer2(hooks, pwd) {
_class_call_check(this, CustomServer2);
this.hooks = hooks;
var webExtension = [];
this.serverMiddlewarePromise = hooks.prepareWebServer.call({
pwd,
config: {
middleware: webExtension
}
});
}
var _proto = CustomServer2.prototype;
_proto.getHookMiddleware = function getHookMiddleware(entryName, routes) {
var _this = this;
return function() {
var _ref = _async_to_generator(function(c, next) {
var routeInfo, monitors, baseHookCtx, afterMatchCtx, getCost, cost, _afterMatchCtx_router, url, status, current, rewriteRoute, afterStreamingRenderContext, afterRenderCtx, getCost1, cost1, newBody;
return _ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
routeInfo = routes.find(function(route) {
return route.entryName === entryName;
});
monitors = c.get("monitors");
baseHookCtx = createBaseHookContext(c);
afterMatchCtx = getAfterMatchCtx(entryName, baseHookCtx);
getCost = time();
return [
4,
_this.hooks.afterMatch.call(afterMatchCtx)
];
case 1:
_state.sent();
cost = getCost();
cost && (monitors === null || monitors === void 0 ? void 0 : monitors.timing(ServerTimings.SERVER_HOOK_AFTER_MATCH, cost));
_afterMatchCtx_router = afterMatchCtx.router, url = _afterMatchCtx_router.url, status = _afterMatchCtx_router.status;
if (url) {
return [
2,
c.redirect(url, status)
];
}
current = afterMatchCtx.router.current;
if (current !== entryName) {
rewriteRoute = routes.find(function(route) {
return route.entryName === current;
});
if (rewriteRoute) {
c.set("matchPathname", rewriteRoute.urlPath);
c.set("matchEntryName", current);
}
}
if (c.finalized) {
return [
2,
void 0
];
}
return [
4,
next()
];
case 2:
_state.sent();
if (c.finalized && (!c.res.body || !isHtmlResponse(c.res) || [
404,
500
].includes(c.res.status))) {
return [
2,
void 0
];
}
if (c.res) {
c.status(c.res.status);
}
if (!routeInfo.isStream)
return [
3,
3
];
afterStreamingRenderContext = createAfterStreamingRenderContext(baseHookCtx, routeInfo);
c.res = transformResponse(c.res, function() {
var _ref2 = _async_to_generator(function(chunk) {
var context, _ref3, newChunk;
return _ts_generator(this, function(_state2) {
switch (_state2.label) {
case 0:
context = afterStreamingRenderContext(chunk);
return [
4,
_this.hooks.afterStreamingRender.call(context)
];
case 1:
_ref3 = _state2.sent(), newChunk = _ref3.chunk;
return [
2,
newChunk
];
}
});
});
return function(chunk) {
return _ref2.apply(this, arguments);
};
}());
return [
3,
6
];
case 3:
return [
4,
getAfterRenderCtx(c, baseHookCtx, routeInfo)
];
case 4:
afterRenderCtx = _state.sent();
getCost1 = time();
return [
4,
_this.hooks.afterRender.call(afterRenderCtx)
];
case 5:
_state.sent();
cost1 = getCost1();
cost1 && (monitors === null || monitors === void 0 ? void 0 : monitors.timing(ServerTimings.SERVER_HOOK_AFTER_RENDER, cost1));
if (afterRenderCtx.response.private_overrided) {
return [
2,
void 0
];
}
newBody = afterRenderCtx.template.get();
c.res = c.body(newBody);
_state.label = 6;
case 6:
return [
2
];
}
});
});
return function(c, next) {
return _ref.apply(this, arguments);
};
}();
};
_proto.getServerMiddleware = function getServerMiddleware() {
var _this = this;
return _async_to_generator(function() {
var serverMiddleware, unstableMiddlewares;
return _ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
return [
4,
_this.serverMiddlewarePromise
];
case 1:
serverMiddleware = _state.sent();
if (!serverMiddleware || !isFunction(serverMiddleware) && !isArray(serverMiddleware)) {
return [
2
];
}
if (Array.isArray(serverMiddleware)) {
unstableMiddlewares = getServerMidFromUnstableMid(serverMiddleware);
return [
2,
unstableMiddlewares
];
}
return [
2,
function() {
var _ref = _async_to_generator(function(c, next) {
var _c_env_node_res, _c_env_node, _c_env, monitors, locals, resArgs, customMiddlewareCtx, getCost, cost;
return _ts_generator(this, function(_state2) {
switch (_state2.label) {
case 0:
monitors = c.get("monitors");
locals = {};
resArgs = {
headers: new Headers()
};
customMiddlewareCtx = createCustomMiddlewaresCtx(c, locals, resArgs);
getCost = time();
return [
4,
serverMiddleware(customMiddlewareCtx)
];
case 1:
_state2.sent();
cost = getCost();
cost && (monitors === null || monitors === void 0 ? void 0 : monitors.timing(ServerTimings.SERVER_MIDDLEWARE, cost));
c.set("locals", locals);
if (isRedirect(resArgs.headers, resArgs.status)) {
return [
2,
c.redirect(resArgs.headers.get("Location") || "", resArgs.status || 302)
];
}
if ((_c_env = c.env) === null || _c_env === void 0 ? void 0 : (_c_env_node = _c_env.node) === null || _c_env_node === void 0 ? void 0 : (_c_env_node_res = _c_env_node.res) === null || _c_env_node_res === void 0 ? void 0 : _c_env_node_res.headersSent) {
return [
2,
void 0
];
}
if (!c.finalized) {
return [
2,
next()
];
}
return [
2
];
}
});
});
return function(c, next) {
return _ref.apply(this, arguments);
};
}()
];
}
});
})();
};
return CustomServer2;
}();
function getServerMidFromUnstableMid(serverMiddleware) {
return serverMiddleware.map(function(middleware) {
return function() {
var _ref = _async_to_generator(function(c, next) {
var context;
return _ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
return [
4,
createMiddlewareContextFromHono(c)
];
case 1:
context = _state.sent();
return [
2,
middleware(context, next)
];
}
});
});
return function(c, next) {
return _ref.apply(this, arguments);
};
}();
});
}
function isRedirect(headers, code) {
return [
301,
302,
307,
308
].includes(code || 0) || headers.get("Location");
}
function createMiddlewareContextFromHono(c) {
return _createMiddlewareContextFromHono.apply(this, arguments);
}
function _createMiddlewareContextFromHono() {
_createMiddlewareContextFromHono = // TODO: maybe we need use hono ctx directly
// TODO: after we use hono ctx, we should use `c.get('monitors')` to get monitors
_async_to_generator(function(c) {
var loaderContext, rawRequest, method, streamModulePath, createReadableStreamFromReadable, init;
return _ts_generator(this, function(_state) {
switch (_state.label) {
case 0:
loaderContext = getLoaderCtx(c);
rawRequest = c.req.raw;
method = rawRequest.method.toUpperCase();
if (!(![
"GET",
"HEAD"
].includes(method) && !rawRequest.body && c.env.node.req))
return [
3,
2
];
streamModulePath = "../../adapters/node/polyfills/stream.js";
return [
4,
import(streamModulePath)
];
case 1:
createReadableStreamFromReadable = _state.sent().createReadableStreamFromReadable;
init = {
body: createReadableStreamFromReadable(c.env.node.req),
headers: rawRequest.headers,
signal: rawRequest.signal,
method: rawRequest.method
};
init.duplex = "half";
c.req.raw = new Request(rawRequest.url, init);
_state.label = 2;
case 2:
return [
2,
{
get request() {
return c.req.raw;
},
set request(request) {
c.req.raw = request;
},
get response() {
return c.res;
},
set response(newRes) {
c.res = newRes;
},
get route() {
return c.get("route");
},
get: function get(key) {
return loaderContext.get(key);
},
set: function set(key, value) {
return loaderContext.set(key, value);
},
status: c.status.bind(c),
header: c.header.bind(c),
body: c.body.bind(c),
html: c.html.bind(c),
redirect: c.redirect.bind(c)
}
];
}
});
});
return _createMiddlewareContextFromHono.apply(this, arguments);
}
export {
CustomServer,
getServerMidFromUnstableMid
};