client_example.html•45.5 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSON Schema Validator SSE Client</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.container {
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.section {
margin-bottom: 30px;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
}
.section h2 {
margin-top: 0;
color: #333;
}
textarea {
width: 100%;
height: 150px;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-family: monospace;
font-size: 14px;
resize: vertical;
}
input[type="text"] {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
margin-bottom: 10px;
}
button {
background-color: #007bff;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
margin-bottom: 10px;
}
button:hover {
background-color: #0056b3;
}
button:disabled {
background-color: #6c757d;
cursor: not-allowed;
}
.progress-bar {
width: 100%;
height: 20px;
background-color: #e9ecef;
border-radius: 10px;
overflow: hidden;
margin: 10px 0;
}
.progress-fill {
height: 100%;
background-color: #28a745;
width: 0%;
transition: width 0.3s ease;
}
.log {
background-color: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
padding: 15px;
height: 200px;
overflow-y: auto;
font-family: monospace;
font-size: 12px;
white-space: pre-wrap;
}
.status {
padding: 10px;
border-radius: 4px;
margin: 10px 0;
}
.status.success {
background-color: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
.status.error {
background-color: #f8d7da;
border: 1px solid #f5c6cb;
color: #721c24;
}
.status.info {
background-color: #d1ecf1;
border: 1px solid #bee5eb;
color: #0c5460;
}
.checkbox-container {
margin: 10px 0;
}
.checkbox-container input[type="checkbox"] {
margin-right: 8px;
}
</style>
</head>
<body>
<div class="container">
<h1>JSON Schema Validator SSE Client</h1>
<p>Example client to demonstrate Server-Sent Events with real-time JSON Schema validation.</p>
<!-- Section 1: Direct Validation -->
<div class="section">
<h2>🔍 Direct Validation (Streaming)</h2>
<label for="jsonData">JSON Data:</label>
<textarea id="jsonData" placeholder='{"name": "John", "age": 30}'>{
"name": "John",
"age": 30,
"email": "john@email.com"
}</textarea>
<label for="jsonSchema">JSON Schema:</label>
<textarea id="jsonSchema" placeholder='{"type": "object", "properties": {...}}'>{
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"email": {
"type": "string",
"format": "email"
}
},
"required": ["name", "age"]
}</textarea>
<div class="checkbox-container">
<input type="checkbox" id="strictValidation" checked>
<label for="strictValidation">Strict validation</label>
</div>
<button onclick="validateDirect()">Validate with SSE</button>
<button onclick="validateDirectImmediate()">Validate Immediate</button>
<div class="progress-bar">
<div class="progress-fill" id="progress1"></div>
</div>
<div id="status1" class="status" style="display: none;"></div>
</div>
<!-- Section 2: Validation from Collection -->
<div class="section">
<h2>📚 Validation from Collection</h2>
<label for="jsonDataCollection">JSON Data:</label>
<textarea id="jsonDataCollection" placeholder='{"user_id": 123, "username": "john_doe"}'>{
"user_id": 123,
"username": "john_doe",
"email": "john@example.com",
"created_at": "2024-01-15T10:30:00Z"
}</textarea>
<label for="schemaId">Schema ID (must exist in .schemas collection):</label>
<input type="text" id="schemaId" placeholder="user/profile.json" value="user.json">
<div class="checkbox-container">
<input type="checkbox" id="strictValidationCollection" checked>
<label for="strictValidationCollection">Strict validation</label>
</div>
<button onclick="validateFromCollection()">Validate from Collection (SSE)</button>
<button onclick="validateFromCollectionImmediate()">Validate Immediate</button>
<div class="progress-bar">
<div class="progress-fill" id="progress2"></div>
</div>
<div id="status2" class="status" style="display: none;"></div>
</div>
<!-- Section 3: Add Schema -->
<div class="section">
<h2>➕ Add/Update Schema</h2>
<label for="newSchemaId">Schema ID:</label>
<input type="text" id="newSchemaId" placeholder="user/profile.json" value="example_user.json">
<label for="newSchemaContent">Schema Content:</label>
<textarea id="newSchemaContent" placeholder='{"type": "object", ...}'>{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"title": "User Profile Schema",
"description": "Schema for user profile validation",
"properties": {
"user_id": {
"type": "integer",
"minimum": 1
},
"username": {
"type": "string",
"pattern": "^[a-zA-Z0-9_]{3,20}$"
},
"email": {
"type": "string",
"format": "email"
},
"created_at": {
"type": "string",
"format": "date-time"
}
},
"required": ["user_id", "username", "email"]
}</textarea>
<div class="checkbox-container">
<input type="checkbox" id="updateIfExists">
<label for="updateIfExists">Update if already exists</label>
</div>
<button onclick="addSchema()">Add Schema (SSE)</button>
<button onclick="addSchemaImmediate()">Add Immediate</button>
<div class="progress-bar">
<div class="progress-fill" id="progress3"></div>
</div>
<div id="status3" class="status" style="display: none;"></div>
</div>
<!-- Section 4: List Schemas -->
<div class="section">
<h2>📋 List Available Schemas</h2>
<button onclick="listSchemas()">List Schemas (SSE)</button>
<button onclick="listSchemasImmediate()">List Immediate</button>
<div class="progress-bar">
<div class="progress-fill" id="progress4"></div>
</div>
<div id="status4" class="status" style="display: none;"></div>
<label for="schemaList">Available Schemas:</label>
<textarea id="schemaList" readonly placeholder="The schema list will appear here..."></textarea>
</div>
<!-- Section 5: Generate Schema from JSON -->
<div class="section">
<h2>🎯 Generate Schema from JSON</h2>
<label for="generateSchemaId">Schema ID to generate:</label>
<input type="text" id="generateSchemaId" placeholder="generated_schema.json" value="generated_user.json">
<label for="generateJsonData">Sample JSON data:</label>
<textarea id="generateJsonData" placeholder='{"name": "John Doe", "age": 30, "email": "john@example.com", "active": true}'>{"name": "John Doe", "age": 30, "email": "john@example.com", "active": true, "address": {"street": "123 Main St", "city": "New York", "zip": null}}</textarea>
<label for="nullHandling">Null value handling:</label>
<select id="nullHandling" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px;">
<option value="allow">Allow - Allows null values</option>
<option value="ignore">Ignore - Ignores fields with null</option>
<option value="strict">Strict - Treats nulls as strings</option>
</select>
<br><br>
<button onclick="generateSchema()">Generate Schema (SSE)</button>
<button onclick="generateSchemaImmediate()">Generate Immediate</button>
<div class="progress-bar">
<div class="progress-fill" id="progress5"></div>
</div>
<div id="status5" class="status" style="display: none;"></div>
<label for="generatedSchema">Generated Schema:</label>
<textarea id="generatedSchema" readonly placeholder="The generated schema will appear here..."></textarea>
</div>
<!-- Section 6: Get Schema -->
<div class="section">
<h2>📖 Get Schema</h2>
<label for="getSchemaId">Schema ID to retrieve:</label>
<input type="text" id="getSchemaId" placeholder="user/profile.json" value="example_user.json">
<button onclick="getSchema()">Get Schema (SSE)</button>
<button onclick="getSchemaImmediate()">Get Immediate</button>
<div class="progress-bar">
<div class="progress-fill" id="progress6"></div>
</div>
<div id="status6" class="status" style="display: none;"></div>
<label for="schemaOutput">Schema Content:</label>
<textarea id="schemaOutput" readonly placeholder="The schema content will appear here..."></textarea>
</div>
<!-- Section 7: Delete Schema -->
<div class="section">
<h2>🗑️ Delete Schema</h2>
<label for="deleteSchemaId">Schema ID to delete:</label>
<input type="text" id="deleteSchemaId" placeholder="user/profile.json" value="example_user.json">
<div class="checkbox-container">
<input type="checkbox" id="confirmDeletion">
<label for="confirmDeletion">I confirm that I want to delete this schema (irreversible)</label>
</div>
<button onclick="deleteSchema()">Delete Schema (SSE)</button>
<button onclick="deleteSchemaImmediate()">Delete Immediate</button>
<div class="progress-bar">
<div class="progress-fill" id="progress7"></div>
</div>
<div id="status7" class="status" style="display: none;"></div>
</div>
<!-- Section 8: Validator Information -->
<div class="section">
<h2>ℹ️ Validator Information</h2>
<p>Get information about the JSON Schema validation server capabilities.</p>
<button onclick="getValidationInfo()">Get Information</button>
<div class="progress-bar">
<div class="progress-fill" id="progress8"></div>
</div>
<div id="status8" class="status" style="display: none;"></div>
<label for="validatorInfo">Validator Information:</label>
<textarea id="validatorInfo" readonly placeholder="The validator information will appear here..."></textarea>
</div>
<!-- Event Log -->
<div class="section">
<h2>📋 SSE Event Log</h2>
<button onclick="clearLog()">Clear Log</button>
<div id="eventLog" class="log"></div>
</div>
</div>
<script>
const SERVER_URL = 'http://localhost:8000';
let eventSource = null;
function log(message, type = 'info') {
const logElement = document.getElementById('eventLog');
const timestamp = new Date().toLocaleTimeString();
const logEntry = `[${timestamp}] ${type.toUpperCase()}: ${message}\n`;
logElement.textContent += logEntry;
logElement.scrollTop = logElement.scrollHeight;
}
function clearLog() {
document.getElementById('eventLog').textContent = '';
}
function updateProgress(progressId, percentage) {
document.getElementById(progressId).style.width = percentage + '%';
}
function showStatus(statusId, message, type) {
const statusElement = document.getElementById(statusId);
statusElement.textContent = message;
statusElement.className = `status ${type}`;
statusElement.style.display = 'block';
}
function hideStatus(statusId) {
document.getElementById(statusId).style.display = 'none';
}
function setupSSEConnection(endpoint, data, progressId, statusId, method = 'POST') {
// Close previous connection if it exists
if (eventSource) {
eventSource.close();
}
// Reset progress
updateProgress(progressId, 0);
hideStatus(statusId);
// Send data via POST and get streaming response
fetch(`${SERVER_URL}${endpoint}`, {
method: method,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
function readStream() {
reader.read().then(({ done, value }) => {
if (done) {
log('Stream completed');
return;
}
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
let currentEvent = {};
for (const line of lines) {
if (line.startsWith('event:')) {
currentEvent.type = line.substring(6).trim();
} else if (line.startsWith('data:')) {
try {
currentEvent.data = JSON.parse(line.substring(5).trim());
} catch (e) {
log(`Error parsing SSE data: ${e.message}`, 'error');
}
} else if (line.trim() === '' && currentEvent.type && currentEvent.data) {
// Process complete event
handleSSEEvent(currentEvent, progressId, statusId);
currentEvent = {};
}
}
readStream();
});
}
readStream();
})
.catch(error => {
log(`SSE connection error: ${error.message}`, 'error');
showStatus(statusId, `Error: ${error.message}`, 'error');
});
}
function handleSSEEvent(event, progressId, statusId) {
const { type, data } = event;
log(`Evento ${type}: ${data.message} (${data.progress}%)`, type);
updateProgress(progressId, data.progress);
switch (type) {
case 'start':
showStatus(statusId, data.message, 'info');
break;
case 'progress':
showStatus(statusId, data.message, 'info');
break;
case 'complete':
if (data.valid !== undefined) {
const status = data.valid ? 'success' : 'error';
const message = data.valid
? `✅ Validation successful`
: `❌ Validation failed: ${data.error_count} errors`;
showStatus(statusId, message, status);
if (!data.valid) {
log(`Errors found: ${JSON.stringify(data.errors, null, 2)}`, 'error');
}
} else if (data.deleted_from_database !== undefined || data.deleted_from_file !== undefined) {
// Special handling for schema deletion
showStatus(statusId, '✅ Schema deleted successfully', 'success');
log(`Schema deleted: ${JSON.stringify(data.schema_info, null, 2)}`, 'info');
// Clear fields after successful deletion
if (statusId === 'status7') {
document.getElementById('deleteSchemaId').value = '';
document.getElementById('confirmDeletion').checked = false;
}
} else if (data.schema_content !== undefined && data.schema_json !== undefined) {
// Special handling for schema retrieval
showStatus(statusId, '✅ Schema retrieved successfully', 'success');
log(`Schema retrieved: ${data.schema_id}`, 'info');
// Show schema content in textarea if status6 (get schema)
if (statusId === 'status6') {
document.getElementById('schemaOutput').value = data.schema_json;
}
} else if (data.schema_ids !== undefined && data.count !== undefined) {
// Special handling for schema listing
showStatus(statusId, `✅ List retrieved: ${data.count} schemas found`, 'success');
log(`Schemas found: ${data.count}`, 'info');
// Show schema list in textarea if status4 (list schemas)
if (statusId === 'status4') {
let listText = `Source: ${data.source}\nTotal schemas: ${data.count}\n\n`;
if (data.count === 0) {
listText += data.message || "No schemas available";
} else {
listText += "Available schemas:\n";
data.schema_ids.forEach((schema_id, index) => {
listText += `${index + 1}. ${schema_id}\n`;
});
}
document.getElementById('schemaList').value = listText;
}
} else if (data.generated_schema !== undefined && data.schema_info !== undefined) {
// Special handling for schema generation
showStatus(statusId, '✅ Schema generated and saved successfully', 'success');
log(`Schema generated: ${data.schema_id}`, 'info');
// Show generated schema info if status5 (generate schema)
if (statusId === 'status5') {
const schemaInfo = data.schema_info || {};
const summary = `🎯 Schema generated successfully:
- ID: ${data.schema_id}
- Título: ${schemaInfo.title || 'N/A'}
- Tipo: ${schemaInfo.type || 'N/A'}
- Propiedades: ${schemaInfo.property_count || 0}
- Required fields: ${schemaInfo.required_count || 0}
- Manejo de nulls: ${data.null_handling}
📋 Use 'Get Schema' with ID '${data.schema_id}' to view the complete schema.`;
document.getElementById('generatedSchema').value = summary;
// Clear inputs after success
document.getElementById('generateSchemaId').value = '';
document.getElementById('generateJsonData').value = '';
}
} else {
showStatus(statusId, '✅ Operation completed successfully', 'success');
}
break;
case 'error':
showStatus(statusId, `❌ Error: ${data.message}`, 'error');
if (data.error) {
log(`Error details: ${JSON.stringify(data, null, 2)}`, 'error');
}
break;
}
}
function validateDirect() {
try {
const jsonData = JSON.parse(document.getElementById('jsonData').value);
const schema = JSON.parse(document.getElementById('jsonSchema').value);
const strict = document.getElementById('strictValidation').checked;
const data = {
json_data: jsonData,
schema: schema,
strict: strict
};
log('Starting direct validation with SSE');
setupSSEConnection('/validate/stream', data, 'progress1', 'status1');
} catch (e) {
log(`Error parsing JSON: ${e.message}`, 'error');
showStatus('status1', `JSON Error: ${e.message}`, 'error');
}
}
function validateDirectImmediate() {
try {
const jsonData = JSON.parse(document.getElementById('jsonData').value);
const schema = JSON.parse(document.getElementById('jsonSchema').value);
const strict = document.getElementById('strictValidation').checked;
const data = {
json_data: jsonData,
schema: schema,
strict: strict
};
log('Starting immediate direct validation');
fetch(`${SERVER_URL}/validate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
log(`Immediate result: ${JSON.stringify(result, null, 2)}`);
const status = result.valid ? 'success' : 'error';
const message = result.valid
? '✅ Validation successful (immediate)'
: `❌ Validation failed: ${result.error_count} errors`;
showStatus('status1', message, status);
updateProgress('progress1', 100);
})
.catch(error => {
log(`Error: ${error.message}`, 'error');
showStatus('status1', `Error: ${error.message}`, 'error');
});
} catch (e) {
log(`Error parsing JSON: ${e.message}`, 'error');
showStatus('status1', `JSON Error: ${e.message}`, 'error');
}
}
function validateFromCollection() {
try {
const jsonData = JSON.parse(document.getElementById('jsonDataCollection').value);
const schemaId = document.getElementById('schemaId').value;
const strict = document.getElementById('strictValidationCollection').checked;
const data = {
json_data: jsonData,
schema_id: schemaId,
strict: strict
};
log('Starting validation from collection with SSE');
setupSSEConnection('/validate/collection/stream', data, 'progress2', 'status2');
} catch (e) {
log(`Error parsing JSON: ${e.message}`, 'error');
showStatus('status2', `JSON Error: ${e.message}`, 'error');
}
}
function validateFromCollectionImmediate() {
try {
const jsonData = JSON.parse(document.getElementById('jsonDataCollection').value);
const schemaId = document.getElementById('schemaId').value;
const strict = document.getElementById('strictValidationCollection').checked;
const data = {
json_data: jsonData,
schema_id: schemaId,
strict: strict
};
log('Starting immediate validation from collection');
fetch(`${SERVER_URL}/validate/collection`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => response.json())
.then(result => {
log(`Immediate result: ${JSON.stringify(result, null, 2)}`);
const status = result.valid ? 'success' : 'error';
const message = result.valid
? '✅ Validation successful (immediate)'
: `❌ Validation failed: ${result.error_count} errors`;
showStatus('status2', message, status);
updateProgress('progress2', 100);
})
.catch(error => {
log(`Error: ${error.message}`, 'error');
showStatus('status2', `Error: ${error.message}`, 'error');
});
} catch (e) {
log(`Error parsing JSON: ${e.message}`, 'error');
showStatus('status2', `JSON Error: ${e.message}`, 'error');
}
}
function addSchema() {
const schemaId = document.getElementById('newSchemaId').value;
const schemaContent = document.getElementById('newSchemaContent').value;
const updateIfExists = document.getElementById('updateIfExists').checked;
if (!schemaId || !schemaContent) {
showStatus('status3', 'Error: Schema ID and content are required', 'error');
return;
}
const data = {
schema_id: schemaId,
schema_content: schemaContent,
update_if_exists: updateIfExists
};
log('Starting schema addition with SSE');
setupSSEConnection('/schema/add/stream', data, 'progress3', 'status3');
}
function addSchemaImmediate() {
const schemaId = document.getElementById('newSchemaId').value;
const schemaContent = document.getElementById('newSchemaContent').value;
const updateIfExists = document.getElementById('updateIfExists').checked;
if (!schemaId || !schemaContent) {
showStatus('status3', 'Error: Schema ID and content are required', 'error');
return;
}
const data = {
schema_id: schemaId,
schema_content: schemaContent,
update_if_exists: updateIfExists
};
fetch(`${SERVER_URL}/schema/add`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
return response.json().then(err => Promise.reject(err));
}
return response.json();
})
.then(result => {
log(`Immediate result: ${JSON.stringify(result, null, 2)}`);
showStatus('status3', `✅ Schema saved successfully: ${data.schema_id}`, 'success');
updateProgress('progress3', 100);
})
.catch(error => {
log(`Error: ${error.detail || error.message}`, 'error');
showStatus('status3', `Error: ${error.detail || error.message}`, 'error');
});
}
function listSchemas() {
log('Starting schema listing with SSE');
setupSSEConnection('/schema/list/stream', {}, 'progress4', 'status4');
}
function listSchemasImmediate() {
log('Starting immediate schema listing');
fetch(`${SERVER_URL}/schema/list`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
})
.then(response => {
if (!response.ok) {
return response.json().then(err => Promise.reject(err));
}
return response.json();
})
.then(result => {
log(`Immediate result: ${JSON.stringify(result, null, 2)}`);
if (result.success) {
showStatus('status4', `✅ List retrieved: ${result.count} schemas found (immediate)`, 'success');
updateProgress('progress4', 100);
// Show schema list in textarea
let listText = `Source: ${result.source}\nTotal schemas: ${result.count}\n\n`;
if (result.count === 0) {
listText += result.message || "No schemas available";
} else {
listText += "Available schemas:\n";
result.schema_ids.forEach((schema_id, index) => {
listText += `${index + 1}. ${schema_id}\n`;
});
}
document.getElementById('schemaList').value = listText;
} else {
showStatus('status4', `❌ Error: ${result.error}`, 'error');
document.getElementById('schemaList').value = `Error: ${result.error}`;
}
})
.catch(error => {
log(`Error: ${error.detail || error.message}`, 'error');
showStatus('status4', `Error: ${error.detail || error.message}`, 'error');
document.getElementById('schemaList').value = '';
});
}
function getSchema() {
const schemaId = document.getElementById('getSchemaId').value;
if (!schemaId) {
showStatus('status5', 'Error: Schema ID es requerido', 'error');
return;
}
const data = {
schema_id: schemaId
};
log('Starting schema retrieval with SSE');
setupSSEConnection('/schema/get/stream', data, 'progress5', 'status5');
}
function getSchema() {
const schemaId = document.getElementById('getSchemaId').value;
if (!schemaId) {
showStatus('status6', 'Error: Schema ID es requerido', 'error');
return;
}
const data = {
schema_id: schemaId
};
log('Starting schema retrieval with SSE');
setupSSEConnection('/schema/get/stream', data, 'progress6', 'status6');
}
function getSchemaImmediate() {
const schemaId = document.getElementById('getSchemaId').value;
if (!schemaId) {
showStatus('status6', 'Error: Schema ID es requerido', 'error');
return;
}
log('Starting immediate schema retrieval');
fetch(`${SERVER_URL}/schema/get?schema_id=${encodeURIComponent(schemaId)}`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
})
.then(response => {
if (!response.ok) {
return response.json().then(err => Promise.reject(err));
}
return response.json();
})
.then(result => {
log(`Immediate result: ${JSON.stringify(result, null, 2)}`);
showStatus('status6', '✅ Schema retrieved successfully (immediate)', 'success');
updateProgress('progress6', 100);
// Show schema content in textarea
document.getElementById('schemaOutput').value = result.schema_content;
// Clear input after success
document.getElementById('getSchemaId').value = '';
})
.catch(error => {
log(`Error: ${error.detail || error.message}`, 'error');
showStatus('status6', `Error: ${error.detail || error.message}`, 'error');
});
}
function deleteSchema() {
const schemaId = document.getElementById('deleteSchemaId').value;
const confirmDeletion = document.getElementById('confirmDeletion').checked;
if (!schemaId) {
showStatus('status7', 'Error: Schema ID es requerido', 'error');
return;
}
if (!confirmDeletion) {
showStatus('status7', 'Error: You must confirm deletion by checking the checkbox', 'error');
return;
}
const data = {
schema_id: schemaId,
confirm_deletion: confirmDeletion
};
log('Starting schema deletion with SSE');
setupSSEConnection('/schema/delete/stream', data, 'progress7', 'status7', 'DELETE');
}
function deleteSchemaImmediate() {
const schemaId = document.getElementById('deleteSchemaId').value;
const confirmDeletion = document.getElementById('confirmDeletion').checked;
if (!schemaId) {
showStatus('status7', 'Error: Schema ID es requerido', 'error');
return;
}
if (!confirmDeletion) {
showStatus('status7', 'Error: You must confirm deletion by checking the checkbox', 'error');
return;
}
const data = {
schema_id: schemaId,
confirm_deletion: confirmDeletion
};
log('Starting immediate schema deletion');
fetch(`${SERVER_URL}/schema/delete`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
return response.json().then(err => Promise.reject(err));
}
return response.json();
})
.then(result => {
log(`Immediate result: ${JSON.stringify(result, null, 2)}`);
showStatus('status7', '✅ Schema deleted successfully (immediate)', 'success');
updateProgress('progress7', 100);
// Clear input after successful deletion
document.getElementById('deleteSchemaId').value = '';
document.getElementById('confirmDeletion').checked = false;
})
.catch(error => {
log(`Error: ${error.detail || error.message}`, 'error');
showStatus('status7', `Error: ${error.detail || error.message}`, 'error');
});
}
function generateSchema() {
const schemaId = document.getElementById('generateSchemaId').value;
const jsonDataText = document.getElementById('generateJsonData').value;
const nullHandling = document.getElementById('nullHandling').value;
if (!schemaId) {
showStatus('status5', 'Error: Schema ID es requerido', 'error');
return;
}
if (!jsonDataText) {
showStatus('status5', 'Error: JSON data is required', 'error');
return;
}
let jsonData;
try {
jsonData = JSON.parse(jsonDataText);
} catch (e) {
showStatus('status5', 'Error: Invalid JSON data', 'error');
return;
}
const data = {
schema_id: schemaId,
json_data: jsonData,
null_handling: nullHandling
};
log('Starting schema generation with SSE');
setupSSEConnection('/schema/generate/stream', data, 'progress5', 'status5');
}
function generateSchemaImmediate() {
const schemaId = document.getElementById('generateSchemaId').value;
const jsonDataText = document.getElementById('generateJsonData').value;
const nullHandling = document.getElementById('nullHandling').value;
if (!schemaId) {
showStatus('status5', 'Error: Schema ID es requerido', 'error');
return;
}
if (!jsonDataText) {
showStatus('status5', 'Error: JSON data is required', 'error');
return;
}
let jsonData;
try {
jsonData = JSON.parse(jsonDataText);
} catch (e) {
showStatus('status5', 'Error: Invalid JSON data', 'error');
return;
}
const data = {
schema_id: schemaId,
json_data: jsonData,
null_handling: nullHandling
};
log('Starting immediate schema generation');
fetch(`${SERVER_URL}/schema/generate`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
.then(response => {
if (!response.ok) {
return response.json().then(err => Promise.reject(err));
}
return response.json();
})
.then(result => {
log(`Immediate result: ${JSON.stringify(result, null, 2)}`);
showStatus('status5', '✅ Schema generated and saved successfully (immediate)', 'success');
updateProgress('progress5', 100);
// Show generated schema in textarea
const schemaInfo = result.schema_info || {};
const summary = `🎯 Schema generated successfully:
- ID: ${result.schema_id}
- Título: ${schemaInfo.title || 'N/A'}
- Tipo: ${schemaInfo.type || 'N/A'}
- Propiedades: ${schemaInfo.property_count || 0}
- Required fields: ${schemaInfo.required_count || 0}
- Manejo de nulls: ${result.null_handling}
📋 Use 'Get Schema' with ID '${result.schema_id}' to view the complete schema.`;
document.getElementById('generatedSchema').value = summary;
// Clear inputs after success
document.getElementById('generateSchemaId').value = '';
document.getElementById('generateJsonData').value = '';
})
.catch(error => {
log(`Error: ${error.detail || error.message}`, 'error');
showStatus('status5', `Error: ${error.detail || error.message}`, 'error');
});
}
function getValidationInfo() {
log('Getting validator information');
updateProgress('progress8', 20);
fetch(`${SERVER_URL}/validation/info`, {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
})
.then(response => {
updateProgress('progress8', 60);
if (!response.ok) {
return response.json().then(err => Promise.reject(err));
}
return response.json();
})
.then(result => {
updateProgress('progress8', 100);
log(`Validator information obtained: ${JSON.stringify(result, null, 2)}`);
showStatus('status8', '✅ Validator information retrieved successfully', 'success');
// Format and display the validation info
const info = result.validation_info;
const formattedInfo = `🔍 ${info.validator_name} v${info.version}
📋 JSON Schema Draft: ${info.draft_version}
✨ Features:
${info.features.map((feature, index) => `${index + 1}. ${feature}`).join('\n')}
📝 Supported formats:
${info.supported_formats.map((format, index) => `${index + 1}. ${format}`).join('\n')}
🗂️ Collections support:
- Schema storage: ${info.collections_support.schema_storage ? '✅' : '❌'}
- CRUD operations: ${info.collections_support.schema_crud ? '✅' : '❌'}
- Schema listing: ${info.collections_support.schema_listing ? '✅' : '❌'}
- Schema generation: ${info.collections_support.schema_generation ? '✅' : '❌'}
🔗 Available endpoints:
📍 Validation:
${info.endpoints.validation.map((endpoint, index) => `${index + 1}. ${endpoint}`).join('\n')}
📍 Schema management:
${info.endpoints.schema_management.map((endpoint, index) => `${index + 1}. ${endpoint}`).join('\n')}
📍 Information:
${info.endpoints.info.map((endpoint, index) => `${index + 1}. ${endpoint}`).join('\n')}
🕒 Timestamp: ${new Date(info.timestamp * 1000).toLocaleString()}`;
document.getElementById('validatorInfo').value = formattedInfo;
})
.catch(error => {
updateProgress('progress8', 0);
log(`Error: ${error.detail || error.message}`, 'error');
showStatus('status8', `Error: ${error.detail || error.message}`, 'error');
document.getElementById('validatorInfo').value = '';
});
}
// Initialization
log('SSE Client started. Server at: ' + SERVER_URL);
// Check server status
fetch(`${SERVER_URL}/health`)
.then(response => response.json())
.then(data => {
log(`Server connected: ${data.status}`);
})
.catch(error => {
log(`Error connecting to server: ${error.message}`, 'error');
});
</script>
</body>
</html>