96 lines
6.2 KiB
JavaScript
96 lines
6.2 KiB
JavaScript
'use strict';
|
|
const fs = require('fs'), path = require('path'), vm = require('vm');
|
|
const names = ['matching', 'stage1', 'stage2', 'stage3', 'art'];
|
|
function files(folder) {
|
|
if (!fs.existsSync(folder)) return [];
|
|
return fs.readdirSync(folder).sort().reduce((out, name) => {
|
|
const file = path.join(folder, name), stat = fs.lstatSync(file);
|
|
if (stat.isSymbolicLink()) throw Error('Unexpected symlink in build output: ' + file);
|
|
return out.concat(stat.isDirectory() ? files(file) : [file]);
|
|
}, []);
|
|
}
|
|
function pack(destination, versionFile = path.join(__dirname, '../../assets/cloud_rise/version.json')) {
|
|
const release = JSON.parse(fs.readFileSync(versionFile, 'utf8'));
|
|
if (typeof release.version !== 'string' || release.version.length > 32 || !/^\d+\.\d+\.\d+$/.test(release.version)) {
|
|
throw Error('Cloud Rise version must have three numeric parts, e.g. 1.0.0');
|
|
}
|
|
const root = path.resolve(destination), remote = path.join(root, 'remote');
|
|
const gameFile = path.join(root, 'game.json'), settingsFile = path.join(root, 'src/settings.js');
|
|
const game = JSON.parse(fs.readFileSync(gameFile, 'utf8'));
|
|
const context = { window: {} };
|
|
vm.runInNewContext(fs.readFileSync(settingsFile, 'utf8'), context);
|
|
const settings = context.window._CCSettings;
|
|
if (!settings || !settings.bundleVers) throw Error('Missing Creator bundle settings');
|
|
const server = String(settings.server || '').replace(/\/+$/, '');
|
|
if (!/^https:\/\/[^\s?#]+$/.test(server)) throw Error('Configure the WeChat HTTPS resource server before building Cloud Rise');
|
|
const entries = [];
|
|
for (const name of names) {
|
|
const folder = path.join(remote, name), version = settings.bundleVers[name];
|
|
if (!version || !fs.existsSync(path.join(folder, 'config.' + version + '.json'))) {
|
|
throw Error('Missing remote Cloud Rise bundle (enable MD5 Cache): ' + name);
|
|
}
|
|
if (!(settings.remoteBundles || []).includes(name)) throw Error('Cloud Rise must be a remote bundle: ' + name);
|
|
const config = JSON.parse(fs.readFileSync(path.join(folder, 'config.' + version + '.json'), 'utf8'));
|
|
if (config.name !== name || config.isZip) throw Error('Use Merge All JSON for independent remote bundles: ' + name);
|
|
if (!fs.existsSync(path.join(root, 'src/scripts', name, 'index.js'))) {
|
|
throw Error('Missing locally shipped Creator bundle script: ' + name);
|
|
}
|
|
for (const file of files(folder)) {
|
|
if (path.dirname(file) === folder && /^config\..*\.json$/.test(path.basename(file))
|
|
&& path.basename(file) !== 'config.' + version + '.json') continue;
|
|
if (/\.js$/i.test(file)) throw Error('Executable scripts must remain in the client package: ' + file);
|
|
const relative = path.relative(folder, file).replace(/\\/g, '/');
|
|
const isConfig = relative === 'config.' + version + '.json';
|
|
// A fixed entry point avoids a separate manifest of Creator's config hashes.
|
|
const target = isConfig ? 'config.json' : relative;
|
|
const data = isConfig ? Buffer.from(JSON.stringify(Object.assign({}, config, { cloudRiseVersion: release.version }))) : fs.readFileSync(file);
|
|
entries.push({ name: name + '/' + target, data });
|
|
}
|
|
}
|
|
const config = { baseUrl: server + '/remote/cloud_rise/' };
|
|
const bootFile = path.join(root, 'game.js');
|
|
let boot = fs.readFileSync(bootFile, 'utf8');
|
|
const entry = "require('./cloud-rise-package');";
|
|
if (!boot.includes(entry)) {
|
|
if (!boot.includes('window.boot();')) throw Error('Missing WeChat boot insertion point');
|
|
boot = boot.replace('window.boot();', entry + '\nwindow.boot();');
|
|
}
|
|
// Publish loose remote bundles outside the WeChat code upload directory.
|
|
const publishDir = path.join(path.dirname(root), path.basename(root) + '-cloud-rise', 'remote', 'cloud_rise');
|
|
fs.mkdirSync(publishDir, { recursive: true });
|
|
const oldZip = path.join(publishDir, 'cloud_rise.zip');
|
|
if (fs.existsSync(oldZip)) fs.unlinkSync(oldZip);
|
|
for (const name of names) {
|
|
const target = path.resolve(publishDir, name);
|
|
if (path.dirname(target) !== path.resolve(publishDir) || !names.includes(path.basename(target))) throw Error('Unsafe bundle output');
|
|
if (fs.existsSync(target)) fs.rmdirSync(target, { recursive: true });
|
|
}
|
|
for (const file of entries) {
|
|
const target = path.join(publishDir, file.name);
|
|
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
fs.writeFileSync(target, file.data);
|
|
}
|
|
fs.writeFileSync(path.join(publishDir, 'version.json'), JSON.stringify({ version: release.version }, null, 2) + '\n');
|
|
fs.writeFileSync(path.join(root, 'cloud-rise-package-config.js'), 'module.exports=' + JSON.stringify(config) + ';\n');
|
|
fs.copyFileSync(path.join(__dirname, 'runtime.js'), path.join(root, 'cloud-rise-package.js'));
|
|
game.subpackages = (game.subpackages || []).filter(item => !names.includes(item.name) && item.name !== 'cloud_rise');
|
|
settings.subpackages = (settings.subpackages || []).filter(name => !names.includes(name) && name !== 'cloud_rise');
|
|
fs.writeFileSync(gameFile, JSON.stringify(game, null, 2) + '\n');
|
|
fs.writeFileSync(settingsFile, 'window._CCSettings=' + JSON.stringify(settings) + ';\n');
|
|
fs.writeFileSync(bootFile, boot);
|
|
// Exclude remote output and stale subpackages from the WeChat code upload.
|
|
const projectFile = path.join(root, 'project.config.json');
|
|
if (fs.existsSync(projectFile)) {
|
|
const project = JSON.parse(fs.readFileSync(projectFile, 'utf8'));
|
|
project.packOptions = project.packOptions || {};
|
|
const ignore = project.packOptions.ignore || [];
|
|
for (const value of ['remote', 'subpackages/cloud_rise', ...names.map(name => 'subpackages/' + name)]) {
|
|
if (!ignore.some(item => item.type === 'folder' && item.value === value)) ignore.push({ type: 'folder', value });
|
|
}
|
|
project.packOptions.ignore = ignore;
|
|
fs.writeFileSync(projectFile, JSON.stringify(project, null, 2) + '\n');
|
|
}
|
|
return { publishDir, version: release.version, size: entries.reduce((sum, file) => sum + file.data.length, 0) };
|
|
}
|
|
module.exports = { pack, names };
|