feat: migrate runtime backend to node server
This commit is contained in:
93
server-node/src/server.ts
Normal file
93
server-node/src/server.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import { pathToFileURL } from 'node:url';
|
||||
|
||||
import { createApp } from './app.js';
|
||||
import { type AppConfig,loadConfig } from './config.js';
|
||||
import type { AppContext } from './context.js';
|
||||
import { createDatabase } from './db.js';
|
||||
import { createLogger } from './logging.js';
|
||||
import { RuntimeRepository } from './repositories/runtimeRepository.js';
|
||||
import { UserRepository } from './repositories/userRepository.js';
|
||||
import { CustomWorldSessionStore } from './services/customWorldSessionStore.js';
|
||||
import { UpstreamLlmClient } from './services/llmClient.js';
|
||||
|
||||
function resolveListenTarget(serverAddr: string) {
|
||||
const trimmed = serverAddr.trim();
|
||||
if (!trimmed) {
|
||||
return { host: '0.0.0.0', port: 8081 };
|
||||
}
|
||||
if (trimmed.startsWith(':')) {
|
||||
return {
|
||||
host: '0.0.0.0',
|
||||
port: Number(trimmed.slice(1)),
|
||||
};
|
||||
}
|
||||
if (trimmed.startsWith('http://') || trimmed.startsWith('https://')) {
|
||||
const url = new URL(trimmed);
|
||||
return {
|
||||
host: url.hostname,
|
||||
port: Number(url.port || 80),
|
||||
};
|
||||
}
|
||||
if (trimmed.includes(':')) {
|
||||
const [host, portText] = trimmed.split(':');
|
||||
return {
|
||||
host: host || '0.0.0.0',
|
||||
port: Number(portText),
|
||||
};
|
||||
}
|
||||
return {
|
||||
host: '0.0.0.0',
|
||||
port: Number(trimmed),
|
||||
};
|
||||
}
|
||||
|
||||
export function createAppContext(config: AppConfig = loadConfig()) {
|
||||
const logger = createLogger(config);
|
||||
const db = createDatabase(config);
|
||||
const context: AppContext = {
|
||||
config,
|
||||
logger,
|
||||
db,
|
||||
userRepository: new UserRepository(db),
|
||||
runtimeRepository: new RuntimeRepository(db),
|
||||
llmClient: new UpstreamLlmClient(config, logger),
|
||||
customWorldSessions: new CustomWorldSessionStore(),
|
||||
};
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const context = createAppContext();
|
||||
const app = createApp(context);
|
||||
const { host, port } = resolveListenTarget(context.config.serverAddr);
|
||||
const server = app.listen(port, host, () => {
|
||||
context.logger.info(
|
||||
{
|
||||
host,
|
||||
port,
|
||||
sqlite_path: context.config.sqlitePath,
|
||||
},
|
||||
'server-node started',
|
||||
);
|
||||
});
|
||||
|
||||
const shutdown = () => {
|
||||
context.logger.info('server-node shutting down');
|
||||
server.close(() => {
|
||||
context.db.close();
|
||||
process.exit(0);
|
||||
});
|
||||
};
|
||||
|
||||
process.on('SIGINT', shutdown);
|
||||
process.on('SIGTERM', shutdown);
|
||||
}
|
||||
|
||||
const isEntryPoint =
|
||||
typeof process.argv[1] === 'string' &&
|
||||
import.meta.url === pathToFileURL(process.argv[1]).href;
|
||||
|
||||
if (isEntryPoint) {
|
||||
void main();
|
||||
}
|
||||
Reference in New Issue
Block a user