import { createHash } from 'node:crypto'; import { access, mkdir, readFile, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { collectDirectoryFiles, createDeterministicZip, createThirdPartyLicenseBundle, } from './release-archive.mjs'; const projectRoot = path.resolve( path.dirname(fileURLToPath(import.meta.url)), '..' ); const packageJson = JSON.parse( await readFile(path.join(projectRoot, 'package.json'), 'utf8') ); const releaseDirectory = path.join(projectRoot, 'release'); const archiveName = `pdf-tools-${packageJson.version}.zip`; const archivePath = path.join(releaseDirectory, archiveName); const checksumPath = path.join( releaseDirectory, `pdf-tools-${packageJson.version}.sha256` ); const force = process.argv.slice(2).includes('--force'); const unknownArguments = process.argv .slice(2) .filter((argument) => argument !== '--force'); if (unknownArguments.length > 0) { throw new Error(`Unknown release argument: ${unknownArguments.join(', ')}`); } await mkdir(releaseDirectory, { recursive: true }); if (!force) { await assertDoesNotExist(archivePath); await assertDoesNotExist(checksumPath); } const files = await collectDirectoryFiles(path.join(projectRoot, 'dist')); files['CHANGELOG.md'] = await readFile(path.join(projectRoot, 'CHANGELOG.md')); files['SOURCE.md'] = Buffer.from( [ '# Corresponding source', '', `The source code corresponding to PDF Tools ${packageJson.version} is available at:`, '', `https://git.add-ideas.de/lotobo/pdf-tools/src/tag/v${packageJson.version}`, '', 'Third-party components remain available under the separate terms reproduced in LICENSES/.', '', ].join('\n'), 'utf8' ); files['LICENSES/pdf-tools-LICENSE.txt'] = await readFile( path.join(projectRoot, 'LICENSE') ); files['LICENSES/core-js-3.49.0-LICENSE.txt'] = await readFile( path.join(projectRoot, 'licenses', 'core-js-3.49.0-LICENSE.txt') ); files['LICENSES/THIRD-PARTY-LICENSES.txt'] = await createThirdPartyLicenseBundle(projectRoot, [ '@add-ideas/toolbox-contract', '@add-ideas/toolbox-shell-react', '@pdf-lib/standard-fonts', '@pdf-lib/upng', 'fflate', 'pako', 'pdf-lib', 'pdfjs-dist', 'react', 'react-dom', 'scheduler', 'tslib', ]); const archive = createDeterministicZip(files); const checksum = createHash('sha256').update(archive).digest('hex'); const writeFlag = force ? 'w' : 'wx'; await writeFile(archivePath, archive, { flag: writeFlag }); await writeFile(checksumPath, `${checksum} ${archiveName}\n`, { encoding: 'utf8', flag: writeFlag, }); console.log(`Created release/${archiveName}`); console.log(`SHA-256 ${checksum}`); async function assertDoesNotExist(outputPath) { try { await access(outputPath); } catch (error) { if (error && typeof error === 'object' && error.code === 'ENOENT') return; throw error; } throw new Error( `${path.relative(projectRoot, outputPath)} already exists; pass --force to replace this exact version.` ); }