mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 11:56:15 -08:00
68 lines
5.0 KiB
JavaScript
68 lines
5.0 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
import { hash, refactorDir } from './releases.mjs'
|
|
|
|
const root = path.resolve(refactorDir, '..')
|
|
const filename = path.join(refactorDir, 'baselines/distribution.json')
|
|
function files(dir) {
|
|
if (!fs.existsSync(dir)) return []
|
|
return fs.readdirSync(dir, { withFileTypes: true }).flatMap(entry => entry.isDirectory() ? files(path.join(dir, entry.name)) : [path.join(dir, entry.name)])
|
|
}
|
|
function targets(value, field) {
|
|
if (typeof value === 'string') return [{ field, path: value }]
|
|
if (value && typeof value === 'object') return Object.entries(value).flatMap(([key, child]) => targets(child, `${field}.${key}`))
|
|
return []
|
|
}
|
|
export function captureDistribution() {
|
|
const initial = JSON.parse(fs.readFileSync(path.join(refactorDir, 'package-inventory.json'), 'utf8'))
|
|
return { schemaVersion: 1, task: 'BASE-05', capturedAt: new Date().toISOString(), sourceCommit: '2b7054d8',
|
|
note: 'Workspace manifest and observed resource inventory. Existing dist files may be stale; presence and hashes are not proof of a fresh build or npm publication. Only core/chapter published tarballs are verified in releases.json and consumers.json.',
|
|
packages: initial.packages.map(pkg => {
|
|
const dir = path.join(root, 'packages', pkg.name)
|
|
const manifestBytes = fs.readFileSync(path.join(dir, 'package.json'))
|
|
const manifest = JSON.parse(manifestBytes)
|
|
const resources = ['dist', 'types'].flatMap(name => files(path.join(dir, name))).map(file => ({ path: path.relative(dir, file).replaceAll('\\', '/'), bytes: fs.statSync(file).size, sha256: hash(fs.readFileSync(file)) })).sort((a, b) => a.path.localeCompare(b.path))
|
|
const declaredTargets = ['main', 'module', 'legacy', 'types', 'typings', 'exports', 'typesVersions', 'browser', 'unpkg', 'jsdelivr'].flatMap(field => targets(manifest[field], field)).map(target => {
|
|
const normalized = target.path.replace(/^\.\//, '')
|
|
const regex = new RegExp(`^${normalized.split('*').map(part => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')).join('.*')}$`)
|
|
return { ...target, observedMatches: resources.filter(resource => regex.test(resource.path)).map(resource => resource.path) }
|
|
})
|
|
const site = pkg.name === 'artplayer-vitepress'
|
|
return { name: pkg.name, kind: site ? 'documentation-site' : 'npm-library', manifest, manifestSha256Lf: hash(manifestBytes.toString().replaceAll('\r\n', '\n')), declaredTargets, resources,
|
|
sourceAssets: files(path.join(dir, 'src')).filter(file => !/\.[cm]?[jt]sx?$/.test(file)).map(file => path.relative(dir, file).replaceAll('\\', '/')).sort(),
|
|
buildOutputs: site ? ['docs/document/** via vitepress outDir'] : [`dist/${pkg.name}.js`, `dist/${pkg.name}.legacy.js`, `dist/${pkg.name}.mjs`, `docs/compiled/${pkg.name}.{js,legacy.js,mjs} copied by root build`],
|
|
distributionStatus: site ? 'Actual workflow builds a static site; no library entrypoints. Manifest lacks private:true; publication intent needs SITE/REL confirmation, not an automatic npm release.' : 'Workspace inventory; per-package published contract remains required unless listed in releases.json.',
|
|
}
|
|
}),
|
|
}
|
|
}
|
|
export function validateDistribution(report) {
|
|
const initial = JSON.parse(fs.readFileSync(path.join(refactorDir, 'package-inventory.json'), 'utf8'))
|
|
assert.equal(report.schemaVersion, 1)
|
|
assert.deepEqual(report.packages.map(pkg => pkg.name), initial.packages.map(pkg => pkg.name), 'Distribution package coverage changed')
|
|
for (const pkg of report.packages) {
|
|
assert.equal(pkg.manifest.name, pkg.name)
|
|
if (pkg.kind === 'npm-library') assert(pkg.resources.length > 0 && pkg.declaredTargets.length > 0, `Missing library resources: ${pkg.name}`)
|
|
for (const resource of pkg.resources) assert(!resource.path.startsWith('/') && !resource.path.split('/').includes('..') && /^[a-f0-9]{64}$/.test(resource.sha256), 'Invalid resource provenance')
|
|
}
|
|
assert.equal(report.packages.filter(pkg => pkg.kind === 'documentation-site').length, 1)
|
|
const thumbnail = report.packages.find(pkg => pkg.name === 'artplayer-tool-thumbnail')
|
|
assert(thumbnail.declaredTargets.some(target => target.path.endsWith('.esm.js') && !target.observedMatches.length), 'Missing thumbnail entrypoint discrepancy')
|
|
}
|
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
if (process.argv.includes('--capture')) {
|
|
assert(!fs.existsSync(filename), 'Do not overwrite the historical distribution inventory')
|
|
const report = captureDistribution()
|
|
validateDistribution(report)
|
|
fs.writeFileSync(filename, `${JSON.stringify(report, null, 2)}\n`)
|
|
}
|
|
else {
|
|
assert(process.argv.slice(2).every(arg => arg === '--check'), 'Use --capture or --check')
|
|
const report = JSON.parse(fs.readFileSync(filename, 'utf8'))
|
|
validateDistribution(report)
|
|
console.log(`Frozen distribution inventory: ${report.packages.length} packages; current build and npm contents are not revalidated by this command`)
|
|
}
|
|
}
|