fix: start tamagotchi (#630)
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env tsx
|
||||
/**
|
||||
* Development script to start both the WebSocket server and Tamagotchi app
|
||||
* This ensures the server-runtime is running before starting the app
|
||||
*/
|
||||
|
||||
import type { Buffer } from 'node:buffer'
|
||||
|
||||
import process from 'node:process'
|
||||
|
||||
import { spawn } from 'node:child_process'
|
||||
|
||||
const isWindows = process.platform === 'win32'
|
||||
|
||||
console.log('🚀 Starting AIRI WebSocket server and Tamagotchi app...\n')
|
||||
|
||||
// Start the WebSocket server in the background
|
||||
console.log('📡 Starting WebSocket server on port 6121...')
|
||||
const serverProcess = spawn(
|
||||
'pnpm',
|
||||
['-F', '@proj-airi/server-runtime', 'dev'],
|
||||
{
|
||||
stdio: ['pipe', 'pipe', 'pipe'], // Change from 'inherit' to capture output
|
||||
shell: isWindows,
|
||||
},
|
||||
)
|
||||
|
||||
// Wait for the server to be ready by listening for a ready message
|
||||
console.log('⏳ Waiting for server to initialize...\n')
|
||||
const serverReady = new Promise<void>((resolve, reject) => {
|
||||
// Listen typically outputs a URL when ready, looking for patterns like:
|
||||
// "Listening on http://localhost:6121" or similar
|
||||
const readyPatterns = [
|
||||
/listening.*:6121/i,
|
||||
/ready.*:6121/i,
|
||||
/localhost:6121/i,
|
||||
/http:\/\/localhost:6121/i,
|
||||
]
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
console.log('⚠️ Server ready timeout reached, continuing anyway...')
|
||||
resolve() // Resolve even if we don't see the message to avoid hanging
|
||||
}, 10000) // 10 second timeout
|
||||
|
||||
// Handle errors from the server process
|
||||
serverProcess.on('error', (error) => {
|
||||
console.error('Failed to start server:', error)
|
||||
clearTimeout(timeout)
|
||||
reject(error)
|
||||
})
|
||||
|
||||
const checkOutput = (data: Buffer) => {
|
||||
const output = data.toString()
|
||||
console.log(output) // Still output to console for visibility
|
||||
|
||||
if (readyPatterns.some(pattern => pattern.test(output))) {
|
||||
clearTimeout(timeout)
|
||||
resolve()
|
||||
}
|
||||
}
|
||||
|
||||
serverProcess.stdout?.on('data', checkOutput)
|
||||
serverProcess.stderr?.on('data', checkOutput)
|
||||
})
|
||||
|
||||
await serverReady
|
||||
|
||||
// Start the Tamagotchi app
|
||||
console.log('🎮 Starting Tamagotchi app...\n')
|
||||
const tamagotchiProcess = spawn(
|
||||
'pnpm',
|
||||
['-F', '@proj-airi/stage-tamagotchi', 'app:dev'],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
shell: isWindows,
|
||||
},
|
||||
)
|
||||
|
||||
let isCleaningUp = false
|
||||
|
||||
// Handle cleanup on exit
|
||||
function cleanup() {
|
||||
if (isCleaningUp)
|
||||
return
|
||||
isCleaningUp = true
|
||||
console.log('\n🛑 Shutting down...')
|
||||
try {
|
||||
if (serverProcess && !serverProcess.killed) {
|
||||
serverProcess.kill()
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error killing server process:', error)
|
||||
}
|
||||
try {
|
||||
if (tamagotchiProcess && !tamagotchiProcess.killed) {
|
||||
tamagotchiProcess.kill()
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error killing tamagotchi process:', error)
|
||||
}
|
||||
}
|
||||
|
||||
process.on('SIGINT', cleanup)
|
||||
process.on('SIGTERM', cleanup)
|
||||
|
||||
// Wait for processes
|
||||
const serverExit = new Promise(resolve => serverProcess.on('exit', code => resolve({ name: 'Server', code })))
|
||||
const tamagotchiExit = new Promise(resolve => tamagotchiProcess.on('exit', code => resolve({ name: 'Tamagotchi', code })))
|
||||
|
||||
const firstToExit = await Promise.race([serverExit, tamagotchiExit])
|
||||
|
||||
console.log(`${firstToExit.name} process exited with code ${firstToExit.code}, shutting down...`)
|
||||
cleanup()
|
||||
|
||||
// Wait for both processes to terminate before exiting the script.
|
||||
await Promise.all([serverExit, tamagotchiExit])
|
||||
|
||||
console.log('All child processes have terminated.')
|
||||
process.exit(firstToExit.code ?? 0)
|
||||
@@ -61,7 +61,9 @@ function createWindow(): void {
|
||||
})
|
||||
|
||||
mainWindow.setAlwaysOnTop(true)
|
||||
mainWindow.setWindowButtonVisibility(false)
|
||||
if (isMacOS) {
|
||||
mainWindow.setWindowButtonVisibility(false)
|
||||
}
|
||||
mainWindow.on('ready-to-show', () => mainWindow!.show())
|
||||
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
shell.openExternal(details.url)
|
||||
@@ -125,6 +127,8 @@ app.whenReady().then(() => {
|
||||
app.on('browser-window-created', (_, window) => optimizer.watchWindowShortcuts(window))
|
||||
|
||||
createWindow()
|
||||
}).catch((err) => {
|
||||
console.error('Error during app initialization:', err)
|
||||
})
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
|
||||
Reference in New Issue
Block a user