esm-logging/scripts/pack.ts
2025-04-25 16:17:37 +02:00

129 lines
3.7 KiB
TypeScript

import * as yargs from 'yargs';
import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as child_process from 'child_process';
const usage = `Create a tarball from a package
This script is a wrapper around \`npm pack\`.
It copies the current working directory to a temporary directory, moves the
build artifacts to the root of it and then starts \`npm pack\` from within that
directory.
This is necessary, because traditional directory layout of build environments
isn't really compatible with npm and Typescript transpilation. With
Typescript/npm packages, usually build artifacts are transpiled into the same
directory as their sources and then excluded via e.g. \`.gitignore\`. This is
how the \`npm pack\` workflow expects it. I don't like the isolation between
build artifacts and sources that come with it.`
const argv = require('yargs')
.usage('$0 [args] inputDir outputDir', usage)
.positional('inputDir', {
type: 'string',
default: 'build/production',
describe: 'path to package build'
})
.positional('outputDir', {
type: 'string',
default: 'dist',
describe: 'path to dist directory'
})
.demandOption(['inputDir', 'outputDir'])
.help()
.argv;
var cwd = process.cwd();
if (path.dirname(argv.inputDir) == path.basename(argv.inputDir)) {
throw new Error('inputDir must have a nesting depth of at least 2')
}
if ([path.sep, '.'].includes(argv.inputDir[0])) {
throw new Error(`inputDir must be a relative path inside of '${cwd}'`)
}
const buildDir = path.join(cwd, 'build', 'pack');
const nodeModulesDir = path.join(cwd, 'node_modules');
const gitDir = path.join(cwd, '.git/');
const tempDir = fs.mkdtempSync(path.join(
os.tmpdir(),
`${path.basename(cwd)}-`
));
const tempBuildPath = path.join(tempDir, argv.inputDir)
const tempBuildDir = path.join(tempDir, path.dirname(argv.inputDir))
const tempDistDir = path.join(tempDir, 'dist');
console.log(`cp: ${process.cwd()} > ${tempDir}`);
fs.cpSync(
process.cwd(),
tempDir,
{
recursive: true,
filter: (src: string, dest: string) => {
if (src.startsWith(nodeModulesDir)) { return false }
if (src.startsWith(gitDir)) { return false }
if (src.startsWith(buildDir)) { return false }
console.log(
`cp: ${path.relative(cwd, src)} > ${path.relative(cwd, dest)}`
);
return true;
}
}
);
console.log(`cp: ${tempBuildPath} > ${tempDir}`);
fs.cpSync(
tempBuildPath,
tempDir,
{
recursive: true,
filter: (src: string, dest: string) => {
console.log(
`cp (tmp): ${path.relative(tempDir, src)} > ${path.relative(tempDir, dest)}`
);
return true;
}
}
);
console.log(`rm: ${tempBuildDir}`);
fs.rmSync(tempBuildDir, { recursive: true, force: true });
console.log(`mkdir: ${tempDistDir}`);
fs.mkdirSync(tempDistDir, { recursive: true });
console.log(`npm: pack --pack-destination ${argv.outputDir}`);
if (child_process.spawnSync(
'npm',
[
'pack',
'--pack-destination',
argv.outputDir
],
{
cwd: tempDir,
stdio: "inherit"
}
).status) { process.exit(1) }
console.log(`mkdir: ${argv.outputDir}`);
fs.mkdirSync(argv.outputDir, {recursive: true});
console.log(`cp: ${tempDistDir} > ${argv.outputDir}`);
fs.cpSync(
tempDistDir,
argv.outputDir,
{
recursive: true,
filter: (src: string, dest: string) => {
console.log(
`cp (tmp): ${path.relative(tempDir, src)} > ${path.relative(tempDir, dest)}`
);
return true;
}
}
);