Source: index.js

// Copyright (c) 2014. David M. Lee, II.
/*jshint unused:vars */
'use strict';

/**
 * Platform specific directory locator.
 *
 * The API's all follow the same general pattern:
 * <ul>
 *   <li>All arguments are optional. When called with no arguments, the function
 *       returns the base path, instead of one specific for an application.</li>
 *   <li>The version is only appended if the <code>appname</code> is provided.
 *   </li>
 *   <li>Windows requires the application author, in addition to the application
 *       name, for locating application specific directories. If not give, this
 *       defaults to <code>appname</code>.</li>
 *   <li>Both the OS X and XDG implementations are portable, and will run on any
 *       platform.</li>
 *   <li>Windows support is unimplemented, because reasons. When it is
 *       implemented, it will probably only run on Windows</li>
 * </ul>
 * @module appdirs
 */

var os = require('os'),
    path = require('path');

/**
 * Append the name and and version to a path.
 *
 * Both the appname and version are optional. The version is only appended if
 * the appname.
 *
 * @param {string} dir Base directory.
 * @param {string} [appname] Optional name to append.
 * @param {string} [version] Optional version to append.
 * @returns {string} Resulting path
 * @private
 */
var appendNameVersion = function (dir, appname, version) {
  if (appname) {
    dir = path.join(dir, appname);
    if (version) {
      dir = path.join(dir, version);
    }
  }
  return dir;
};

/*jshint maxlen:false */
/**
 * Windows appdirs implementation. (unimplemented)
 *
 * The standard directory structure for Windows can be found on
 * [MSDN]{@link http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120}.
 */
/*jshint maxlen:80 */
exports.windows = {
  // Judging from appdirs.py, Windows support is quite complicated.
  // Maybe another time...
  userDataDir: function (appname, appauthor, version, roaming) {
    throw new Error('Unimplemented');
  },
  userConfigDir: function (appname, appauthor, version, roaming) {
    throw new Error('Unimplemented');
  },
  userCacheDir: function (appname, appauthor, version) {
    throw new Error('Unimplemented');
  },
  siteDataDir: function (appname, appauthor, version, multipath) {
    throw new Error('Unimplemented');
  },
  siteConfigDir: function (appname, appauthor, version, multipath) {
    throw new Error('Unimplemented');
  },
  userLogDir: function (appname, appauthor, version) {
    throw new Error('Unimplemented');
  }
};

/*jshint maxlen:false */
/**
 * OS X appdirs implementation.
 *
 * The standard directory structure for OS X can be found on
 * [the apple developer site]{@link https://developer.apple.com/library/mac/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html}.
 */
/*jshint maxlen:80 */
exports.darwin = {
  userDataDir: function (appname, appauthor, version, roaming) {
    var dir = path.join(process.env.HOME, 'Library/Application Support');
    return appendNameVersion(dir, appname, version);
  },
  userConfigDir: function (appname, appauthor, version, roaming) {
    return exports.darwin.userDataDir(appname, appauthor, version, roaming);
  },
  userCacheDir: function (appname, appauthor, version) {
    var dir = path.join(process.env.HOME, 'Library/Caches');
    return appendNameVersion(dir, appname, version);
  },
  siteDataDir: function (appname, appauthor, version, multipath) {
    var dir = appendNameVersion('/Library/Application Support', appname, version);
    if (multipath) {
      return [dir];
    }
    return dir;
  },
  siteConfigDir: function (appname, appauthor, version, multipath) {
    return exports.darwin.siteDataDir(appname, appauthor, version, multipath);
  },
  userLogDir: function (appname, appauthor, version) {
    var dir = path.join(process.env.HOME, 'Library/Logs');
    return appendNameVersion(dir, appname, version);
  }
};

/*jshint maxlen:false */
/**
 * XDG appdirs implementation.
 *
 * The is the standard directory structure appdirs uses for *NIX operating
 * systems. The XDG spec can be found on
 * [the FreeDesktop standards site]{@link http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html}.
 */
