311 lines
12 KiB
HTML
311 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>IndexedDB Inspector</title>
|
|
<style>
|
|
body {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
line-height: 1.6;
|
|
margin: 0;
|
|
padding: 20px;
|
|
background-color: #f5f5f5;
|
|
color: #333;
|
|
}
|
|
h1, h2, h3 {
|
|
color: #2c3e50;
|
|
}
|
|
.container {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
background-color: #fff;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
pre {
|
|
background-color: #f8f8f8;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
padding: 15px;
|
|
overflow: auto;
|
|
max-height: 400px;
|
|
}
|
|
button {
|
|
background-color: #4CAF50;
|
|
border: none;
|
|
color: white;
|
|
padding: 10px 15px;
|
|
text-align: center;
|
|
text-decoration: none;
|
|
display: inline-block;
|
|
font-size: 14px;
|
|
margin: 4px 2px;
|
|
cursor: pointer;
|
|
border-radius: 4px;
|
|
}
|
|
button:hover {
|
|
background-color: #45a049;
|
|
}
|
|
.error {
|
|
color: #e74c3c;
|
|
background-color: #fceaea;
|
|
padding: 10px;
|
|
border-radius: 4px;
|
|
margin: 10px 0;
|
|
}
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin: 20px 0;
|
|
}
|
|
th, td {
|
|
padding: 12px 15px;
|
|
border-bottom: 1px solid #ddd;
|
|
text-align: left;
|
|
}
|
|
th {
|
|
background-color: #f2f2f2;
|
|
}
|
|
tr:hover {
|
|
background-color: #f5f5f5;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>IndexedDB Inspector</h1>
|
|
|
|
<h2>Database Information</h2>
|
|
<div>
|
|
<p>Database Name: <strong>CryptoSpaceDB</strong></p>
|
|
<p>Store Name: <strong>keySpaces</strong></p>
|
|
</div>
|
|
|
|
<h2>Actions</h2>
|
|
<div>
|
|
<button id="list-dbs">List All Databases</button>
|
|
<button id="open-db">Open CryptoSpaceDB</button>
|
|
<button id="list-stores">List Object Stores</button>
|
|
<button id="list-keys">List All Keys</button>
|
|
</div>
|
|
|
|
<h2>Result</h2>
|
|
<div id="result-area">
|
|
<pre id="result">Results will appear here...</pre>
|
|
</div>
|
|
|
|
<h2>Key-Value Viewer</h2>
|
|
<div id="kv-viewer">
|
|
<table id="kv-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Key</th>
|
|
<th>Value</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="kv-body">
|
|
<!-- Data will be populated here -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// Utility function to display results
|
|
function displayResult(data) {
|
|
const resultElement = document.getElementById('result');
|
|
if (typeof data === 'object') {
|
|
resultElement.textContent = JSON.stringify(data, null, 2);
|
|
} else {
|
|
resultElement.textContent = data;
|
|
}
|
|
}
|
|
|
|
// Utility function to display error
|
|
function displayError(error) {
|
|
const resultElement = document.getElementById('result');
|
|
resultElement.textContent = `ERROR: ${error.message || error}`;
|
|
resultElement.classList.add('error');
|
|
}
|
|
|
|
// List all available databases
|
|
document.getElementById('list-dbs').addEventListener('click', async () => {
|
|
try {
|
|
if (!window.indexedDB) {
|
|
throw new Error("Your browser doesn't support IndexedDB");
|
|
}
|
|
|
|
if (!indexedDB.databases) {
|
|
displayResult("Your browser doesn't support indexedDB.databases() method. Try opening the database directly.");
|
|
return;
|
|
}
|
|
|
|
const databases = await indexedDB.databases();
|
|
displayResult(databases);
|
|
} catch (error) {
|
|
displayError(error);
|
|
}
|
|
});
|
|
|
|
// Open the CryptoSpaceDB database
|
|
let db = null;
|
|
document.getElementById('open-db').addEventListener('click', () => {
|
|
try {
|
|
if (!window.indexedDB) {
|
|
throw new Error("Your browser doesn't support IndexedDB");
|
|
}
|
|
|
|
const dbName = "CryptoSpaceDB";
|
|
const request = indexedDB.open(dbName);
|
|
|
|
request.onerror = (event) => {
|
|
displayError(`Failed to open database: ${event.target.error}`);
|
|
};
|
|
|
|
request.onsuccess = (event) => {
|
|
db = event.target.result;
|
|
displayResult(`Successfully opened database: ${db.name}, version ${db.version}`);
|
|
};
|
|
|
|
request.onupgradeneeded = (event) => {
|
|
db = event.target.result;
|
|
displayResult(`Database ${db.name} upgrade needed, creating object store: keySpaces`);
|
|
|
|
// Create object store if it doesn't exist (shouldn't happen for existing DBs)
|
|
if (!db.objectStoreNames.contains("keySpaces")) {
|
|
db.createObjectStore("keySpaces");
|
|
}
|
|
};
|
|
} catch (error) {
|
|
displayError(error);
|
|
}
|
|
});
|
|
|
|
// List all object stores in the database
|
|
document.getElementById('list-stores').addEventListener('click', () => {
|
|
try {
|
|
if (!db) {
|
|
throw new Error("Database not opened. Click 'Open CryptoSpaceDB' first.");
|
|
}
|
|
|
|
const storeNames = Array.from(db.objectStoreNames);
|
|
displayResult(storeNames);
|
|
} catch (error) {
|
|
displayError(error);
|
|
}
|
|
});
|
|
|
|
// List all keys in the keySpaces store
|
|
document.getElementById('list-keys').addEventListener('click', () => {
|
|
try {
|
|
if (!db) {
|
|
throw new Error("Database not opened. Click 'Open CryptoSpaceDB' first.");
|
|
}
|
|
|
|
if (!db.objectStoreNames.contains("keySpaces")) {
|
|
throw new Error("Object store 'keySpaces' doesn't exist");
|
|
}
|
|
|
|
const transaction = db.transaction(["keySpaces"], "readonly");
|
|
const store = transaction.objectStore("keySpaces");
|
|
const request = store.getAllKeys();
|
|
|
|
request.onerror = (event) => {
|
|
displayError(`Failed to get keys: ${event.target.error}`);
|
|
};
|
|
|
|
request.onsuccess = (event) => {
|
|
const keys = event.target.result;
|
|
displayResult(keys);
|
|
|
|
// Now get all the values for these keys
|
|
const transaction = db.transaction(["keySpaces"], "readonly");
|
|
const store = transaction.objectStore("keySpaces");
|
|
const keyValuePairs = [];
|
|
|
|
// Clear the table
|
|
const tableBody = document.getElementById('kv-body');
|
|
tableBody.innerHTML = '';
|
|
|
|
// For each key, get its value
|
|
let pendingRequests = keys.length;
|
|
|
|
if (keys.length === 0) {
|
|
const row = tableBody.insertRow();
|
|
const cell = row.insertCell(0);
|
|
cell.colSpan = 3;
|
|
cell.textContent = "No data found in the database";
|
|
}
|
|
|
|
keys.forEach(key => {
|
|
const request = store.get(key);
|
|
|
|
request.onerror = (event) => {
|
|
displayError(`Failed to get value for key ${key}: ${event.target.error}`);
|
|
pendingRequests--;
|
|
};
|
|
|
|
request.onsuccess = (event) => {
|
|
const value = event.target.result;
|
|
keyValuePairs.push({ key, value });
|
|
|
|
// Add a row to the table
|
|
const row = tableBody.insertRow();
|
|
|
|
// Key cell
|
|
const keyCell = row.insertCell(0);
|
|
keyCell.textContent = key;
|
|
|
|
// Value cell (truncated for display)
|
|
const valueCell = row.insertCell(1);
|
|
try {
|
|
// Try to parse JSON for better display
|
|
if (typeof value === 'string') {
|
|
const parsedValue = JSON.parse(value);
|
|
valueCell.innerHTML = `<pre>${JSON.stringify(parsedValue, null, 2).substring(0, 100)}${parsedValue.length > 100 ? '...' : ''}</pre>`;
|
|
} else {
|
|
valueCell.innerHTML = `<pre>${JSON.stringify(value, null, 2).substring(0, 100)}${value.length > 100 ? '...' : ''}</pre>`;
|
|
}
|
|
} catch (e) {
|
|
// If not JSON, display as string with truncation
|
|
valueCell.textContent = typeof value === 'string' ?
|
|
`${value.substring(0, 100)}${value.length > 100 ? '...' : ''}` :
|
|
String(value);
|
|
}
|
|
|
|
// Actions cell
|
|
const actionsCell = row.insertCell(2);
|
|
const viewButton = document.createElement('button');
|
|
viewButton.textContent = 'View Full';
|
|
viewButton.addEventListener('click', () => {
|
|
const valueStr = typeof value === 'object' ?
|
|
JSON.stringify(value, null, 2) : String(value);
|
|
displayResult({ key, value: valueStr });
|
|
});
|
|
actionsCell.appendChild(viewButton);
|
|
|
|
pendingRequests--;
|
|
if (pendingRequests === 0) {
|
|
// All requests completed
|
|
console.log("All key-value pairs retrieved:", keyValuePairs);
|
|
}
|
|
};
|
|
});
|
|
};
|
|
} catch (error) {
|
|
displayError(error);
|
|
}
|
|
});
|
|
|
|
// Initialize by checking if IndexedDB is available
|
|
window.addEventListener('DOMContentLoaded', () => {
|
|
if (!window.indexedDB) {
|
|
displayError("Your browser doesn't support IndexedDB");
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |