fix blank page, icons, add logging and EVM balance chart
- Fix blank page: set viewsRoot, base:'', history.replaceState in index.html - Fix chain icons: add dist/icons→views/mainview/icons copy rule - Add file-based logger (src/bun/lib/logger.ts) with logToFile RPC - Add frontend error overlay + global error listeners in index.svelte - Add EVM balance chart with time range filters (EvmDashboard.svelte) - Replace console.log with file logger throughout backend - Improve get-env.ts to read version.json for channel detection
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
import { migrate } from 'drizzle-orm/bun-sqlite/migrator'
|
||||
import { db } from './lib/db'
|
||||
import { join } from 'path'
|
||||
import { existsSync } from 'fs'
|
||||
import { getENV } from './lib/get-env'
|
||||
import { createEvmHandlers } from './rpc/evm'
|
||||
import { createMoneroHandlers } from './rpc/monero'
|
||||
@@ -17,15 +18,22 @@ import { canPromptTouchID, promptTouchID } from './lib/biometric'
|
||||
import { sqlite } from './lib/sqlite'
|
||||
import { evmWallets } from './lib/db/schema'
|
||||
import type { RPC } from '../lib/rpc-schema'
|
||||
import { log, logError } from './lib/logger'
|
||||
|
||||
const env = getENV()
|
||||
|
||||
console.log(env)
|
||||
log(`env: ${JSON.stringify(env)}`)
|
||||
|
||||
if (env.env === 'prod') {
|
||||
migrate(db, {
|
||||
migrationsFolder: join(PATHS.RESOURCES_FOLDER, 'app', 'drizzle'),
|
||||
})
|
||||
if (env.env === 'stable') {
|
||||
try {
|
||||
log('running migrations...')
|
||||
migrate(db, {
|
||||
migrationsFolder: join(PATHS.RESOURCES_FOLDER, 'app', 'drizzle'),
|
||||
})
|
||||
log('migrations complete')
|
||||
} catch (e) {
|
||||
logError('migration failed', e)
|
||||
}
|
||||
}
|
||||
|
||||
const DEV_SERVER_PORT = 5173
|
||||
@@ -33,19 +41,17 @@ const DEV_SERVER_URL = `http://localhost:${DEV_SERVER_PORT}`
|
||||
|
||||
async function getMainViewUrl(): Promise<string> {
|
||||
const channel = await Updater.localInfo.channel()
|
||||
log(`channel from Updater: ${channel}`)
|
||||
if (channel === 'dev') {
|
||||
try {
|
||||
await fetch(DEV_SERVER_URL, { method: 'HEAD' })
|
||||
console.log(
|
||||
`HMR enabled: Using Vite dev server at ${DEV_SERVER_URL}`,
|
||||
)
|
||||
log(`HMR enabled: Using Vite dev server at ${DEV_SERVER_URL}`)
|
||||
return DEV_SERVER_URL
|
||||
} catch {
|
||||
console.log(
|
||||
"Vite dev server not running. Run 'bun run dev:hmr' for HMR support.",
|
||||
)
|
||||
log("Vite dev server not running, falling back to bundled view")
|
||||
}
|
||||
}
|
||||
log('using bundled view')
|
||||
return 'views://mainview/index.html'
|
||||
}
|
||||
|
||||
@@ -76,6 +82,12 @@ ApplicationMenu.setApplicationMenu([
|
||||
|
||||
const url = await getMainViewUrl()
|
||||
|
||||
log(`view URL: ${url}`)
|
||||
const viewsRoot = join(PATHS.RESOURCES_FOLDER, 'app', 'views')
|
||||
log(`viewsRoot: ${viewsRoot}`)
|
||||
log(`viewsRoot exists: ${existsSync(viewsRoot)}`)
|
||||
log(`index.html exists: ${existsSync(join(viewsRoot, 'mainview', 'index.html'))}`)
|
||||
|
||||
const moneroState = {
|
||||
manager: null as MoneroWalletState | null,
|
||||
downloading: false,
|
||||
@@ -159,14 +171,19 @@ rpc.setRequestHandler({
|
||||
margin: 1,
|
||||
})
|
||||
},
|
||||
logToFile: async ({ message }) => {
|
||||
log(message)
|
||||
},
|
||||
...createEvmHandlers(rpc, syncState),
|
||||
...createMoneroHandlers(moneroState),
|
||||
})
|
||||
|
||||
log('creating BrowserWindow...')
|
||||
const win = new BrowserWindow({
|
||||
title: 'Koins',
|
||||
url,
|
||||
rpc,
|
||||
viewsRoot: join(PATHS.RESOURCES_FOLDER, 'app', 'views'),
|
||||
frame: {
|
||||
width: 900,
|
||||
height: 700,
|
||||
@@ -174,5 +191,6 @@ const win = new BrowserWindow({
|
||||
y: 200,
|
||||
},
|
||||
})
|
||||
log('BrowserWindow created')
|
||||
|
||||
console.log('Koins app started!')
|
||||
log('Koins app started!')
|
||||
|
||||
@@ -1,21 +1,28 @@
|
||||
const env = (Bun.env.ELECTROBUN_ENV as string) || 'dev'
|
||||
import { PATHS } from 'electrobun/bun'
|
||||
import { readFileSync, existsSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
|
||||
console.log('ENV', env)
|
||||
|
||||
export const getENV = () => {
|
||||
let appName
|
||||
let dbFilename
|
||||
if (env === 'stable') {
|
||||
appName = 'koins'
|
||||
dbFilename = 'koins.db'
|
||||
} else {
|
||||
appName = 'koins-dev'
|
||||
dbFilename = 'koins-dev.db'
|
||||
function detectEnv(): { env: string; appName: string; dbFilename: string } {
|
||||
const channel = (Bun.env.ELECTROBUN_ENV as string) || ''
|
||||
if (channel === 'stable') {
|
||||
return { env: 'stable', appName: 'koins', dbFilename: 'koins.db' }
|
||||
}
|
||||
|
||||
return {
|
||||
env,
|
||||
appName,
|
||||
dbFilename,
|
||||
}
|
||||
try {
|
||||
const p = join(PATHS.RESOURCES_FOLDER, 'version.json')
|
||||
if (existsSync(p)) {
|
||||
const { channel: c } = JSON.parse(readFileSync(p, 'utf-8'))
|
||||
if (c === 'stable') {
|
||||
return { env: 'stable', appName: 'koins', dbFilename: 'koins.db' }
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return { env: 'dev', appName: 'koins-dev', dbFilename: 'koins-dev.db' }
|
||||
}
|
||||
|
||||
const env = detectEnv()
|
||||
|
||||
console.log('ENV', env.env)
|
||||
|
||||
export const getENV = () => env
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { appendFileSync, mkdirSync, existsSync } from 'fs'
|
||||
import { join } from 'path'
|
||||
import envPaths from 'env-paths'
|
||||
import { getENV } from './get-env'
|
||||
|
||||
const { appName } = getENV()
|
||||
const { data } = envPaths(appName, { suffix: '' })
|
||||
const logDir = join(data, 'logs')
|
||||
mkdirSync(logDir, { recursive: true })
|
||||
|
||||
const date = () => {
|
||||
const d = new Date()
|
||||
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
const file = join(logDir, `${appName}-${date()}.log`)
|
||||
|
||||
export const log = (msg: string) => {
|
||||
const line = `[${new Date().toISOString()}] ${msg}\n`
|
||||
try {
|
||||
appendFileSync(file, line, 'utf-8')
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export const logError = (msg: string, err?: unknown) => {
|
||||
const detail = err instanceof Error ? err.stack || err.message : String(err ?? '')
|
||||
log(`[ERROR] ${msg}${detail ? ' — ' + detail : ''}`)
|
||||
}
|
||||
Reference in New Issue
Block a user