a collection of lightweight TypeScript packages for AT Protocol, the protocol powering Bluesky

chore: remove pkg-size-report

mary.my.id da50d073 1eb0fe8c

verified
+1 -397
-12
README.md
··· 106 106 pnpm run -r generate 107 107 ``` 108 108 109 - ### package size reporting 110 - 111 - check bundle sizes with the `pkg-size-report` tool: 112 - 113 - > [!WARNING] 114 - > run `pnpm run -r build` first, otherwise measurements may be inaccurate. 115 - 116 - ```sh 117 - pnpm pkg-size-report # show sizes (and diff if previously saved) 118 - pnpm pkg-size-report --save # save current sizes for comparison 119 - pnpm pkg-size-report --compare # show only changed packages 120 - ```
-1
package.json
··· 15 15 "oxfmt": "^0.28.0", 16 16 "oxlint": "^1.43.0", 17 17 "oxlint-tsgolint": "^0.11.4", 18 - "pkg-size-report": "workspace:^", 19 18 "prettier": "^3.8.1", 20 19 "typescript": "~5.9.3" 21 20 }
-7
packages/internal/pkg-size-report/CHANGELOG.md
··· 1 - # pkg-size-report 2 - 3 - ## 1.0.2 4 - 5 - ### Patch Changes 6 - 7 - - b30da0e: add `declarationMap` to tsconfig
-2
packages/internal/pkg-size-report/cli.mjs
··· 1 - #!/usr/bin/env node 2 - import './dist/index.js';
-25
packages/internal/pkg-size-report/package.json
··· 1 - { 2 - "name": "pkg-size-report", 3 - "version": "1.0.2", 4 - "private": true, 5 - "description": "cli tool to compute and analyze package sizes", 6 - "license": "0BSD", 7 - "repository": { 8 - "url": "https://github.com/mary-ext/atcute", 9 - "directory": "packages/internal/pkg-size-report" 10 - }, 11 - "bin": "./cli.mjs", 12 - "type": "module", 13 - "scripts": { 14 - "build": "tsgo" 15 - }, 16 - "dependencies": { 17 - "esbuild": "^0.25.12", 18 - "js-yaml": "^4.1.1", 19 - "picocolors": "^1.1.1" 20 - }, 21 - "devDependencies": { 22 - "@types/js-yaml": "^4.0.9", 23 - "@types/node": "^25.2.1" 24 - } 25 - }
-38
packages/internal/pkg-size-report/src/bundle.ts
··· 1 - import * as fs from 'node:fs'; 2 - import * as os from 'node:os'; 3 - import * as path from 'node:path'; 4 - import * as url from 'node:url'; 5 - 6 - import * as esbuild from 'esbuild'; 7 - 8 - import { computeFolderSize } from './fs.js'; 9 - 10 - export function computeBundleInformation(entry: URL, entryQualifier: string, keepBuild = false) { 11 - const tmpDirPrefix = path.join( 12 - os.tmpdir(), 13 - `atcute-pkg-size-build--${entryQualifier.replaceAll('/', '__')}--`, 14 - ); 15 - 16 - const tmpDir = fs.mkdtempSync(tmpDirPrefix); 17 - 18 - const { metafile } = esbuild.buildSync({ 19 - bundle: true, 20 - minify: true, 21 - target: 'esnext', 22 - format: 'esm', 23 - splitting: true, 24 - outdir: tmpDir, 25 - metafile: true, 26 - entryPoints: [url.fileURLToPath(entry)], 27 - }); 28 - 29 - const tmpDirUrl = url.pathToFileURL(tmpDir); 30 - const bundledSize = computeFolderSize(tmpDirUrl, true); 31 - 32 - if (!keepBuild) fs.rmSync(tmpDir, { recursive: true }); 33 - 34 - return { 35 - metafile, 36 - ...bundledSize, 37 - }; 38 - }
-3
packages/internal/pkg-size-report/src/consts.ts
··· 1 - export const WORKSPACE_ROOT = new URL('../../../../', import.meta.url); 2 - 3 - export const PKGSIZE_FOLDER = new URL('.pkgsize/', WORKSPACE_ROOT);
-44
packages/internal/pkg-size-report/src/data.ts
··· 1 - import * as fs from 'node:fs'; 2 - 3 - import type { Metafile } from 'esbuild'; 4 - 5 - import { PKGSIZE_FOLDER } from './consts.js'; 6 - 7 - const PKGSIZE_DATA = new URL(`data.json`, PKGSIZE_FOLDER); 8 - fs.mkdirSync(PKGSIZE_FOLDER, { recursive: true }); 9 - 10 - export interface EntrypointSizeInformation { 11 - name: string; 12 - size: number; 13 - gzip: number; 14 - brotli: number; 15 - metafile: Metafile; 16 - } 17 - 18 - export interface PackageSizeInformation { 19 - name: string; 20 - installSize: number; 21 - entries: EntrypointSizeInformation[]; 22 - } 23 - 24 - export function saveSizeData(data: PackageSizeInformation[]): void { 25 - const json = JSON.stringify(data, (k, v) => (k === 'metafile' ? void 0 : v), '\t'); 26 - fs.writeFileSync(PKGSIZE_DATA, json); 27 - } 28 - 29 - export function readSizeData(): PackageSizeInformation[] | null { 30 - if (!fs.existsSync(PKGSIZE_DATA)) return null; 31 - 32 - const json = fs.readFileSync(PKGSIZE_DATA, 'utf8'); 33 - return JSON.parse(json); 34 - } 35 - 36 - export function saveEsbuildMetafiles(data: PackageSizeInformation[]): void { 37 - for (const pkg of data) { 38 - for (const { name, metafile } of pkg.entries) { 39 - const path = new URL(`${name.replaceAll('/', '__')}-esbuild-metafile.json`, PKGSIZE_FOLDER); 40 - const json = JSON.stringify(metafile, null, '\t'); 41 - fs.writeFileSync(path, json); 42 - } 43 - } 44 - }
-35
packages/internal/pkg-size-report/src/diff.ts
··· 1 - import type { PackageSizeInformation } from './data.js'; 2 - 3 - export interface DiffInformation { 4 - [key: string]: { 5 - diff: number; 6 - entries: { 7 - [key: string]: { diff: number; gzip: number; brotli: number }; 8 - }; 9 - }; 10 - } 11 - 12 - export function computeSizeDiff( 13 - data: PackageSizeInformation[], 14 - old: PackageSizeInformation[], 15 - ): DiffInformation { 16 - const diff: DiffInformation = {}; 17 - for (const pkg of data) { 18 - const oldPkg = old.find((p) => p.name == pkg.name); 19 - if (!oldPkg) continue; 20 - 21 - diff[pkg.name] = { diff: pkg.installSize - oldPkg.installSize, entries: {} }; 22 - for (const entry of pkg.entries) { 23 - const oldEntry = oldPkg.entries.find((e) => e.name === entry.name); 24 - if (!oldEntry) continue; 25 - 26 - diff[pkg.name].entries[entry.name] = { 27 - diff: entry.size - oldEntry.size, 28 - gzip: entry.gzip - oldEntry.gzip, 29 - brotli: entry.brotli - oldEntry.brotli, 30 - }; 31 - } 32 - } 33 - 34 - return diff; 35 - }
-32
packages/internal/pkg-size-report/src/fs.ts
··· 1 - import * as fs from 'node:fs'; 2 - import * as zlib from 'node:zlib'; 3 - 4 - export function computeFolderSize(folder: URL, detailed = false) { 5 - folder.pathname += '/'; 6 - let res = { size: 0, gzip: 0, brotli: 0 }; 7 - 8 - for (const entry of fs.readdirSync(folder)) { 9 - const path = new URL(entry, folder); 10 - const stat = fs.statSync(path); 11 - 12 - if (stat.isDirectory()) { 13 - const nested = computeFolderSize(path); 14 - res.size += nested.size; 15 - res.gzip += nested.gzip; 16 - res.brotli += nested.brotli; 17 - } 18 - 19 - if (stat.isFile()) { 20 - res.size += stat.size; 21 - if (detailed) { 22 - const buf = fs.readFileSync(path); 23 - const gzipBuf = zlib.gzipSync(buf); 24 - const brotliBuf = zlib.brotliCompressSync(buf); 25 - res.gzip += gzipBuf.length; 26 - res.brotli += brotliBuf.length; 27 - } 28 - } 29 - } 30 - 31 - return res; 32 - }
-67
packages/internal/pkg-size-report/src/index.ts
··· 1 - import pc from 'picocolors'; 2 - 3 - import { readSizeData, saveEsbuildMetafiles, saveSizeData } from './data.js'; 4 - import { computeSizeDiff } from './diff.js'; 5 - import { computePackageSizeInformation, getAllWorkspacePackages } from './package.js'; 6 - 7 - const TREE_SYM_HAS_NEXT = '├'; 8 - const TREE_SYM_FINAL = '└'; 9 - 10 - const FLAG_SAVE = process.argv.includes('--save'); 11 - const FLAG_SAVE_META = process.argv.includes('--save-meta'); 12 - const FLAG_COMPARE = process.argv.includes('--compare'); 13 - const FLAG_KEEP_BUILDS = process.argv.includes('--keep-builds'); 14 - 15 - function formatSize(size: number) { 16 - return `${(size / 1000).toFixed(2)}kB`.padEnd(7, ' '); 17 - } 18 - 19 - function formatDiffSize(size: number) { 20 - const str = Math.abs(size) < 1000 ? `${size}B` : `${(size / 1000).toFixed(3)}kB`; 21 - return size < 0 ? pc.green(str) : pc.red(`+${str}`); 22 - } 23 - 24 - // Get package info 25 - const packages = getAllWorkspacePackages(); 26 - const sizeData = packages.map((pkg) => computePackageSizeInformation(pkg, FLAG_KEEP_BUILDS)); 27 - 28 - // Compute diff if applicable 29 - const prevData = readSizeData(); 30 - const diff = prevData && computeSizeDiff(sizeData, prevData); 31 - 32 - // Save files 33 - if (FLAG_SAVE) saveSizeData(sizeData); 34 - if (FLAG_SAVE || FLAG_SAVE_META) saveEsbuildMetafiles(sizeData); 35 - 36 - // Print to stdout. 37 - for (const pkg of sizeData) { 38 - const pkgDiff = diff?.[pkg.name]; 39 - if (FLAG_COMPARE && pkgDiff?.diff === 0) continue; 40 - 41 - let pkgInfo = `${pkg.name.padEnd(34, ' ')}\t${formatSize(pkg.installSize).padEnd(8, ' ')} ${pc.gray('install size')}`; 42 - if (pkgDiff?.diff) pkgInfo += ` ${formatDiffSize(pkgDiff.diff)}`; 43 - 44 - console.log(pkgInfo); 45 - 46 - for (let i = 0; i < pkg.entries.length; i++) { 47 - const entry = pkg.entries[i]; 48 - const entryDiff = pkgDiff?.entries[entry.name]; 49 - 50 - const size = formatSize(entry.size); 51 - const gzip = `${formatSize(entry.gzip)} ${pc.gray('gzip')}`; 52 - const brotli = `${formatSize(entry.brotli)} ${pc.gray('brotli')}`; 53 - 54 - const treeSym = i === pkg.entries.length - 1 ? TREE_SYM_FINAL : TREE_SYM_HAS_NEXT; 55 - let entryInfo = `${treeSym}── ${entry.name.padEnd(30, ' ')}\t${treeSym}── ${size}\t${gzip}\t${brotli}`; 56 - if (entryDiff?.diff) { 57 - const size = formatDiffSize(entryDiff.diff); 58 - const gzip = formatDiffSize(entryDiff.gzip); 59 - const brotli = formatDiffSize(entryDiff.brotli); 60 - entryInfo += ` ${size}/${gzip}/${brotli}`; 61 - } 62 - 63 - console.log(entryInfo); 64 - } 65 - 66 - console.log(); 67 - }
-80
packages/internal/pkg-size-report/src/package.ts
··· 1 - import * as fs from 'node:fs'; 2 - 3 - import { load as parseYaml } from 'js-yaml'; 4 - 5 - import { computeBundleInformation } from './bundle.js'; 6 - import { WORKSPACE_ROOT } from './consts.js'; 7 - import type { PackageSizeInformation } from './data.js'; 8 - import { computeFolderSize } from './fs.js'; 9 - 10 - interface PackageJsonData { 11 - folder: URL; 12 - relpath: string; 13 - name: string; 14 - private: boolean; 15 - exports: Record<string, string | { default: string }> | null; 16 - } 17 - 18 - const PNPM_LOCKFILE = new URL('pnpm-lock.yaml', WORKSPACE_ROOT); 19 - 20 - export function getAllWorkspacePackages(): PackageJsonData[] { 21 - const pnpmLockfileYaml = fs.readFileSync(PNPM_LOCKFILE, 'utf8'); 22 - const pnpmLockfile = parseYaml(pnpmLockfileYaml) as any; 23 - const packages = Object.keys(pnpmLockfile.importers); 24 - 25 - return packages 26 - .map((p) => { 27 - const packageFolder = new URL(`${p}/`, WORKSPACE_ROOT); 28 - const packageJsonFile = new URL('package.json', packageFolder); 29 - const packageJson = fs.readFileSync(packageJsonFile, 'utf8'); 30 - return Object.assign({}, JSON.parse(packageJson), { 31 - folder: packageFolder, 32 - relpath: p, 33 - }) as PackageJsonData; 34 - }) 35 - .filter((p) => !p.private); 36 - } 37 - 38 - export function computePackageSizeInformation( 39 - pkg: PackageJsonData, 40 - keepBuilds = false, 41 - ): PackageSizeInformation { 42 - const dist = new URL('dist/', pkg.folder); 43 - const { size: installSize } = computeFolderSize(dist); 44 - 45 - const pkgSizeInformation: PackageSizeInformation = { 46 - name: pkg.name, 47 - installSize, 48 - entries: [], 49 - }; 50 - 51 - // Those are just declaration packages with no useful payload. 52 - if (pkg.relpath.includes('definitions')) return pkgSizeInformation; 53 - 54 - // CLI & what not 55 - if (!pkg.exports) return pkgSizeInformation; 56 - 57 - // Non-web packages 58 - if (pkg.name.endsWith('-node') || pkg.name.endsWith('-bun') || pkg.name.endsWith('-deno')) 59 - return pkgSizeInformation; 60 - 61 - for (const entry in pkg.exports) { 62 - if (!Object.hasOwn(pkg.exports, entry)) continue; 63 - 64 - let res = pkg.exports[entry]; 65 - if (typeof res !== 'string') { 66 - res = res.default; 67 - } 68 - 69 - const entryQualifier = pkg.name + entry.slice(1); 70 - const entryFile = new URL(res, pkg.folder); 71 - 72 - const data = computeBundleInformation(entryFile, entryQualifier, keepBuilds); 73 - pkgSizeInformation.entries.push({ 74 - name: entryQualifier, 75 - ...data, 76 - }); 77 - } 78 - 79 - return pkgSizeInformation; 80 - }
-24
packages/internal/pkg-size-report/tsconfig.json
··· 1 - { 2 - "compilerOptions": { 3 - "rootDir": "src/", 4 - "outDir": "dist/", 5 - "esModuleInterop": true, 6 - "skipLibCheck": true, 7 - "target": "ESNext", 8 - "allowJs": true, 9 - "resolveJsonModule": true, 10 - "moduleDetection": "force", 11 - "isolatedModules": true, 12 - "verbatimModuleSyntax": true, 13 - "strict": true, 14 - "noImplicitOverride": true, 15 - "noUnusedLocals": true, 16 - "noUnusedParameters": true, 17 - "noFallthroughCasesInSwitch": true, 18 - "module": "NodeNext", 19 - "sourceMap": true, 20 - "declaration": true, 21 - "declarationMap": true 22 - }, 23 - "include": ["src"] 24 - }
+1 -27
pnpm-lock.yaml
··· 35 35 oxlint-tsgolint: 36 36 specifier: ^0.11.4 37 37 version: 0.11.4 38 - pkg-size-report: 39 - specifier: workspace:^ 40 - version: link:packages/internal/pkg-size-report 41 38 prettier: 42 39 specifier: ^3.8.1 43 40 version: 3.8.1 ··· 563 560 uint8arrays: 564 561 specifier: ^5.1.0 565 562 version: 5.1.0 566 - 567 - packages/internal/pkg-size-report: 568 - dependencies: 569 - esbuild: 570 - specifier: ^0.25.12 571 - version: 0.25.12 572 - js-yaml: 573 - specifier: ^4.1.1 574 - version: 4.1.1 575 - picocolors: 576 - specifier: ^1.1.1 577 - version: 1.1.1 578 - devDependencies: 579 - '@types/js-yaml': 580 - specifier: ^4.0.9 581 - version: 4.0.9 582 - '@types/node': 583 - specifier: ^25.2.1 584 - version: 25.2.1 585 563 586 564 packages/lexicons/lex-cli: 587 565 dependencies: ··· 2763 2741 2764 2742 '@types/estree@1.0.8': 2765 2743 resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} 2766 - 2767 - '@types/js-yaml@4.0.9': 2768 - resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} 2769 2744 2770 2745 '@types/node@12.20.55': 2771 2746 resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} ··· 6590 6565 6591 6566 '@types/estree@1.0.8': {} 6592 6567 6593 - '@types/js-yaml@4.0.9': {} 6594 - 6595 6568 '@types/node@12.20.55': {} 6596 6569 6597 6570 '@types/node@25.2.1': ··· 7084 7057 '@esbuild/win32-arm64': 0.25.12 7085 7058 '@esbuild/win32-ia32': 0.25.12 7086 7059 '@esbuild/win32-x64': 0.25.12 7060 + optional: true 7087 7061 7088 7062 esbuild@0.27.3: 7089 7063 optionalDependencies: