Observed since 21 Oct, 09:19 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
@0xobelisk/graphql-server
Tookit for interacting with dubhe graphql server
The Dubhe GraphQL Server is an intelligent universal server adapter that automatically connects to databases created by dubhe-indexer and dynamically generates complete GraphQL APIs. Built on PostGraphile, it provides advanced filtering, real-time subscriptions, and comprehensive data access capabilities with zero configuration required.
Install the package in your project:
pnpm install @0xobelisk/graphql-server
Or install globally for CLI usage:
npm install -g @0xobelisk/graphql-server
The server provides a comprehensive CLI interface for configuration:
# Start with default configuration
dubhe-graphql-server start
# Start with custom configuration
dubhe-graphql-server start --port 4000 --database-url postgres://user:pass@localhost:5432/db
# Development mode with debug logging
dubhe-graphql-server start --debug --enable-metrics
# Production mode
dubhe-graphql-server start --env production --no-cors
All configuration can be managed through CLI arguments or environment variables:
| Option | Environment Variable | Default | Description |
|---|---|---|---|
--port, -p | PORT | 4000 | Server port |
--database-url, -d | DATABASE_URL | postgres://postgres:postgres@127.0.0.1:5432/postgres | Database connection URL |
--schema, -s | PG_SCHEMA | public | PostgreSQL schema name |
--endpoint, -e | GRAPHQL_ENDPOINT | /graphql | GraphQL endpoint path |
--cors | ENABLE_CORS | true | Enable CORS |
--subscriptions | ENABLE_SUBSCRIPTIONS | true | Enable GraphQL subscriptions |
--env | NODE_ENV | development | Environment mode |
--debug | DEBUG | false | Enable debug mode (verbose logging) |
--query-timeout | QUERY_TIMEOUT | 30000 | GraphQL query timeout (ms) |
--max-connections | MAX_CONNECTIONS | 1000 | Maximum database connections |
--heartbeat-interval | HEARTBEAT_INTERVAL | 30000 | WebSocket heartbeat interval (ms) |
--enable-metrics | ENABLE_METRICS | false | Enable performance metrics |
--enable-live-queries | ENABLE_LIVE_QUERIES | true | Enable GraphQL live queries |
--enable-pg-subscriptions | ENABLE_PG_SUBSCRIPTIONS | true | Enable PostgreSQL subscriptions |
--enable-native-websocket | ENABLE_NATIVE_WEBSOCKET | true | Enable native WebSocket support |
--realtime-port | REALTIME_PORT | undefined | Realtime WebSocket port |
You can also use a .env file instead of CLI arguments:
# Database configuration (connect to dubhe-indexer database)
DATABASE_URL=postgres://username:password@localhost:5432/sui_indexer_db
# Server configuration
PORT=4000
NODE_ENV=development
# GraphQL configuration
GRAPHQL_ENDPOINT=/graphql
PG_SCHEMA=public
# Feature toggles
ENABLE_CORS=true
ENABLE_SUBSCRIPTIONS=true
# Performance settings
QUERY_TIMEOUT=30000
MAX_CONNECTIONS=1000
HEARTBEAT_INTERVAL=30000
# Debug and monitoring
DEBUG=false
ENABLE_METRICS=false
# Subscription capabilities
ENABLE_LIVE_QUERIES=true
ENABLE_PG_SUBSCRIPTIONS=true
ENABLE_NATIVE_WEBSOCKET=true
REALTIME_PORT=4001
The server automatically scans and adapts to your database structure:
dubhe-indexerThe server uses a modular plugin architecture:
The server provides comprehensive filtering capabilities through the postgraphile-plugin-connection-filter plugin:
# Basic filtering
query GetHighValueAccounts {
accounts(filter: { balance: { gt: "1000" } }) {
nodes {
assetId
account
balance
}
}
}
# Complex logical combinations
query GetComplexFilteredAccounts {
accounts(
filter: {
and: [
{ or: [{ balance: { gt: "1000" } }, { assetId: { like: "%special%" } }] }
{ not: { account: { includesInsensitive: "test" } } }
]
}
) {
nodes {
assetId
account
balance
}
}
}
Advanced WebSocket support powered by PostgreSQL LISTEN/NOTIFY:
# Subscribe to specific table changes
subscription OnAccountChanges {
accounts(first: 10, orderBy: [CREATED_AT_TIMESTAMP_DESC]) {
nodes {
assetId
account
balance
}
}
}
After starting the server, you can access:
http://localhost:4000/ - Server information and table overviewhttp://localhost:4000/playground - Modern GraphQL IDEhttp://localhost:4000/graphql - API endpointhttp://localhost:4000/health - Server health statushttp://localhost:4000/subscription-config - Client configurationws://localhost:4000/graphql - Subscription endpoint# Start development server
pnpm install
dubhe-graphql-server start --debug --enable-metrics
# Build the project
pnpm install
pnpm build
# Start production server
dubhe-graphql-server start \
--env production \
--max-connections 500 \
--query-timeout 60000
Create a docker-compose.yml:
version: '3.8'
services:
graphql-server:
image: node:22-alpine
working_dir: /app
command: npx @0xobelisk/graphql-server start
ports:
- '4000:4000'
environment:
- DATABASE_URL=postgres://user:password@postgres:5432/sui_indexer
- PORT=4000
- ENABLE_SUBSCRIPTIONS=true
- NODE_ENV=production
depends_on:
- postgres
postgres:
image: postgres:15
environment:
- POSTGRES_DB=sui_indexer
- POSTGRES_USER=user
- POSTGRES_PASSWORD=password
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
# CLI approach for production
dubhe-graphql-server start \
--env production \
--database-url "postgres://user:password@prod-db:5432/sui_indexer" \
--port 4000 \
--no-cors \
--max-connections 500 \
--query-timeout 60000 \
--enable-metrics
The server uses a comprehensive configuration interface:
interface ServerConfig {
// Basic server configuration
port: string;
databaseUrl: string;
schema: string;
endpoint: string;
cors: boolean;
subscriptions: boolean;
env: string;
// Debug configuration
debug: boolean;
// Performance configuration
queryTimeout: number;
maxConnections: number;
heartbeatInterval: number;
enableMetrics: boolean;
// Subscription capabilities
enableLiveQueries: boolean;
enablePgSubscriptions: boolean;
enableNativeWebSocket: boolean;
realtimePort?: number;
// Internal debug flags
debugNotifications: boolean;
}
Set up proper database permissions:
-- Create read-only user
CREATE USER graphql_readonly WITH PASSWORD 'secure_password';
-- Grant query permissions
GRANT CONNECT ON DATABASE sui_indexer TO graphql_readonly;
GRANT USAGE ON SCHEMA public TO graphql_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO graphql_readonly;
-- If write permissions needed
GRANT INSERT, UPDATE, DELETE ON specific_tables TO graphql_readonly;
The server provides comprehensive monitoring endpoints:
http://localhost:4000/ - Welcome page with system informationhttp://localhost:4000/health - Health check endpoint with subscription statushttp://localhost:4000/subscription-config - Client configuration for subscriptionshttp://localhost:4000/subscription-docs - Configuration documentationhttp://localhost:4000/playground - Enhanced GraphQL PlaygroundEnable debug mode for detailed logging:
# Enable debug mode with verbose logging
dubhe-graphql-server start --debug
# Enable performance metrics
dubhe-graphql-server start --enable-metrics
# Combine both for comprehensive monitoring
dubhe-graphql-server start --debug --enable-metrics
The server includes built-in performance monitoring:
--debug)Database Connection Failed
Solution: Check DATABASE_URL and database service status
Table Scan Empty
Solution: Ensure dubhe-indexer is running and has created tables
Schema Generation Failed
Solution: Check if table_fields table exists and has data
WebSocket Connection Failed
Solution: Check firewall settings and ENABLE_SUBSCRIPTIONS configuration
# View generated schema
ls -la *.graphql
# Check database connection
psql $DATABASE_URL -c "SELECT version();"
# Test GraphQL endpoint
curl -X POST http://localhost:4000/graphql \
-H "Content-Type: application/json" \
-d '{"query": "{ __schema { types { name } } }"}'
dubhe-indexer database
↓
[Database Introspector] ← Scans table structures
↓
[PostGraphile] ← Generates GraphQL schema
↓
[Enhanced Server Manager] ← Manages HTTP/WebSocket
↓
[GraphQL API + WebSocket] ← Unified endpoint
Database Introspector:
store_* tables and system tablestable_fieldsPostGraphile Engine:
Subscription Manager:
Enhanced Server Manager:
System Tables: Auto-detected indexer tables
table_fields - Table structure metadata (stores field definitions for dynamic tables)Dynamic Tables: Contract-defined tables
store_* - Tables created from your dubhe.config.json (e.g., store_component0, store_component1)created_at_timestamp_ms, updated_at_timestamp_ms, is_deleted--debug --enable-metrics--max-connections appropriately--query-timeout based on usage--no-cors or configure specific origins--enable-metrics for production monitoringDownload counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
pgEnvironment{
"local_name": "pg",
"alias": false,
"peer_metadata": null
} | ^8.11.3 | runtime |
wsEnvironment{
"local_name": "ws",
"alias": false,
"peer_metadata": null
} | ^8.14.2 | runtime |
corsEnvironment{
"local_name": "cors",
"alias": false,
"peer_metadata": null
} | ^2.8.5 | runtime |
pinoEnvironment{
"local_name": "pino",
"alias": false,
"peer_metadata": null
} | ^8.16.2 | runtime |
yargsEnvironment{
"local_name": "yargs",
"alias": false,
"peer_metadata": null
} | ^17.7.2 | runtime |
dotenvEnvironment{
"local_name": "dotenv",
"alias": false,
"peer_metadata": null
} | ^16.3.1 | runtime |
expressEnvironment{
"local_name": "express",
"alias": false,
"peer_metadata": null
} | ^4.21.2 | runtime |
graphqlEnvironment{
"local_name": "graphql",
"alias": false,
"peer_metadata": null
} | ^15.8.0 | runtime |
graphql-wsEnvironment{
"local_name": "graphql-ws",
"alias": false,
"peer_metadata": null
} | ^5.16.2 | runtime |
node-fetchEnvironment{
"local_name": "node-fetch",
"alias": false,
"peer_metadata": null
} | ^3.3.2 | runtime |
pino-prettyEnvironment{
"local_name": "pino-pretty",
"alias": false,
"peer_metadata": null
} | ^10.2.3 | runtime |
postgraphileEnvironment{
"local_name": "postgraphile",
"alias": false,
"peer_metadata": null
} | ^4.13.0 | runtime |
graphile-utilsEnvironment{
"local_name": "graphile-utils",
"alias": false,
"peer_metadata": null
} | ^4.14.1 | runtime |
@graphile/pg-pubsubEnvironment{
"local_name": "@graphile/pg-pubsub",
"alias": false,
"peer_metadata": null
} | ^4.14.1 | runtime |
apollo-server-expressEnvironment{
"local_name": "apollo-server-express",
"alias": false,
"peer_metadata": null
} | ^3.13.0 | runtime |
graphql-subscriptionsEnvironment{
"local_name": "graphql-subscriptions",
"alias": false,
"peer_metadata": null
} | ^2.0.0 | runtime |
@graphile/subscriptions-ldsEnvironment{
"local_name": "@graphile/subscriptions-lds",
"alias": false,
"peer_metadata": null
} | ^4.14.1 | runtime |
postgraphile-plugin-connection-filterEnvironment{
"local_name": "postgraphile-plugin-connection-filter",
"alias": false,
"peer_metadata": null
} | ^2.3.0 | runtime |
@graphile-contrib/pg-simplify-inflectorEnvironment{
"local_name": "@graphile-contrib/pg-simplify-inflector",
"alias": false,
"peer_metadata": null
} | ^6.1.0 | runtime |
tsxEnvironment{
"local_name": "tsx",
"alias": false,
"peer_metadata": null
} | ^3.12.10 | development |
jestEnvironment{
"local_name": "jest",
"alias": false,
"peer_metadata": null
} | ^29.7.0 | development |
eslintEnvironment{
"local_name": "eslint",
"alias": false,
"peer_metadata": null
} | ^8.52.0 | development |
nodemonEnvironment{
"local_name": "nodemon",
"alias": false,
"peer_metadata": null
} | ^3.1.10 | development |
ts-nodeEnvironment{
"local_name": "ts-node",
"alias": false,
"peer_metadata": null
} | ^10.9.1 | development |
@types/pgEnvironment{
"local_name": "@types/pg",
"alias": false,
"peer_metadata": null
} | ^8.10.7 | development |
@types/wsEnvironment{
"local_name": "@types/ws",
"alias": false,
"peer_metadata": null
} | ^8.5.8 | development |
typescriptEnvironment{
"local_name": "typescript",
"alias": false,
"peer_metadata": null
} | ^5.2.2 | development |
@types/corsEnvironment{
"local_name": "@types/cors",
"alias": false,
"peer_metadata": null
} | ^2.8.18 | development |
@types/nodeEnvironment{
"local_name": "@types/node",
"alias": false,
"peer_metadata": null
} | ^20.8.10 | development |
@types/yargsEnvironment{
"local_name": "@types/yargs",
"alias": false,
"peer_metadata": null
} | ^17.0.24 | development |
@types/expressEnvironment{
"local_name": "@types/express",
"alias": false,
"peer_metadata": null
} | ^4.17.23 | development |
@typescript-eslint/parserEnvironment{
"local_name": "@typescript-eslint/parser",
"alias": false,
"peer_metadata": null
} | ^6.9.1 | development |
@typescript-eslint/eslint-pluginEnvironment{
"local_name": "@typescript-eslint/eslint-plugin",
"alias": false,
"peer_metadata": null
} | ^6.9.1 | development |
Source distribution
{
"shasum": "9b824fda1c0aba3a98b20f48cfb972ef1c4978b8",
"tarball": "https://registry.npmjs.org/@0xobelisk/graphql-server/-/graphql-server-1.2.0-pre.48.tgz",
"fileCount": 85,
"integrity": "sha512-L2wMTgUV1fdElBdrXjfuwYIXjTYhVbJTn7Img2yT7uriYl169B2Tbgi/izHSycD5D0hQ44wAtMstcEC/Cm5hRQ==",
"signatures": [
{
"sig": "MEUCIFlDr31MCinlsgB/7yhoj62URLnjpPpETRMpkfzzlW+oAiEAh45Z7GfRUhv8lQaQ069QLOz5otFGE2zw+/2q14WBgLA=",
"keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
}
],
"unpackedSize": 340136
}Observed since 21 Oct, 09:19 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:02fc01e9d37a41b8ea080663d2803fe0608705222d2e4d47c628f3b36fb8a95f