From fcc69232ec3fdd121dce35b4cd6da55bd37ae0e7 Mon Sep 17 00:00:00 2001 From: NeoNexus DeMortis Date: Wed, 4 Oct 2023 20:05:27 -0500 Subject: [PATCH] Few minor improvements. --- README.md | 89 +++++++++++++++++++++++++++++++++++++++++++---- lib.js | 47 +++++++++++++++++-------- package-lock.json | 4 +-- package.json | 2 +- 4 files changed, 117 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index f1086dd..544b4d8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # dzfg - Download Zipball From GitHub + + ## How to use -The idea of this package, is to make downloading / extracting / installing a GitHub repo's latest release a breeze. Both in the terminal, and programmatically if you are into that kind of thing... +The idea of this package, is to make downloading / extracting / installing a GitHub repo's latest release a breeze (without creating a new repo, or Git for that matter). Both in the terminal, and programmatically, if you are into that kind of thing... ### Terminal Usage @@ -19,9 +21,12 @@ npx dzfg my-new-site neonexus/sails-react-bootstrap-webpack #### A little more advanced... You can disable the `npm install` after extraction: + `npx dzfg ` -You can also provide a specific version to download / extract: `npx dzfg ` +You can also provide a specific version to download / extract: + +`npx dzfg ` This will download `v4.2.0`, and will skip the `npm install` step: ```shell @@ -35,7 +40,7 @@ Using `.then()`: ```javascript const dzfg = require('dzfg'); -dzfg.downloadAndExtract('destination-folder', 'username/my-repo').then(() => {}); +dzfg.downloadAndExtract('new-folder', 'username/my-repo').then(() => {}); // OR @@ -49,7 +54,7 @@ Using `await`: ```javascript const dzfg = require('dzfg'); -await dzfg.downloadAndExtract('destination-folder', 'username/my-repo'); +await dzfg.downloadAndExtract('new-folder', 'username/my-repo'); // OR @@ -59,13 +64,13 @@ await dzfg.downloadAndExtract({ }); ``` -Advanced usage: +#### Advanced usage: ```javascript const dzfg = require('dzfg'); // Parameters are: destination-folder, repo, version, skipNpmInstall -await dzfg.downloadAndExtract('destination-folder', 'username/my-repo', 'v1.0.1', true); +await dzfg.downloadAndExtract('new-folder', 'username/my-repo', 'v1.0.1', true); // OR await dzfg.downloadAndExtract({ @@ -76,8 +81,78 @@ await dzfg.downloadAndExtract({ }); ``` +#### Getting version info for a repo: + +```javascript +const dzfg = require('dzfg'); + +const latestVersionInfo = await dzfg.getVersionAndUrls('username/my-repo'); + +// OR + +dzfg.getVersionAndUrls('username/my-repo').then((latestVersionInfo) => { + // Do stuff with the info... +}); +``` + +`latestVersionInfo` will look something like: + +```json5 +{ + name: 'v1.0.1 (2023-10-01)', + description: 'The version description body. This will likely contain markdown.', + version: 'v1.0.1', + isDraft: false, + isPrerelease: false, + createdAt: '2023-10-01T04:19:00Z', + publishedAt: '2023-10-01T04:19:00Z', + + // `userSite` is the HTML URL for human use: + userSite: 'https://github.com/{username/repo}/releases/tag/v1.0.1', + + // `zipball` is the URL dzfg will use internally to download the repo: + zipball: 'https://api.github.com/repos/{username/repo}/zipball/v1.0.1' +} +``` + +Get info for a specific version: + +```javascript +const dzfg = require('dzfg'); + +const latestVersionInfo = await dzfg.getVersionAndUrls('username/my-repo', 'v1.0.1'); +``` + +#### Don't forget to handle errors... + +```javascript +const dzfg = require('dzfg'); + +dzfg.downloadAndExtract('new-folder', 'username/my-repo') + .then((successMessage) => {}) + .catch((e) => {}); + +dzfg.getVersionAndUrls('username/my-repo') + .then((latestVersionInfo) => {}) + .catch((e) => {}); + +// OR + +try { + const successMessage = await dzfg.downloadAndExtract('new-folder', 'username/my-repo'); +} catch (e) { + // Display the error... +} + +try { + const latestVersionInfo = await dzfg.getVersionAndUrls('username/my-repo'); +} catch (e) { + // Display the error... +} +``` + ## This works for ALMOST any GitHub repo... As long as the repository is using GitHub's releases feature correctly, this script will work. -If a call to `https://api.github.com/repos/{repo-name-here}/releases/latest` returns a `name` and `zipball_url` properties, then the script will download the zipball from `zipball_url`. +If a call to `https://api.github.com/repos/{username/repo}/releases/latest` returns a `tag_name` and `zipball_url`, then the script will download the zipball from `zipball_url`. diff --git a/lib.js b/lib.js index 448e13e..fe7429c 100644 --- a/lib.js +++ b/lib.js @@ -5,8 +5,8 @@ const unzip = require('extract-zip'); const {spawn} = require('child_process'); const currentVersion = require('./package.json').version; -const zipFilePath = path.join(process.cwd(), 'latest-release-dzfg.zip'); -const extractionPoint = path.join(process.cwd(), 'temp-extraction-dzfg'); +const zipFilePath = path.join(process.cwd(), 'dzfg-temp.zip'); +const extractionPoint = path.join(process.cwd(), 'dzfg-temp-extraction'); const reqOptions = { headers: { @@ -109,7 +109,7 @@ const dzfg = { * @property {boolean} [skipInstall=false] - Whether to skip `npm install` or not. */ /** - * Download and Extract the zipball from a GitHub repo. Defaults to the latest release. + * Download and extract the zipball from a GitHub repo. Defaults to the latest release. * * @param {string|optionsObj} destinationFolder - The place to extract the repo into. Relative to the current working directory. * @param {string} repo - The GitHub repo to download / clone. Should be in the form: repo/my-awesome-repo @@ -121,7 +121,7 @@ const dzfg = { downloadAndExtract: (destinationFolder, repo, version = 'latest', skipInstall = false) => new Promise(async (resolve, reject) => { if (typeof destinationFolder === 'object') { if (!destinationFolder.repo || destinationFolder.repo === '' || !destinationFolder.destinationFolder || destinationFolder.destinationFolder === '') { - return reject('When calling `dzfg.downloadZipballFromGitHub(options)`, `options.repo` and `options.destinationFolder` are required!'); + return reject('When calling `dzfg.downloadAndExtract(options)`, `options.repo` and `options.destinationFolder` are required!'); } repo = destinationFolder.repo; @@ -130,7 +130,7 @@ const dzfg = { destinationFolder = destinationFolder.destinationFolder; } - const release = await dzfg.getVersionAndZipballUrl(repo, version).catch((e) => { + const release = await dzfg.getVersionAndUrls(repo, version).catch((e) => { return reject(e); }); @@ -138,7 +138,7 @@ const dzfg = { lib.downloadZipball(release.zipball).then(() => { lib.extractZipball(destinationFolder).then(async () => { if (!skipInstall && fs.existsSync(path.join(process.cwd(), destinationFolder, 'package.json'))) { - await lib.runNpmInstall(destinationFolder).catch((e) => {}); + await lib.runNpmInstall(destinationFolder).catch(() => {}); } return resolve(release.version); @@ -152,19 +152,26 @@ const dzfg = { }), /** - * @typedef versionAndZipUrl + * @typedef versionAndUrls + * @property {string} name - The name of the version. Likely the same as the version tag. + * @property {string} description - The version description. Will likely contain markdown. * @property {string} version - The version returned from the API. + * @property {boolean} isDraft - If the version is a draft or not. + * @property {boolean} isPrerelease - If this version is a prerelease version or not. + * @property {string} createdAt - The datetime stamp of the version creation. + * @property {string} publishedAt - The datetime stamp of the version publication. + * @property {string} userSite - An HTML URL for human use, to view this version info. * @property {string} zipball - The URL for the zipball. */ /** - * Get Version and Zipball URL + * Get version data and URLs * * @param {string} repo - The GitHub repo to get info for. * @param {string} [version=latest] - The version to get the zipball URL for. * - * @returns {Promise} + * @returns {Promise} */ - getVersionAndZipballUrl: (repo, version = 'latest') => new Promise((resolve, reject) => { + getVersionAndUrls: (repo, version = 'latest') => new Promise((resolve, reject) => { if (!version || version === '') { version = 'latest'; } @@ -173,7 +180,8 @@ const dzfg = { version = 'tags/' + version; // Why GitHub, why?... } - https.get('https://api.github.com/repos/' + repo + '/releases/' + version, reqOptions, (res) => { + const reqUrl = 'https://api.github.com/repos/' + repo + '/releases/' + version; + https.get(reqUrl, reqOptions, (res) => { let data = ''; res.on('data', (chunk) => { @@ -183,13 +191,22 @@ const dzfg = { res.on('end', () => { const release = JSON.parse(data); - if (release.message === 'Not Found' || !release.name || release.name === '' || !release.zipball_url || release.zipball_url === '') { - console.log(release); - return reject('The repo "' + repo + '" does not appear to be using GitHub releases, does not exist, or the version requested does not exist.'); + if (release.message === 'Not Found' || !release.tag_name || release.tag_name === '' || !release.zipball_url || release.zipball_url === '') { + return reject( + '\nVersion "' + version.replace('tags/', '') + '" of the repo "' + repo + '" does not seem to exist. Make sure the repo is using GitHub Releases.' + + '\n\nRequest made to: ' + reqUrl + '\n' + ); } return resolve({ - version: release.name, + name: release.name, + description: release.body, + version: release.tag_name, + isDraft: release.draft, + isPrerelease: release.prerelease, + createdAt: release.created_at, + publishedAt: release.published_at, + userSite: release.html_url, zipball: release.zipball_url }); }); diff --git a/package-lock.json b/package-lock.json index 1d78586..cec76ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dzfg", - "version": "0.0.2", + "version": "0.0.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dzfg", - "version": "0.0.2", + "version": "0.0.3", "license": "GPL-3.0-only", "dependencies": { "extract-zip": "2.0.1" diff --git a/package.json b/package.json index 919f3d2..e7ad4e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dzfg", - "version": "0.0.2", + "version": "0.0.3", "description": "Download Zipball From GitHub, and extract it into a new directory.", "bin": "./bin.js", "main": "./lib.js",