# 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 { 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.