derby
Version:
MVC framework making it easy to write realtime, collaborative applications that run in both Node.js and browsers.
103 lines (102 loc) • 4.03 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.PageForServer = void 0;
var Page_1 = require("./Page");
var PageForServer = /** @class */ (function (_super) {
__extends(PageForServer, _super);
function PageForServer(app, model, req, res) {
var _this = _super.call(this, app, model) || this;
_this.req = req;
_this.res = res;
_this.page = _this;
return _this;
}
PageForServer.prototype.render = function (ns, status) {
var _this = this;
this.app.emit('render', this);
if (status)
this.res.statusCode = status;
// Prevent the browser from storing the HTML response in its back cache, since
// that will cause it to render with the data from the initial load first
this.res.setHeader('Cache-Control', 'no-store');
// Set HTML utf-8 content type unless already set
if (!this.res.getHeader('Content-Type')) {
this.res.setHeader('Content-Type', 'text/html; charset=utf-8');
}
this._setRenderParams(ns);
var pageHtml = this.get('Page', ns);
this.res.write(pageHtml);
this.app.emit('htmlDone', this);
this.res.write('<script data-derby-app-state type="application/json">');
var tailHtml = this.get('Tail', ns);
this.model.destroy('$components');
this.model.bundle(function (err, bundle) {
if (_this.model.hasErrored)
return;
if (err)
return _this.emit('error', err);
var json = stringifyBundle(bundle);
_this.res.write(json);
_this.res.end('</script>' + tailHtml);
_this.app.emit('routeDone', _this, 'render');
});
};
PageForServer.prototype.renderStatic = function (status, ns) {
if (typeof status !== 'number') {
ns = status;
status = null;
}
this.app.emit('renderStatic', this);
if (status)
this.res.statusCode = status;
this.params = pageParams(this.req);
this._setRenderParams(ns);
var pageHtml = this.get('Page', ns);
var tailHtml = this.get('Tail', ns);
this.res.send(pageHtml + tailHtml);
this.app.emit('routeDone', this, 'renderStatic');
};
return PageForServer;
}(Page_1.Page));
exports.PageForServer = PageForServer;
function stringifyBundle(bundle) {
var json = JSON.stringify(bundle);
return json.replace(/<[/!]/g, function (match) {
// Replace the end tag sequence with an equivalent JSON string to make
// sure the script is not prematurely closed
if (match === '</')
return '<\\/';
// Replace the start of an HTML comment tag sequence with an equivalent
// JSON string
if (match === '<!')
return '<\\u0021';
throw new Error('Unexpected match when escaping JSON');
});
}
// TODO: Cleanup; copied from tracks
function pageParams(req) {
var params = Object.create(null);
Object.assign(params, {
url: req.url,
body: req.body,
query: req.query,
});
for (var key in req.params) {
params[key] = req.params[key];
}
return params;
}