A complete integration of Moose OLAP with Hono API server, running side by side with shared ClickHouse database.
This project demonstrates how to integrate Moose's powerful data modeling and ClickHouse integration with a custom Hono API server. The architecture uses a dual-process approach where Moose and Hono run as separate, independent services that share the same ClickHouse database.
my-app/
├── app/
│ ├── index.ts # Moose resource definitions (compiler plugin target)
│ ├── server.ts # Hono API server
│ └── db/
│ ├── models.ts # Moose data models (OlapTable definitions)
│ ├── views.ts # Moose views
│ └── client.ts # ClickHouse client for Hono
├── tsconfig.json # Main TS config (CommonJS + Moose plugins)
├── tsconfig.node.json # Runtime TS config (ESNext + Moose plugins)
├── nodemon.json # File watching configuration
└── moose.config.toml # Moose configuration
app/index.ts: Only exports Moose resources for the compiler pluginapp/server.ts: Contains the Hono API server logic- No server code in
index.ts: Prevents Moose from trying to run the Hono server
tsconfig.json: CommonJS + Moose compiler plugins (for building)tsconfig.node.json: ESNext + Moose compiler plugins (for runtime with ts-node)
- Moose: Uses ports 4000, 5001 (from
moose.config.toml) - Hono: Uses port 3000 (from
server.ts)
- Node.js 18+
- ClickHouse running locally
- Moose CLI installed
npm installStart both services concurrently:
npm run devThis runs:
- Moose process:
moose-cli dev- Handles data layer, ClickHouse setup, compiler plugins - Hono process:
npm run dev:hono- Serves API endpoints with file watching
# Start only Moose
npm run dev:moose
# Start only Hono (with file watching)
npm run dev:honoBoth services connect to the same ClickHouse instance:
- Moose: Manages schema, tables, materialized views
- Hono: Queries data using
QueryClientfrom@514labs/moose-lib
// app/db/client.ts
const clickhouseClient = getClickhouseClient({
host: "localhost",
port: "18123",
username: "panda",
password: "pandapass",
database: "local",
useSSL: "false",
});export interface FooModel {
primaryKey: Key<string>;
timestamp: number;
optionalText?: string;
}export interface BarModel {
primaryKey: Key<string>;
utcTimestamp: Date;
hasText: boolean;
textLength: number;
}export interface BarAggregatedModel {
dayOfMonth: number & ClickHouseInt<"int64">;
totalRows: number & ClickHouseInt<"int64">;
rowsWithText: number & ClickHouseInt<"int64">;
totalTextLength: number & ClickHouseInt<"int64">;
maxTextLength: number & ClickHouseInt<"int64">;
}GET http://localhost:3000/POST http://localhost:3000/ingest/Foo
Content-Type: application/json
{
"primaryKey": "test-123",
"timestamp": 1704067200,
"optionalText": "This is a test message"
}# Get bar data with query parameters
GET http://localhost:3000/bar?limit=5&orderBy=totalRows
# Get bar data v1
GET http://localhost:3000/bar/1-
Moose (
moose-cli dev):- Processes
app/index.tswith compiler plugins - Sets up ClickHouse tables and materialized views
- Manages data pipeline and transformations
- Processes
-
Hono (
npm run dev:hono):- Serves API endpoints on port 3000
- Uses
QueryClientto query ClickHouse - Can insert data via
FooTable.insert()
The Hono server automatically restarts when you modify TypeScript files in the app/ directory, thanks to nodemon configuration.
Both configurations include Moose's TypeScript compiler plugins:
@514labs/moose-lib/dist/compilerPlugin.jstypia/lib/transform
- Moose: Automatically processes changes to data models
- Hono: Restarts server on file changes
curl -X POST http://localhost:3000/ingest/Foo \
-H "Content-Type: application/json" \
-d '{
"primaryKey": "test-123",
"timestamp": 1704067200,
"optionalText": "This is a test message"
}'curl "http://localhost:3000/bar?limit=3&orderBy=totalRows"Main TypeScript configuration for building:
- CommonJS modules
- Moose compiler plugins
- Strict type checking
Runtime TypeScript configuration:
- ESNext modules
- ts-node specific settings
- Moose compiler plugins for runtime
File watching configuration:
- Watches
app/directory - Ignores test files
- Uses ts-node with Moose compiler plugins
- Process Separation: Moose and Hono run independently, avoiding conflicts
- Compiler Plugin Compatibility: Both configs include Moose's TypeScript compiler plugins
- Shared Database: Both services use the same ClickHouse instance
- Proper Module Resolution: CommonJS for building, ESNext for runtime
- File Watching: nodemon provides development experience without breaking Moose plugins
npm run dev- Start both Moose and Hono concurrentlynpm run dev:moose- Start only Moosenpm run dev:hono- Start only Hono with file watchingnpm run build- Build the projectnpm run start- Start the built application
This integration demonstrates how to combine Moose's powerful data modeling capabilities with custom API servers. The architecture can be adapted for other web frameworks or use cases.