45 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from 'node:fs/promises';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { createHash } from 'node:crypto';
import { execFileSync } from 'node:child_process';
import { assertPiNodeVersion } from '../src/runtime-policy.mjs';
// A local portable build. Never copy a profile, credential, project or request journal.
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const [binaryArg, destinationArg, nodeArg = process.execPath, licenseArg] = process.argv.slice(2);
if (!binaryArg || !destinationArg) throw Error('指定已验证的原生程序与新的输出目录');
const destination = path.resolve(destinationArg), binary = path.resolve(binaryArg), node = path.resolve(nodeArg);
if (destination === root || destination.startsWith(root + path.sep) || !path.isAbsolute(binary)) throw Error('输出目录必须独立于源码');
const version = execFileSync(node, ['--version'], { encoding: 'utf8', windowsHide: true }).trim();
assertPiNodeVersion(version);
await fs.mkdir(path.dirname(destination), { recursive: true });
await fs.mkdir(destination); // Refuse to overwrite an existing client or user data.
await fs.copyFile(binary, path.join(destination, 'photocraft.exe'));
const agent = path.join(destination, 'agent');
await fs.mkdir(agent);
await fs.copyFile(node, path.join(agent, 'node.exe'));
const nodeLicense = licenseArg ? path.resolve(licenseArg) : path.join(path.dirname(node), 'LICENSE');
await fs.copyFile(nodeLicense, path.join(agent, 'LICENSE-Node.txt'));
for (const file of ['package.json', 'package-lock.json']) await fs.copyFile(path.join(root, file), path.join(agent, file));
for (const directory of ['src', 'node_modules']) await fs.cp(path.join(root, directory), path.join(agent, directory), { recursive: true, dereference: true });
const native = path.resolve(root, '../detail-photocraft');
for (const file of ['LICENSE-MIT', 'LICENSE-APACHE', 'NOTICE', 'ATTRIBUTION.md']) await fs.copyFile(path.join(native, file), path.join(destination, file));
await fs.writeFile(path.join(destination, '启动客户端.cmd'), '@echo off\r\nstart "" "%~dp0photocraft.exe"\r\n', 'utf8');
await fs.writeFile(path.join(destination, '本地构建说明.txt'), `由壹点详情页本地开发构建\r\n双击“启动客户端.cmd”。Agent运行组件已随包提供,无需另装Node。\r\n账户、个人Key、项目与会话保存在当前Windows用户的独立配置和凭据库,不在本目录内。\r\n本包未签名,尚不是正式安装程序。Node ${version};Pi SDK 1.3.0。\r\n`, 'utf8');
const files = [];
async function inventory(dir) {
for (const entry of await fs.readdir(dir, { withFileTypes: true })) {
const file = path.join(dir, entry.name);
if (entry.isDirectory()) await inventory(file);
else {
const bytes = await fs.readFile(file);
files.push({ path: path.relative(destination, file).replaceAll('\\', '/'), bytes: bytes.length, sha256: createHash('sha256').update(bytes).digest('hex') });
}
}
}
await inventory(destination);
const manifest = { at: new Date().toISOString(), kind: 'unsigned-local-development-portable', node: version, pi: '1.3.0', bytes: files.reduce((sum, file) => sum + file.bytes, 0), files };
await fs.writeFile(path.join(destination, 'build-manifest.json'), JSON.stringify(manifest, null, 2));
console.log(JSON.stringify({ destination, files: files.length, bytes: manifest.bytes, node: version, pi: manifest.pi }));