{"version":3,"sources":["meteor://💻app/packages/autoupdate/autoupdate_server.js","meteor://💻app/packages/autoupdate/client_versions.js"],"names":["module","export","Autoupdate","ClientVersions","link","v","onMessage","Future","Npm","require","__meteor_runtime_config__","autoupdate","versions","clientVersions","autoupdateVersion","autoupdateVersionRefreshable","autoupdateVersionCordova","appId","process","env","APP_ID","syncQueue","Meteor","_SynchronousQueue","updateVersions","shouldReloadClientProgram","WebAppInternals","reloadClientPrograms","AUTOUPDATE_VERSION","clientArchs","Object","keys","WebApp","clientPrograms","forEach","arch","version","calculateClientHash","versionRefreshable","calculateClientHashRefreshable","versionNonRefreshable","calculateClientHashNonRefreshable","generateBoilerplate","onListening","payload","assets","getRefreshableAssets","set","publish","check","Match","OneOf","String","undefined","stop","watch","isNew","added","changed","call","_id","onStop","ready","is_auto","startup","fut","queueTask","wait","return","enqueueVersionsRefresh","on","bindEnvironment","Tracker","constructor","_versions","Map","_watchCallbacks","Set","createStore","update","id","msg","fields","hasVersions","size","get","assign","fn","filter","skipInitial","resolved","Promise","resolve","then","callback","add","delete","newClientAvailable","currentVersion","isNewVersion","some","field","dependency","Dependency","depend"],"mappings":"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","file":"/packages/autoupdate.js","sourcesContent":["// Publish the current client versions for each client architecture\n// (web.browser, web.browser.legacy, web.cordova). When a client observes\n// a change in the versions associated with its client architecture,\n// it will refresh itself, either by swapping out CSS assets or by\n// reloading the page.\n//\n// There are three versions for any given client architecture: `version`,\n// `versionRefreshable`, and `versionNonRefreshable`. The refreshable\n// version is a hash of just the client resources that are refreshable,\n// such as CSS, while the non-refreshable version is a hash of the rest of\n// the client assets, excluding the refreshable ones: HTML, JS, and static\n// files in the `public` directory. The `version` version is a combined\n// hash of everything.\n//\n// If the environment variable `AUTOUPDATE_VERSION` is set, it will be\n// used in place of all client versions. You can use this variable to\n// control when the client reloads. For example, if you want to force a\n// reload only after major changes, use a custom AUTOUPDATE_VERSION and\n// change it only when something worth pushing to clients happens.\n//\n// The server publishes a `meteor_autoupdate_clientVersions` collection.\n// The ID of each document is the client architecture, and the fields of\n// the document are the versions described above.\n\nimport { ClientVersions } from \"./client_versions.js\";\nvar Future = Npm.require(\"fibers/future\");\n\nexport const Autoupdate = __meteor_runtime_config__.autoupdate = {\n // Map from client architectures (web.browser, web.browser.legacy,\n // web.cordova) to version fields { version, versionRefreshable,\n // versionNonRefreshable, refreshable } that will be stored in\n // ClientVersions documents (whose IDs are client architectures). This\n // data gets serialized into the boilerplate because it's stored in\n // __meteor_runtime_config__.autoupdate.versions.\n versions: {}\n};\n\n// Stores acceptable client versions.\nconst clientVersions = new ClientVersions();\n\n// The client hash includes __meteor_runtime_config__, so wait until\n// all packages have loaded and have had a chance to populate the\n// runtime config before using the client hash as our default auto\n// update version id.\n\n// Note: Tests allow people to override Autoupdate.autoupdateVersion before\n// startup.\nAutoupdate.autoupdateVersion = null;\nAutoupdate.autoupdateVersionRefreshable = null;\nAutoupdate.autoupdateVersionCordova = null;\nAutoupdate.appId = __meteor_runtime_config__.appId = process.env.APP_ID;\n\nvar syncQueue = new Meteor._SynchronousQueue();\n\nfunction updateVersions(shouldReloadClientProgram) {\n // Step 1: load the current client program on the server\n if (shouldReloadClientProgram) {\n WebAppInternals.reloadClientPrograms();\n }\n\n const {\n // If the AUTOUPDATE_VERSION environment variable is defined, it takes\n // precedence, but Autoupdate.autoupdateVersion is still supported as\n // a fallback. In most cases neither of these values will be defined.\n AUTOUPDATE_VERSION = Autoupdate.autoupdateVersion\n } = process.env;\n\n // Step 2: update __meteor_runtime_config__.autoupdate.versions.\n const clientArchs = Object.keys(WebApp.clientPrograms);\n clientArchs.forEach(arch => {\n Autoupdate.versions[arch] = {\n version: AUTOUPDATE_VERSION ||\n WebApp.calculateClientHash(arch),\n versionRefreshable: AUTOUPDATE_VERSION ||\n WebApp.calculateClientHashRefreshable(arch),\n versionNonRefreshable: AUTOUPDATE_VERSION ||\n WebApp.calculateClientHashNonRefreshable(arch),\n };\n });\n\n // Step 3: form the new client boilerplate which contains the updated\n // assets and __meteor_runtime_config__.\n if (shouldReloadClientProgram) {\n WebAppInternals.generateBoilerplate();\n }\n\n // Step 4: update the ClientVersions collection.\n // We use `onListening` here because we need to use\n // `WebApp.getRefreshableAssets`, which is only set after\n // `WebApp.generateBoilerplate` is called by `main` in webapp.\n WebApp.onListening(() => {\n clientArchs.forEach(arch => {\n const payload = {\n ...Autoupdate.versions[arch],\n assets: WebApp.getRefreshableAssets(arch),\n };\n\n clientVersions.set(arch, payload);\n });\n });\n}\n\nMeteor.publish(\n \"meteor_autoupdate_clientVersions\",\n function (appId) {\n // `null` happens when a client doesn't have an appId and passes\n // `undefined` to `Meteor.subscribe`. `undefined` is translated to\n // `null` as JSON doesn't have `undefined.\n check(appId, Match.OneOf(String, undefined, null));\n\n // Don't notify clients using wrong appId such as mobile apps built with a\n // different server but pointing at the same local url\n if (Autoupdate.appId && appId && Autoupdate.appId !== appId)\n return [];\n\n const stop = clientVersions.watch((version, isNew) => {\n (isNew ? this.added : this.changed)\n .call(this, \"meteor_autoupdate_clientVersions\", version._id, version);\n });\n\n this.onStop(() => stop());\n this.ready();\n },\n {is_auto: true}\n);\n\nMeteor.startup(function () {\n updateVersions(false);\n\n // Force any connected clients that are still looking for these older\n // document IDs to reload.\n [\"version\",\n \"version-refreshable\",\n \"version-cordova\",\n ].forEach(_id => {\n clientVersions.set(_id, {\n version: \"outdated\"\n });\n });\n});\n\nvar fut = new Future();\n\n// We only want 'refresh' to trigger 'updateVersions' AFTER onListen,\n// so we add a queued task that waits for onListen before 'refresh' can queue\n// tasks. Note that the `onListening` callbacks do not fire until after\n// Meteor.startup, so there is no concern that the 'updateVersions' calls from\n// 'refresh' will overlap with the `updateVersions` call from Meteor.startup.\n\nsyncQueue.queueTask(function () {\n fut.wait();\n});\n\nWebApp.onListening(function () {\n fut.return();\n});\n\nfunction enqueueVersionsRefresh() {\n syncQueue.queueTask(function () {\n updateVersions(true);\n });\n}\n\n// Listen for messages pertaining to the client-refresh topic.\nimport { onMessage } from \"meteor/inter-process-messaging\";\nonMessage(\"client-refresh\", enqueueVersionsRefresh);\n\n// Another way to tell the process to refresh: send SIGHUP signal\nprocess.on('SIGHUP', Meteor.bindEnvironment(function () {\n enqueueVersionsRefresh();\n}, \"handling SIGHUP signal for refresh\"));\n","import { Tracker } from \"meteor/tracker\";\n\nexport class ClientVersions {\n constructor() {\n this._versions = new Map();\n this._watchCallbacks = new Set();\n }\n\n // Creates a Livedata store for use with `Meteor.connection.registerStore`.\n // After the store is registered, document updates reported by Livedata are\n // merged with the documents in this `ClientVersions` instance.\n createStore() {\n return {\n update: ({ id, msg, fields }) => {\n if (msg === \"added\" || msg === \"changed\") {\n this.set(id, fields);\n }\n }\n };\n }\n\n hasVersions() {\n return this._versions.size > 0;\n }\n\n get(id) {\n return this._versions.get(id);\n }\n\n // Adds or updates a version document and invokes registered callbacks for the\n // added/updated document. If a document with the given ID already exists, its\n // fields are merged with `fields`.\n set(id, fields) {\n let version = this._versions.get(id);\n let isNew = false;\n\n if (version) {\n Object.assign(version, fields);\n } else {\n version = {\n _id: id,\n ...fields\n };\n\n isNew = true;\n this._versions.set(id, version);\n }\n\n this._watchCallbacks.forEach(({ fn, filter }) => {\n if (! filter || filter === version._id) {\n fn(version, isNew);\n }\n });\n }\n\n // Registers a callback that will be invoked when a version document is added\n // or changed. Calling the function returned by `watch` removes the callback.\n // If `skipInitial` is true, the callback isn't be invoked for existing\n // documents. If `filter` is set, the callback is only invoked for documents\n // with ID `filter`.\n watch(fn, { skipInitial, filter } = {}) {\n if (! skipInitial) {\n const resolved = Promise.resolve();\n\n this._versions.forEach((version) => {\n if (! filter || filter === version._id) {\n resolved.then(() => fn(version, true));\n }\n });\n }\n\n const callback = { fn, filter };\n this._watchCallbacks.add(callback);\n\n return () => this._watchCallbacks.delete(callback);\n }\n\n // A reactive data source for `Autoupdate.newClientAvailable`.\n newClientAvailable(id, fields, currentVersion) {\n function isNewVersion(version) {\n return (\n version._id === id &&\n fields.some((field) => version[field] !== currentVersion[field])\n );\n }\n\n const dependency = new Tracker.Dependency();\n const version = this.get(id);\n\n dependency.depend();\n\n const stop = this.watch(\n (version) => {\n if (isNewVersion(version)) {\n dependency.changed();\n stop();\n }\n },\n { skipInitial: true }\n );\n\n return !! version && isNewVersion(version);\n }\n}\n"]}