cmux/node_modules/xdg-app-paths/index.js
2026-01-29 17:36:26 -08:00

187 lines
6.1 KiB
JavaScript

// # spell-checker:ignore macos APPDATA LOCALAPPDATA
/* eslint-env es6, node */
'use strict';
const path = require('path');
const os = require('os');
const xdg = require('xdg-portable');
const isWinOS = /^win/i.test(process.platform);
function _normalizeOptions(options, isolated) {
options = options || {};
if (typeof options !== 'object') {
options = {isolated: options};
}
options.isolated = ((options.isolated === undefined) || (options.isolated === null)) ? isolated : options.isolated;
if (typeof options.isolated !== 'boolean') {
throw new TypeError(`Expected boolean for "isolated" argument, got ${typeof options.isolated}`);
}
return options;
}
const base = (name, isolated) => {
const object = {};
object.cache = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return path.join(xdg.cache(), options.isolated ? name : '');
};
object.config = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return path.join(xdg.config(), options.isolated ? name : '');
};
object.data = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return path.join(xdg.data(), options.isolated ? name : '');
};
object.runtime = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return xdg.runtime() ? path.join(xdg.runtime(), options.isolated ? name : '') : undefined;
};
object.state = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return path.join(xdg.state(), options.isolated ? name : '');
};
object.configDirs = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return (xdg.configDirs()).map(s => path.join(s, options.isolated ? name : ''));
};
object.dataDirs = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return (xdg.dataDirs()).map(s => path.join(s, options.isolated ? name : ''));
};
return object;
};
const windows = (name, isolated) => {
const {env} = process;
const homedir = os.homedir();
const tmpdir = os.tmpdir();
// # ref: <https://www.thewindowsclub.com/local-localnow-roaming-folders-windows-10> @@ <http://archive.is/tDEPl>
const appData = env.APPDATA || path.join(homedir || tmpdir, 'AppData', 'Roaming'); // APPDATA == "AppData/Roaming" contains data which may follow user between machines
const localAppData = env.LOCALAPPDATA || path.join(homedir || tmpdir, 'AppData', 'Local'); // LOCALAPPDATA == "AppData/Local" contains local-machine-only user data
const object = {};
// Locations for data/config/cache/state are invented (Windows doesn't have a popular convention)
object.cache = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return (!options.isolated || env.XDG_CACHE_HOME) ?
path.join(xdg.cache(), options.isolated ? name : '') :
path.join(localAppData, options.isolated ? name : '', 'Cache');
};
object.config = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
const config = (!options.isolated || env.XDG_CONFIG_HOME) ?
path.join(xdg.config(), options.isolated ? name : '') :
path.join(appData, options.isolated ? name : '', 'Config');
return config;
};
object.data = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
const data = (!options.isolated || env.XDG_DATA_HOME) ?
path.join(xdg.data(), options.isolated ? name : '') :
path.join(appData, options.isolated ? name : '', 'Data');
return data;
};
object.runtime = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return xdg.runtime() ? path.join(xdg.runtime(), options.isolated ? name : '') : undefined;
};
object.state = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
return (!options.isolated || env.XDG_STATE_HOME) ?
path.join(xdg.state(), options.isolated ? name : '') :
path.join(localAppData, options.isolated ? name : '', 'State');
};
object.configDirs = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
const dirs = [object.config(options)];
if (env.XDG_CONFIG_DIRS) {
dirs.push(...env.XDG_CONFIG_DIRS.split(path.delimiter).map(s => path.join(s, options.isolated ? name : '')));
}
return dirs;
};
object.dataDirs = (options = {isolated: null}) => {
options = _normalizeOptions(options, isolated);
const dirs = [object.data(options)];
if (env.XDG_DATA_DIRS) {
dirs.push(...env.XDG_DATA_DIRS.split(path.delimiter).map(s => path.join(s, options.isolated ? name : '')));
}
return dirs;
};
return object;
};
class _XDGAppPaths {
constructor(options = {name: null, suffix: null, isolated: true}) {
const XDGAppPaths = function (options = {name: null, suffix: null, isolated: true}) {
return new _XDGAppPaths(options);
};
this._fn = XDGAppPaths;
options = options || {};
if (typeof options !== 'object') {
options = {name: options};
}
let name = options.name || '';
if (typeof name !== 'string') {
throw new TypeError(`Expected string for "name" argument, got ${typeof name}`);
}
const suffix = options.suffix || '';
if (typeof suffix !== 'string') {
throw new TypeError(`Expected string for "suffix" argument, got ${typeof suffix}`);
}
const isolated = ((options.isolated === undefined) || (options.isolated === null)) ? true : options.isolated;
if (typeof isolated !== 'boolean') {
throw new TypeError(`Expected boolean for "isolated" argument, got ${typeof isolated}`);
}
if (!name) {
// Find a suitable application name (ref: <https://stackoverflow.com/a/46110961/43774>)
name = path.parse(process.pkg ? process.execPath : (require.main ? require.main.filename : process.argv[0])).name;
}
if (suffix) {
name += suffix;
}
this._fn.$name = () => name;
this._fn.$isolated = () => isolated;
// Connect to platform-specific API functions by extension
const extension = isWinOS ? windows(name, isolated) : base(name, isolated);
Object.keys(extension).forEach(key => {
this._fn[key] = extension[key];
});
return this._fn;
}
}
module.exports = new _XDGAppPaths();