neft
Version:
Universal Platform
1,579 lines (1,381 loc) • 776 kB
JavaScript
var Neft = (function(){
var process = typeof global !== 'undefined' && global.process || {env: {}};
process.env['NEFT_PLATFORM'] = "node";
process.env['NEFT_SERVER'] = "1";
process.env['NEFT_NODE'] = "1";
var __modules = {"index.coffee": function(exports){
var module = {exports: exports};
var require = __createRequire({"src/app":"src/app/index.litcoffee","src/signal":"src/signal/index.litcoffee","src/dict":"src/dict/index.litcoffee","src/utils":"src/utils/index.litcoffee","src/log":"src/log/index.litcoffee","src/list":"src/list/index.litcoffee","src/resources":"src/resources/index.litcoffee","src/renderer":"src/renderer/index.litcoffee","src/schema":"src/schema/index.litcoffee","src/assert":"src/assert/index.litcoffee","src/db":"src/db/index.litcoffee","src/nml-parser":"src/nml-parser/index.coffee","src/binding":"src/binding/index.coffee","src/styles":"src/styles/index.coffee","src/document":"src/document/index.litcoffee","src/networking":"src/networking/index.litcoffee","src/tryCatch":"src/tryCatch/index.coffee","src/eventLoop":"src/eventLoop/index.coffee"});
var exports = module.exports;
(function(){
(function() {
'use strict';
var exports;
exports = module.exports = require('src/app');
exports.utils = require('src/utils');
exports.signal = require('src/signal');
exports.Dict = require('src/dict');
exports.List = require('src/list');
exports.log = require('src/log');
exports.Resources = require('src/resources');
exports.Renderer = require('src/renderer');
exports.Networking = require('src/networking');
exports.Schema = require('src/schema');
exports.Document = require('src/document');
exports.styles = require('src/styles');
exports.assert = require('src/assert');
exports.db = require('src/db');
exports.eventLoop = require('src/eventLoop');
exports.tryCatch = require('src/tryCatch');
exports.Binding = require('src/binding');
exports["native"] = (function() {
try {
return require('src/native');
} catch (undefined) {}
})();
exports.nmlParser = (function() {
try {
return require('src/nml-parser');
} catch (undefined) {}
})();
}).call(this);
}());
return module.exports;
},
"lib/module-cache/index.js": function(exports){
var module = {exports: exports};
var require = __createRequire({"path":"path","crypto":"crypto","util":"util","babel-core":"node_modules/babel-core/index.js","fs-extra":"node_modules/fs-extra/lib/index.js","js-yaml":"node_modules/js-yaml/index.js","coffee-script":"node_modules/coffee-script/lib/coffee-script/coffee-script.js"});
var exports = module.exports;
(function(){
'use strict';
var readCacheFile = function () {
var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(path) {
var file;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return fsReadFile(path, 'utf-8');
case 2:
file = _context.sent;
return _context.abrupt('return', {
hash: file.slice(0, HASH_LENGTH),
code: file.slice(HASH_LENGTH)
});
case 4:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
return function readCacheFile(_x) {
return _ref.apply(this, arguments);
};
}();
var writeCacheFile = function () {
var _ref2 = _asyncToGenerator(regeneratorRuntime.mark(function _callee2(path, hash, code) {
var file;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
file = hash + code;
_context2.next = 3;
return promisify(fs.writeFile)(path, file, 'utf-8');
case 3:
case 'end':
return _context2.stop();
}
}
}, _callee2, this);
}));
return function writeCacheFile(_x2, _x3, _x4) {
return _ref2.apply(this, arguments);
};
}();
function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }
var fs = require('fs-extra');
var pathUtils = require('path');
var crypto = require('crypto');
var babel = require('babel-core');
var CoffeeScript = require('coffee-script');
var yaml = require('js-yaml');
var _require = require('util'),
promisify = _require.promisify;
var HASH = 'sha';
var TMP_DIR = pathUtils.join(fs.realpathSync('./'), './build/tmp/');
var BABEL_OPTIONS = {
presets: ['es2015', 'es2016', 'es2017'],
filename: '',
babelrc: false,
ast: false
};
var COFFEE_SCRIPT_EXTS = ['.coffee', '.litcoffee'];
var YAML_EXTS = ['.yaml', '.yml'];
var REALPATH = fs.realpathSync('.');
var HASH_LENGTH = 40;
var MTIME_DELAY = 1000;
var filesCache = Object.create(null);
var fsReadFile = promisify(fs.readFile);
fs.ensureDirSync(TMP_DIR);
process.on('exit', function () {
var files = fs.readdirSync(TMP_DIR);
var maxDate = Date.now() - 1000 * 60 * 60;
for (var i = 0; i < files.length; i++) {
var filename = pathUtils.join(TMP_DIR, files[i]);
var stat = fs.statSync(filename);
if (stat.atime < maxDate) {
fs.unlinkSync(filename);
}
}
});
function absolutePath(path) {
if (pathUtils.isAbsolute(path)) {
return path;
}
return pathUtils.join(REALPATH, path);
}
function createHash(string) {
return crypto.createHash(HASH).update(string).digest('hex');
}
function readCacheFileSync(path) {
var file = fs.readFileSync(path, 'utf-8');
return {
hash: file.slice(0, HASH_LENGTH),
code: file.slice(HASH_LENGTH)
};
}
function writeCacheFileSync(path, hash, code) {
var file = hash + code;
fs.writeFileSync(path, file, 'utf-8');
}
exports.BABEL_OPTIONS = BABEL_OPTIONS;
exports.compileFile = function (file, filename) {
var path = absolutePath(filename);
var extname = pathUtils.extname(path);
switch (extname) {
case '.coffee':
return CoffeeScript.compile(file);
case '.litcoffee':
return CoffeeScript.compile(file, { literate: true });
case '.js':
BABEL_OPTIONS.filename = path;
return babel.transform(file, BABEL_OPTIONS).code;
case '.yaml':
case '.yml':
{
var object = yaml.safeLoad(file, { filename: path, json: true });
return JSON.stringify(object);
}
case '.nml':
{
var bundle = require('src/nml-parser').bundle({ nml: file, path: path }).bundle;
return CoffeeScript.compile(bundle);
}
default:
return file;
}
};
exports.fileHash = function () {
var _ref3 = _asyncToGenerator(regeneratorRuntime.mark(function _callee3(filename) {
var code;
return regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
_context3.next = 2;
return exports.getFile(filename);
case 2:
code = _context3.sent;
return _context3.abrupt('return', createHash(code));
case 4:
case 'end':
return _context3.stop();
}
}
}, _callee3, this);
}));
return function (_x5) {
return _ref3.apply(this, arguments);
};
}();
exports.getFile = function () {
var _ref4 = _asyncToGenerator(regeneratorRuntime.mark(function _callee4(filename) {
var path, fileCache, fileStat, code, hash, pathHash, cacheFilename, cacheStat, cache, file, _cache;
return regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
path = absolutePath(filename);
// get file from memory cache
fileCache = filesCache[path];
_context4.next = 4;
return promisify(fs.stat)(path);
case 4:
fileStat = _context4.sent;
if (fileStat.isFile()) {
_context4.next = 7;
break;
}
throw new TypeError('Path ' + path + ' is not a file');
case 7:
if (!fileCache) {
_context4.next = 10;
break;
}
if (!(fileStat.mtime < fileCache.mtime)) {
_context4.next = 10;
break;
}
return _context4.abrupt('return', fileCache.code);
case 10:
// get file from cache
code = void 0;
hash = void 0;
pathHash = createHash(path);
cacheFilename = pathUtils.join(TMP_DIR, pathHash);
cacheStat = void 0;
_context4.prev = 15;
_context4.next = 18;
return promisify(fs.stat)(cacheFilename);
case 18:
cacheStat = _context4.sent;
if (!(cacheStat.mtime - MTIME_DELAY >= fileStat.mtime)) {
_context4.next = 25;
break;
}
_context4.next = 22;
return readCacheFile(cacheFilename);
case 22:
cache = _context4.sent;
code = cache.code;
hash = cache.hash;
case 25:
_context4.next = 29;
break;
case 27:
_context4.prev = 27;
_context4.t0 = _context4['catch'](15);
case 29:
if (!(code === undefined)) {
_context4.next = 42;
break;
}
_context4.next = 32;
return promisify(fs.readFile)(path, 'utf-8');
case 32:
file = _context4.sent;
if (!cacheStat) {
_context4.next = 38;
break;
}
_context4.next = 36;
return readCacheFile(cacheFilename);
case 36:
_cache = _context4.sent;
if (_cache.hash === createHash(file)) {
code = _cache.code;
}
case 38:
if (!(code === undefined)) {
_context4.next = 42;
break;
}
code = exports.compileFile(file, path);
_context4.next = 42;
return writeCacheFile(cacheFilename, createHash(file), code);
case 42:
// update memory cache
if (!fileCache) {
fileCache = filesCache[path] = { mtime: 0, code: '' };
}
// some of systems has 1 second precision for file modification time;
// to prevent using cache for new files, we use current time back by 1 second;
// if you're getting file multiple times just after change; it won't be optimized
fileCache.mtime = Date.now() - MTIME_DELAY;
fileCache.code = code;
return _context4.abrupt('return', code);
case 46:
case 'end':
return _context4.stop();
}
}
}, _callee4, this, [[15, 27]]);
}));
return function (_x6) {
return _ref4.apply(this, arguments);
};
}();
exports.getFileSync = function (filename) {
var path = absolutePath(filename);
// get file from memory cache
var fileCache = filesCache[path];
var fileStat = fs.statSync(path);
if (!fileStat.isFile()) {
throw new TypeError('Path ' + path + ' is not a file');
}
if (fileCache) {
if (fileStat.mtime < fileCache.mtime) {
return fileCache.code;
}
}
// get file from cache
var code = void 0;
var hash = void 0;
var pathHash = createHash(path);
var cacheFilename = pathUtils.join(TMP_DIR, pathHash);
var cacheStat = void 0;
try {
cacheStat = fs.statSync(cacheFilename);
if (cacheStat.mtime - MTIME_DELAY >= fileStat.mtime) {
var cache = readCacheFileSync(cacheFilename);
code = cache.code;
hash = cache.hash;
}
} catch (error) {}
// get file
if (code === undefined) {
var file = fs.readFileSync(path, 'utf-8');
// use cache when both files are the same
if (cacheStat) {
var _cache2 = readCacheFileSync(cacheFilename);
if (_cache2.hash === createHash(file)) {
code = _cache2.code;
}
}
if (code === undefined) {
code = exports.compileFile(file, path);
writeCacheFileSync(cacheFilename, createHash(file), code);
}
}
// update memory cache
if (!fileCache) {
fileCache = filesCache[path] = { mtime: 0, code: '' };
}
// some of systems has 1 second precision for file modification time;
// to prevent using cache for new files, we use current time back by 1 second;
// if you're getting file multiple times just after change; it won't be optimized
fileCache.mtime = Date.now() - MTIME_DELAY;
fileCache.code = code;
return code;
};
exports.registerFilenameResolver = function () {
var Module = module.constructor;
var filenamesCache = Object.create(null);
var resolveFilename = Module._resolveFilename;
Module._resolveFilename = function (request, parent, isMain) {
var cache = filenamesCache[request];
if (cache) {
return cache;
} else {
var filename = resolveFilename(request, parent, isMain);
if (request[0] !== '.') {
filenamesCache[request] = filename;
}
return filename;
}
};
exports.registerFilenameResolver = function () {};
};
exports.registerCoffeeScript = function () {
function compile(module, filename) {
var file = exports.getFileSync(filename);
return module._compile(file, filename);
}
for (var i = 0; i < COFFEE_SCRIPT_EXTS.length; i++) {
require.extensions[COFFEE_SCRIPT_EXTS[i]] = compile;
}
exports.registerCoffeeScript = function () {};
};
exports.registerBabel = function () {
var _super = require.extensions['.js'];
require.extensions['.js'] = function (module, filename) {
if (filename.indexOf('node_modules') >= 0 && (filename.indexOf('node_modules/neft') < 0 || filename.indexOf('node_modules/neft/node_modules') >= 0)) {
return _super(module, filename);
}
var file = exports.getFileSync(filename);
return module._compile(file, filename);
};
exports.registerBabel = function () {};
};
exports.registerYaml = function () {
function compile(module, filename) {
var file = exports.getFileSync(filename);
module.exports = JSON.parse(file);
}
for (var i = 0; i < YAML_EXTS.length; i++) {
require.extensions[YAML_EXTS[i]] = compile;
}
exports.registerYaml = function () {};
};
exports.registerTxt = function () {
var registeredExtensions = Object.create(null);
return function (extnames) {
if (!Array.isArray(extnames)) {
extnames = ['.txt'];
}
function compile(module, filename) {
module.exports = exports.getFileSync(filename);
}
for (var i = 0; i < extnames.length; i++) {
var extname = extnames[i];
if (registeredExtensions[extname]) {
continue;
}
registeredExtensions[extname] = true;
require.extensions[extname] = compile;
}
};
}();
exports.registerNml = function () {
require.extensions['.nml'] = function (module, filename) {
var file = exports.getFileSync(filename);
return module._compile(file, filename);
};
exports.registerNml = function () {};
};
exports.register = function () {
exports.registerFilenameResolver();
exports.registerCoffeeScript();
exports.registerBabel();
exports.registerYaml();
exports.registerTxt();
exports.registerNml();
};
}());
return module.exports;
},
"package.json": function(exports){
var module = {exports: exports};
var require = __createRequire({});
var exports = module.exports;
(function(){
module.exports = {
"name": "neft",
"version": "0.11.23",
"preferGlobal": true,
"description": "Universal Platform",
"keywords": [
"framework",
"native",
"android",
"ios",
"webgl"
],
"bin": {
"neft": "bin/neft.js"
},
"main": "index.coffee",
"license": "Apache-2.0",
"homepage": "http://neft.io",
"author": "Krystian Kruk <krystian@neft.io>",
"contributors": [],
"repository": {
"type": "git",
"url": "https://github.com/Neft-io/neft.git"
},
"bugs": "https://github.com/Neft-io/neft/issues",
"engines": {
"node": ">=8.0.0"
},
"scripts": {
"bundle": "cross-env NODE_PATH=./ coffee --nodejs --harmony scripts/bundle.coffee",
"test": "node ./bin/neft.js test",
"update-api-docs": "cross-env NODE_PATH=./ coffee scripts/api-docs.coffee",
"prepublishOnly": "npm run bundle"
},
"dependencies": {
"acorn": "^5.2.1",
"babel-core": "6.22.1",
"babel-preset-es2015": "6.22.0",
"babel-preset-es2016": "6.22.0",
"babel-preset-es2017": "6.22.0",
"chokidar": "1.5.1",
"coffee-script": "1.10.0",
"cross-env": "1.0.8",
"form-data": "1.0.0-rc4",
"fs-extra": "0.30.0",
"glob": "7.0.3",
"htmlparser2": "3.9.0",
"http-server": "0.9.0",
"jimp": "0.2.27",
"js-yaml": "3.6.1",
"mkdirp": "0.5.1",
"mustache": "2.2.1",
"node-notifier": "4.6.0",
"node-static": "0.7.7",
"open": "0.0.5",
"pegjs": "0.10.0",
"pngjs": "3.0.0",
"qs": "6.2.0",
"semver": "5.1.0",
"slash": "1.0.0",
"uglify-js": "2.7.5",
"which": "1.2.12",
"xcode": "0.8.7"
},
"devDependencies": {
"coffee-coverage": "1.0.1",
"coveralls": "2.11.14",
"escape-html": "1.0.3",
"imgur": "0.2.1",
"istanbul": "^0.4.5",
"wd": "0.4.0"
},
"android": {
"package": "io.neft.tests",
"versionCode": 1,
"versionName": "1.0",
"application": {
"label": "Neft.io Tests"
}
},
"ios": {
"package": "io.neft.tests",
"application": {
"label": "Neft.io Tests"
}
}
}
;
}());
return module.exports;
},
"src/app/bootstrap/route.node.litcoffee": function(exports){
var module = {exports: exports};
var require = __createRequire({"fs":"fs","path":"path","src/utils":"src/utils/index.litcoffee","src/log":"src/log/index.litcoffee","src/dict":"src/dict/index.litcoffee","src/document":"src/document/index.litcoffee","src/networking":"src/networking/index.litcoffee"});
var exports = module.exports;
(function(){
(function() {
// when=NEFT_NODE;
'use strict';
var Dict, Document, Networking, VIEW_HTML, fs, log, pathUtils, utils;
utils = require('src/utils');
log = require('src/log');
fs = require('fs');
pathUtils = require('path');
Dict = require('src/dict');
Document = require('src/document');
Networking = require('src/networking');
log = log.scope('App', 'Bootstrap');
VIEW_HTML = '<!doctype html>\n<html>\n<head>\n <meta charset="utf-8">\n <title>${context.title}</title>\n <script type="text/javascript" src="${context.neftFilePath}"></script>\n <script type="text/javascript" src="${context.appFilePath}"></script>\n <meta name="viewport" content="width=device-width, initial-scale=1.0">\n <meta http-equiv="X-UA-Compatible" content="IE=Edge">\n</head>\n<body>\n <noscript>\n <meta http-equiv="refresh" content="0; url=${context.appTextModeUrl}"></meta>\n </noscript>\n</body>\n</html>';
module.exports = function(app) {
var APP_JS_URI, JS_HTML_BUNDLE_FILE_PATH, JS_NEFT_HTML_FILE_PATH, JS_NEFT_WEBGL_FILE_PATH, JS_WEBGL_BUNDLE_FILE_PATH, NEFT_JS_URI, TEXT_MODE_URI_PREFIX, TYPE_COOKIE_NAME, VIEW_NAME, appFile, appWebglFile, getType, loadAppFiles, neftFile, neftGameFile, reservedUris, reservedUrisRe, view;
APP_JS_URI = '/app.js';
NEFT_JS_URI = '/neft.js';
JS_NEFT_HTML_FILE_PATH = './build/neft-html-release.js';
JS_NEFT_WEBGL_FILE_PATH = './build/neft-webgl-release.js';
JS_HTML_BUNDLE_FILE_PATH = './build/app-html-release.js';
JS_WEBGL_BUNDLE_FILE_PATH = './build/app-webgl-release.js';
VIEW_NAME = '_app_bootstrap';
TEXT_MODE_URI_PREFIX = '/neft-type=text';
TYPE_COOKIE_NAME = 'neft-type';
//<development>;
JS_NEFT_HTML_FILE_PATH = './build/neft-html-develop.js';
JS_NEFT_WEBGL_FILE_PATH = './build/neft-webgl-develop.js';
JS_HTML_BUNDLE_FILE_PATH = './build/app-html-develop.js';
JS_WEBGL_BUNDLE_FILE_PATH = './build/app-webgl-develop.js';
//</development>;
view = Document.fromHTML(VIEW_NAME, VIEW_HTML);
Document.parse(view);
reservedUris = ['app.js', 'favicon.ico', 'static'];
reservedUrisRe = (function() {
var i, len, re, uri;
re = '';
for (i = 0, len = reservedUris.length; i < len; i++) {
uri = reservedUris[i];
re += (utils.addSlashes(uri)) + "|";
}
re = re.slice(0, -1);
return new RegExp("^(?:" + re + ")");
})();
getType = function(req) {
var cookie;
cookie = req.headers.cookie;
if (cookie && cookie.indexOf(TYPE_COOKIE_NAME) !== -1) {
return /neft\-type=([a-z]+)/.exec(cookie)[1];
} else {
return app.config.type;
}
};
//;
new app.Route({
uri: APP_JS_URI,
getData: function(callback) {
var isGameType;
isGameType = getType(this.request) === 'game';
//<development>;
if (isGameType) {
fs.readFile(JS_WEBGL_BUNDLE_FILE_PATH, 'utf-8', callback);
} else {
fs.readFile(JS_HTML_BUNDLE_FILE_PATH, 'utf-8', callback);
}
//</development>;
//;
}
});
//;
new app.Route({
uri: NEFT_JS_URI,
getData: function(callback) {
var isGameType;
isGameType = getType(this.request) === 'game';
//<development>;
if (isGameType) {
fs.readFile(JS_NEFT_WEBGL_FILE_PATH, 'utf-8', callback);
} else {
fs.readFile(JS_NEFT_HTML_FILE_PATH, 'utf-8', callback);
}
//</development>;
//;
}
});
new app.Route({
uri: 'favicon.ico',
redirect: 'static/favicon.ico'
});
new app.Route({
uri: 'neft-type={type}{rest*}',
getData: function(callback) {
var req, res;
req = this.request;
res = this.response;
res.setHeader('Set-Cookie', TYPE_COOKIE_NAME + "=" + req.params.type + "; path=/;");
return res.redirect("" + app.networking.url + req.params.rest);
}
});
return new app.Route({
uri: '*',
getData: function(callback) {
var req, userAgent;
req = this.request;
if (getType(req) === 'text' || req.headers['x-expected-type']) {
return this.next();
}
userAgent = req.headers['user-agent'] || '';
if (req.type !== Networking.Request.HTML_TYPE || reservedUrisRe.test(req.uri) || utils.has(userAgent, 'bot') || utils.has(userAgent, 'Baiduspider') || utils.has(userAgent, 'facebook') || utils.has(userAgent, 'Links')) {
return this.next();
}
return callback(null);
},
destroyHTML: function() {
return this.response.data.destroy();
},
toHTML: function() {
return view.render(null, {
title: app.config.title,
appTextModeUrl: TEXT_MODE_URI_PREFIX + this.request.uri,
neftFilePath: NEFT_JS_URI,
appFilePath: APP_JS_URI
});
}
});
};
}).call(this);
}());
return module.exports;
},
"src/app/index.litcoffee": function(exports){
var module = {exports: exports};
var require = __createRequire({"src/utils":"src/utils/index.litcoffee","src/log":"src/log/index.litcoffee","src/signal":"src/signal/index.litcoffee","src/renderer":"src/renderer/index.litcoffee","src/resources":"src/resources/index.litcoffee","src/dict":"src/dict/index.litcoffee","src/db":"src/db/index.litcoffee","src/assert":"src/assert/index.litcoffee","src/schema":"src/schema/index.litcoffee","src/styles":"src/styles/index.coffee","./bootstrap/route.node":"src/app/bootstrap/route.node.litcoffee","src/networking":"src/networking/index.litcoffee","src/document":"src/document/index.litcoffee","./route":"src/app/route.litcoffee","package.json":"package.json"});
var exports = module.exports;
(function(){
(function() {
'use strict';
var AppRoute, BASE_FILE_NAME_RE, DEFAULT_CONFIG, Dict, Document, Networking, Renderer, Resources, Schema, Styles, assert, bootstrapRoute, db, exports, log, pkg, signal, utils;
utils = require('src/utils');
log = require('src/log');
signal = require('src/signal');
db = require('src/db');
assert = require('src/assert');
Schema = require('src/schema');
Networking = require('src/networking');
Document = require('src/document');
Renderer = require('src/renderer');
Styles = require('src/styles');
Resources = require('src/resources');
Dict = require('src/dict');
AppRoute = require('./route');
bootstrapRoute = (function() {
try {
return require('./bootstrap/route.node');
} catch (undefined) {}
})();
//<development>;
pkg = require('package.json');
//</development>;
BASE_FILE_NAME_RE = /(.+)\.(?:node|server|client|browser|ios|android|native)/;
DEFAULT_CONFIG = {
title: 'Neft.io Application',
protocol: 'http',
port: 3000,
host: 'localhost',
language: 'en',
type: 'app'
};
exports = module.exports = function(opts, extraOpts) {
var COOKIES_KEY, IS_CLIENT, app, component, config, ext, i, init, j, k, l, len, len1, len2, len3, method, obj, onCookiesReady, path, r, ref, ref1, ref2, ref3, ref4, ref5, route, style, stylesInitObject, windowStyle, windowStyleItem;
if (opts == null) {
opts = {};
}
if (extraOpts == null) {
extraOpts = {};
}
null;
//<development>;
log.ok("Welcome! Neft.io v" + pkg.version + "; Feedback appreciated");
log.warn("Use this bundle only in development; type --release when it's ready");
//</development>;
config = utils.clone(DEFAULT_CONFIG);
config = utils.mergeAll(config, opts.config, extraOpts);
app = new Dict;
app.config = config;
app.networking = new Networking({
type: Networking.HTTP,
protocol: config.protocol,
port: parseInt(config.port, 10),
host: config.host,
url: config.url,
language: config.language
});
app.routes = {};
app.styles = {};
app.components = {};
app.resources = (function() {
if (opts.resources) {
return Resources.fromJSON(opts.resources);
} else {
return new Resources;
}
})();
signal.create(app, 'onReady');
if (config.type == null) {
config.type = 'app';
}
assert.ok(utils.has(['app', 'game', 'text'], config.type), "Unexpected app.config.type value. Accepted app/game/text, but '" + config.type + "' got.");
app.Route = AppRoute(app);
COOKIES_KEY = '__neft_cookies';
IS_CLIENT = !process.env.NEFT_SERVER;
app.cookies = Dict();
onCookiesReady = function(dict) {
app.cookies = dict;
if (IS_CLIENT) {
return dict.set('sessionId', utils.uid(16));
}
};
db.get(COOKIES_KEY, db.OBSERVABLE, function(err, dict) {
var cookies;
if (dict) {
return onCookiesReady(dict);
} else {
if (IS_CLIENT) {
cookies = {
clientId: utils.uid(16)
};
} else {
cookies = {};
}
return db.set(COOKIES_KEY, cookies, function(err) {
return db.get(COOKIES_KEY, db.OBSERVABLE, function(err, dict) {
if (dict) {
return onCookiesReady(dict);
}
});
});
}
});
app.networking.onRequest(function(req, res) {
if (IS_CLIENT) {
utils.merge(req.cookies, app.cookies);
} else {
utils.merge(res.cookies, app.cookies);
}
req.onLoadEnd.listeners.unshift(function() {
var key, ref, val;
if (IS_CLIENT) {
ref = res.cookies;
for (key in ref) {
val = ref[key];
if (!utils.isEqual(app.cookies[key], val)) {
app.cookies.set(key, val);
}
}
}
}, null);
});
Renderer.setResources(app.resources);
Renderer.setServerUrl(app.networking.url);
Renderer.onLinkUri(function(uri) {
return app.networking.createLocalRequest({
method: Networking.Request.GET,
type: Networking.Request.HTML_TYPE,
uri: uri
});
});
app.documentScripts = utils.arrayToObject(opts.scripts, function(index, elem) {
return elem.name;
}, function(index, elem) {
return elem.file;
});
Document.Scripts.initialize(app.documentScripts);
if (opts.styles != null) {
ref = opts.styles;
for (i = 0, len = ref.length; i < len; i++) {
style = ref[i];
if ((ref1 = style.name) === 'windowItem' || ref1 === '__windowItem__') {
style.file._init({
windowItem: null
});
windowStyle = style.file._main({
document: null
});
break;
}
}
}
app.windowItem = windowStyleItem = windowStyle != null ? windowStyle.item : void 0;
assert.ok(windowStyleItem, '__windowItem__ style must be defined');
Renderer.setWindowItem(windowStyleItem);
if (opts.styles != null) {
stylesInitObject = {
windowItem: windowStyleItem
};
ref2 = opts.styles;
for (j = 0, len1 = ref2.length; j < len1; j++) {
style = ref2[j];
if (!(style.name != null)) {
continue;
}
if (style.name !== 'windowItem') {
style.file._init(stylesInitObject);
}
app.styles[style.name] = style.file;
}
}
Styles({
windowStyle: windowStyle,
styles: app.styles,
queries: opts.styleQueries,
resources: app.resources
});
if (typeof bootstrapRoute === "function") {
bootstrapRoute(app);
}
init = function(files, target) {
var _, baseName, baseNameMatch, file, fileObj, k, len2;
for (k = 0, len2 = files.length; k < len2; k++) {
file = files[k];
if (!(file.name != null)) {
continue;
}
if (typeof file.file !== 'function') {
continue;
}
fileObj = file.file(app);
target[file.name] = fileObj;
if (baseNameMatch = BASE_FILE_NAME_RE.exec(file.name)) {
_ = baseNameMatch[0], baseName = baseNameMatch[1];
if (target[baseName] != null) {
if (utils.isPlainObject(target[baseName]) && utils.isPlainObject(fileObj)) {
fileObj = utils.merge(Object.create(target[baseName]), fileObj);
}
}
target[baseName] = fileObj;
}
}
};
if (utils.isObject(opts.extensions)) {
ref3 = opts.extensions;
for (k = 0, len2 = ref3.length; k < len2; k++) {
ext = ref3[k];
ext(app);
}
}
exports.app = {
Route: app.Route
};
ref4 = opts.components;
for (l = 0, len3 = ref4.length; l < len3; l++) {
component = ref4[l];
if (component.name != null) {
app.components[component.name] = Document.fromJSON(component.file);
}
}
init(opts.routes, app.routes);
ref5 = app.routes;
for (path in ref5) {
obj = ref5[path];
r = {};
if (utils.isObject(obj) && !(obj instanceof app.Route)) {
for (method in obj) {
opts = obj[method];
if (utils.isObject(opts)) {
route = new app.Route(method, opts);
r[route.name] = route;
} else {
r[method] = opts;
}
}
}
app.routes[path] = r;
}
if (!app.routes.index) {
app.routes.index = new app.Route('get /', {});
}
app.onReady.emit();
return app;
};
}).call(this);
}());
return module.exports;
},
"src/app/route.litcoffee": function(exports){
var module = {exports: exports};
var require = __createRequire({"src/utils":"src/utils/index.litcoffee","src/signal":"src/signal/index.litcoffee","src/assert":"src/assert/index.litcoffee","src/log":"src/log/index.litcoffee","src/schema":"src/schema/index.litcoffee","src/networking":"src/networking/index.litcoffee","src/document":"src/document/index.litcoffee","src/renderer":"src/renderer/index.litcoffee","src/dict":"src/dict/index.litcoffee"});
var exports = module.exports;
(function(){
(function() {
'use strict';
var Dict, Document, IS_CLIENT, IS_NODE, Networking, Renderer, Schema, assert, log, signal, utils;
utils = require('src/utils');
signal = require('src/signal');
assert = require('src/assert');
log = require('src/log');
Schema = require('src/schema');
Networking = require('src/networking');
Document = require('src/document');
Renderer = require('src/renderer');
Dict = require('src/dict');
log = log.scope('App', 'Route');
IS_NODE = process.env.NEFT_NODE;
IS_CLIENT = !IS_NODE;
module.exports = function(app) {
var Route;
return Route = (function() {
var callNextIfNeeded, createToHTMLFromObject, destroyRoute, factoryRoute, finishRequest, getDefaultRouteComponentName, getRouteName, handleRequest, onResponseSent, pendingRoutes, prepareRouteData, renderComponentFromConfig, resolveAsyncGetDataFuncCallback, resolveSyncGetDataFunc, routeToString, routesCache, templates, usedTemplates;
if (IS_NODE) {
usedTemplates = [];
} else {
templates = Object.create(null);
}
Route.lastClientRoute = null;
Route.onLastClientRouteChange = signal.create();
Route.getTemplateComponent = (function() {
if (IS_NODE) {
return function(name) {
var scope, tmpl;
scope = {
app: app,
routes: new Dict
};
tmpl = app.components[name].render(null, scope);
usedTemplates.push(tmpl);
return tmpl;
};
} else {
return function(name) {
var scope;
scope = {
app: app,
routes: new Dict
};
return templates[name] != null ? templates[name] : templates[name] = app.components[name].render(null, scope);
};
}
})();
function Route(method, uri, opts) {
var key, spaceIndex, val;
if (utils.isObject(method)) {
opts = method;
} else if (utils.isObject(uri)) {
opts = uri;
} else if (!utils.isObject(opts)) {
opts = {};
}
if (typeof method === 'string' && typeof uri !== 'string') {
opts.uri = method;
} else if (typeof method === 'string' && typeof uri === 'string') {
if (opts.method == null) {
opts.method = method;
}
if (opts.uri == null) {
opts.uri = uri;
}
}
if (typeof uri === 'function') {
if (opts.getData == null) {
opts.getData = uri;
}
}
assert.isObject(opts);
opts = utils.clone(opts);
if (typeof opts.uri === 'string') {
spaceIndex = opts.uri.indexOf(' ');
if (spaceIndex !== -1) {
if (opts.method == null) {
opts.method = opts.uri.slice(0, spaceIndex);
}
opts.uri = opts.uri.slice(spaceIndex + 1);
}
opts.uri = new Networking.Uri(opts.uri);
}
assert.instanceOf(opts.uri, Networking.Uri);
if (opts.method == null) {
opts.method = 'get';
}
assert.isString(opts.method);
opts.method = opts.method.toLowerCase();
assert.ok(utils.has(Networking.Request.METHODS, opts.method), "Networking doesn't provide a `" + opts.method + "` method");
if (opts.schema != null) {
if (utils.isPlainObject(opts.schema)) {
opts.schema = new Schema(opts.schema);
}
assert.instanceOf(opts.schema, Schema);
}
if (opts.redirect != null) {
if (typeof opts.redirect === 'string') {
opts.redirect = new Networking.Uri(opts.redirect);
} else {
assert.isFunction(opts.redirect);
}
}
if (utils.isObject(opts.toHTML)) {
opts.toHTML = createToHTMLFromObject(opts.toHTML);
}
for (key in opts) {
val = opts[key];
this[key] = val;
}
this.__id__ = utils.uid();
this.app = app;
this.name || (this.name = getRouteName(this));
app.networking.createHandler({
method: this.method,
uri: this.uri,
schema: this.schema,
callback: utils.bindFunctionContext(handleRequest, this)
});
}
getRouteName = function(route) {
var uri;
assert.instanceOf(route, Route);
uri = route.uri._uri;
uri = uri.replace(Networking.Uri.NAMES_RE, '');
uri = uri.replace(/\*/g, '');
while (uri.indexOf('//') !== -1) {
uri = uri.replace(/\/\//g, '/');
}
uri = uri.replace(/^\//, '');
uri = uri.replace(/\/$/, '');
return uri;
};
routesCache = Object.create(null);
pendingRoutes = Object.create(null);
factoryRoute = (function() {
var createInstance;
createInstance = function(route) {
var r;
r = Object.create(route);
r.__hash__ = utils.uid();
if (typeof r.factory === "function") {
r.factory();
}
return r;
};
return function(route) {
var id, r;
assert.instanceOf(route, Route);
id = route.__id__;
if (routesCache[id] == null) {
routesCache[id] = [];
}
r = routesCache[id].pop() || createInstance(route);
r = Object.create(r);
r.request = r.response = null;
r.route = r;
r._dataPrepared = false;
r._destroyComponentOnEnd = false;
return r;
};
})();
destroyRoute = function(route) {
assert.instanceOf(route, Route);
route.response.onSend.disconnect(onResponseSent, route);
delete pendingRoutes[route.__hash__];
if (typeof route.destroy === "function") {
route.destroy();
}
if (route._dataPrepared) {
switch (route.request.type) {
case 'text':
if (typeof route.destroyText === "function") {
route.destroyText();
}
break;
case 'json':
if (typeof route.destroyJSON === "function") {
route.destroyJSON();
}
break;
case 'html':
if (typeof route.destroyHTML === "function") {
route.destroyHTML();
}
}
}
if (route._destroyComponentOnEnd) {
route.response.data.destroy();
}
routesCache[route.__id__].push(Object.getPrototypeOf(route));
if (Route.lastClientRoute === route) {
Route.lastClientRoute = null;
Route.onLastClientRouteChange.emit(route);
}
};
resolveSyncGetDataFunc = function(route) {
assert.instanceOf(route, Route);
return route.data = route.getData();
};
resolveAsyncGetDataFuncCallback = function(route, err, data) {
assert.instanceOf(route, Route);
if (err != null) {
if (route.response.status === 200) {
route.response.status = 500;
}
if (route._dataPrepared && route.error === err) {
return false;
}
route.error = err;
} else {
if (route._dataPrepared && route.data === data) {
return false;
}
route.data = data;
}
return true;
};
prepareRouteData = function(route) {
var data, respData, response;
assert.instanceOf(route, Route);
response = route.response;
if (route.error) {
log.error("Error in route '" + route.uri + "':\n" + route.error);
}
respData = response.data;
switch (route.request.type) {
case 'text':
data = route.toText();
break;
case 'json':
data = route.toJSON();
break;
case 'html':
data = route.toHTML();
if (respData instanceof Document && route._destroyComponentOnEnd) {
respData.destroy();
response.data = null;
}
if (!(data instanceof Document) && response.data === respData) {
data = renderComponentFromConfig.call(route, data);
}
}
route._dataPrepared = true;
if (data != null) {
return response.data = data;
} else if (response.data === respData) {
return response.data = '';
}
};
onResponseSent = function() {
if (IS_NODE || this.request.type !== 'html') {
destroyRoute(this);
if (IS_NODE && utils.has(usedTemplates, this.response.data)) {
this.response.data.destroy();
utils.remove(usedTemplates, this.response.data);
}
}
};
finishRequest = function(route) {
assert.instanceOf(route, Route);
if (IS_CLIENT && route.response.data instanceof Document) {
app.windowItem.node = route.response.data.node;
}
if (route.response.pending) {
route.response.send();
}
};
callNextIfNeeded = function(route, next) {
if (!pendingRoutes[route.__hash__]) {
if (route.response.pending) {
next();
}
return true;
}
return false;
};
handleRequest = function(req, res, next) {
var fakeAsync, getData, hash, lastClientRoute, redirect, route;
assert.instanceOf(req, Networking.Request);
assert.instanceOf(res, Networking.Response);
assert.isFunction(next);
route = factoryRoute(this);
hash = route.__hash__;
assert.notOk(pendingRoutes[hash]);
if (IS_CLIENT) {
if (Route.lastClientRoute) {
destroyRoute(Route.lastClientRoute);
}
lastClientRoute = Route.lastClientRoute;
Route.lastClientRoute = route;
Route.onLastClientRouteChange.emit(lastClientRoute);
}
route.request = req;
route.response = res;
pendingRoutes[hash] = true;
res.onSend(onResponseSent, route);
if (typeof route.init === "function") {
route.init();
}
if (!pendingRoutes[hash]) {
return next();
}
redirect = route.redirect;
if (typeof redirect === 'function') {
redirect = route.redirect();
if (!pendingRoutes[hash]) {
return next();
}
}
if (typeof redirect === 'string') {
redirect = new Networking.Uri(redirect);
}
if (redirect instanceof Networking.Uri) {
res.redirect(redirect.toString(req.params));
return;
}
getData = route.getData;
fakeAsync = false;
if (typeof getData === 'function') {
if (getData.length === 1) {
route.getData(function(err, data) {
fakeAsync = true;
if (callNextIfNeeded(route, next)) {
return;
}
if (!resolveAsyncGetDataFuncCallback(route, err, data)) {
return;
}
prepareRouteData(route);
if (callNextIfNeeded(route, next)) {
return;
}
return finishRequest(route);
});
} else {
resolveSyncGetDataFunc(route);
if (callNextIfNeeded(route, next)) {
return;
}
prepareRouteData(route);
if (callNextIfNeeded(route, next)) {
return;
}
finishRequest(route);
}
} else {
prepareRouteData(route);
if (callNextIfNeeded(route, next)) {
return;
}
finishRequest(route);
}
if (!fakeAsync && callNextIfNeeded(route, next)) {
}
};
Route.prototype.next = function() {
assert.ok(pendingRoutes[this.__hash__]);
return destroyRoute(this);
};
Route.prototype.toJSON = function() {
var base, ref;
if (this.response.status < 400) {
return ((ref = this.data) != null ? typeof ref.toJSON === "function" ? ref.toJSON() : void 0 : void 0) || this.data;
} else {
return (typeof (base = this.error).toJSON === "function" ? base.toJSON() : void 0) || this.error;
}
};
Route.prototype.toText = function() {
if (this.response.status < 400) {
return this.data + '';
} else {
return this.error + '';
}
};
routeToString = function() {
return this.method + " " + this.uri;
};
getDefaultRouteComponentName = function() {
var path;
path = "components/" + this.name + ".xhtml";
if (app.components[path]) {
return path;
}
};
renderComponentFromConfig = function(opts) {
var component, componentName, logtime, r, tmpl, tmplComponent, tmplName, useName;
componentName = (opts != null ? opts.component : void 0) || getDefaultRouteComponentName.call(this) || 'components/index.xhtml';
tmplName = (opts != null ? opts.template : void 0) || componentName;
useName = (opts != null ? opts.use : void 0) || 'body';
logtime = log.time('Render');
if (componentName !== tmplName) {
if (tmpl = app.components[tmplName]) {
tmplComponent = Route.getTemplateComponent(tmplName);
tmplComponent.use(useName, null);
} else {
log.warn("Template component '" + tmplName + "' can't be found for route '" + (routeToString.call(this)) + "'");
}
}
if (component = app.components[componentName]) {
r = component.render(null, this);
} else {
log.warn("Component '" + tmplName + "' can't be found for route '" + (routeToString.call(this)) + "'");
}
if (tmplComponent) {
if (r != null) {
r = tmplComponent.use(useName, r);
} else {
r = tmplComponent;
}
if (tmplComponent.context.routes.has(useName)) {
tmplComponent.context.routes.pop(useName);
}
tmplComponent.context.routes.set(useName, this);
this._destroyComponentOnEnd = false;
} else {
this._destroyComponentOnEnd = true;
}
log.end(logtime);
return r;
};
createToHTMLFromObject = function(opts) {
return function() {
return renderComponentFromConfig.call(this, opts);
};
};
Route.prototype.toHTML = createToHTMLFromObject({
component: '',
template: '',
use: ''
});
return Route;
})();
};
}).call(this);
}());
return module.exports;
},
"src/assert/index.litcoffee": function(exports){
var module = {exports: exports};
var requ