new wco wwws compatible with new backeend

This commit is contained in:
2025-07-23 12:36:48 +02:00
parent bc76840707
commit b6ae865332
23 changed files with 1702 additions and 94 deletions

View File

@@ -0,0 +1,8 @@
<div id="privatri-container">
<!-- Le contenu du composant privatri sera rendu ici -->
<h2>Messages Privés (privatri)</h2>
<p>Ce composant gère le stockage sécurisé des messages dans le navigateur.</p>
<div id="privatri-threads">
<!-- La liste des fils de discussion pourrait être affichée ici -->
</div>
</div>

194
wco/privatri/privatri.js Normal file
View File

@@ -0,0 +1,194 @@
/**
* @file privatri.js
* @description WCO component for managing private, thread-based messages in IndexedDB.
* @version 1.0
*/
((window) => {
'use strict';
// --- Component Definition ---
const privatri = {};
// --- Private State ---
let _db = null; // Holds the single, persistent IndexedDB connection
const DB_NAME = 'privatriDB';
const DB_VERSION = 1;
/**
* Logs messages to the console with a consistent prefix.
* @param {string} level - The log level (e.g., 'log', 'error', 'warn').
* @param {...any} args - The messages to log.
*/
const _log = (level, ...args) => {
console[level]('[privatri]', ...args);
};
/**
* Opens and initializes the IndexedDB database.
* This function is called by init() and handles the connection and schema upgrades.
* @param {string[]} initialStoreNames - An array of store names (thread IDs) to ensure exist.
* @returns {Promise<IDBDatabase>} A promise that resolves with the database connection.
*/
const _openDatabase = (initialStoreNames = []) => {
return new Promise((resolve, reject) => {
_log('log', `Opening database "${DB_NAME}" with version ${DB_VERSION}.`);
const request = indexedDB.open(DB_NAME, DB_VERSION);
// This event is only triggered for new databases or version changes.
request.onupgradeneeded = (event) => {
const db = event.target.result;
_log('log', 'Database upgrade needed. Current stores:', [...db.objectStoreNames]);
initialStoreNames.forEach(storeName => {
if (!db.objectStoreNames.contains(storeName)) {
_log('log', `Creating new object store: "${storeName}"`);
db.createObjectStore(storeName, { keyPath: 'key' });
}
});
};
request.onsuccess = (event) => {
_log('log', 'Database opened successfully.');
_db = event.target.result;
// Generic error handler for the connection
_db.onerror = (event) => {
_log('error', 'Database error:', event.target.error);
};
resolve(_db);
};
request.onerror = (event) => {
_log('error', 'Failed to open database:', event.target.error);
reject(event.target.error);
};
});
};
// --- Public API ---
/**
* Initializes the privatri component.
* Opens the database connection and ensures initial object stores are created.
* @param {object} config - Configuration object.
* @param {string[]} [config.threads=[]] - An array of initial thread IDs (store names) to create.
* @returns {Promise<void>}
*/
privatri.init = async (config = {}) => {
if (_db) {
_log('warn', 'privatri component already initialized.');
return;
}
const threads = config.threads || [];
await _openDatabase(threads);
};
/**
* Retrieves a value from a specific store (thread).
* @param {string} storeName - The name of the store (thread ID).
* @param {string} key - The key of the item to retrieve.
* @returns {Promise<any|null>} A promise that resolves with the value or null if not found.
*/
privatri.getValue = (storeName, key) => {
return new Promise((resolve, reject) => {
if (!_db || !_db.objectStoreNames.contains(storeName)) {
_log('warn', `Store "${storeName}" does not exist.`);
return resolve(null);
}
const transaction = _db.transaction(storeName, 'readonly');
const store = transaction.objectStore(storeName);
const request = store.get(key);
request.onsuccess = () => resolve(request.result ? request.result.value : null);
request.onerror = (e) => {
_log('error', `Error getting value for key "${key}" from store "${storeName}":`, e.target.error);
reject(e.target.error);
};
});
};
/**
* Adds or updates a key-value pair in a specific store (thread).
* @param {string} storeName - The name of the store (thread ID).
* @param {string} key - The key of the item to set.
* @param {any} value - The value to store.
* @returns {Promise<void>}
*/
privatri.setValue = (storeName, key, value) => {
return new Promise((resolve, reject) => {
if (!_db || !_db.objectStoreNames.contains(storeName)) {
_log('error', `Cannot set value. Store "${storeName}" does not exist.`);
return reject(new Error(`Store "${storeName}" not found.`));
}
const transaction = _db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
const request = store.put({ key: key, value: value });
request.onsuccess = () => resolve();
request.onerror = (e) => {
_log('error', `Error setting value for key "${key}" in store "${storeName}":`, e.target.error);
reject(e.target.error);
};
});
};
/**
* Removes a key-value pair from a specific store (thread).
* @param {string} storeName - The name of the store (thread ID).
* @param {string} key - The key of the item to remove.
* @returns {Promise<void>}
*/
privatri.removeKey = (storeName, key) => {
return new Promise((resolve, reject) => {
if (!_db || !_db.objectStoreNames.contains(storeName)) {
_log('warn', `Cannot remove key. Store "${storeName}" does not exist.`);
return resolve(); // Resolve peacefully if store doesn't exist
}
const transaction = _db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
const request = store.delete(key);
request.onsuccess = () => resolve();
request.onerror = (e) => {
_log('error', `Error removing key "${key}" from store "${storeName}":`, e.target.error);
reject(e.target.error);
};
});
};
/**
* A utility function to save a batch of messages, demonstrating how to use the component.
* @param {object} threadsObj - An object where keys are thread IDs and values are message objects.
* @example
* const messages = {
* "thread-123": { "1678886400": { text: "Hello" } },
* "thread-456": { "1678886401": { text: "Hi there" } }
* };
* await privatri.storeMessages(messages);
*/
privatri.storeMessages = async (threadsObj = {}) => {
if (!_db) {
_log('error', 'Database not initialized. Please call privatri.init() first.');
return;
}
_log('log', 'Storing messages in IndexedDB...');
for (const [uuid, threadObj] of Object.entries(threadsObj)) {
// Ensure the object store exists before trying to write to it.
if (!_db.objectStoreNames.contains(uuid)) {
_log('warn', `Store "${uuid}" not found during message storage. You may need to re-init with this thread.`);
continue;
}
for (const [timestamp, messageObj] of Object.entries(threadObj)) {
await privatri.setValue(uuid, timestamp, messageObj);
}
}
_log('log', 'Finished storing messages.');
};
// Expose the component to the global window object
window.privatri = privatri;
})(window);