forked from phcode-dev/staging.phcode.dev
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathExtensionManager.js
More file actions
1 lines (1 loc) · 17 KB
/
ExtensionManager.js
File metadata and controls
1 lines (1 loc) · 17 KB
1
define(function(require,exports,module){const _=require("thirdparty/lodash"),EventDispatcher=require("utils/EventDispatcher"),Package=require("extensibility/Package"),AppInit=require("utils/AppInit"),Async=require("utils/Async"),ExtensionLoader=require("utils/ExtensionLoader"),ExtensionUtils=require("utils/ExtensionUtils"),FileSystem=require("filesystem/FileSystem"),FileUtils=require("file/FileUtils"),PreferencesManager=require("preferences/PreferencesManager"),Strings=require("strings"),StringUtils=require("utils/StringUtils"),ThemeManager=require("view/ThemeManager"),TaskManager=require("features/TaskManager"),Metrics=require("utils/Metrics"),EXTENSION_REGISTRY_LOCAL_STORAGE_KEY=Phoenix.isTestWindow?"test_extension_registry":"extension_registry",EXTENSION_REGISTRY_LOCAL_STORAGE_VERSION_KEY=Phoenix.isTestWindow?"test_extension_registry_version":"extension_registry_version";localStorage.removeItem(EXTENSION_REGISTRY_LOCAL_STORAGE_KEY);const REGISTRY_CACHE_FILE=Phoenix.isTestWindow?"test_registry_cache.json":"registry_cache.json",REGISTRY_CACHE_PATH=path.normalize(Phoenix.app.getExtensionsDirectory()+"/"+REGISTRY_CACHE_FILE);function _getCachedRegistry(){return new Promise(resolve=>{const registryFile=FileSystem.getFileForPath(REGISTRY_CACHE_PATH);FileUtils.readAsText(registryFile,!0).done(resolve).fail(function(err){console.error(`Registry cache not found ${REGISTRY_CACHE_PATH}`,err),resolve(null)})})}function _putCachedRegistry(registryFileText){return new Promise(resolve=>{const registryFile=FileSystem.getFileForPath(REGISTRY_CACHE_PATH);FileUtils.writeText(registryFile,registryFileText,!0).done(resolve).fail(function(err){logger.reportError(err,`Registry cache write error ${REGISTRY_CACHE_PATH}`),resolve()})})}function _removeCachedRegistry(){const registryFile=FileSystem.getFileForPath(REGISTRY_CACHE_PATH);return registryFile.unlinkAsync()}var semver=require("thirdparty/semver.browser"),pendingDownloadRegistry=null,ENABLED="enabled",DISABLED="disabled",START_FAILED="startFailed",LOCATION_DEFAULT="default",LOCATION_DEV="dev",LOCATION_USER="user",LOCATION_UNKNOWN="unknown",FOLDER_AUTOINSTALL="auto-install-extensions",extensions={},_idsToRemove={},_idsToUpdate={},_idsToDisable={};function synchronizeEntry(id){var entry=extensions[id];if(entry&&entry.installInfo&&entry.registryInfo){entry.installInfo.owner=entry.registryInfo.owner,entry.installInfo.updateAvailable=!1,entry.registryInfo.updateAvailable=!1,entry.installInfo.updateCompatible=!1,entry.registryInfo.updateCompatible=!1;var currentVersion=entry.installInfo.metadata?entry.installInfo.metadata.version:null;if(currentVersion&&semver.lt(currentVersion,entry.registryInfo.metadata.version)){entry.registryInfo.updateAvailable=!0,entry.installInfo.updateAvailable=!0;var lastCompatibleVersionInfo=_.findLast(entry.registryInfo.versions,function(versionInfo){return!versionInfo.brackets||semver.satisfies(brackets.metadata.apiVersion,versionInfo.brackets)});lastCompatibleVersionInfo&&lastCompatibleVersionInfo.version&&semver.lt(currentVersion,lastCompatibleVersionInfo.version)&&(entry.installInfo.updateCompatible=!0,entry.registryInfo.updateCompatible=!0,entry.installInfo.lastCompatibleVersion=lastCompatibleVersionInfo.version,entry.registryInfo.lastCompatibleVersion=lastCompatibleVersionInfo.version)}exports.trigger("registryUpdate",id)}}function loadTheme(id){var extension=extensions[id];extension.installInfo&&extension.installInfo.metadata&&extension.installInfo.metadata.theme&&ThemeManager.loadPackage(extension.installInfo)}function _setExtensions(newExtensions){exports.extensions=extensions=newExtensions,Object.keys(extensions).forEach(function(id){synchronizeEntry(id)})}function _reset(){exports.extensions=extensions={},_idsToRemove={},_idsToUpdate={},_idsToDisable={}}function _populateExtensions(registry){Object.keys(registry).forEach(function(id){extensions[id]||(extensions[id]={}),extensions[id].registryInfo=registry[id],synchronizeEntry(id)}),exports.trigger("registryDownload")}function _shouldUpdateExtensionRegistry(){return new Promise((resolve,reject)=>{const currentRegistryVersion=localStorage.getItem(EXTENSION_REGISTRY_LOCAL_STORAGE_VERSION_KEY)||"1";Metrics.countEvent(Metrics.EVENT_TYPE.EXTENSIONS,"registryVersion",`${currentRegistryVersion}`),$.ajax({url:brackets.config.extension_registry_version,dataType:"json",cache:!1}).done(function(registryVersion){registryVersion.version!==parseInt(currentRegistryVersion)?resolve(registryVersion.version):_getCachedRegistry().then(registryJson=>{registryJson?reject():resolve(registryVersion.version)})}).fail(function(err){console.error("error Fetching Extension Registry version",err),_getCachedRegistry().then(registryJson=>{registryJson?reject():resolve(1)})})})}async function _patchDownloadCounts(){let registryJson=await _getCachedRegistry();registryJson&&$.ajax({url:brackets.config.extension_registry_popularity,dataType:"json",cache:!1}).done(async function(popularity){registryJson=await _getCachedRegistry();let registry=JSON.parse(registryJson);for(let key of Object.keys(popularity))registry[key]&&(registry[key].totalDownloads=popularity[key].totalDownloads||registry[key].totalDownloads||null,registry[key].gihubStars=popularity[key].gihubStars||registry[key].gihubStars||null);_putCachedRegistry(JSON.stringify(registry))})}function _filterIncompatibleEntries(registry){let filteredRegistry={};for(let registryKey of Object.keys(registry)){const registryEntry=registry[registryKey];let nodeNeeded=!1;registryEntry.metadata&®istryEntry.metadata.nodeConfig&®istryEntry.metadata.nodeConfig.nodeIsRequired&&(nodeNeeded=!0),nodeNeeded&&!Phoenix.isNativeApp||(filteredRegistry[registryKey]=registryEntry)}return filteredRegistry}function _getTaskManager(){return Phoenix.isTestWindow?{close:()=>{}}:TaskManager.addNewTask(Strings.EXTENSIONS_REGISTRY_TASK_TITLE,Strings.EXTENSIONS_REGISTRY_TASK_MESSAGE,'<i class="fa-solid fa-list"></i>')}function downloadRegistry(force){if(pendingDownloadRegistry)return pendingDownloadRegistry.promise();function _updateRegistry(newVersion){console.log("downloading extension registry: ",newVersion,brackets.config.extension_registry);const downloadTask=_getTaskManager();$.ajax({url:brackets.config.extension_registry,dataType:"json",cache:!1}).done(function(registry){registry=_filterIncompatibleEntries(registry),localStorage.setItem(EXTENSION_REGISTRY_LOCAL_STORAGE_VERSION_KEY,newVersion),_putCachedRegistry(JSON.stringify(registry)).then(()=>{pendingDownloadRegistry.alreadyResolvedFromCache||(_populateExtensions(registry),pendingDownloadRegistry.resolve(),pendingDownloadRegistry.alreadyResolvedFromCache=!0)}).finally(()=>{pendingDownloadRegistry=null,downloadTask.close()})}).fail(function(err){downloadTask.close(),console.error("error Fetching Extension Registry",err),pendingDownloadRegistry.alreadyResolvedFromCache||pendingDownloadRegistry.reject(),pendingDownloadRegistry=null})}if(pendingDownloadRegistry=new $.Deferred,force)return _updateRegistry(),pendingDownloadRegistry.promise();async function _getLocalRegistry(){try{const response=await fetch("extensions/registry/registry.json");return response.ok?await response.json():(console.error(`Failed to fetch local registry: ${response.status} ${response.statusText}`),null)}catch(error){return console.error(`Error fetching local registry: ${error.message}`),null}}return _getCachedRegistry().then(registryJson=>{registryJson?(console.log("Using cached extension registry"),setTimeout(()=>{Metrics.countEvent(Metrics.EVENT_TYPE.EXTENSIONS,"registry","cachedUse");let registry=JSON.parse(registryJson);_populateExtensions(registry=_filterIncompatibleEntries(registry)),pendingDownloadRegistry.resolve()},0),pendingDownloadRegistry.alreadyResolvedFromCache=!0):_getLocalRegistry().then(localRegistry=>{localRegistry&&pendingDownloadRegistry&&!pendingDownloadRegistry.alreadyResolvedFromCache&&(console.log("Using outdated local extension registry as no cached registry found."),Metrics.countEvent(Metrics.EVENT_TYPE.EXTENSIONS,"registry","outdatedUse"),_populateExtensions(localRegistry=_filterIncompatibleEntries(localRegistry)),pendingDownloadRegistry.resolve(),pendingDownloadRegistry.alreadyResolvedFromCache=!0)}),_shouldUpdateExtensionRegistry().then(_updateRegistry).catch(()=>{console.log("Registry update skipped")}),_patchDownloadCounts()}),pendingDownloadRegistry.promise()}function _handleExtensionLoad(e,baseURL){function setData(metadata){let locationType,id=metadata.name,userExtensionPath=ExtensionLoader.getUserExtensionPath(),path=baseURL;if(Phoenix.VFS.getPathForVirtualServingURL(baseURL)&&(path=Phoenix.VFS.getPathForVirtualServingURL(baseURL)),metadata.title=metadata.title||metadata.name,0===path.indexOf(userExtensionPath))locationType=LOCATION_USER;else{var segments=path.split("/"),parent;segments.length>2&&(parent=segments[segments.length-2]),locationType="dev"===parent?LOCATION_DEV:"default"===parent?LOCATION_DEFAULT:"user"===parent?LOCATION_USER:LOCATION_UNKNOWN}extensions[id]||(extensions[id]={}),extensions[id].installInfo={metadata:metadata,path:baseURL,locationType:locationType,status:"loadFailed"===e.type?START_FAILED:"disabled"===e.type?DISABLED:ENABLED},synchronizeEntry(id),loadTheme(id),exports.trigger("statusChange",id)}function deduceMetadata(){const match=baseURL.match(/\/([^\/]+)$/),name=match&&match[1]||baseURL,metadata={name:name,title:name};return metadata}ExtensionUtils.loadMetadata(baseURL).done(function(metadata){setData(metadata)}).fail(function(disabled){var metadata=deduceMetadata();metadata.disabled=disabled,setData(metadata)})}function getCompatibilityInfoForVersion(extVersion,apiVersion){var requiredVersion=extVersion.brackets||extVersion.engines&&extVersion.engines.brackets,result={};if(result.isCompatible=!requiredVersion||semver.satisfies(apiVersion,requiredVersion),result.isCompatible)result.compatibleVersion=extVersion.version;else if("<"===requiredVersion.charAt(0))result.requiresNewer=!1;else if(">"===requiredVersion.charAt(0))result.requiresNewer=!0;else if("~"===requiredVersion.charAt(0)){var compareVersion=requiredVersion.slice(1);compareVersion.match(/^[0-9]+$/)?compareVersion+=".0.0":compareVersion.match(/^[0-9]+\.[0-9]+$/)&&(compareVersion+=".0"),result.requiresNewer=semver.lt(apiVersion,compareVersion)}return result}function getCompatibilityInfo(entry,apiVersion){if(!entry.versions){var fallback=getCompatibilityInfoForVersion(entry.metadata,apiVersion);return fallback.isCompatible&&(fallback.isLatestVersion=!0),fallback}var i=entry.versions.length-1,latestInfo=getCompatibilityInfoForVersion(entry.versions[i],apiVersion);if(latestInfo.isCompatible)return latestInfo.isLatestVersion=!0,latestInfo;for(i--;i>=0;i--){var compatInfo=getCompatibilityInfoForVersion(entry.versions[i],apiVersion);if(compatInfo.isCompatible)return compatInfo.isLatestVersion=!1,compatInfo.requiresNewer=latestInfo.requiresNewer,compatInfo}return latestInfo}function getExtensionURL(id,version){return`${brackets.config.extension_url}${id}-${version}.zip`}function remove(id){var result=new $.Deferred;return extensions[id]&&extensions[id].installInfo?Package.remove(extensions[id].installInfo.path).done(function(){extensions[id].installInfo=null,result.resolve(),exports.trigger("statusChange",id)}).fail(function(err){result.reject(err)}):result.reject(StringUtils.format(Strings.EXTENSION_NOT_INSTALLED,id)),result.promise()}function _enableOrDisable(id,enable){var result=new $.Deferred,extension=extensions[id];return extension&&extension.installInfo?Package[enable?"enable":"disable"](extension.installInfo.path).done(function(){extension.installInfo.status=enable?ENABLED:DISABLED,extension.installInfo.metadata.disabled=!enable,result.resolve(),exports.trigger("statusChange",id)}).fail(function(err){result.reject(err)}):result.reject(StringUtils.format(Strings.EXTENSION_NOT_INSTALLED,id)),result.promise()}function disable(id){return _enableOrDisable(id,!1)}function enable(id){return _enableOrDisable(id,!0)}function update(id,packagePath,keepFile){return Package.installUpdate(packagePath,id).done(function(){keepFile||FileSystem.getFileForPath(packagePath).unlink()})}function cleanupUpdates(){Object.keys(_idsToUpdate).forEach(function(id){var installResult=_idsToUpdate[id],keepFile=installResult.keepFile,filename=installResult.localPath;filename&&!keepFile&&FileSystem.getFileForPath(filename).unlink()}),_idsToUpdate={}}function unmarkAllForRemoval(){_idsToRemove={}}function markForRemoval(id,mark){mark?_idsToRemove[id]=!0:delete _idsToRemove[id],exports.trigger("statusChange",id)}function isMarkedForRemoval(id){return!!_idsToRemove[id]}function hasExtensionsToRemove(){return Object.keys(_idsToRemove).length>0}function markForDisabling(id,mark){mark?_idsToDisable[id]=!0:delete _idsToDisable[id],exports.trigger("statusChange",id)}function isMarkedForDisabling(id){return!!_idsToDisable[id]}function hasExtensionsToDisable(){return Object.keys(_idsToDisable).length>0}function unmarkAllForDisabling(){_idsToDisable={}}function updateFromDownload(installationResult){void 0===installationResult.keepFile&&(installationResult.keepFile=!1);var installationStatus=installationResult.installationStatus;if(installationStatus===Package.InstallationStatuses.ALREADY_INSTALLED||installationStatus===Package.InstallationStatuses.NEEDS_UPDATE||installationStatus===Package.InstallationStatuses.SAME_VERSION||installationStatus===Package.InstallationStatuses.OLDER_VERSION){var id=installationResult.name;delete _idsToRemove[id],_idsToUpdate[id]=installationResult,exports.trigger("statusChange",id)}}function removeUpdate(id){var installationResult=_idsToUpdate[id];installationResult&&(installationResult.localPath&&!installationResult.keepFile&&FileSystem.getFileForPath(installationResult.localPath).unlink(),delete _idsToUpdate[id],exports.trigger("statusChange",id))}function isMarkedForUpdate(id){return!!_idsToUpdate[id]}function hasExtensionsToUpdate(){return Object.keys(_idsToUpdate).length>0}function removeMarkedExtensions(){return Async.doInParallel_aggregateErrors(Object.keys(_idsToRemove),function(id){return remove(id)})}function disableMarkedExtensions(){return Async.doInParallel_aggregateErrors(Object.keys(_idsToDisable),function(id){return disable(id)})}function updateExtensions(){return Async.doInParallel_aggregateErrors(Object.keys(_idsToUpdate),function(id){var installationResult=_idsToUpdate[id];return update(installationResult.name,installationResult.localPath,installationResult.keepFile)})}function getAvailableUpdates(){var result=[];return Object.keys(extensions).forEach(function(extensionId){var extensionInfo=extensions[extensionId];extensionInfo.installInfo&&extensionInfo.registryInfo&&extensionInfo.registryInfo.updateCompatible&&result.push({id:extensionId,installVersion:extensionInfo.installInfo.metadata.version,registryVersion:extensionInfo.registryInfo.lastCompatibleVersion})}),result}function cleanAvailableUpdates(updates){return updates.reduce(function(arr,updateInfo){var extDefinition=extensions[updateInfo.id];if(!extDefinition||!extDefinition.installInfo)return arr;var installedVersion=extDefinition.installInfo.metadata.version;return semver.lt(installedVersion,updateInfo.registryVersion)&&arr.push(updateInfo),arr},[])}PreferencesManager.stateManager.definePreference(FOLDER_AUTOINSTALL,"object",void 0),PreferencesManager.definePreference("extensions.sort","string","totalDownloads",{description:Strings.SORT_EXTENSION_METHOD}),AppInit.appReady(function(){}),ExtensionLoader.on(ExtensionLoader.EVENT_EXTENSION_LOADED,_handleExtensionLoad).on(ExtensionLoader.EVENT_EXTENSION_LOAD_FAILED,_handleExtensionLoad).on(ExtensionLoader.EVENT_EXTENSION_DISABLED,_handleExtensionLoad),EventDispatcher.makeEventDispatcher(exports),exports.downloadRegistry=downloadRegistry,exports.getCompatibilityInfo=getCompatibilityInfo,exports.getExtensionURL=getExtensionURL,exports.remove=remove,exports.update=update,exports.disable=disable,exports.enable=enable,exports.extensions=extensions,exports.cleanupUpdates=cleanupUpdates,exports.markForRemoval=markForRemoval,exports.isMarkedForRemoval=isMarkedForRemoval,exports.unmarkAllForRemoval=unmarkAllForRemoval,exports.hasExtensionsToRemove=hasExtensionsToRemove,exports.markForDisabling=markForDisabling,exports.isMarkedForDisabling=isMarkedForDisabling,exports.unmarkAllForDisabling=unmarkAllForDisabling,exports.hasExtensionsToDisable=hasExtensionsToDisable,exports.updateFromDownload=updateFromDownload,exports.removeUpdate=removeUpdate,exports.isMarkedForUpdate=isMarkedForUpdate,exports.hasExtensionsToUpdate=hasExtensionsToUpdate,exports.removeMarkedExtensions=removeMarkedExtensions,exports.disableMarkedExtensions=disableMarkedExtensions,exports.updateExtensions=updateExtensions,exports.getAvailableUpdates=getAvailableUpdates,exports.cleanAvailableUpdates=cleanAvailableUpdates,exports.isExtensionTakenDown=ExtensionLoader.isExtensionTakenDown,exports.ENABLED=ENABLED,exports.DISABLED=DISABLED,exports.START_FAILED=START_FAILED,exports.LOCATION_DEFAULT=LOCATION_DEFAULT,exports.LOCATION_DEV=LOCATION_DEV,exports.LOCATION_USER=LOCATION_USER,exports.LOCATION_UNKNOWN=LOCATION_UNKNOWN,exports._reset=_reset,exports._setExtensions=_setExtensions,Phoenix.isTestWindow&&(exports._getCachedRegistry=_getCachedRegistry,exports._putCachedRegistry=_putCachedRegistry,exports._removeCachedRegistry=_removeCachedRegistry)});