/*jshint maxlen:80 */
exports.xdg = {
  userDataDir: function (appname, appauthor, version, roaming) {
    var dir = process.env.XDG_DATA_HOME ||
        path.join(process.env.HOME, '.local/share');
    return appendNameVersion(dir, appname, version);
  },
  userConfigDir: function (appname, appauthor, version, roaming) {
    var dir = process.env.XDG_CONFIG_HOME ||
        path.join(process.env.HOME, '.config');
    return appendNameVersion(dir, appname, version);
  },
  userCacheDir: function (appname, appauthor, version) {
    var dir = process.env.XDG_CACHE_HOME ||
        path.join(process.env.HOME, '.cache');
    return appendNameVersion(dir, appname, version);
  },
  siteDataDir: function (appname, appauthor, version, multipath) {
    var dirstr = process.env.XDG_DATA_DIRS ||
            ['/usr/local/share', '/usr/share'].join(path.delimiter),
        dirs = dirstr.split(path.delimiter).map(function (dir) {
          return appendNameVersion(dir, appname, version);
        });
    if (multipath) {
      return dirs;
    } else {
      return dirs[0];
    }
  },
  siteConfigDir: function (appname, appauthor, version, multipath) {
    var dirstr = process.env.XDG_CONFIG_DIRS || '/etc/xdg',
        dirs = dirstr.split(path.delimiter).map(function (dir) {
          return appendNameVersion(dir, appname, version);
        });
    if (multipath) {
      return dirs;
    } else {
      return dirs[0];
    }
  },
  userLogDir: function (appname, appauthor, version) {
    var cacheDir = exports.xdg.userCacheDir(appname, appauthor, version);
    return path.join(cacheDir, 'log');
  }
};

var impl = (function () {
  switch (os.platform()) {
    case 'win32':
      return exports.windows;
    case 'darwin':
      return exports.darwin;
    default:
      return exports.xdg;
  }
})();

/**
 * Build an AppDirs convenience object.
 *
 * @param {string} appname Application name.
 * @param {string} [appauthor] Application author. Defaults to appname.
 * @param {string} [version] Application version.
 * @param {boolean} [roaming] If true, use directory for roaming profile.
 * @param {boolean} [multipath] If true, return arrays for multipath functions
 *                              (siteDataDir, siteConfigDir).
 * @constructor
 */
var AppDirs = exports.AppDirs =
    function AppDirs(appname, appauthor, version, roaming, multipath) {
      this.appname = appname;
      this.appauthor = appauthor;
      this.version = version;
      this.roaming = roaming;
      this.multipath = multipath;
    };

/**
 * User data directory.
 * @returns {string}
 */
AppDirs.prototype.userDataDir = function () {
  return impl.userDataDir(this.appname, this.appauthor, this.version,
      this.roaming);
};

/**
 * User configuration directory.
 * @returns {string}
 */
AppDirs.prototype.userConfigDir = function () {
  return impl.userConfigDir(this.appname, this.appauthor, this.version,
      this.roaming);
};

/**
 * User cache directory.
 * @returns {string}
 */
AppDirs.prototype.userCacheDir = function () {
  return impl.userCacheDir(this.appname, this.appauthor, this.version);
};

/**
 * Site data directory.
 * @returns {string}
 */
AppDirs.prototype.siteDataDir = function () {
  return impl.siteDataDir(this.appname, this.appauthor, this.version,
      this.multipath);
};

/**
 * Site configuration directory.
 * @returns {string}
 */
AppDirs.prototype.siteConfigDir = function () {
  return impl.siteConfigDir(this.appname, this.appauthor, this.version,
      this.multipath);
};

/**
 * User log directory.
 * @returns {string}
 */
AppDirs.prototype.userLogDir = function () {
  return impl.userLogDir(this.appname, this.appauthor, this.version);
};

/**
 * Return full path to the user-specific data dir for this application.
 *
 * Typical user cache directories are:
 * <dl>
 *    <dt>Mac OS X</dt>
 *      <dd>~/Library/Application Support/{AppName}</dd>
 *    <dt>Unix</dt>
 *      <dd>~/.local/share/{AppName}/log</dd>
 *    <dt>Win 7 (not roaming)</dt>
 *      <dd>C:\Users\{username}\AppData\Local\{AppAuthor}\{AppName}</dd>
 *    <dt>Win 7 (roaming)</dt>
 *      <dd>C:\Users\{username}\AppData\Roaming\{AppAuthor}\{AppName}</dd>
 * </dl>
 *
 * @param {string} [appname] Application name. If not give, then the base user
 *    data directory is returned.
 * @param {string} [appauthor] Application author's name. This falls back to
 *    appname.
 * @param {string} [version] Optional version to append to the path. Only
 *    applied when appname is present.
 * @param {boolean} [roaming] When set, use the Windows roaming
 *    appdata directory
 * @returns {string} User data directory.
 * @function
 */
