UNPKG

ts-dev

Version:

Typescript development tools

121 lines 5.61 kB
/* 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