ts-dev
Version:
Typescript development tools
121 lines • 5.61 kB
JavaScript
/* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/type-annotation-spacing */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { once } from 'node:events';
import { createWriteStream } from 'node:fs';
import { open, readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { pipeline } from 'node:stream/promises';
import { createGzip } from 'node:zlib';
import { Pack } from '@sosoba/tar-stream/pack';
import npmLogger from './npmLogger';
import npmRequire from './npmRequire';
const npmBundled = npmRequire('npm-bundled');
const npmPacklist = npmRequire('npm-packlist');
const pacote = npmRequire('pacote');
const columnify = npmRequire('columnify');
export const formatBytes = (bytes) => {
const s = bytes.toString();
const l = s.length;
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
const o = 2 - (l - 1) % 3;
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
return `${Array(Math.ceil(l / 3)).fill(null).map((d, i) => s.substring(i * 3 - o, (i + 1) * 3 - o)).join(' ')} B`;
};
const MICROSECONDS_TO_MILISECONDS = 1000;
export default class PackCommand {
logger = npmLogger(this.constructor.name);
packageJsonIndentLevel = 2;
async execute(projectDirname) {
if (!projectDirname) {
projectDirname = '.';
}
const packageJson = JSON.parse(await readFile(resolve(projectDirname, 'package.json'), 'utf8'));
if (packageJson.private !== true) {
this.logger.error('Package is not private');
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
process.exit(9);
}
const options = {
path: projectDirname,
};
const bundleWalker = new npmBundled.BundleWalker(options);
bundleWalker.start();
const [bundled] = await once(bundleWalker, 'done');
this.logger.info('bundled', bundled);
const walker = new npmPacklist.Walker({
...options,
packageJsonCache: bundleWalker.packageJsonCache,
// bundled,
});
walker.start();
const [files] = await once(walker, 'done');
// this.logger.info('files', files);
const tarOptions = pacote.DirFetcher.tarCreateOptions(packageJson);
const mtime = tarOptions.mtime.getTime() / MICROSECONDS_TO_MILISECONDS;
const pack = new Pack();
const mainTgzFilename = resolve(projectDirname, `${packageJson.name}-${packageJson.version}.tgz`.replace(/^@/, '').replace(/\//, '-'));
const headers = [];
await Promise.all([
pipeline(pack.outputStream, createGzip(tarOptions.gzip), createWriteStream(mainTgzFilename)),
(async () => {
for (const fileName of files) {
const fileHandle = await open(fileName, 'r');
try {
const stat = await fileHandle.stat();
const header = {
name: `${tarOptions.prefix}${fileName}`,
uid: stat.uid,
gid: stat.gid,
mtime,
};
headers.push(header);
if (fileName === 'package.json') {
const mainPackument = {
name: packageJson.name,
version: packageJson.version,
};
const packumentBuffer = Buffer.from(JSON.stringify(mainPackument, null, this.packageJsonIndentLevel));
header.size = packumentBuffer.length;
await pack.addFile(header, packumentBuffer);
continue;
}
header.size = stat.size;
tarOptions.filter(fileName, header);
const writable = await pack.addFile(header);
await pipeline(fileHandle.createReadStream(), writable);
}
finally {
await fileHandle.close();
}
}
await pack.end();
})(),
]);
this.logger.info('mainTgzFilename', mainTgzFilename);
// TODO:
const unicode = true;
this.logger.notice('');
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
this.logger.notice('', `${unicode ? '📦 ' : 'package:'} ${packageJson.name}@${packageJson.version}`);
this.logger.notice('=== Tarball Contents ===');
this.logger.notice('', columnify(headers
.filter(f => !f.name.startsWith('node_modules/'))
.map(f => ({
path: f.name,
size: `${formatBytes(f.size ?? 0)}`,
})), { config: {
size: { align: 'right' },
} }));
if (bundled.length) {
this.logger.notice('=== Bundled Dependencies ===');
bundled.forEach(name => {
this.logger.notice('', name);
});
}
}
}
//# sourceMappingURL=pack.js.map