feat: Complete Issue #3 - Schema Management with Enhanced Format Control
Some checks failed
Test Suite / security-scan (push) Has been cancelled
Test Suite / test-summary (push) Has been cancelled
Test Suite / unit-tests (3.11) (push) Has been cancelled
Test Suite / unit-tests (3.12) (push) Has been cancelled
Test Suite / integration-tests (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / performance-tests (push) Has been cancelled
Test Suite / code-quality (push) Has been cancelled
Some checks failed
Test Suite / security-scan (push) Has been cancelled
Test Suite / test-summary (push) Has been cancelled
Test Suite / unit-tests (3.11) (push) Has been cancelled
Test Suite / unit-tests (3.12) (push) Has been cancelled
Test Suite / integration-tests (push) Has been cancelled
Test Suite / e2e-tests (push) Has been cancelled
Test Suite / performance-tests (push) Has been cancelled
Test Suite / code-quality (push) Has been cancelled
🔧 Schema Management System: - schema-ingest: Store JSON schema files in database with metadata parsing - schema-list: List all stored schemas with --format and --names-only options - schema-get: Retrieve stored schemas to stdout or file - schema-delete: Remove schemas with confirmation prompts - Full database integration with schemas table 📊 Enhanced Format Control: - MARKITECT_DEFAULT_FORMAT environment variable for global format defaults - Consistent --format options across all CLI commands (table|json|yaml|simple) - get_default_format() function with fallback logic for invalid values - Applied format control to query, schema, metadata, list, and ast-stats commands 🛠️ Bug Fixes: - Fixed ast-stats command empty output by adding 'simple' format handler - Created missing schema_summary.py for schema visualization tests - All 394 tests now passing ✨ Usability Improvements: - Unified format handling across the entire CLI interface - Environment-based configuration for user preferences - Enhanced schema management workflow with comprehensive CRUD operations 🧪 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
"""
|
||||
Database management functionality for MarkiTect.
|
||||
|
||||
This module provides SQLite database initialization and markdown file storage
|
||||
with front matter support.
|
||||
This module provides SQLite database initialization, markdown file storage
|
||||
with front matter support, and JSON schema storage (Issue #3).
|
||||
"""
|
||||
|
||||
import sqlite3
|
||||
@@ -58,6 +58,19 @@ class DatabaseManager:
|
||||
)
|
||||
''')
|
||||
|
||||
# Create schemas table for Issue #3
|
||||
cursor.execute('''
|
||||
CREATE TABLE IF NOT EXISTS schemas (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
filename TEXT NOT NULL UNIQUE,
|
||||
title TEXT,
|
||||
description TEXT,
|
||||
schema_content TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
''')
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
@@ -257,4 +270,152 @@ class DatabaseManager:
|
||||
|
||||
except sqlite3.Error as e:
|
||||
conn.close()
|
||||
raise e
|
||||
raise e
|
||||
|
||||
# Schema management methods for Issue #3
|
||||
def store_schema_file(self, filename: str, schema_content: str) -> Optional[int]:
|
||||
"""
|
||||
Store a JSON schema file in the database.
|
||||
|
||||
Args:
|
||||
filename: Name of the schema file
|
||||
schema_content: JSON schema content as string
|
||||
|
||||
Returns:
|
||||
ID of the inserted/updated record, or None if operation failed
|
||||
"""
|
||||
try:
|
||||
# Parse and validate JSON schema
|
||||
schema_data = json.loads(schema_content)
|
||||
title = schema_data.get('title', filename)
|
||||
description = schema_data.get('description', '')
|
||||
except json.JSONDecodeError:
|
||||
return None
|
||||
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
# Check if schema already exists
|
||||
cursor.execute('SELECT id FROM schemas WHERE filename = ?', (filename,))
|
||||
existing = cursor.fetchone()
|
||||
|
||||
if existing:
|
||||
# Update existing schema
|
||||
cursor.execute('''
|
||||
UPDATE schemas
|
||||
SET title = ?, description = ?, schema_content = ?, updated_at = ?
|
||||
WHERE filename = ?
|
||||
''', (title, description, schema_content, datetime.now().isoformat(), filename))
|
||||
record_id = existing[0]
|
||||
else:
|
||||
# Insert new schema
|
||||
cursor.execute('''
|
||||
INSERT INTO schemas (filename, title, description, schema_content, created_at, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
''', (filename, title, description, schema_content,
|
||||
datetime.now().isoformat(), datetime.now().isoformat()))
|
||||
record_id = cursor.lastrowid
|
||||
|
||||
conn.commit()
|
||||
return record_id
|
||||
|
||||
except sqlite3.Error:
|
||||
conn.rollback()
|
||||
return None
|
||||
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_schema_file(self, filename: str) -> Optional[Dict[str, Any]]:
|
||||
"""
|
||||
Retrieve a schema file from the database.
|
||||
|
||||
Args:
|
||||
filename: Name of the schema file to retrieve
|
||||
|
||||
Returns:
|
||||
Dictionary containing schema data, or None if not found
|
||||
"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute('''
|
||||
SELECT id, filename, title, description, schema_content, created_at, updated_at
|
||||
FROM schemas
|
||||
WHERE filename = ?
|
||||
''', (filename,))
|
||||
|
||||
row = cursor.fetchone()
|
||||
conn.close()
|
||||
|
||||
if row:
|
||||
return {
|
||||
'id': row[0],
|
||||
'filename': row[1],
|
||||
'title': row[2],
|
||||
'description': row[3],
|
||||
'schema_content': row[4],
|
||||
'created_at': row[5],
|
||||
'updated_at': row[6]
|
||||
}
|
||||
|
||||
return None
|
||||
|
||||
def list_schema_files(self) -> list:
|
||||
"""
|
||||
List all schema files in the database.
|
||||
|
||||
Returns:
|
||||
List of dictionaries containing schema metadata
|
||||
"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
cursor.execute('''
|
||||
SELECT id, filename, title, description, created_at, updated_at
|
||||
FROM schemas
|
||||
ORDER BY updated_at DESC
|
||||
''')
|
||||
|
||||
rows = cursor.fetchall()
|
||||
conn.close()
|
||||
|
||||
schemas = []
|
||||
for row in rows:
|
||||
schemas.append({
|
||||
'id': row[0],
|
||||
'filename': row[1],
|
||||
'title': row[2],
|
||||
'description': row[3],
|
||||
'created_at': row[4],
|
||||
'updated_at': row[5]
|
||||
})
|
||||
|
||||
return schemas
|
||||
|
||||
def delete_schema_file(self, filename: str) -> bool:
|
||||
"""
|
||||
Delete a schema file from the database.
|
||||
|
||||
Args:
|
||||
filename: Name of the schema file to delete
|
||||
|
||||
Returns:
|
||||
True if deletion was successful, False otherwise
|
||||
"""
|
||||
conn = sqlite3.connect(self.db_path)
|
||||
cursor = conn.cursor()
|
||||
|
||||
try:
|
||||
cursor.execute('DELETE FROM schemas WHERE filename = ?', (filename,))
|
||||
success = cursor.rowcount > 0
|
||||
conn.commit()
|
||||
return success
|
||||
|
||||
except sqlite3.Error:
|
||||
conn.rollback()
|
||||
return False
|
||||
|
||||
finally:
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user