exports.userDataDir = impl.userDataDir;
/**
 * Return full path to the user-specific config dir for this application.
 *
 * Typical user data directories are:
 * <dl>
 *   <dt>Mac OS X</dt>
 *     <dd>same as user_data_dir</dd>
 *   <dt>Unix</dt>
 *     <dd>~/.config/{AppName}</dd>
 *   <dt>Windows</dt>
 *     <dd>same as user_data_dir</dd>
 * </dl>
 *
 * @param {string} [appname] Application name. If not give, then the base user
 *    config directory is returned.
 * @param {string} [appauthor] Application author's name. This falls back to
 *    appname.
 * @param {string} [version] Optional version to append to the path. Only
 *    applied when appname is present.
 * @param {boolean} [roaming] When set, use the Windows roaming
 *    appdata directory
 * @returns {string} User config directory.
 * @function
 */
exports.userConfigDir = impl.userConfigDir;
/**
 * Return full path to the user-specific cache dir for this application.
 *
 * Typical user cache directories are:
 * <dl>
 *   <dt>Mac OS X</dt>
 *     <dd>~/Library/Caches/{AppName}</dd>
 *   <dt>Unix</dt>
 *     <dd>~/.cache/{AppName}</dd>
 * </dl>
 *
 * @param {string} [appname] Application name. If not give, then the base user
 *    cache directory is returned.
 * @param {string} [appauthor] Application author's name. This falls back to
 *    appname.
 * @param {string} [version] Optional version to append to the path. Only
 *    applied when appname is present.
 * @returns {string} User cache directory
 * @function
 */
exports.userCacheDir = impl.userCacheDir;
/**
 * Return full path to the user-shared data dir for this application.
 *
 * Typical site data directories are:
 * <dl>
 *   <dt>Mac OS X</dt>
 *     <dd>/Library/Application Support/{AppName}</dd>
 *   <dt>Unix</dt>
 *     <dd>/usr/local/share/{AppName} or /usr/share/{AppName}</dd>
 * </dl>
 *
 * @param {string} [appname] Application name. If not give, then the base site
 *    data directory is returned.
 * @param {string} [appauthor] Application author's name. This falls back to
 *    appname.
 * @param {string} [version] Optional version to append to the path. Only
 *    applied when appname is present.
 * @param {boolean} [multipath] If true, on *NIX, all site data dirs are
 *                              returned.
 * @returns {string} Site data directory.
 * @function
 */
exports.siteDataDir = impl.siteDataDir;
/**
 * Return full path to the user-shared config dir for this application.
 *
 * Typical user data directories are:
 * <dl>
 *   <dt>Mac OS X</dt>
 *     <dd>same as site_data_dir</dd>
 *   <dt>Unix</dt>
 *     <dd>/etc/xdg/{AppName}</dd>
 *   <dt>Windows</dt>
 *     <dd>same as site_data_dir</dd>
 * </dl>
 *
 * @param {string} [appname] Application name. If not give, then the base site
 *    data directory is returned.
 * @param {string} [appauthor] Application author's name. This falls back to
 *    appname.
 * @param {string} [version] Optional version to append to the path. Only
 *    applied when appname is present.
 * @param {boolean} [multipath] If true, on *NIX, all site data dirs are
 *                              returned.
 * @returns {string} Site config directory.
 * @function
 */
exports.siteConfigDir = impl.siteConfigDir;
/**
 * Return full path to the user-specific log dir for this application.
 *
 * Typical user cache directories are:
 * <dl>
 *   <dt>Mac OS X</dt>
 *     <dd>~/Library/Logs/{AppName}</dd>
 *   <dt>Unix</dt>
 *     <dd>~/.cache/{AppName}/log</dd>
 * <dl>
 *
 * @param {string} [appname] Application name. If not give, then the base site
 *    data directory is returned.
 * @param {string} [appauthor] Application author's name. This falls back to
 *    appname.
 * @param {string} [version] Optional version to append to the path. Only
 *    applied when appname is present.
 * @returns {string} User log directory.
 * @function
 */
exports.userLogDir = impl.userLogDir;