{"version":3,"sources":["routepolicy/routepolicy.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,kE;AACA,qE;AACA,mE;AACA,qC;AACA,E;AACA,sE;AACA,mE;AACA,2C;AACA,E;AACA,+E;AACA,E;AACA,qE;AACA,iE;AACA,+D;AACA,E;AACA,sE;AACA,iE;AACA,mE;AACA,sE;AACA,+D;;AAEA,mE;AACA,mE;AACA,iE;AACA,2B;;AAEA,qB;;AAEA,wE;AACA,kB;AACA,2B;AACA,E;;AAEA,4C;;AAEA,+C;AACA,yD;AACA,I;;AAEA,8B;AACA,yD;AACA,mE;AACA,gB;AACA,I;;AAEA,8C;AACA,oB;;AAEA,oC;AACA,0D;;AAEA,0B;AACA,8C;;AAEA,sD;AACA,8C;AACA,8G;;AAEA,gB;AACA,I;;AAEA,yE;AACA,oB;AACA,iC;AACA,kB;AACA,iD;AACA,gD;AACA,+F;AACA,wD;AACA,6D;AACA,2D;AACA,4B;AACA,kB;AACA,K;AACA,mC;AACA,uF;AACA,yD;AACA,2C;AACA,4C;AACA,8D;AACA,O;AACA,iB;AACA,sE;AACA,4C;AACA,Q;AACA,kB;AACA,I;;AAEA,uC;AACA,oB;AACA,yC;AACA,yD;AACA,mE;AACA,gB;AACA,+B;AACA,0D;AACA,0C;AACA,I;;AAEA,8B;AACA,iC;AACA,I;;AAEA,4B;AACA,oB;AACA,8B;AACA,4D;AACA,yE;AACA,iD;AACA,O;AACA,e;AACA,yC;AACA,Q;AACA,kB;AACA,I;;AAEA,mC;AACA,oB;AACA,sB;AACA,2D;AACA,yB;AACA,+B;AACA,O;AACA,2B;AACA,G;AACA,G;;AAEA,2C","file":"/packages/routepolicy.js","sourcesContent":["// In addition to listing specific files to be cached, the browser\n// application cache manifest allows URLs to be designated as NETWORK\n// (always fetched from the Internet) and FALLBACK (which we use to\n// serve app HTML on arbitrary URLs).\n//\n// The limitation of the manifest file format is that the designations\n// are by prefix only: if \"/foo\" is declared NETWORK then \"/foobar\"\n// will also be treated as a network route.\n//\n// RoutePolicy is a low-level API for declaring the route type of URL prefixes:\n//\n// \"network\": for network routes that should not conflict with static\n// resources. (For example, if \"/sockjs/\" is a network route, we\n// shouldn't have \"/sockjs/red-sock.jpg\" as a static resource).\n//\n// \"static-online\": for static resources which should not be cached in\n// the app cache. This is implemented by also adding them to the\n// NETWORK section (as otherwise the browser would receive app HTML\n// for them because of the FALLBACK section), but static-online routes\n// don't need to be checked for conflict with static resources.\n\n// The route policy is a singleton in a running application, but we\n// can't unit test the real singleton because messing with the real\n// routes would break tinytest... so allow policy instances to be\n// constructed for testing.\n\nRoutePolicyTest = {};\n\nvar RoutePolicyConstructor = RoutePolicyTest.Constructor = function () {\n var self = this;\n self.urlPrefixTypes = {};\n};\n\n_.extend(RoutePolicyConstructor.prototype, {\n\n urlPrefixMatches: function (urlPrefix, url) {\n return url.substr(0, urlPrefix.length) === urlPrefix;\n },\n\n checkType: function (type) {\n if (! _.contains(['network', 'static-online'], type))\n return 'the route type must be \"network\" or \"static-online\"';\n return null;\n },\n\n checkUrlPrefix: function (urlPrefix, type) {\n var self = this;\n\n if (urlPrefix.charAt(0) !== '/')\n return 'a route URL prefix must begin with a slash';\n\n if (urlPrefix === '/')\n return 'a route URL prefix cannot be /';\n\n var existingType = self.urlPrefixTypes[urlPrefix];\n if (existingType && existingType !== type)\n return 'the route URL prefix ' + urlPrefix + ' has already been declared to be of type ' + existingType;\n\n return null;\n },\n\n checkForConflictWithStatic: function (urlPrefix, type, _testManifest) {\n var self = this;\n if (type === 'static-online')\n return null;\n if (!Package.webapp || !Package.webapp.WebApp\n || !Package.webapp.WebApp.clientPrograms\n || !Package.webapp.WebApp.clientPrograms[Package.webapp.WebApp.defaultArch].manifest) {\n // Hack: If we don't have a manifest, deal with it\n // gracefully. This lets us load livedata into a nodejs\n // environment that doesn't have a HTTP server (eg, a\n // command-line tool).\n return null;\n }\n var manifest = _testManifest ||\n Package.webapp.WebApp.clientPrograms[Package.webapp.WebApp.defaultArch].manifest;\n var conflict = _.find(manifest, function (resource) {\n return (resource.type === 'static' &&\n resource.where === 'client' &&\n self.urlPrefixMatches(urlPrefix, resource.url));\n });\n if (conflict)\n return ('static resource ' + conflict.url + ' conflicts with ' +\n type + ' route ' + urlPrefix);\n else\n return null;\n },\n\n declare: function (urlPrefix, type) {\n var self = this;\n var problem = self.checkType(type) ||\n self.checkUrlPrefix(urlPrefix, type) ||\n self.checkForConflictWithStatic(urlPrefix, type);\n if (problem)\n throw new Error(problem);\n // TODO overlapping prefixes, e.g. /foo/ and /foo/bar/\n self.urlPrefixTypes[urlPrefix] = type;\n },\n\n isValidUrl: function (url) {\n return url.charAt(0) === '/';\n },\n\n classify: function (url) {\n var self = this;\n if (url.charAt(0) !== '/')\n throw new Error('url must be a relative URL: ' + url);\n var prefix = _.find(_.keys(self.urlPrefixTypes), function (_prefix) {\n return self.urlPrefixMatches(_prefix, url);\n });\n if (prefix)\n return self.urlPrefixTypes[prefix];\n else\n return null;\n },\n\n urlPrefixesFor: function (type) {\n var self = this;\n var prefixes = [];\n _.each(self.urlPrefixTypes, function (_type, _prefix) {\n if (_type === type)\n prefixes.push(_prefix);\n });\n return prefixes.sort();\n }\n});\n\nRoutePolicy = new RoutePolicyConstructor();\n"]}