Files
markitect-main/docs/graphql_interface.md
tegwick 2dd1704e51 feat: implement comprehensive GraphQL read interface (issue #9)
Adds a complete GraphQL API for querying MarkiTect database content including:

CORE FEATURES:
- Type-safe GraphQL schema with comprehensive field definitions
- Full database access: markdown files, schemas, ASTs, and metadata
- Advanced search capabilities with relevance scoring
- Pagination support for efficient data access
- Real-time schema introspection and development tools

IMPLEMENTATION:
- GraphQL schema definition with 6 core types (MarkdownFile, Schema, AST, etc.)
- Complete resolver implementation with database integration
- Flask-based GraphQL server with CORS support
- GraphQL Playground for interactive development
- Health check and schema introspection endpoints

CLI INTEGRATION:
- graphql-serve: Start GraphQL server with customizable options
- graphql-query: Execute queries from command line (local/remote)
- graphql-schema: Retrieve schema definition in SDL/JSON format
- graphql-examples: Comprehensive usage examples and documentation

API FEATURES:
- Single item queries (by ID or filename)
- List queries with filtering and pagination
- Full-text search across files and schemas
- Database statistics and analytics
- AST querying with JSONPath expressions
- Computed fields (word count, line count, etc.)

TESTING:
- Comprehensive test suite with 38 passing tests
- Unit tests for schema, resolvers, server, and client
- Integration tests for query execution
- Error handling and edge case coverage
- Mock and fixture support for isolated testing

DOCUMENTATION:
- Complete API documentation with examples
- Usage guide for all CLI commands
- Programming examples in Python and JavaScript
- Performance optimization guidelines
- Troubleshooting and security considerations

The GraphQL interface enables developers to build rich applications on top of
MarkiTect data with flexible, efficient querying capabilities.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-03 11:53:53 +02:00

697 lines
12 KiB
Markdown

# GraphQL Read Interface for MarkiTect
## Overview
The GraphQL read interface provides a powerful, type-safe way to query MarkiTect's database content including Markdown files, ASTs, schemas, and metadata. This interface enables developers to build rich applications on top of MarkiTect's data with flexible querying capabilities.
## Features
- **Complete Type Safety**: Strongly-typed GraphQL schema with comprehensive field definitions
- **Flexible Querying**: Query exactly the data you need with GraphQL's selective field syntax
- **Rich Data Access**: Access markdown files, schemas, ASTs, and computed fields
- **Search Capabilities**: Full-text search across files and schemas with relevance scoring
- **Pagination Support**: Efficient pagination for large datasets
- **Real-time Introspection**: Schema introspection and GraphQL Playground for development
- **Multiple Access Methods**: HTTP server, local execution, and CLI integration
## Getting Started
### Prerequisites
Install the required dependencies:
```bash
pip install graphene flask flask-cors jsonpath-ng requests
```
### Starting the GraphQL Server
Start the GraphQL server using the CLI:
```bash
markitect graphql-serve
```
By default, this starts the server on `http://localhost:5000`. You can customize the host and port:
```bash
markitect graphql-serve --host 0.0.0.0 --port 8080
```
### Accessing the GraphQL Playground
Once the server is running, visit `http://localhost:5000/graphql` in your browser to access the GraphQL Playground, an interactive development environment for testing queries.
## GraphQL Schema
### Core Types
#### MarkdownFile
Represents a Markdown file in the MarkiTect database:
```graphql
type MarkdownFile {
id: Int!
filename: String!
content: String
frontMatter: [FrontMatter]
frontMatterRaw: JSONString
createdAt: DateTime
wordCount: Int
lineCount: Int
hasFrontMatter: Boolean
}
```
#### Schema
Represents a JSON schema:
```graphql
type Schema {
id: Int!
filename: String!
title: String
description: String
schemaContent: JSONString!
createdAt: DateTime
updatedAt: DateTime
schemaVersion: String
propertyCount: Int
}
```
#### AST
Represents an Abstract Syntax Tree for a Markdown file:
```graphql
type AST {
fileId: Int
filename: String!
tree: [ASTNode]
metadata: JSONString
headingCount: Int
linkCount: Int
imageCount: Int
codeBlockCount: Int
}
```
#### DatabaseStats
Provides statistics about the MarkiTect database:
```graphql
type DatabaseStats {
totalFiles: Int
totalSchemas: Int
totalSizeBytes: Int
lastUpdated: DateTime
}
```
#### SearchResult
Represents search results across files and schemas:
```graphql
type SearchResult {
type: String!
score: Float
file: MarkdownFile
schema: Schema
highlight: String
}
```
### Query Operations
#### Single Item Queries
Get a specific markdown file:
```graphql
{
markdownFile(id: 1) {
id
filename
content
wordCount
hasFrontMatter
}
}
```
Get a specific schema:
```graphql
{
schema(filename: "user-schema.json") {
title
description
schemaVersion
propertyCount
}
}
```
Get AST for a file:
```graphql
{
ast(filename: "document.md") {
headingCount
linkCount
tree {
type
value
level
}
}
}
```
#### List Queries
Get all markdown files with pagination:
```graphql
{
markdownFiles(limit: 10, offset: 0) {
id
filename
createdAt
hasFrontMatter
}
}
```
Filter files by front matter presence:
```graphql
{
markdownFiles(hasFrontMatter: true, limit: 5) {
filename
frontMatter {
key
value
}
}
}
```
Get all schemas:
```graphql
{
schemas(limit: 20) {
filename
title
description
propertyCount
}
}
```
#### Search Queries
Search across all content:
```graphql
{
search(query: "documentation", type: "all", limit: 10) {
type
score
file {
filename
content
}
schema {
title
description
}
highlight
}
}
```
Search only in files:
```graphql
{
search(query: "API", type: "file", limit: 5) {
score
file {
filename
wordCount
}
highlight
}
}
```
#### Database Statistics
Get database overview:
```graphql
{
databaseStats {
totalFiles
totalSchemas
totalSizeBytes
lastUpdated
}
}
```
#### Advanced AST Queries
Query AST using JSONPath expressions:
```graphql
{
astQuery(
filename: "document.md",
jsonpath: "$.children[?(@.type=='heading')]"
)
}
```
## CLI Integration
### Available Commands
#### graphql-serve
Start the GraphQL server:
```bash
markitect graphql-serve [OPTIONS]
Options:
--host TEXT Host to bind to (default: 127.0.0.1)
--port INTEGER Port to bind to (default: 5000)
--debug Enable debug mode
--no-cors Disable CORS
```
#### graphql-query
Execute GraphQL queries from the command line:
```bash
markitect graphql-query QUERY [OPTIONS]
Options:
--variables TEXT JSON string of query variables
--endpoint TEXT GraphQL endpoint URL
--local Execute query locally without HTTP
--format [json|yaml|table] Output format (default: json)
```
Examples:
```bash
# Execute a simple query locally
markitect graphql-query "{ databaseStats { totalFiles } }" --local
# Execute query with variables
markitect graphql-query "query($limit: Int) { markdownFiles(limit: $limit) { filename } }" --variables '{"limit": 5}' --local
# Execute query against remote server
markitect graphql-query "{ schemas { title } }" --endpoint http://localhost:5000/graphql
```
#### graphql-schema
Get the GraphQL schema definition:
```bash
markitect graphql-schema [OPTIONS]
Options:
--format [sdl|json] Schema format (default: sdl)
--endpoint TEXT GraphQL endpoint URL
```
#### graphql-examples
Show example queries and usage:
```bash
markitect graphql-examples
```
## Programming API
### Using the GraphQL Client
```python
from markitect.graphql import GraphQLClient
# Create a client
client = GraphQLClient("http://localhost:5000/graphql")
# Execute a query
result = client.execute("""
{
markdownFiles(limit: 5) {
filename
wordCount
}
}
""")
print(result['data'])
```
### Local Execution
```python
from markitect.graphql import GraphQLClient
# Execute queries locally without HTTP
client = GraphQLClient()
result = client.execute_local("""
{
databaseStats {
totalFiles
totalSchemas
}
}
""")
print(result['data'])
```
### Using the Server Directly
```python
from markitect.graphql import GraphQLServer
# Create and start server
server = GraphQLServer(db_path="/path/to/markitect.db")
app = server.create_app()
# Start server
server.run(host="0.0.0.0", port=8080, debug=True)
```
## API Endpoints
When running the GraphQL server, the following endpoints are available:
- `POST /graphql` - Main GraphQL endpoint for queries
- `GET /graphql` - GraphQL Playground interface
- `GET /schema` - Schema introspection
- `GET /health` - Health check endpoint
### Health Check Response
```json
{
"status": "healthy",
"database": "connected",
"database_path": "/path/to/markitect.db"
}
```
## Error Handling
The GraphQL interface provides comprehensive error handling:
### Query Errors
Invalid GraphQL syntax or non-existent fields return structured errors:
```json
{
"data": null,
"errors": [
{
"message": "Cannot query field 'nonexistentField' on type 'Query'"
}
]
}
```
### Database Errors
Database connectivity issues are handled gracefully:
```json
{
"data": {
"databaseStats": null
},
"errors": [
{
"message": "Database connection error"
}
]
}
```
## Performance Considerations
### Pagination
Always use pagination for large datasets:
```graphql
{
markdownFiles(limit: 50, offset: 0) {
id
filename
}
}
```
### Field Selection
Only query the fields you need:
```graphql
# Good - selective fields
{
markdownFiles {
id
filename
}
}
# Avoid - requesting large content fields unnecessarily
{
markdownFiles {
id
filename
content # Only include if needed
}
}
```
### Search Optimization
Use specific search types when possible:
```graphql
# Better - search only files
{
search(query: "API", type: "file", limit: 10) {
file {
filename
}
}
}
# Less efficient - search all types
{
search(query: "API", type: "all", limit: 10) {
type
file { filename }
schema { title }
}
}
```
## Security Considerations
### Read-Only Interface
The GraphQL interface is read-only and does not support mutations, providing safe access to MarkiTect data.
### CORS Configuration
CORS is enabled by default for browser access. Disable with `--no-cors` if needed:
```bash
markitect graphql-serve --no-cors
```
### Database Access
The interface uses the same database path configuration as the main MarkiTect CLI, respecting the `MARKITECT_DB` environment variable.
## Troubleshooting
### Common Issues
#### "Flask is required" Error
Install Flask dependencies:
```bash
pip install flask flask-cors
```
#### "requests is required" Error
Install requests for HTTP client functionality:
```bash
pip install requests
```
#### Database Connection Errors
Check that your MarkiTect database exists and is accessible:
```bash
# Check database location
echo $MARKITECT_DB
# Verify database exists
ls -la ~/.markitect/markitect.db
```
#### GraphQL Syntax Errors
Use the GraphQL Playground at `http://localhost:5000/graphql` to validate your queries with real-time syntax checking and auto-completion.
## Examples
### Complete Data Export
Export all markdown files with metadata:
```graphql
{
markdownFiles {
id
filename
content
createdAt
wordCount
lineCount
hasFrontMatter
frontMatter {
key
value
}
}
}
```
### Schema Analysis
Analyze all schemas in the database:
```graphql
{
schemas {
filename
title
description
schemaVersion
propertyCount
schemaContent
}
}
```
### Content Discovery
Find all documents containing specific terms:
```graphql
{
search(query: "authentication security", type: "all", limit: 20) {
type
score
file {
filename
wordCount
hasFrontMatter
}
schema {
title
description
}
highlight
}
}
```
### Database Overview
Get a complete overview of your MarkiTect database:
```graphql
{
databaseStats {
totalFiles
totalSchemas
totalSizeBytes
lastUpdated
}
recentFiles: markdownFiles(limit: 5) {
filename
createdAt
}
recentSchemas: schemas(limit: 5) {
filename
title
createdAt
}
}
```
## Integration Examples
### With JavaScript/TypeScript
```typescript
interface DatabaseStats {
totalFiles: number;
totalSchemas: number;
totalSizeBytes: number;
lastUpdated: string;
}
async function getStats(): Promise<DatabaseStats> {
const response = await fetch('http://localhost:5000/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `
{
databaseStats {
totalFiles
totalSchemas
totalSizeBytes
lastUpdated
}
}
`
})
});
const { data } = await response.json();
return data.databaseStats;
}
```
### With Python
```python
import requests
from typing import List, Dict, Any
def search_content(query: str, limit: int = 10) -> List[Dict[str, Any]]:
"""Search for content in MarkiTect database."""
response = requests.post('http://localhost:5000/graphql', json={
'query': '''
query SearchContent($query: String!, $limit: Int!) {
search(query: $query, type: "all", limit: $limit) {
type
score
file {
filename
wordCount
}
schema {
title
description
}
highlight
}
}
''',
'variables': {
'query': query,
'limit': limit
}
})
return response.json()['data']['search']
# Usage
results = search_content("API documentation", limit=5)
for result in results:
print(f"Found {result['type']}: {result['highlight']}")
```
This GraphQL interface provides a powerful, flexible way to access and query MarkiTect data, enabling rich integrations and applications built on top of your Markdown content management system.