feat: 完善敲木鱼玩法模板链路
This commit is contained in:
142
scripts/dev.mjs
142
scripts/dev.mjs
@@ -257,6 +257,96 @@ function requireCommand(command) {
|
||||
}
|
||||
}
|
||||
|
||||
function readWorkspaceSpacetimeVersion() {
|
||||
const manifestText = readFileSync(manifestPath, 'utf8');
|
||||
const match = /^spacetimedb\s*=\s*(?:"([^"]+)"|\{[^}]*version\s*=\s*"([^"]+)")/mu.exec(
|
||||
manifestText,
|
||||
);
|
||||
const version = match?.[1] ?? match?.[2] ?? '';
|
||||
if (!version) {
|
||||
throw new Error('无法从 server-rs/Cargo.toml 读取 spacetimedb 版本');
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
function parseSpacetimeToolVersion(output) {
|
||||
const match = /spacetimedb tool version\s+([0-9]+\.[0-9]+\.[0-9]+)/u.exec(output);
|
||||
return match?.[1] ?? '';
|
||||
}
|
||||
|
||||
function readSpacetimeToolVersion() {
|
||||
const result = spawnSync('spacetime', ['--version'], {
|
||||
cwd: repoRoot,
|
||||
encoding: 'utf8',
|
||||
shell: process.platform === 'win32',
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
throw new Error(`读取 spacetime 版本失败: ${result.error.message}`);
|
||||
}
|
||||
|
||||
const output = `${result.stdout ?? ''}\n${result.stderr ?? ''}`;
|
||||
const version = parseSpacetimeToolVersion(output);
|
||||
if (!version) {
|
||||
throw new Error(`无法解析 spacetime 版本输出: ${trimPreview(output)}`);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
function assertSpacetimeToolVersionMatchesWorkspace({
|
||||
toolVersion,
|
||||
workspaceVersion,
|
||||
}) {
|
||||
if (toolVersion === workspaceVersion) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
[
|
||||
`本机 spacetime CLI/standalone 版本 ${toolVersion} 与 server-rs 锁定的 SpacetimeDB ${workspaceVersion} 不一致。`,
|
||||
'版本错位会导致 procedure 返回值 BSATN 反序列化失败,前端表现为 SpacetimeDB procedure 调用超时。',
|
||||
`请执行 spacetime version install ${workspaceVersion} && spacetime version use ${workspaceVersion} 后重新运行本命令。`,
|
||||
].join(''),
|
||||
);
|
||||
}
|
||||
|
||||
function assertReusableSpacetimeProcessVersionMatchesWorkspace({
|
||||
dataDir,
|
||||
serverUrl,
|
||||
}) {
|
||||
const recordedVersion = readRecordedSpacetimeToolVersion(dataDir);
|
||||
const workspaceVersion = readWorkspaceSpacetimeVersion();
|
||||
if (!recordedVersion) {
|
||||
throw new Error(
|
||||
[
|
||||
`检测到正在运行的本地 SpacetimeDB: ${serverUrl},但缺少 SpacetimeDB 版本记录。`,
|
||||
'为避免复用旧 standalone 导致 procedure 返回值 BSATN 反序列化失败和前端调用超时,请先停止该进程,再重新运行 npm run dev:spacetime。',
|
||||
].join(''),
|
||||
);
|
||||
}
|
||||
|
||||
if (recordedVersion === workspaceVersion) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
[
|
||||
`正在运行的本地 SpacetimeDB standalone 版本 ${recordedVersion} 与 server-rs 锁定的 SpacetimeDB ${workspaceVersion} 不一致。`,
|
||||
'版本错位会导致 procedure 返回值 BSATN 反序列化失败,前端表现为 SpacetimeDB procedure 调用超时。',
|
||||
'请停止当前 SpacetimeDB 进程,执行 spacetime version use ',
|
||||
workspaceVersion,
|
||||
' 后重新运行 npm run dev:spacetime。',
|
||||
].join(''),
|
||||
);
|
||||
}
|
||||
|
||||
function ensureSpacetimeToolVersionMatchesWorkspace() {
|
||||
assertSpacetimeToolVersionMatchesWorkspace({
|
||||
toolVersion: readSpacetimeToolVersion(),
|
||||
workspaceVersion: readWorkspaceSpacetimeVersion(),
|
||||
});
|
||||
}
|
||||
|
||||
function ensureRequiredFiles(command) {
|
||||
const requiredFiles = [];
|
||||
|
||||
@@ -478,6 +568,9 @@ class DevRunner {
|
||||
) {
|
||||
requireCommand('spacetime');
|
||||
}
|
||||
if (this.shouldValidateSpacetimeToolVersion(command)) {
|
||||
ensureSpacetimeToolVersionMatchesWorkspace();
|
||||
}
|
||||
|
||||
await this.tryReuseExistingSpacetime(command);
|
||||
await this.resolvePorts(command);
|
||||
@@ -485,6 +578,19 @@ class DevRunner {
|
||||
this.printSummary(command);
|
||||
}
|
||||
|
||||
shouldValidateSpacetimeToolVersion(command) {
|
||||
if (command === 'spacetime') {
|
||||
return true;
|
||||
}
|
||||
if (command === 'all') {
|
||||
return !this.options.skipSpacetime || !this.options.skipPublish;
|
||||
}
|
||||
if (command === 'api-server') {
|
||||
return isLoopbackSpacetimeServer(this.state.spacetimeServer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async tryReuseExistingSpacetime(command) {
|
||||
if (this.options.skipSpacetime) {
|
||||
return;
|
||||
@@ -525,6 +631,11 @@ class DevRunner {
|
||||
continue;
|
||||
}
|
||||
|
||||
assertReusableSpacetimeProcessVersionMatchesWorkspace({
|
||||
dataDir: this.options.spacetimeDataDir,
|
||||
serverUrl: candidate,
|
||||
});
|
||||
|
||||
const port = safeUrlPort(candidate);
|
||||
if (Number.isInteger(port) && port > 0) {
|
||||
this.options.spacetimePort = port;
|
||||
@@ -705,6 +816,15 @@ class DevRunner {
|
||||
const logFile = resolve(options.spacetimeDataDir, 'logs/dev-spacetime-start.log');
|
||||
const logStream = createWriteStream(logFile, {flags: 'a', encoding: 'utf8'});
|
||||
service.logStream = logStream;
|
||||
const spacetimeToolVersion = readSpacetimeToolVersion();
|
||||
assertSpacetimeToolVersionMatchesWorkspace({
|
||||
toolVersion: spacetimeToolVersion,
|
||||
workspaceVersion: readWorkspaceSpacetimeVersion(),
|
||||
});
|
||||
recordSpacetimeToolVersion(
|
||||
options.spacetimeDataDir,
|
||||
spacetimeToolVersion,
|
||||
);
|
||||
|
||||
console.log(`[dev:spacetime] log: ${logFile}`);
|
||||
const env = {
|
||||
@@ -1357,6 +1477,15 @@ function readRecordedSpacetimeUrl(dataDir) {
|
||||
return '';
|
||||
}
|
||||
|
||||
function readRecordedSpacetimeToolVersion(dataDir) {
|
||||
const versionPath = resolve(dataDir, 'dev-spacetime-tool-version');
|
||||
if (!existsSync(versionPath)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return readFileSync(versionPath, 'utf8').split(/\r?\n/u)[0]?.trim() ?? '';
|
||||
}
|
||||
|
||||
function readRecordedSpacetimePidState(dataDir) {
|
||||
const pidPath = resolve(dataDir, 'spacetime.pid');
|
||||
if (!existsSync(pidPath)) {
|
||||
@@ -1389,6 +1518,16 @@ function readRecordedSpacetimePidState(dataDir) {
|
||||
}
|
||||
}
|
||||
|
||||
function recordSpacetimeToolVersion(dataDir, version) {
|
||||
const versionPath = resolve(dataDir, 'dev-spacetime-tool-version');
|
||||
ensureParentDir(versionPath);
|
||||
try {
|
||||
writeFileSync(versionPath, `${version}\n`, 'utf8');
|
||||
} catch (error) {
|
||||
console.warn(`[dev:spacetime] 写入版本记录失败 ${versionPath}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function recordSpacetimeUrl(dataDir, serverUrl) {
|
||||
const targets = [
|
||||
resolve(dataDir, 'dev-spacetime-url'),
|
||||
@@ -1580,10 +1719,13 @@ function isSpacetimePublishPermissionError(error) {
|
||||
|
||||
export {
|
||||
DevRunner,
|
||||
assertReusableSpacetimeProcessVersionMatchesWorkspace,
|
||||
assertSpacetimeToolVersionMatchesWorkspace,
|
||||
buildSpacetimePublishArgs,
|
||||
createDevServerSpawnOptions,
|
||||
createWatchConfigs,
|
||||
isSpacetimePublishPermissionError,
|
||||
parseSpacetimeToolVersion,
|
||||
parseArgs,
|
||||
shouldAcceptWatchEvent,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user