44 lines
1.9 KiB
JavaScript
44 lines
1.9 KiB
JavaScript
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
import { validateAssetBuildManifest } from './asset-build-manifest.mjs'
|
|
import { resolvePythonExecutable, runPythonCommand } from './python-runtime.mjs'
|
|
|
|
const scriptDirectory = path.dirname(fileURLToPath(import.meta.url))
|
|
const pipelineDirectory = path.resolve(scriptDirectory, '..')
|
|
const workspace = path.resolve(pipelineDirectory, '..')
|
|
const argument = process.argv[2]
|
|
if (!argument) throw new Error('用法:node build-raster-assets.mjs <仓库相对清单路径>')
|
|
|
|
// 清单参数本身也必须留在工作区;source/output 的边界由 schema validator 逐项负责。
|
|
const manifestPath = path.resolve(workspace, argument)
|
|
const relativeManifest = path.relative(workspace, manifestPath)
|
|
if (relativeManifest.startsWith('..') || path.isAbsolute(relativeManifest)) {
|
|
throw new Error(`构建清单越出工作区:${argument}`)
|
|
}
|
|
|
|
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'))
|
|
validateAssetBuildManifest(manifest, workspace)
|
|
const supportedModes = new Set(['opaque-resize', 'opaque-cover-crop', 'warm-gold-frame-extract'])
|
|
for (const asset of manifest.assets) {
|
|
if (!supportedModes.has(asset.processing.mode)) {
|
|
throw new Error(`通用 raster 构建器不支持模式:${asset.processing.mode}`)
|
|
}
|
|
}
|
|
|
|
const python = resolvePythonExecutable({ pipelineDirectory })
|
|
const reportPath = path.join(pipelineDirectory, 'generated', manifest.family, 'quality-report.json')
|
|
|
|
// Node 只编排严格 schema、锁定的 Python 入口和质量报告;像素算法只存在于 Python。
|
|
runPythonCommand({
|
|
executable: python,
|
|
args: [path.join(scriptDirectory, 'build_raster_assets.py'), manifestPath, '--workspace', workspace],
|
|
cwd: workspace,
|
|
})
|
|
runPythonCommand({
|
|
executable: python,
|
|
args: [path.join(scriptDirectory, 'verify-assets.py'), manifestPath, '--workspace', workspace, '--report', reportPath],
|
|
cwd: workspace,
|
|
})
|