mirror of
https://github.com/hanzoai/bot-hub.git
synced 2026-10-30 18:46:42 +00:00
Migration from Convex/Vercel to self-hosted infrastructure: API Backend (api/): - Hono server with PostgreSQL (Drizzle ORM) + pgvector - Skills CRUD, search (hybrid vector + lexical), auth (hanzo.id OAuth) - Upload (MinIO S3), stars, comments, API tokens - Rate limiting middleware, session management Frontend Adapter (src/lib/): - api.ts: REST API client replacing Convex SDK - hooks.ts: React hooks replacing convex/react useQuery/useMutation - AuthContext.tsx: Auth provider replacing ConvexAuthProvider Deployment: - Dockerfile (multi-stage: API build + web build + production) - K8s manifests for hub.hanzo.bot on hanzo-k8s - GitHub Actions CI/CD (build → GHCR → deploy) Rebrand: - clawhub/clawdhub/ClawHub → bothub/Bot Hub - Domain: clawhub.ai → hub.hanzo.bot - CLI: clawhub → bothub - Package: @hanzo/bot-hub-api
47 lines
1.3 KiB
TypeScript
Executable File
47 lines
1.3 KiB
TypeScript
Executable File
#!/usr/bin/env bun
|
|
import { existsSync } from 'node:fs'
|
|
import { stat } from 'node:fs/promises'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
const distCliUrl = new URL('./packages/clawdhub/dist/cli.js', import.meta.url)
|
|
const distCliPath = fileURLToPath(distCliUrl)
|
|
const srcRootPath = fileURLToPath(new URL('./packages/clawdhub/src/', import.meta.url))
|
|
|
|
const shouldBuild = await (async () => {
|
|
if (!existsSync(distCliPath)) return true
|
|
try {
|
|
const dist = await stat(distCliPath)
|
|
const latestSrcMtime = await getLatestMtime(srcRootPath)
|
|
return latestSrcMtime > dist.mtimeMs
|
|
} catch {
|
|
return true
|
|
}
|
|
})()
|
|
|
|
if (shouldBuild) {
|
|
const proc = Bun.spawn(['bunx', 'tsc', '-p', 'packages/clawdhub/tsconfig.json'], {
|
|
stdin: 'inherit',
|
|
stdout: 'inherit',
|
|
stderr: 'inherit',
|
|
})
|
|
const code = await proc.exited
|
|
if (code !== 0) process.exit(code)
|
|
}
|
|
|
|
await import(distCliUrl.href)
|
|
|
|
async function getLatestMtime(root: string) {
|
|
let latest = 0
|
|
const glob = new Bun.Glob('**/*.ts')
|
|
for await (const rel of glob.scan({ cwd: root, onlyFiles: true })) {
|
|
const path = `${root}${root.endsWith('/') ? '' : '/'}${rel}`
|
|
try {
|
|
const entry = await stat(path)
|
|
latest = Math.max(latest, entry.mtimeMs)
|
|
} catch {
|
|
// ignore
|
|
}
|
|
}
|
|
return latest
|
|
}
|