UNPKG

atom-nuclide

Version:

A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.

377 lines (325 loc) 13.2 kB
Object.defineProperty(exports, '__esModule', { value: true }); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; exports.activate = activate; exports.deactivate = deactivate; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } /* @noflow */ /* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ /** * _ _ _ _ ____ _ _ ___ ____ * |\ | | | | | | | \ |___ * | \| |__| |___ |___ | |__/ |___ * _ _ _ _ _ ____ _ ____ ___ ___ ____ ____ _ _ ____ ____ ____ * | | |\ | | |___ | |___ | \ |__] |__| | |_/ |__| | __ |___ * |__| | \| | | | |___ |__/ | | | |___ | \_ | | |__] |___ * */ var _pkgCommonsAtomFeatureConfig2; function _pkgCommonsAtomFeatureConfig() { return _pkgCommonsAtomFeatureConfig2 = _interopRequireDefault(require('../pkg/commons-atom/featureConfig')); } var _fs2; function _fs() { return _fs2 = _interopRequireDefault(require('fs')); } var _assert2; function _assert() { return _assert2 = _interopRequireDefault(require('assert')); } // eslint-disable-next-line nuclide-internal/prefer-nuclide-uri var _path2; function _path() { return _path2 = _interopRequireDefault(require('path')); } var _pkgNuclideRemoteConnectionLibServiceManager2; function _pkgNuclideRemoteConnectionLibServiceManager() { return _pkgNuclideRemoteConnectionLibServiceManager2 = require('../pkg/nuclide-remote-connection/lib/service-manager'); } var _electron2; function _electron() { return _electron2 = _interopRequireDefault(require('electron')); } var _atom2; function _atom() { return _atom2 = require('atom'); } var _atomPackageDeps2; function _atomPackageDeps() { return _atomPackageDeps2 = require('atom-package-deps'); } var _packageJson2; function _packageJson() { return _packageJson2 = _interopRequireDefault(require('../package.json')); } var _configMigrator2; function _configMigrator() { return _configMigrator2 = _interopRequireDefault(require('./configMigrator')); } var remote = (_electron2 || _electron()).default.remote; (0, (_assert2 || _assert()).default)(remote != null); // Run settings migrations (0, (_configMigrator2 || _configMigrator()).default)(); // Exported "config" object var config = { installRecommendedPackages: { 'default': false, description: 'On start up, check for and install Atom packages recommended for use with Nuclide. The' + ' list of packages can be found in the <code>package-deps</code> setting in this package\'s' + ' "package.json" file. Disabling this setting will not uninstall packages it previously' + ' installed. Restart Atom after changing this setting for it to take effect.', title: 'Install Recommended Packages on Startup', type: 'boolean' }, useLocalRpc: { 'default': false, description: 'Use RPC marshalling for local services. This ensures better compatibility between the local' + ' and remote case. Useful for internal Nuclide development. Requires restart to take' + ' effect.', title: 'Use RPC for local Services.', type: 'boolean' }, use: { type: 'object', properties: {} } }; exports.config = config; var runningNuclideVersion = (_packageJson2 || _packageJson()).default.version; // Nuclide packages for Atom are called "features" var FEATURES_DIR = (_path2 || _path()).default.join(__dirname, '../pkg'); var features = {}; var disposables = undefined; var hasSetLocalRpc = false; /** * Get the "package.json" of all the features. */ (_fs2 || _fs()).default.readdirSync(FEATURES_DIR).forEach(function (item) { // Optimization: Our directories don't have periods - this must be a file if (item.indexOf('.') !== -1) { return; } var dirname = (_path2 || _path()).default.join(FEATURES_DIR, item); var filename = (_path2 || _path()).default.join(dirname, 'package.json'); try { var stat = (_fs2 || _fs()).default.statSync(filename); (0, (_assert2 || _assert()).default)(stat.isFile()); } catch (err) { if (err && err.code === 'ENOENT') { return; } } var src = (_fs2 || _fs()).default.readFileSync(filename, 'utf8'); // Optimization: Avoid JSON parsing if it can't reasonably be an Atom package if (src.indexOf('"Atom"') === -1) { return; } var pkg = JSON.parse(src); if (pkg.nuclide && pkg.nuclide.packageType === 'Atom') { (0, (_assert2 || _assert()).default)(pkg.name); features[pkg.name] = { pkg: pkg, dirname: dirname, useKeyPath: 'nuclide.use.' + pkg.name, packageModule: null }; } }); /** * Build the "config" object. This determines the config defaults and * it's what is shown by the Settings view. It includes: * (1) An entry to enable/disable each feature - called "nuclide.use.*". * (2) Each feature's merged config. * * https://atom.io/docs/api/latest/Config */ Object.keys(features).forEach(function (name) { var pkg = features[name].pkg; // Sample packages are disabled by default. They are meant for development // use only, and aren't included in Nuclide builds. var enabled = !name.startsWith('sample-'); // Entry for enabling/disabling the feature var setting = { title: 'Enable the "' + name + '" feature', description: pkg.description || '', type: 'boolean', 'default': enabled }; if (pkg.providedServices) { var provides = Object.keys(pkg.providedServices).join(', '); setting.description += '<br/>**Provides:** _' + provides + '_'; } if (pkg.consumedServices) { var consumes = Object.keys(pkg.consumedServices).join(', '); setting.description += '<br/>**Consumes:** _' + consumes + '_'; } config.use.properties[name] = setting; // Merge in the feature's config var pkgConfig = pkg.nuclide.config; if (pkgConfig) { config[name] = { type: 'object', properties: {} }; Object.keys(pkgConfig).forEach(function (key) { config[name].properties[key] = _extends({}, pkgConfig[key], { title: pkgConfig[key].title || key }); }); } }); /** * Load feature deserializers and require them. * This is coming in Atom 1.4.0 - https://github.com/atom/atom/issues/9974 */ Object.keys(features).forEach(function (name) { var _features$name = features[name]; var pkg = _features$name.pkg; var dirname = _features$name.dirname; if (pkg.nuclide.deserializers) { Object.keys(pkg.nuclide.deserializers).forEach(function (deserializerName) { var deserializerPath = pkg.nuclide.deserializers[deserializerName]; var modulePath = (_path2 || _path()).default.join(dirname, deserializerPath); atom.deserializers.add({ name: deserializerName, // https://github.com/atom/atom/blob/v1.8.0/src/package.coffee#L286-L289 deserialize: function deserialize(state, atomEnvironment) { var deserializer = require(modulePath); return deserializer(state, atomEnvironment); } }); }); } }); function activate() { // This version mismatch happens during OSS updates. After updates, Nuclide is // still in the module cache - with all of its glorious state - which usually // results in a red box of some kind because the disk content doesn't match // the expectations of the code that is in memory. var nuclidePack = atom.packages.getLoadedPackage('nuclide'); var installedPkg = JSON.parse((_fs2 || _fs()).default.readFileSync((_path2 || _path()).default.join(nuclidePack.path, 'package.json'))); var installedNuclideVersion = installedPkg.version; if (installedNuclideVersion !== runningNuclideVersion) { atom.notifications.addWarning('Nuclide\'s version has changed from\n v' + runningNuclideVersion + ' to v' + installedNuclideVersion + '.\n Reload Atom to use the new version.', { buttons: [{ className: 'icon icon-zap', onDidClick: function onDidClick() { atom.reload(); }, text: 'Reload Atom' }], dismissable: true }); return; } (0, (_assert2 || _assert()).default)(!disposables); disposables = new (_atom2 || _atom()).CompositeDisposable(); // Add the "Nuclide" menu, if it's not there already. disposables.add(atom.menu.add([{ label: 'Nuclide', submenu: [{ label: 'Version ' + runningNuclideVersion, enabled: false }] }])); // Manually manipulate the menu template order. var insertIndex = atom.menu.template.findIndex(function (item) { return item.role === 'window' || item.role === 'help'; }); if (insertIndex !== -1) { var nuclideIndex = atom.menu.template.findIndex(function (item) { return item.label === 'Nuclide'; }); var menuItem = atom.menu.template.splice(nuclideIndex, 1)[0]; var newIndex = insertIndex > nuclideIndex ? insertIndex - 1 : insertIndex; atom.menu.template.splice(newIndex, 0, menuItem); atom.menu.update(); } // Loading all of the features, then activating them what Atom does on init: // https://github.com/atom/atom/blob/v1.1.0/src/atom-environment.coffee#L625-L631 // https://atom.io/docs/api/latest/PackageManager var loaded = Object.keys(features).map(function (name) { var feature = features[name]; var enabled = atom.config.get(feature.useKeyPath); // `enabled` may be `undefined` if `atom.config.get` is called before the // the default config is built. If the feature is explicitly enabled or // disabled, then the config value will be set regardless of when // `atom.config.get` is called. var shouldEnable = typeof enabled === 'undefined' ? config.use.properties[name].default : enabled; if (shouldEnable && !feature.packageModule) { feature.packageModule = atom.packages.loadPackage(feature.dirname); if (feature.packageModule.mainModule && feature.packageModule.mainModule.config) { // Feature config is handled by the UP loader, not individual features throw new Error('"' + name + '" exported a "config"'); } return feature.packageModule; } }).filter(Boolean); if (!hasSetLocalRpc) { // setUseLocalRpc can only be called once. (0, (_pkgNuclideRemoteConnectionLibServiceManager2 || _pkgNuclideRemoteConnectionLibServiceManager()).setUseLocalRpc)((_pkgCommonsAtomFeatureConfig2 || _pkgCommonsAtomFeatureConfig()).default.get('useLocalRpc')); hasSetLocalRpc = true; } // Activate all of the loaded features. // https://github.com/atom/atom/blob/v1.1.0/src/package-manager.coffee#L431-L440 Promise.all(atom.packages.activatePackages(loaded)).then(function () { // nothing to do... }); // Watch the config to manage toggling features Object.keys(features).forEach(function (name) { var feature = features[name]; var watcher = atom.config.onDidChange(feature.useKeyPath, function (event) { if (event.newValue === true && !feature.packageModule) { feature.packageModule = atom.packages.loadPackage(feature.dirname); feature.packageModule.activate(); } else if (event.newValue === false && feature.packageModule) { safeDeactivate(name); } }); disposables.add(watcher); }); // Install public, 3rd-party Atom packages listed in this package's 'package-deps' setting. Run // this *after* other packages are activated so they can modify this setting if desired before // installation is attempted. if ((_pkgCommonsAtomFeatureConfig2 || _pkgCommonsAtomFeatureConfig()).default.get('installRecommendedPackages')) { // Workaround for restoring multiple Atom windows. This prevents having all // the windows trying to install the deps at the same time - often clobbering // each other's install. var firstWindowId = remote.BrowserWindow.getAllWindows()[0].id; var currentWindowId = remote.getCurrentWindow().id; if (firstWindowId === currentWindowId) { (0, (_atomPackageDeps2 || _atomPackageDeps()).install)('nuclide'); } } } function deactivate() { Object.keys(features).forEach(function (name) { if (features[name].packageModule) { safeDeactivate(name); } }); if (disposables) { disposables.dispose(); disposables = null; } } function safeDeactivate(name) { try { var pkg = atom.packages.getActivePackage(name); if (pkg != null) { // TODO: Atom does not unregister its activation hooks on package deactivation! // Do it manually until https://github.com/atom/atom/pull/12237 is merged. if (pkg.activationHookSubscriptions != null) { pkg.activationHookSubscriptions.dispose(); } } atom.packages.deactivatePackage(name); } catch (err) { // eslint-disable-next-line no-console console.error('Error deactivating "' + name + '": ' + err.message); } finally { features[name].packageModule = null; } }