-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* You can now download multiple packages at once. * Improved UX.
- Loading branch information
Showing
9 changed files
with
200 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,6 @@ | ||
.jscratesrc.json | ||
.jscrates-cache | ||
bin | ||
node_modules | ||
tars | ||
.jscratesrc.json | ||
jscrates |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,16 +43,23 @@ docker run -e HOME=/tmp -v $HOME/.jscrates/docker:/tmp/.jscrates -it --rm jscrat | |
|
||
## Commands | ||
|
||
1. `jscrates download` | ||
1. `unload` | ||
|
||
#### Description | ||
|
||
Downloads the specified package from the official repository of JSCrates. | ||
Downloads the specified package(s) from official repository of JSCrates. | ||
|
||
#### Usage | ||
|
||
```bash | ||
$ jscrates download <package-name> [version] | ||
jscrates unload <packages> | ||
``` | ||
|
||
### Example | ||
|
||
```bash | ||
jscrates unload physics [email protected] | ||
jscrates unload @jscrates/cli @jscrates/[email protected] | ||
``` | ||
|
||
2. `publish` | ||
|
@@ -66,7 +73,7 @@ Have a package that you want to share with the world? This command will help you | |
This command requires you to set or open the terminal in your project directory. | ||
|
||
```bash | ||
$ jscrates publish | ||
jscrates publish | ||
``` | ||
|
||
--- | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// @ts-check | ||
|
||
import https from 'https' | ||
import { createWriteStream, createReadStream } from 'fs' | ||
import Spinner from 'mico-spinner' | ||
import tempDirectory from 'temp-dir' | ||
import chalk from 'chalk' | ||
import tar from 'tar' | ||
import { getPackages } from '../../lib/api/actions.js' | ||
import { logError } from '../../utils/loggers.js' | ||
import upsertDir from '../../utils/upsert-dir.js' | ||
|
||
// This is the directory on the OS's temp location where | ||
// crates will be cached to enable offline operations. | ||
const cacheDir = tempDirectory + '/.jscrates-cache' | ||
// Directory in the current project where packages will | ||
// be installed (unzipped). Consider this as `node_modules` | ||
// for JSCrates | ||
const installDir = './jscrates' | ||
|
||
// Generates directory path suffixed with the package name. | ||
const suffixPackageName = (baseDir, packageName) => baseDir + '/' + packageName | ||
|
||
// Used for storing packages in cache. | ||
const generateCacheDirPath = (packageName = '') => | ||
suffixPackageName(cacheDir, packageName) | ||
|
||
// Used for unzipping packages in the CWD. | ||
const generateCratesInstallDir = (packageName = '') => | ||
suffixPackageName(installDir, packageName) | ||
|
||
// Extracts tarball name from the provided URL. | ||
const getTarballName = (tarballURL) => { | ||
return tarballURL.substring(tarballURL.lastIndexOf('/') + 1) | ||
} | ||
|
||
/** | ||
* Action to download packages from repository. | ||
* | ||
* TODO: Implement logic to check packages in cache before | ||
* requesting the API. | ||
* | ||
* @param {string[]} packages | ||
*/ | ||
async function unloadPackages(packages, ...args) { | ||
// Since we are accepting variadic arguments, other arguments can only | ||
// be accessing by spreading them. | ||
const store = args[1].__store | ||
const spinner = Spinner(`Downloading packages`) | ||
|
||
try { | ||
if (!store?.isOnline) { | ||
return logError('Internet connection is required to download packages.') | ||
} | ||
|
||
spinner.start() | ||
|
||
const response = await getPackages(packages) | ||
|
||
// `data` contains all the resolved packages metadata. | ||
// 1. Download the tarball to cache directory. | ||
// 2. Read the cached tarball & install in CWD. | ||
response?.data?.map((res) => { | ||
const timerLabel = chalk.green(`Installed \`${res.name}\` in`) | ||
console.time(timerLabel) | ||
|
||
const tarballFileName = getTarballName(res?.dist?.tarball) | ||
const cacheLocation = upsertDir(generateCacheDirPath(res?.name)) | ||
const installLocation = upsertDir(generateCratesInstallDir(res?.name)) | ||
|
||
// Create a write file stream to download the tar file | ||
const file = createWriteStream(`${cacheLocation}/${tarballFileName}`) | ||
|
||
// Initiate the HTTP request to download package archive | ||
// (.tgz) files from the cloud repository | ||
https.get(res?.dist?.tarball, function (response) { | ||
response | ||
.on('error', function () { | ||
throw 'Something went wrong downloading the package.' | ||
}) | ||
.on('data', function (data) { | ||
file.write(data) | ||
}) | ||
.on('end', function () { | ||
file.end() | ||
createReadStream(`${cacheLocation}/${tarballFileName}`).pipe( | ||
tar.x({ cwd: installLocation }) | ||
) | ||
}) | ||
}) | ||
|
||
console.timeEnd(timerLabel) | ||
}) | ||
|
||
console.log('\n') | ||
|
||
// When only a few packages are resolved, the errors array | ||
// contains list of packages that were not resolved. | ||
// We shall display these for better UX. | ||
console.group( | ||
chalk.yellow('The following errors occured during this operation:') | ||
) | ||
|
||
if (response?.errors?.length) { | ||
logError(response?.errors?.join('\n')) | ||
} | ||
|
||
console.groupEnd() | ||
|
||
console.log('\n') | ||
|
||
spinner.succeed() | ||
} catch (error) { | ||
spinner.fail() | ||
|
||
// When all the requested packages could not be resolved | ||
// API responds with status 404 and list of errors. | ||
if (Array.isArray(error)) { | ||
return logError(error.join('\n')) | ||
} | ||
|
||
return logError(error) | ||
} | ||
} | ||
|
||
export default unloadPackages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,17 @@ | ||
// @ts-check | ||
#!/usr/bin/env node | ||
|
||
import { readFile } from 'fs/promises' | ||
import { Command } from 'commander' | ||
import Configstore from 'configstore' | ||
import checkOnlineStatus from 'is-online' | ||
|
||
import { CONFIG_FILE } from './lib/constants.js' | ||
import downloadPackage from './actions/download.js' | ||
import unloadPackages from './actions/packages/unload.js' | ||
import publishPackage from './actions/publish.js' | ||
import login from './actions/auth/login.js' | ||
import register from './actions/auth/register.js' | ||
import logout from './actions/auth/logout.js' | ||
|
||
async function jscratesApp() { | ||
const packageJSON = JSON.parse(await readFile('./package.json', 'utf-8')) | ||
const isOnline = await checkOnlineStatus() | ||
const program = new Command() | ||
const configStore = new Configstore(CONFIG_FILE, { | ||
|
@@ -27,7 +25,8 @@ async function jscratesApp() { | |
program | ||
.name('jscrates') | ||
.description(`Welcome to JSCrates 📦, yet another package manager for Node`) | ||
.version(packageJSON.version, '-v, --version', 'display current version') | ||
// TODO: Find a way to read version build time. | ||
.version('0.0.0-alpha', '-v, --version', 'display current version') | ||
.hook('preAction', (_, actionCommand) => { | ||
actionCommand['__store'] = appState | ||
}) | ||
|
@@ -48,11 +47,17 @@ async function jscratesApp() { | |
.action(logout(configStore)) | ||
|
||
program | ||
.command('download') | ||
.description(`Download a package from official JSCrates registry`) | ||
.argument('<package name>', 'package to download') | ||
.argument('[version]', 'version of the package to download') | ||
.action(downloadPackage) | ||
.command('unload') | ||
.description('🔽 Download package(s) from the JSCrates registry') | ||
.argument('<packages...>', 'List of packages delimited by a space') | ||
.action(unloadPackages) | ||
.addHelpText( | ||
'after', | ||
'\nExamples:\n jscrates unload bodmas' + | ||
'\n jscrates unload [email protected]' + | ||
'\n jscrates unload binary-search merge-sort [email protected]' | ||
) | ||
.aliases(['u']) | ||
|
||
program | ||
.command('publish') | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.