.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / update-notifier / index.js
1 'use strict';
2 const spawn = require('child_process').spawn;
3 const path = require('path');
4 const format = require('util').format;
5 const importLazy = require('import-lazy')(require);
6
7 const configstore = importLazy('configstore');
8 const chalk = importLazy('chalk');
9 const semverDiff = importLazy('semver-diff');
10 const latestVersion = importLazy('latest-version');
11 const isNpm = importLazy('is-npm');
12 const isInstalledGlobally = importLazy('is-installed-globally');
13 const boxen = importLazy('boxen');
14 const xdgBasedir = importLazy('xdg-basedir');
15 const isCi = importLazy('is-ci');
16 const ONE_DAY = 1000 * 60 * 60 * 24;
17
18 class UpdateNotifier {
19         constructor(options) {
20                 options = options || {};
21                 this.options = options;
22                 options.pkg = options.pkg || {};
23
24                 // Reduce pkg to the essential keys. with fallback to deprecated options
25                 // TODO: Remove deprecated options at some point far into the future
26                 options.pkg = {
27                         name: options.pkg.name || options.packageName,
28                         version: options.pkg.version || options.packageVersion
29                 };
30
31                 if (!options.pkg.name || !options.pkg.version) {
32                         throw new Error('pkg.name and pkg.version required');
33                 }
34
35                 this.packageName = options.pkg.name;
36                 this.packageVersion = options.pkg.version;
37                 this.updateCheckInterval = typeof options.updateCheckInterval === 'number' ? options.updateCheckInterval : ONE_DAY;
38                 this.hasCallback = typeof options.callback === 'function';
39                 this.callback = options.callback || (() => {});
40                 this.disabled = 'NO_UPDATE_NOTIFIER' in process.env ||
41                         process.argv.indexOf('--no-update-notifier') !== -1 ||
42                         isCi();
43                 this.shouldNotifyInNpmScript = options.shouldNotifyInNpmScript;
44
45                 if (!this.disabled && !this.hasCallback) {
46                         try {
47                                 const ConfigStore = configstore();
48                                 this.config = new ConfigStore(`update-notifier-${this.packageName}`, {
49                                         optOut: false,
50                                         // Init with the current time so the first check is only
51                                         // after the set interval, so not to bother users right away
52                                         lastUpdateCheck: Date.now()
53                                 });
54                         } catch (err) {
55                                 // Expecting error code EACCES or EPERM
56                                 const msg =
57                                         chalk().yellow(format(' %s update check failed ', options.pkg.name)) +
58                                         format('\n Try running with %s or get access ', chalk().cyan('sudo')) +
59                                         '\n to the local update config store via \n' +
60                                         chalk().cyan(format(' sudo chown -R $USER:$(id -gn $USER) %s ', xdgBasedir().config));
61
62                                 process.on('exit', () => {
63                                         console.error('\n' + boxen()(msg, {align: 'center'}));
64                                 });
65                         }
66                 }
67         }
68         check() {
69                 if (this.hasCallback) {
70                         this.checkNpm()
71                                 .then(update => this.callback(null, update))
72                                 .catch(err => this.callback(err));
73                         return;
74                 }
75
76                 if (
77                         !this.config ||
78                         this.config.get('optOut') ||
79                         this.disabled
80                 ) {
81                         return;
82                 }
83
84                 this.update = this.config.get('update');
85
86                 if (this.update) {
87                         this.config.delete('update');
88                 }
89
90                 // Only check for updates on a set interval
91                 if (Date.now() - this.config.get('lastUpdateCheck') < this.updateCheckInterval) {
92                         return;
93                 }
94
95                 // Spawn a detached process, passing the options as an environment property
96                 spawn(process.execPath, [path.join(__dirname, 'check.js'), JSON.stringify(this.options)], {
97                         detached: true,
98                         stdio: 'ignore'
99                 }).unref();
100         }
101         checkNpm() {
102                 return latestVersion()(this.packageName).then(latestVersion => {
103                         return {
104                                 latest: latestVersion,
105                                 current: this.packageVersion,
106                                 type: semverDiff()(this.packageVersion, latestVersion) || 'latest',
107                                 name: this.packageName
108                         };
109                 });
110         }
111         notify(opts) {
112                 const suppressForNpm = !this.shouldNotifyInNpmScript && isNpm();
113                 if (!process.stdout.isTTY || suppressForNpm || !this.update) {
114                         return this;
115                 }
116
117                 opts = Object.assign({isGlobal: isInstalledGlobally()}, opts);
118
119                 opts.message = opts.message || 'Update available ' + chalk().dim(this.update.current) + chalk().reset(' → ') +
120                         chalk().green(this.update.latest) + ' \nRun ' + chalk().cyan('npm i ' + (opts.isGlobal ? '-g ' : '') + this.packageName) + ' to update';
121
122                 opts.boxenOpts = opts.boxenOpts || {
123                         padding: 1,
124                         margin: 1,
125                         align: 'center',
126                         borderColor: 'yellow',
127                         borderStyle: 'round'
128                 };
129
130                 const message = '\n' + boxen()(opts.message, opts.boxenOpts);
131
132                 if (opts.defer === false) {
133                         console.error(message);
134                 } else {
135                         process.on('exit', () => {
136                                 console.error(message);
137                         });
138
139                         process.on('SIGINT', () => {
140                                 console.error('');
141                                 process.exit();
142                         });
143                 }
144
145                 return this;
146         }
147 }
148
149 module.exports = options => {
150         const updateNotifier = new UpdateNotifier(options);
151         updateNotifier.check();
152         return updateNotifier;
153 };
154
155 module.exports.UpdateNotifier = UpdateNotifier;