Skip to content

Commit

Permalink
feat: use pacote to get npm package version && download tarball
Browse files Browse the repository at this point in the history
  • Loading branch information
caohuilin committed Sep 26, 2024
1 parent 5ef4541 commit 0ec33a6
Show file tree
Hide file tree
Showing 4 changed files with 819 additions and 81 deletions.
5 changes: 3 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
"dependencies": {
"@swc/helpers": "0.5.1",
"@modern-js/utils": "^2.58.0",
"axios": "^1.6.0",
"tar": "^6.1.13",
"debug": "4.3.7"
"debug": "4.3.7",
"pacote": "^18.0.6"
},
"devDependencies": {
"@modern-js/module-tools": "^2.58.0",
Expand All @@ -42,6 +42,7 @@
"@types/node": "^14.18.42",
"@types/tar": "^4.0.5",
"@types/debug": "^4.1.12",
"@types/pacote": "^11.1.8",
"typescript": "^4.9.5"
},
"sideEffects": false
Expand Down
60 changes: 24 additions & 36 deletions packages/core/src/utils/downloadPackage.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import os from 'os';
import path from 'path';
import pacote from 'pacote';
import type { Transform } from 'stream';
import { CATCHE_VALIDITY_PREIOD } from '@/constants';
import type { Logger } from '@/logger';
import { fs, semver } from '@modern-js/utils';
import axios from 'axios';
import tar from 'tar';
import { fsExists } from './fsExists';
import { getNpmTarballUrl } from './getNpmTarballUrl';
Expand Down Expand Up @@ -33,37 +35,30 @@ async function isValidCache(cacheDir: string) {
}

async function downloadAndDecompressTargz(
tarballPkg: string,
packageName: string,
version: string,
targetDir: string,
) {
const response = await axios({
method: 'get',
url: tarballPkg,
responseType: 'stream',
adapter: 'http',
});
if (response.status !== 200) {
throw new Error(
`download tar package get bad status code: ${response.status}`,
);
}
// create tmp file
const randomId = Math.floor(Math.random() * 10000);
const tempTgzFilePath = `${os.tmpdir()}/temp-${randomId}.tgz`;
): Promise<void> {
const outputPath = path.join(
os.tmpdir(),
`${packageName.replace('/', '-')}-${version}.tgz`,
);

const dest = fs.createWriteStream(tempTgzFilePath);
await pacote.tarball.stream(
`${packageName}@${version}`,
(stream: Transform) => {
return new Promise<void>((resolve, reject) => {
const writeStream = fs.createWriteStream(outputPath);
stream.pipe(writeStream);

writeStream.on('finish', resolve);
writeStream.on('error', reject);
});
},
);

await new Promise<void>((resolve, reject) => {
response.data.pipe(dest);
response.data.on('error', (err: any) => {
reject(err);
});
dest.on('finish', () => {
resolve();
});
});
await new Promise<void>((resolve, reject) => {
fs.createReadStream(tempTgzFilePath)
fs.createReadStream(outputPath)
.pipe(
tar.x({
strip: 1,
Expand Down Expand Up @@ -121,16 +116,9 @@ export async function downloadPackage(
await fs.remove(targetDir);
await fs.mkdirp(targetDir);

logger?.timing(`🕒 get ${pkgName}@${version} tarball url`);
// get package tarball
const tarballPkg = await getNpmTarballUrl(pkgName, version, {
registryUrl,
});
logger?.timing(`🕒 get ${pkgName}@${version} tarball url`, true);

logger?.timing(`🕒 download ${pkgName}@${version} tarball`);
// download tarball and compress it to target directory
await downloadAndDecompressTargz(tarballPkg, targetDir);
await downloadAndDecompressTargz(pkgName, version, targetDir);
logger?.timing(`🕒 download ${pkgName}@${version} tarball`, true);

if (install) {
Expand Down
27 changes: 7 additions & 20 deletions packages/core/src/utils/getNpmVersion.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { NPM_API_TIMEOUT } from '@/constants';
import { execa } from '@modern-js/utils';
import pacote from 'pacote';
import { timeoutPromise } from './timeoutPromise';

/**
Expand All @@ -17,27 +17,14 @@ interface Options {
export async function getNpmVersion(
packageName: string,
options?: Options,
): Promise<string | undefined> {
): Promise<string> {
const { version, registryUrl } = options || {};
const params = ['view'];
if (version) {
params.push(`${packageName}@${version}`);
} else {
params.push(packageName);
}

params.push('version');

if (registryUrl) {
params.push('--registry');
params.push(registryUrl);
}

const getPkgInfoPromise = execa('npm', params);
const { stdout } = await timeoutPromise(
getPkgInfoPromise,
const manifest = await timeoutPromise(
pacote.manifest(`${packageName}@${version}`, {
registry: registryUrl,
}),
NPM_API_TIMEOUT,
`Get npm version of '${packageName}'`,
);
return stdout;
return manifest.version;
}
Loading

0 comments on commit 0ec33a6

Please sign in to comment.