├── .gitignore
├── README.md
├── index.js
├── package-lock.json
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | test.js
3 | startTest.bat
4 | node_modules/
5 | testing/
6 | tmp/
7 | .vscode
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Auto Git Update
3 | a node.js module used for automatically updating projects from a git repository.
4 |
5 |
6 | ### Notes
7 | - This module comes in two flavors. ECMAScript & Commonjs.
8 | - The default install will be an ECMAScript module which requires use of an import statement.
9 | - __Optionally, install the commonjs module to make use of the more popular require statement.__
10 | - This module uses simple-logger (https://github.com/chegele/Logger).
11 | - To update from private repositories a personal access token needs to be provided.
12 | - During updates a backup of the old version is taken and stored in the configured tempLocation.
13 | - The remote package.json is compared to the local package.json to determine if a different version is available.
14 |
15 |
16 | ### Config Options
17 | - **repository** *String* - The url to the root of a git repository to update from.
18 | - **tempLocation** *String* - The local dir to save temporary information for Auto Git Update.
19 | - **fromReleases** *Boolean* - [optional] Updated based off of latest published GitHub release instead of branch package.json.
20 | - **branch** *String* - [optional] The branch to update from. Defaults to master.
21 | - **token** *String* - [optional] A personal access token used for accessions private repositories.
22 | - **ignoreFiles** *Array[String]* - [optional] An array of files to not install when updating. Useful for config files.
23 | - **executeOnComplete** *String* - [optional] A command to execute after an update completes. Good for restarting the app.
24 | - **exitOnComplete** *Boolean* - [optional] Use process exit to stop the app after a successful update.
25 | - **logConfig** *Object* - [optional] An object with the logging configuration, see https://github.com/chegele/Logger
26 |
27 |
28 | ### Functions
29 | - **autoUpdate()** - Updates if local package.json version is different than remote.
30 | - **compareVersions()** - Compares package.json versions without updating.
31 | - Returns an object with the properties *upToDate*, *currentVersion*, & *remoteVersion*.
32 | - **forceUpdate()** - Updates without comparing package versions.
33 | - **setLogConfig(logConfig)** - Updates logging configuration. https://github.com/chegele/Logger
34 |
35 |
36 | ### ECMAScript Example (default)
37 | ```
38 | npm i auto-git-update
39 | ```
40 | ```
41 | import AutoGitUpdate from 'auto-git-update';
42 |
43 | const config = {
44 | repository: 'https://github.com/chegele/BackupPurger',
45 | fromReleases: true,
46 | tempLocation: 'C:/Users/scheg/Desktop/tmp/',
47 | ignoreFiles: ['util/config.js'],
48 | executeOnComplete: 'C:/Users/scheg/Desktop/worksapce/AutoGitUpdate/startTest.bat',
49 | exitOnComplete: true
50 | }
51 |
52 | const updater = new AutoGitUpdate(config);
53 |
54 | updater.autoUpdate();
55 | ```
56 |
57 |
58 | ### CommonJS Example
59 | ```
60 | npm i auto-git-update@commonjs
61 | ```
62 | ```
63 | const AutoGitUpdate = require('auto-git-update');
64 |
65 | const config = {
66 | repository: 'https://github.com/chegele/BackupPurger',
67 | fromReleases: true,
68 | tempLocation: 'C:/Users/scheg/Desktop/tmp/',
69 | ignoreFiles: ['util/config.js'],
70 | executeOnComplete: 'C:/Users/scheg/Desktop/worksapce/AutoGitUpdate/startTest.bat',
71 | exitOnComplete: true
72 | }
73 |
74 | const updater = new AutoGitUpdate(config);
75 |
76 | updater.autoUpdate();
77 | ```
78 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 |
2 | import path from 'path';
3 | import fs from 'fs-extra';
4 | import {spawn, exec} from 'child_process';
5 | import https from 'https';
6 | import appRootPath from 'app-root-path';
7 | import git from 'simple-git';
8 | import Logger from 'chegs-simple-logger';
9 |
10 | /**
11 | * @typedef {Object} Config - Configuration for Auto Git Update
12 | * @property {String} repository - The url to the root of a git repository to update from, or /latest GitHub release.
13 | * @property {String} branch - The branch to update from. Defaults to master.
14 | * @property {Boolean} fromReleases - Updated based off of latest published GitHub release instead of branch package.json.
15 | * @property {String} token - A personal access token used for accessions private repositories.
16 | * @property {Logger.Options} logConfig - An object with the logging configuration, see https://github.com/chegele/Logger
17 | * @property {String} tempLocation - The local dir to save temporary information for Auto Git Update.
18 | * @property {Array[String]} ignoreFiles - An array of files to not install when updating. Useful for config files.
19 | * @property {String} executeOnComplete - A command to execute after an update completes. Good for restarting the app.
20 | * @property {Boolean} exitOnComplete - Use process exit to stop the app after a successful update.
21 | */
22 |
23 | /** @type {Config} */
24 | let config = {}
25 |
26 | // Subdirectories to use within the configured tempLocation from above.
27 | const cloneSubdirectory = '/AutoGitUpdate/repo/';
28 | const backupSubdirectory = '/AutoGitUpdate/backup/';
29 |
30 | // Enable during testing to prevent overwrite of Auto Git Update
31 | const testing = false;
32 |
33 | // Create a new simple logger. This can be updated to use a new configuration by calling setLogConfig()
34 | // https://github.com/chegele/Logger
35 | let log = new Logger({});
36 | log.logGeneral = true;
37 | log.logWarning = true;
38 | log.logError = true;
39 | log.logDetail = false;
40 | log.logDebug = false;
41 |
42 | // Toggles if performing async setup task
43 | let ready = true;
44 |
45 | export default class AutoGitUpdate {
46 | /**
47 | * Creates an object which can be used to automatically update an application from a remote git repository.
48 | * @param {Config} updateConfig
49 | */
50 | constructor(updateConfig) {
51 | // validate config has required properties
52 | if (updateConfig == undefined) throw new Error('You must pass a config object to AutoGitUpdate.');
53 | if (updateConfig.repository == undefined) throw new Error('You must include a repository link.');
54 | if (updateConfig.branch == undefined) updateConfig.branch = 'master';
55 | if (updateConfig.tempLocation == undefined) throw new Error('You must define a temp location for cloning the repository');
56 |
57 | // Update the logger configuration if provided.
58 | if (updateConfig.logConfig) this.setLogConfig(updateConfig.logConfig);
59 |
60 | // Update config and retrieve current tag if configured to use releases
61 | config = updateConfig;
62 | if (config.fromReleases) {
63 | ready = false;
64 | setBranchToReleaseTag(config.repository);
65 | }
66 |
67 | // Validate that Auto Git Update is being used as a dependency or testing is enabled
68 | // This is to prevent the Auto Git Update module from being overwritten on accident during development
69 | if (!testing) {
70 | let file = path.join(appRootPath.path, 'package.json');
71 | let appPackage = fs.readFileSync(file);
72 | appPackage = JSON.parse(appPackage);
73 | if (appPackage.name == 'auto-git-update') throw new Error('Auto Git Update is not being ran as a dependency & testing is not enabled.');
74 | }
75 |
76 | }
77 |
78 | /**
79 | * Checks local version against the remote version & then updates if different.
80 | */
81 | async autoUpdate() {
82 | while (!ready) { await sleep(1000); log.general('Auto Git Update - Not ready to update...')};
83 | let versionCheck = await this.compareVersions();
84 | if (versionCheck.upToDate) return true;
85 | return await this.forceUpdate();
86 | }
87 |
88 | /**
89 | * @typedef VersionResults
90 | * @param {Boolean} UpToDate - If the local version is the same as the remote version.
91 | * @param {String} currentVersion - The version of the local application.
92 | * @param {String} remoteVersion - The version of the application in the git repository.
93 | *
94 | * Checks the local version of the application against the remote repository.
95 | * @returns {VersionResults} - An object with the results of the version comparison.
96 | */
97 | async compareVersions() {
98 | try {
99 | log.general('Auto Git Update - Comparing versions...');
100 | let currentVersion = readAppVersion();
101 | let remoteVersion = await readRemoteVersion();
102 | log.general('Auto Git Update - Current version: ' + currentVersion);
103 | log.general('Auto Git Update - Remote Version: ' + remoteVersion);
104 | if (currentVersion == remoteVersion) return {upToDate: true, currentVersion};
105 | return {upToDate: false, currentVersion, remoteVersion};
106 | }catch(err) {
107 | log.error('Auto Git Update - Error comparing local and remote versions.');
108 | log.error(err);
109 | return {upToDate: false, currentVersion: 'Error', remoteVersion: 'Error'}
110 | }
111 | }
112 |
113 | /**
114 | * Clones the git repository, purges ignored files, and installs the update over the local application.
115 | * A backup of the application is created before the update is installed.
116 | * If configured, a completion command will be executed and the process for the app will be stopped.
117 | * @returns {Boolean} The result of the update.
118 | */
119 | async forceUpdate() {
120 | try {
121 | log.general('Auto Git Update - Updating application from ' + config.repository);
122 | await downloadUpdate();
123 | await backupApp();
124 | await installUpdate();
125 | await installDependencies();
126 | log.general('Auto Git Update - Finished installing updated version.');
127 | if (config.executeOnComplete) await promiseBlindExecute(config.executeOnComplete);
128 | if (config.exitOnComplete) process.exit(1);
129 | return true;
130 | }catch(err) {
131 | log.error('Auto Git Update - Error updating application');
132 | log.error(err);
133 | return false;
134 | }
135 | }
136 |
137 | /**
138 | * Updates the simple logger to use the provided configuration.
139 | * Reference the readme for configuration options.
140 | * https://github.com/chegele/Logger
141 | * @param {Logger.Options} logConfig - An object with the logging configuration
142 | */
143 | setLogConfig(logConfig) {
144 | log = new Logger(logConfig);
145 | }
146 |
147 | }
148 |
149 | ////////////////////////////
150 | // AUTO GIT UPDATE FUNCTIONS
151 |
152 | /**
153 | * Creates a backup of the application, including node modules.
154 | * The backup is stored in the configured tempLocation. Only one backup is kept at a time.
155 | */
156 | async function backupApp() {
157 | let destination = path.join(config.tempLocation, backupSubdirectory);
158 | log.detail('Auto Git Update - Backing up app to ' + destination);
159 | await fs.ensureDir(destination);
160 | await fs.copy(appRootPath.path, destination, {dereference: true});
161 | return true;
162 | }
163 |
164 | /**
165 | * Downloads the update from the configured git repository.
166 | * The repo is cloned to the configured tempLocation.
167 | */
168 | async function downloadUpdate() {
169 | // Inject token for private repositories
170 | let repo = config.repository;
171 | if (config.token) {
172 | repo = repo.replace('http://', '').replace('https://', '');
173 | repo = `https://${config.token}@${repo}`;
174 | }
175 |
176 | // Empty destination directory & clone repo
177 | let destination = path.join(config.tempLocation, cloneSubdirectory);
178 | log.detail('Auto Git Update - Cloning ' + repo);
179 | log.detail('Auto Git Update - Destination: ' + destination);
180 | await fs.ensureDir(destination);
181 | await fs.emptyDir(destination);
182 | await promiseClone(repo, destination, config.branch);
183 | return true;
184 | }
185 |
186 | /**
187 | * Runs npm install to update/install application dependencies.
188 | */
189 | function installDependencies() {
190 | return new Promise(function(resolve, reject) {
191 | //If testing is enabled, use alternative path to prevent overwrite of app.
192 | let destination = testing ? path.join(appRootPath.path, '/testing/'): appRootPath.path;
193 | log.detail('Auto Git Update - Installing application dependencies in ' + destination);
194 | // Generate and execute command
195 | let command = `cd ${destination} && npm install`;
196 | let child = exec(command);
197 |
198 | // Wait for results
199 | child.stdout.on('end', resolve);
200 | child.stdout.on('data', data => log.general('Auto Git Update - npm install: ' + data.replace(/\r?\n|\r/g, '')));
201 | child.stderr.on('data', data => {
202 | if (data.toLowerCase().includes('error')) {
203 | // npm passes warnings as errors, only reject if "error" is included
204 | data = data.replace(/\r?\n|\r/g, '');
205 | log.error('Auto Git Update - Error installing dependencies');
206 | log.error('Auto Git Update - ' + data);
207 | reject();
208 | }else{
209 | log.warning('Auto Git Update - ' + data);
210 | }
211 | });
212 | });
213 | }
214 |
215 | /**
216 | * Purge ignored files from the update, copy the files to the app directory, and install new modules
217 | * The update is installed from the configured tempLocation.
218 | */
219 | async function installUpdate() {
220 | // Remove ignored files from the new version
221 | if (config.ignoreFiles) {
222 | log.detail('Auto Git Update - Purging ignored files from the update');
223 | config.ignoreFiles.forEach(file => {
224 | file = path.join(config.tempLocation, cloneSubdirectory, file);
225 | log.detail('Auto Git Update - Removing ' + file);
226 | fs.unlinkSync(file);
227 | });
228 | }
229 |
230 | // Install updated files
231 | let source = path.join(config.tempLocation, cloneSubdirectory);
232 | //If testing is enabled, use alternative path to prevent overwrite of app.
233 | let destination = testing ? path.join(appRootPath.path, '/testing/'): appRootPath.path;
234 | log.detail('Auto Git Update - Installing update...');
235 | log.detail('Auto Git Update - Source: ' + source);
236 | log.detail('Auto Git Update - Destination: ' + destination);
237 | await fs.ensureDir(destination);
238 | await fs.copy(source, destination);
239 | return true;
240 | }
241 |
242 | /**
243 | * Reads the applications version from the package.json file.
244 | */
245 | function readAppVersion() {
246 | let file = path.join(appRootPath.path, 'package.json');
247 | log.detail('Auto Git Update - Reading app version from ' + file);
248 | let appPackage = fs.readFileSync(file);
249 | return JSON.parse(appPackage).version;
250 | }
251 |
252 | /**
253 | * Reads the applications version from the git repository.
254 | */
255 | async function readRemoteVersion() {
256 | // Generate request details
257 | let options = {}
258 | let url = config.repository + `/${config.branch}/package.json`;
259 | if (url.includes('github')) url = url.replace('github.com', 'raw.githubusercontent.com');
260 | if (config.token) options.headers = {Authorization: `token ${config.token}`}
261 | log.detail('Auto Git Update - Reading remote version from ' + url);
262 | // Send request for repositories raw package.json file
263 | try {
264 | let body = await promiseHttpsRequest(url, options);
265 | let remotePackage = JSON.parse(body);
266 | let version = remotePackage.version;
267 | return version;
268 | }catch(err) {
269 | if (err = 404) throw new Error('This repository requires a token or does not exist. \n ' + url);
270 | throw err;
271 | }
272 | }
273 |
274 |
275 | /**
276 | * Updates the configuration for this updater to use the latest release as the repo branch
277 | * @param {String} repository - The link to the repo
278 | */
279 | async function setBranchToReleaseTag(repository) {
280 | // Validate the configuration & generate request details
281 | let options = {headers: {"User-Agent": "Auto-Git-Update - " + repository}}
282 | if (config.token) options.headers.Authorization = `token ${config.token}`;
283 | repository = repository.toLocaleLowerCase().replace('github.com/', 'api.github.com/repos/');
284 | if (!repository.includes('github')) throw new Error('fromReleases is enabled but this does not seem to be a GitHub repo.');
285 | if (repository.endsWith('/')) repository = repository.slice(0, -1);
286 | const url = (repository + '/releases/latest')
287 | log.general('Auto Git Update - Checking release tag from ' + url);
288 |
289 | // Attempt to identify the tag/version of the latest release
290 | try {
291 | let body = await promiseHttpsRequest(url, options);
292 | let response = JSON.parse(body);
293 | let tag = response.tag_name;
294 | config.branch = tag;
295 | ready = true;
296 | }catch(err) {
297 | if (err = 404) throw new Error('This repository requires a token or does not exist. \n ' + url);
298 | throw err;
299 | }
300 | }
301 |
302 |
303 | ////////////////////////////
304 | // HELPER & MISC FUNCTIONS
305 |
306 | /**
307 | * A promise wrapper for the simple-git clone function
308 | * @param {String} repo - The url of the repository to clone.
309 | * @param {String} destination - The local path to clone into.
310 | * @param {String} branch - The repo branch to clone.
311 | */
312 | function promiseClone(repo, destination, branch) {
313 | return new Promise(function(resolve, reject) {
314 | git().clone(repo, destination, [`--branch=${branch}`], result => {
315 | if (result != null) reject(`Unable to clone repo \n ${repo} \n ${result}`);
316 | resolve();
317 | });
318 | });
319 | }
320 |
321 | /**
322 | * A promise wrapper for the child-process spawn function. Does not listen for results.
323 | * @param {String} command - The command to execute.
324 | */
325 | function promiseBlindExecute(command) {
326 | return new Promise(function(resolve, reject) {
327 | spawn(command, [], {shell: true, detached: true});
328 | setTimeout(resolve, 1000);
329 | });
330 | }
331 |
332 | /**
333 | * A promise wrapper for sending a get https requests.
334 | * @param {String} url - The Https address to request.
335 | * @param {String} options - The request options.
336 | */
337 | function promiseHttpsRequest(url, options) {
338 | return new Promise(function(resolve, reject) {
339 | let req = https.request(url, options, res => {
340 | //Construct response
341 | let body = '';
342 | res.on('data', data => {body += data});
343 | res.on('end', function() {
344 | if (res.statusCode == '200') return resolve(body);
345 | log.detail('Auto Git Update - Bad Response ' + res.statusCode);
346 | reject(res.statusCode);
347 | });
348 | });
349 | log.detail('Auto Git Update - Sending request to ' + url);
350 | log.detail('Auto Git Update - Options: ' + JSON.stringify(options));
351 | req.on('error', reject);
352 | req.end();
353 | });
354 | }
355 |
356 | async function sleep(time) {
357 | return new Promise(function(resolve, reject) {
358 | setTimeout(resolve, time);
359 | });
360 | }
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auto-git-update",
3 | "version": "1.1.1",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "auto-git-update",
9 | "version": "1.1.1",
10 | "license": "ISC",
11 | "dependencies": {
12 | "app-root-path": "^3.0.0",
13 | "chegs-simple-logger": "^1.1.0",
14 | "fs-extra": "^8.1.0",
15 | "simple-git": "^3.3.0"
16 | }
17 | },
18 | "node_modules/@kwsites/file-exists": {
19 | "version": "1.1.1",
20 | "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
21 | "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
22 | "dependencies": {
23 | "debug": "^4.1.1"
24 | }
25 | },
26 | "node_modules/@kwsites/promise-deferred": {
27 | "version": "1.1.1",
28 | "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
29 | "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
30 | },
31 | "node_modules/app-root-path": {
32 | "version": "3.0.0",
33 | "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz",
34 | "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==",
35 | "engines": {
36 | "node": ">= 6.0.0"
37 | }
38 | },
39 | "node_modules/chegs-simple-logger": {
40 | "version": "1.1.0",
41 | "resolved": "https://registry.npmjs.org/chegs-simple-logger/-/chegs-simple-logger-1.1.0.tgz",
42 | "integrity": "sha512-GR7VaKpWw3oAQV9vmjQdNlIVjxCmx15dQpj9b4m9IrGDg4unKykx74pGp8taOxnFEIU0/uqi9XGy5CHNuYwfcA==",
43 | "dependencies": {
44 | "rotating-file-stream": "^1.4.2"
45 | }
46 | },
47 | "node_modules/debug": {
48 | "version": "4.3.4",
49 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
50 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
51 | "dependencies": {
52 | "ms": "2.1.2"
53 | },
54 | "engines": {
55 | "node": ">=6.0"
56 | },
57 | "peerDependenciesMeta": {
58 | "supports-color": {
59 | "optional": true
60 | }
61 | }
62 | },
63 | "node_modules/fs-extra": {
64 | "version": "8.1.0",
65 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
66 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
67 | "dependencies": {
68 | "graceful-fs": "^4.2.0",
69 | "jsonfile": "^4.0.0",
70 | "universalify": "^0.1.0"
71 | },
72 | "engines": {
73 | "node": ">=6 <7 || >=8"
74 | }
75 | },
76 | "node_modules/graceful-fs": {
77 | "version": "4.2.3",
78 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
79 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
80 | },
81 | "node_modules/jsonfile": {
82 | "version": "4.0.0",
83 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
84 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
85 | "optionalDependencies": {
86 | "graceful-fs": "^4.1.6"
87 | }
88 | },
89 | "node_modules/ms": {
90 | "version": "2.1.2",
91 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
92 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
93 | },
94 | "node_modules/rotating-file-stream": {
95 | "version": "1.4.6",
96 | "resolved": "https://registry.npmjs.org/rotating-file-stream/-/rotating-file-stream-1.4.6.tgz",
97 | "integrity": "sha512-QS7vGxBK6sGc1mCqlmAuwV4J0fmmVCKaUgMvKbkTueZr4jdkXN3bSpTEOQxtdtAVEzi1aUqdHzwIQ0ejNn+CQg==",
98 | "deprecated": "please use version 2.x",
99 | "engines": {
100 | "node": ">=6.0"
101 | }
102 | },
103 | "node_modules/simple-git": {
104 | "version": "3.3.0",
105 | "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.3.0.tgz",
106 | "integrity": "sha512-K9qcbbZwPHhk7MLi0k0ekvSFXJIrRoXgHhqMXAFM75qS68vdHTcuzmul1ilKI02F/4lXshVgBoDll2t++JK0PQ==",
107 | "dependencies": {
108 | "@kwsites/file-exists": "^1.1.1",
109 | "@kwsites/promise-deferred": "^1.1.1",
110 | "debug": "^4.3.3"
111 | },
112 | "funding": {
113 | "type": "github",
114 | "url": "https://github.com/sponsors/steveukx/"
115 | }
116 | },
117 | "node_modules/universalify": {
118 | "version": "0.1.2",
119 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
120 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
121 | "engines": {
122 | "node": ">= 4.0.0"
123 | }
124 | }
125 | },
126 | "dependencies": {
127 | "@kwsites/file-exists": {
128 | "version": "1.1.1",
129 | "resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
130 | "integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
131 | "requires": {
132 | "debug": "^4.1.1"
133 | }
134 | },
135 | "@kwsites/promise-deferred": {
136 | "version": "1.1.1",
137 | "resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
138 | "integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
139 | },
140 | "app-root-path": {
141 | "version": "3.0.0",
142 | "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.0.0.tgz",
143 | "integrity": "sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw=="
144 | },
145 | "chegs-simple-logger": {
146 | "version": "1.1.0",
147 | "resolved": "https://registry.npmjs.org/chegs-simple-logger/-/chegs-simple-logger-1.1.0.tgz",
148 | "integrity": "sha512-GR7VaKpWw3oAQV9vmjQdNlIVjxCmx15dQpj9b4m9IrGDg4unKykx74pGp8taOxnFEIU0/uqi9XGy5CHNuYwfcA==",
149 | "requires": {
150 | "rotating-file-stream": "^1.4.2"
151 | }
152 | },
153 | "debug": {
154 | "version": "4.3.4",
155 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
156 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
157 | "requires": {
158 | "ms": "2.1.2"
159 | }
160 | },
161 | "fs-extra": {
162 | "version": "8.1.0",
163 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
164 | "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
165 | "requires": {
166 | "graceful-fs": "^4.2.0",
167 | "jsonfile": "^4.0.0",
168 | "universalify": "^0.1.0"
169 | }
170 | },
171 | "graceful-fs": {
172 | "version": "4.2.3",
173 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
174 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
175 | },
176 | "jsonfile": {
177 | "version": "4.0.0",
178 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
179 | "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
180 | "requires": {
181 | "graceful-fs": "^4.1.6"
182 | }
183 | },
184 | "ms": {
185 | "version": "2.1.2",
186 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
187 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
188 | },
189 | "rotating-file-stream": {
190 | "version": "1.4.6",
191 | "resolved": "https://registry.npmjs.org/rotating-file-stream/-/rotating-file-stream-1.4.6.tgz",
192 | "integrity": "sha512-QS7vGxBK6sGc1mCqlmAuwV4J0fmmVCKaUgMvKbkTueZr4jdkXN3bSpTEOQxtdtAVEzi1aUqdHzwIQ0ejNn+CQg=="
193 | },
194 | "simple-git": {
195 | "version": "3.3.0",
196 | "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.3.0.tgz",
197 | "integrity": "sha512-K9qcbbZwPHhk7MLi0k0ekvSFXJIrRoXgHhqMXAFM75qS68vdHTcuzmul1ilKI02F/4lXshVgBoDll2t++JK0PQ==",
198 | "requires": {
199 | "@kwsites/file-exists": "^1.1.1",
200 | "@kwsites/promise-deferred": "^1.1.1",
201 | "debug": "^4.3.3"
202 | }
203 | },
204 | "universalify": {
205 | "version": "0.1.2",
206 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
207 | "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
208 | }
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "auto-git-update",
3 | "version": "1.1.1",
4 | "description": "Update node app from git repo.",
5 | "keywords": [
6 | "auto",
7 | "automatic",
8 | "git",
9 | "github",
10 | "update",
11 | "updater"
12 | ],
13 | "main": "index.js",
14 | "type": "module",
15 | "scripts": {
16 | "test": "echo \"Error: no test specified\" && exit 1"
17 | },
18 | "repository": {
19 | "type": "git",
20 | "url": "git+https://github.com/chegele/AutoGitUpdate.git"
21 | },
22 | "author": "",
23 | "license": "ISC",
24 | "bugs": {
25 | "url": "https://github.com/chegele/AutoGitUpdate/issues"
26 | },
27 | "homepage": "https://github.com/chegele/AutoGitUpdate#readme",
28 | "dependencies": {
29 | "app-root-path": "^3.0.0",
30 | "chegs-simple-logger": "^1.1.0",
31 | "fs-extra": "^8.1.0",
32 | "simple-git": "^3.3.0"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------