UNPKG

neft

Version:

Universal Platform

1,579 lines (1,381 loc) 776 kB
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