{"id":140,"date":"2019-12-24T13:38:31","date_gmt":"2019-12-24T04:38:31","guid":{"rendered":"https:\/\/blog.wsd.sh\/?p=140"},"modified":"2019-12-24T13:38:31","modified_gmt":"2019-12-24T04:38:31","slug":"framework-notes-apps","status":"publish","type":"post","link":"https:\/\/blog.wsd.sh\/?p=140","title":{"rendered":"Framework Notes (apps)"},"content":{"rendered":"\n<p>While it would be nice to move the framework around get it arranged, maybe we can look into the framework itself to start getting some context of specifically what&#8217;s running and where. We have a couple of options of do we go alphabetically or do we just jump in and start looking at what&#8217;s interesting? To start out we don&#8217;t need to pick and choose because the first file App.js looks extremely interesting.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/* ***** LICENSE BLOCK *****\n * Version: GPL 3\n *\n * This program is Copyright (C) 2007-2008 Aptana, Inc. All Rights Reserved\n * This program is licensed under the GNU General Public license, version 3 (GPL).\n *\n * This program is distributed in the hope that it will be useful, but\n * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or\n * NONINFRINGEMENT. Redistribution, except as permitted by the GPL,\n * is prohibited.\n *\n * You can redistribute and\/or modify this program under the terms of the GPL, \n * as published by the Free Software Foundation.  You should\n * have received a copy of the GNU General Public License, Version 3 along\n * with this program; if not, write to the Free Software Foundation, Inc., 51\n * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n * \n * Aptana provides a special exception to allow redistribution of this file\n * with certain other code and certain additional terms\n * pursuant to Section 7 of the GPL. You may view the exception and these\n * terms on the web at http:\/\/www.aptana.com\/legal\/gpl\/.\n * \n * You may view the GPL, and Aptana's exception and additional terms in the file\n * titled license-jaxer.html in the main distribution folder of this program.\n * \n * Any modifications to this file must keep this entire header intact.\n *\n * ***** END LICENSE BLOCK ***** *\/\n\n(function() {\n\n    var log = Log.forModule(\"App\");\n\n\n    function App(props) {\n\n        var defaultApp = Jaxer.Config.DEFAULT_APP || {};\n\n        if (!props) throw new Exception(\"When constructing a new App, you must specify the props argument\");\n\n        if (log.getLevel() == Log.TRACE) log.trace(\"Constructing App from props: \" + uneval(props) + \" and a default app of: \" + uneval(defaultApp));\n\n        this.urlTest = props.urlTest || defaultApp.urlTest;\n        this.name = props.name || defaultApp.name;\n        this.appKey = props.appKey || props.name || defaultApp.appKey;\n        this.pageKey = props.pageKey || defaultApp.pageKey;\n        this.db = props.db || defaultApp.db;\n        this.path = props.path || defaultApp.path;\n        this.handler = props.handler || defaultApp.handler;\n        this.init();\n\n        for (var extraProp in props) {\n            if (!(extraProp in this)) {\n                this&#91;extraProp] = props&#91;extraProp];\n            }\n        }\n\n    }\n\n    App.prototype.init = function init() {\n\n        var parsedUrl = (Jaxer.request ? Jaxer.request.parsedUrl : null);\n\n        var _NAME = extractFunctionOrString(this.name, &#91;parsedUrl]);\n        this.__defineGetter__(\"NAME\", function() {\n            return _NAME;\n        });\n\n        log.trace(\"Initializing app '\" + _NAME + \"' (urlTest: \" + this.urlTest + \")\");\n\n        var _APP_KEY = parsedUrl ? extractFunctionOrString(this.appKey, &#91;parsedUrl]) : null;\n        this.__defineGetter__(\"APP_KEY\", function() {\n            return _APP_KEY;\n        });\n        log.trace(\"APP_KEY for app '\" + this.NAME + \"': \" + _APP_KEY);\n\n        var _PAGE_KEY = parsedUrl ? extractFunctionOrString(this.pageKey, &#91;parsedUrl]) : null;\n        this.__defineGetter__(\"PAGE_KEY\", function() {\n            return _PAGE_KEY;\n        });\n        log.trace(\"PAGE_KEY for app '\" + this.NAME + \"': \" + _PAGE_KEY);\n\n        var _DB = extractFunctionOrObject(this.db, &#91;_NAME, parsedUrl]);\n        this.__defineGetter__(\"DB\", function() {\n            return _DB;\n        });\n\n        var _PATH = extractFunctionOrString(this.path, &#91;_NAME, parsedUrl]);\n        this.__defineGetter__(\"PATH\", function() {\n            return _PATH;\n        });\n        log.trace(\"PATH for app '\" + this.NAME + \"': \" + _PATH);\n        if (_PATH) this.initPath();\n\n    }\n\n    function extractFunctionOrString(obj, args) {\n        switch (typeof obj) {\n            case \"function\":\n                return String(obj.apply(null, args));\n            case \"string\":\n                return obj;\n            default:\n                return null;\n        }\n    }\n\n    function extractFunctionOrObject(obj, args) {\n        switch (typeof obj) {\n            case \"function\":\n                return obj.apply(null, args);\n            case \"object\":\n                return obj;\n            default:\n                return null;\n        }\n    }\n\n    App.prototype.initPath = function initPath() {\n        if (this.PATH) {\n            var path = Dir.resolve(this.PATH);\n            var dir = new Dir(path);\n            if (dir.exists) {\n                if (!dir.isDir) {\n                    throw new Exception(\"The path '\" + path + \"' for app '\" + this.NAME + \"' exists but is not a folder!\");\n                }\n            } else if (Config.AUTO_CREATE_APP_PATHS) {\n                log.trace(\"Creating or verifying hierarchy for app '\" + this.NAME + \"': \" + path);\n                dir.createHierarchy();\n            }\n        }\n    }\n\n    App.prototype.callHandler = function callHandler() {\n        var _HANDLER;\n        var parsedUrl = (Jaxer.request ? Jaxer.request.parsedUrl : null);\n        switch (typeof this.handler) {\n            case \"function\":\n                _HANDLER = this.handler(this.NAME, parsedUrl);\n                if (typeof _HANDLER != 'string') _HANDLER = null;\n                break;\n            case \"string\":\n                _HANDLER = this.handler;\n                break;\n            default:\n                _HANDLER = null;\n        }\n        this.__defineGetter__(\"HANDLER\", function() {\n            return _HANDLER;\n        });\n        log.trace(\"HANDLER for app '\" + this.NAME + \"': \" + _HANDLER);\n        return _HANDLER;\n    }\n\n    App.initStatic = function initStatic() {\n        for (var appName in Config.appsByName) {\n            var app = Config.appsByName&#91;appName];\n            app.initPath();\n        }\n    }\n\n    frameworkGlobal.App = Jaxer.App = App;\n\n    Log.trace(\"*** App.js loaded\");\n\n})();<\/code><\/pre>\n\n\n\n<p>The source code actually looks mercifully simple. We have a constructor function for the <strong>App <\/strong>prototype, which will use the default configuration as a base, and then replace any base functionality (name, urlTest, appKey, pageKey, db, path, handler). This means that it might be a good idea to get rid of the default app configuration from the configuration files and then include it in this function directly. That would simplify the file structure a little bit and the default app configuration is kind of hidden at the bottom of the file it&#8217;s defined in anyways, so that change could be made without too much modification to the current configuration.<\/p>\n\n\n\n<p>As for the concept of Apps in general, I&#8217;ve very tempted to remove this functionality as much as possible as it seems like a better idea to host a single application on a single Jaxer instance and try not to overload Jaxer too much. However in the case of hosting multiple subdomains on the same server, it might actually be useful functionality. <\/p>\n\n\n\n<p>For the &#8216;App&#8217; functionality I think it can be minimized and left in for now, as the basic default application that is provided to the user and can be used as-is without changes. And then if this functionality can be taken advantage of in the future, then the ground-work can be there.  Though in general I think the main way to take advantage of it is basically to provide a default database implementation for a specific path or URL, so the database connection parameters don&#8217;t need to be included under the public directory path.<\/p>\n\n\n\n<p>Though a very similar effect can be achieved by defining a &#8216;connect.js&#8217; file that is defined as &#8216;run-at=server&#8217; and placed in a &#8216;jaxer-include&#8217; folder where it&#8217;s needed. And this would provide almost exactly the same functionality as the concept of what Aptana defined as Apps, that would be a lot more simple and intuitive to use as opposed to having to edit the server configuration for the &#8216;App&#8217; to be implemented. So in general I think it&#8217;s generally a good idea to continue to minimize this functionality. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>While it would be nice to move the framework around get it arranged, maybe we can look into the framework itself to start getting some context of specifically what&#8217;s running and where. We have a couple of options of do we go alphabetically or do we just jump in and start looking at what&#8217;s interesting? To start out we don&#8217;t need to pick and choose because the first file App.js looks extremely interesting.<\/p>\n","protected":false},"author":1,"featured_media":141,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_mi_skip_tracking":false},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts\/140"}],"collection":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=140"}],"version-history":[{"count":1,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts\/140\/revisions"}],"predecessor-version":[{"id":142,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/posts\/140\/revisions\/142"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=\/wp\/v2\/media\/141"}],"wp:attachment":[{"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=140"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=140"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.wsd.sh\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=140"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}