chore: reduce design pipeline to runtime asset checks
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
import { createHash } from 'node:crypto'
|
||||
import { readFile, readdir } from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
|
||||
import { validateAssetBuildManifest } from './asset-build-manifest.mjs'
|
||||
|
||||
const formalManifestKinds = new Set(['asset-build-manifest', 'runtime-asset-inventory'])
|
||||
const formalManifestKinds = new Set(['runtime-asset-inventory'])
|
||||
const assertOnlyFields = (value, fields, label) => {
|
||||
for (const field of Object.keys(value)) {
|
||||
if (!fields.has(field)) throw new Error(`${label} contains unknown field: ${field}`)
|
||||
@@ -88,25 +87,7 @@ export const expandRuntimeAssetInventory = async (rootManifestPath, workspace) =
|
||||
manifests.push(absolutePath)
|
||||
const manifest = await readManifest(absolutePath)
|
||||
|
||||
if (manifest.kind === 'asset-build-manifest') {
|
||||
validateAssetBuildManifest(manifest, workspacePath)
|
||||
for (const asset of manifest.assets) {
|
||||
addAsset(
|
||||
{
|
||||
id: asset.id,
|
||||
output: asset.output,
|
||||
width: asset.outputPixels.width,
|
||||
height: asset.outputPixels.height,
|
||||
// 不透明构建模式依法不声明 alpha;只有透明模式存在该对象,避免把“字段缺失”误判为清单损坏。
|
||||
alpha: asset.alpha?.required ?? false,
|
||||
maxBytes: asset.quality.maxBytes,
|
||||
provenance: 'generated-from-manifest',
|
||||
rebuildable: true,
|
||||
},
|
||||
absolutePath,
|
||||
)
|
||||
}
|
||||
} else if (manifest.kind === 'runtime-asset-inventory') {
|
||||
if (manifest.kind === 'runtime-asset-inventory') {
|
||||
assertOnlyFields(manifest, new Set(['schemaVersion', 'kind', 'scope', 'imports', 'assets']), 'runtime manifest')
|
||||
if (manifest.schemaVersion !== 1) throw new Error('runtime inventory schemaVersion must be 1')
|
||||
if (typeof manifest.scope !== 'string' || manifest.scope.trim() === '') throw new Error('runtime inventory scope is required')
|
||||
@@ -136,6 +117,23 @@ export const validateRuntimeAssetRegistry = async (rootManifestPath, workspace,
|
||||
const inventory = await expandRuntimeAssetInventory(rootManifestPath, workspacePath)
|
||||
const registered = new Set(inventory.manifests.map((manifest) => path.resolve(manifest)))
|
||||
|
||||
for (const asset of inventory.assets) {
|
||||
let binary
|
||||
try {
|
||||
binary = await readFile(resolveInsideWorkspace(workspacePath, asset.output, `${asset.id}.output`))
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') throw new Error(`missing runtime asset: ${asset.output}`)
|
||||
throw error
|
||||
}
|
||||
if (binary.length !== asset.bytes) {
|
||||
throw new Error(`${asset.id}.bytes does not match ${asset.output}`)
|
||||
}
|
||||
const digest = createHash('sha256').update(binary).digest('hex')
|
||||
if (digest !== asset.sha256) {
|
||||
throw new Error(`${asset.id}.sha256 does not match ${asset.output}`)
|
||||
}
|
||||
}
|
||||
|
||||
// 顶层注册表必须覆盖目录内每一份正式 owner。这样新增清单若没有接入全局图会立即失败,
|
||||
// output 与 id 的唯一性也就不再局限于某个业务域的 imports 闭包。
|
||||
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
||||
|
||||
Reference in New Issue
Block a user