chore: checkpoint local workspace changes

This commit is contained in:
2026-04-23 12:45:15 +08:00
parent 3eb9390e8f
commit a6cd9afcbb
47 changed files with 2154 additions and 529 deletions

View File

@@ -1,4 +1,4 @@
import {spawn} from 'node:child_process';
import {spawn, spawnSync} from 'node:child_process';
import {existsSync, readFileSync} from 'node:fs';
import net from 'node:net';
import path from 'node:path';
@@ -33,6 +33,14 @@ const DEFAULT_RUST_API_PORT = '3100';
const DEFAULT_SPACETIME_SERVER_URL = 'http://127.0.0.1:3001';
const DEFAULT_SPACETIME_DATABASE = 'genarrative-dev';
const DEFAULT_INTERNAL_API_SECRET = 'genarrative-dev-internal-bridge';
const spacetimeModulePath = path.join(serverRsRoot, 'crates', 'spacetime-module');
const spacetimeRustBindingsOutDir = path.join(
serverRsRoot,
'crates',
'spacetime-client',
'src',
'module_bindings',
);
function parseEnvContents(contents) {
return contents
@@ -195,6 +203,98 @@ function prependEnvPath(envMap, nextEntry) {
envMap[pathKey] = [nextEntry, ...segments].join(path.delimiter);
}
function resolveSpacetimeCommand() {
const command = process.platform === 'win32' ? 'where' : 'which';
const result = spawnSync(command, ['spacetime'], {
cwd: repoRoot,
env: mergedEnv,
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'pipe'],
});
if (result.status !== 0) {
return null;
}
const firstLine = `${result.stdout || ''}`
.split(/\r?\n/u)
.map((line) => line.trim())
.find(Boolean);
return firstLine || 'spacetime';
}
function runRequiredCommand(command, args, label) {
const result = spawnSync(command, args, {
cwd: repoRoot,
env: mergedEnv,
stdio: 'inherit',
});
if (result.status !== 0) {
console.error(`[dev:node] ${label} failed with exit code ${result.status ?? 1}`);
process.exit(result.status ?? 1);
}
}
function ensureSpacetimeSchemaReady() {
const spacetimeCommand = resolveSpacetimeCommand();
if (!spacetimeCommand) {
console.error(
'[dev:node] Missing `spacetime` CLI. Install or expose it in PATH before starting local dev.',
);
process.exit(1);
}
const spacetimeServerUrl = `${mergedEnv.GENARRATIVE_SPACETIME_SERVER_URL || ''}`.trim();
const spacetimeDatabase = `${mergedEnv.GENARRATIVE_SPACETIME_DATABASE || ''}`.trim();
if (!spacetimeServerUrl || !spacetimeDatabase) {
console.error(
'[dev:node] Missing GENARRATIVE_SPACETIME_SERVER_URL or GENARRATIVE_SPACETIME_DATABASE, cannot publish local schema.',
);
process.exit(1);
}
console.log(
`[dev:node] Publishing spacetime-module to ${spacetimeDatabase} (${spacetimeServerUrl}) before Rust api-server starts...`,
);
runRequiredCommand(
spacetimeCommand,
[
'publish',
spacetimeDatabase,
'--server',
spacetimeServerUrl,
'--module-path',
spacetimeModulePath,
'--yes',
...(mergedEnv.GENARRATIVE_SPACETIME_DELETE_DATA_ON_CONFLICT === '1'
? ['--delete-data=on-conflict']
: []),
],
'spacetime publish',
);
console.log('[dev:node] Generating Rust Spacetime bindings before Rust api-server starts...');
runRequiredCommand(
spacetimeCommand,
[
'generate',
'--no-config',
'--lang',
'rust',
'--out-dir',
spacetimeRustBindingsOutDir,
'--module-path',
spacetimeModulePath,
'--include-private',
'--yes',
],
'spacetime generate (rust)',
);
}
const exampleEnv = readEnvFile(envExamplePath);
const localEnv = readEnvFile(envLocalPath);
const spacetimeConfig = readJsonFile(spacetimeConfigPath);
@@ -292,6 +392,8 @@ console.log(`[dev:node] DATABASE_URL=${redactDatabaseUrl(mergedEnv.DATABASE_URL)
console.log(`[dev:node] VITE_DEV_HOST=${mergedEnv.VITE_DEV_HOST}`);
console.log(`[dev:node] NODE_RUNTIME=${runtimeNodePath}`);
ensureSpacetimeSchemaReady();
const children = new Set();
let shuttingDown = false;
let pendingExitCode = 0;