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>
697 lines
12 KiB
Markdown
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. |