diff --git a/smart-collections/ObsAJSON.js b/smart-collections/ObsAJSON.js deleted file mode 100644 index 73a50285..00000000 --- a/smart-collections/ObsAJSON.js +++ /dev/null @@ -1,7 +0,0 @@ -// DEPRECATED: file for backward compatibility with Smart Collections v2.1 -class ObsAJSON { - constructor(env) { - this.env = env; - } -} -exports.ObsAJSON = ObsAJSON; \ No newline at end of file diff --git a/smart-collections/ObsMultiAJSON.js b/smart-collections/ObsMultiAJSON.js deleted file mode 100644 index b8713a3e..00000000 --- a/smart-collections/ObsMultiAJSON.js +++ /dev/null @@ -1,9 +0,0 @@ -// DEPRECATED: file for backward compatibility with Smart Collections v2.1 - -class ObsMultiAJSON { - constructor(env) { - this.env = env; - } -} - -exports.ObsMultiAJSON = ObsMultiAJSON; \ No newline at end of file diff --git "a/smart-collections/\342\231\273\357\270\217/AJSON.js" "b/smart-collections/\342\231\273\357\270\217/AJSON.js" deleted file mode 100644 index 5c903185..00000000 --- "a/smart-collections/\342\231\273\357\270\217/AJSON.js" +++ /dev/null @@ -1,57 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const { LongTermMemory } = require('./long_term_memory'); - -class AJSON extends LongTermMemory { - load() { - console.log("Loading: " + this.file_path); - // const timestamp = Date.now(); - try { - const file_content = fs.readFileSync(this.file_path, 'utf8'); - this.items = JSON.parse(`{${file_content.slice(0, -2)}}`, this.reviver.bind(this)); - // this.keys = Object.keys(this.items); // replaced by getter - // console.log("Loaded " + this.file_path + " in " + (Date.now() - timestamp) + "ms"); - } catch (err) { - console.log("Error loading: " + this.file_path); - console.log(err.stack); // stack trace - - // Create folder and file if they don't exist - try { - fs.mkdirSync(this.data_path, { recursive: true }); - fs.writeFileSync(this.file_path, ""); - this.items = {}; - // this.keys = []; // replaced by getter - } catch (creationErr) { - console.log("Failed to create folder or file: ", creationErr); - } - } - } - // wraps _save in timeout to prevent multiple saves at once - save() { - // console.log("Saving: " + this.file_name); - if (this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = setTimeout(this._save.bind(this), 1000); - } - // saves collection to file - _save() { - this.save_timeout = null; - const start = Date.now(); - console.log("Saving: " + this.file_name); - try { - fs.writeFileSync( - this.file_path, - JSON.stringify(this.items, this.replacer.bind(this), 2).slice(0, -1).slice(1) + ",\n" - ); - } catch (err) { - console.error("Error saving: " + this.file_name); - console.error(err.stack); - return; - } - const end = Date.now(); // log time - const time = end - start; - console.log("Saved " + this.file_name + " in " + time + "ms"); - } - get file_name() { return super.file_name + '.ajson'; } -} - -exports.AJSON = AJSON; \ No newline at end of file diff --git "a/smart-collections/\342\231\273\357\270\217/Brain.js" "b/smart-collections/\342\231\273\357\270\217/Brain.js" deleted file mode 100644 index 7e77bafe..00000000 --- "a/smart-collections/\342\231\273\357\270\217/Brain.js" +++ /dev/null @@ -1,20 +0,0 @@ -const { SmartEnv } = require('./env.js'); -// const { LongTermMemory: LTM } = require('./long_term_memory.js'); -// ORCHESTRATOR CLASS -// class Brain { -// constructor(ltm_adapter = LTM) { -// this.config = {}; -// this.item_types = {}; -// this.collections = {}; -// this.ltm_adapter = ltm_adapter; -// this.data_path = './test/data'; -// } -// init() { -// this.load_collections(); -// } -// load_collections() { -// Object.entries(this.collections).map(([collection_name, collection]) => this[collection_name] = collection.load(this)); -// } -// get_ref(ref) { return this[ref.collection_name].get(ref.key); } -// } -exports.Brain = SmartEnv; \ No newline at end of file diff --git "a/smart-collections/\342\231\273\357\270\217/ObsAJSON.js" "b/smart-collections/\342\231\273\357\270\217/ObsAJSON.js" deleted file mode 100644 index 5969be82..00000000 --- "a/smart-collections/\342\231\273\357\270\217/ObsAJSON.js" +++ /dev/null @@ -1,128 +0,0 @@ -const { LongTermMemory } = require('./long_term_memory'); -/** - * Class ObsAJSON extends LongTermMemory to handle JSON-based storage of collections. - * This class provides methods to load and save collections to a JSON file with asynchronous operations, - * ensuring data integrity and error handling. It uses an adapter to interact with the file system. - */ -class ObsAJSON extends LongTermMemory { - /** - * Constructs an instance of ObsAJSON. - * @param {Object} collection - The collection to be managed. - */ - constructor(collection) { - super(collection); - this.adapter = this.env.main.app.vault.adapter; - } - - /** - * Asynchronously loads the collection from a JSON file. - * Parses the file content and initializes collection items based on the stored data. - * Handles file not found errors by creating necessary directories and files. - */ - async load() { - console.log("Loading: " + this.file_path); - try { - (await this.adapter.read(this.file_path)) - .split(",\n") - .filter(batch => batch) // remove empty strings - .forEach((batch, i) => { - const items = JSON.parse(`{${batch}}`); - Object.entries(items).forEach(([key, value]) => { - this.collection.items[key] = new (this.env.item_types[value.class_name])(this.env, value); - }); - }) - ; - console.log("Loaded: " + this.file_name); - } catch (err) { - console.log("Error loading: " + this.file_path); - console.log(err.stack); // stack trace - // Create folder and file if they don't exist - if (err.code === 'ENOENT') { - this.items = {}; - // this.keys = []; // replaced by getter - try { - await this.adapter.mkdir(this.data_path); - await this.adapter.write(this.file_path, ""); - } catch (creationErr) { - console.log("Failed to create folder or file: ", creationErr); - } - } - } - } - - // wraps _save in timeout to prevent multiple saves at once - save() { - if(this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = setTimeout(() => { this._save(); }, 10000); - } - - /** - * Saves the collection to a JSON file. This method is throttled to prevent multiple saves at once. - * @param {boolean} [force=false] - Forces the save operation even if currently saving. - */ - async _save(force=false) { - if(this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = null; - if(this._saving) return console.log("Already saving: " + this.file_name); - this._saving = true; // prevent multiple saves at once - setTimeout(() => { this._saving = false; }, 10000); // set _saving to false after 10 seconds - const start = Date.now(); - console.log("Saving: " + this.file_name); - // rename temp file - const temp_file_path = this.file_path.replace('.ajson', '.temp.ajson'); - if(await this.adapter.exists(temp_file_path)) await this.adapter.remove(temp_file_path); - try { - // init temp file - await this.adapter.write(temp_file_path, ""); - let file_content = []; - const items = Object.values(this.items).filter(i => i.vec); - const batches = Math.ceil(items.length / 1000); - for(let i = 0; i < batches; i++) { - file_content = items.slice(i * 1000, (i + 1) * 1000).map(i => i.ajson); - const batch_content = file_content.join(","); - await this.adapter.append(temp_file_path, batch_content + ",\n"); - } - // append last batch - if(items.length > batches * 1000) { - await this.adapter.append(temp_file_path, items.slice(batches * 1000).map(i => i.ajson).join(",") + ",\n"); - } - const end = Date.now(); // log time - const time = end - start; - if(force || await this.validate_save(temp_file_path, this.file_path)) { - if(await this.adapter.exists(this.file_path)) await this.adapter.remove(this.file_path); - await this.adapter.rename(temp_file_path, this.file_path); - console.log("Saved " + this.file_name + " in " + time + "ms"); - }else{ - console.log("Not saving " + this.file_name + " because new file is less than 50% of old file"); - } - } catch (err) { - console.error("Error saving: " + this.file_name); - console.error(err.stack); - // set new file to "failed" and rename to inlclude datetime - const failed_file_path = temp_file_path.replace('.temp.', '.failed-' + Date.now() + '.'); - await this.adapter.rename(temp_file_path, failed_file_path); - } - this._saving = false; - // remove temp file after new file is saved - if(await this.adapter.exists(temp_file_path) && await this.adapter.exists(this.file_path)) await this.adapter.remove(temp_file_path); - } - - /** - * Validates the new file size against the old file size to ensure data integrity. - * @param {string} new_file_path - Path to the new file. - * @param {string} old_file_path - Path to the old file. - * @returns {Promise} True if the new file size is more than 50% of the old file size, otherwise false. - */ - async validate_save(new_file_path, old_file_path) { - const new_file_size = (await this.adapter.stat(new_file_path))?.size; - const old_file_size = (await this.adapter.stat(old_file_path))?.size; - if(!old_file_size) return true; - console.log("New file size: " + new_file_size + " bytes"); - console.log("Old file size: " + old_file_size + " bytes"); - return new_file_size > (old_file_size * 0.5); - } - - get file_name() { return super.file_name + '.ajson'; } -} - -exports.ObsAJSON = ObsAJSON; \ No newline at end of file diff --git "a/smart-collections/\342\231\273\357\270\217/ObsMultiAJSON.js" "b/smart-collections/\342\231\273\357\270\217/ObsMultiAJSON.js" deleted file mode 100644 index 4ce6bf96..00000000 --- "a/smart-collections/\342\231\273\357\270\217/ObsMultiAJSON.js" +++ /dev/null @@ -1,113 +0,0 @@ -const { LongTermMemory } = require('./long_term_memory'); - -/** - * Class representing a specialized form of LongTermMemory that handles multiple .ajson files. - * It extends the LongTermMemory class to manage collections of items stored in .ajson format. - */ -class ObsMultiAJSON extends LongTermMemory { - /** - * Creates an instance of ObsMultiAJSON. - * @param {Object} collection - The collection of items to be managed. - */ - constructor(collection) { - super(collection); - this.adapter = this.env.main.app.vault.adapter; - } - - /** - * Asynchronously loads collection items from .ajson files within the specified data path. - * It ensures that only .ajson files are processed and handles JSON parsing and item instantiation. - */ - async load() { - console.log("Loading collection items"); - if(!(await this.adapter.exists(this.data_path))) await this.adapter.mkdir(this.data_path); - const files = (await this.adapter.list(this.data_path)).files; // List all files in the directory - for (const file_path of files) { - try { - if (file_path.endsWith('.ajson')) { // Ensure it's an .ajson file - const content = await this.adapter.read(file_path); - // if last char is , remove it before wrapping in {} and parse - const data = JSON.parse(`{${content.endsWith(',') ? content.slice(0, -1) : content}}`); - let pruned = ''; - Object.entries(data).forEach(([key, value]) => { - const entity = new (this.env.item_types[value.class_name])(this.env, value); - this.env[entity.collection_name].items[key] = entity; - pruned += entity.ajson + ',\n'; - }); - // parsed data removes any duplicate keys (pruned) - await this.adapter.write(file_path, pruned.trim()); - } - } catch (err) { - console.log("Error loading file: " + file_path); - console.log(err.stack); // stack trace - } - } - console.log("Loaded collection items"); - } - - /** - * Schedules a save operation to prevent multiple saves happening at the same time. - */ - save() { - if(this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = setTimeout(() => { this._save(); }, 10000); - } - - /** - * Asynchronously saves modified collection items to their respective .ajson files. - * @param {boolean} [force=false] - Forces the save operation even if it's currently flagged as saving. - */ - async _save(force = false) { - let saved_ct = 0; - if(this._saving) return console.log("Already saving"); - this._saving = true; // prevent multiple saves at once - setTimeout(() => { this._saving = false; }, 10000); // set _saving to false after 10 seconds - const start = Date.now(); - console.log("Saving collection items"); - // ensure data_path exists - if(!(await this.adapter.exists(this.data_path))) await this.adapter.mkdir(this.data_path); - const items = Object.values(this.items).filter(i => i.vec && i.changed); - if(items.length === 0) { - this._saving = false; - console.log("Nothing to save"); - return; - } - try { - for (const item of items) { - const item_file_path = `${this.data_path}/${item.multi_ajson_file_name}.ajson`; // Use item.file_name for file naming - await this.adapter.append(item_file_path, '\n' + item.ajson + ','); - saved_ct++; - } - const end = Date.now(); // log time - const time = end - start; - console.log(`Saved ${saved_ct} collection items in ${time}ms`); - } catch (err) { - console.error("Error saving collection items"); - console.error(err.stack); - } - this._saving = false; - } - - /** - * Validates the save operation by comparing the file sizes of the new and old files. - * @param {string} new_file_path - Path to the new file. - * @param {string} old_file_path - Path to the old file. - * @returns {Promise} - True if the new file size is at least 50% of the old file size, otherwise false. - */ - async validate_save(new_file_path, old_file_path) { - const new_file_size = (await this.adapter.stat(new_file_path))?.size; - const old_file_size = (await this.adapter.stat(old_file_path))?.size; - if(!old_file_size) return true; - console.log("New file size: " + new_file_size + " bytes"); - console.log("Old file size: " + old_file_size + " bytes"); - return new_file_size > (old_file_size * 0.5); - } - - /** - * Gets the data path for storing .ajson files, appending '/multi' to the base path. - * @returns {string} The data path for .ajson files. - */ - get data_path() { return super.data_path + '/multi'; } -} - -exports.ObsMultiAJSON = ObsMultiAJSON; \ No newline at end of file diff --git "a/smart-collections/\342\231\273\357\270\217/ObsidianAJSON.js" "b/smart-collections/\342\231\273\357\270\217/ObsidianAJSON.js" deleted file mode 100644 index 0860b327..00000000 --- "a/smart-collections/\342\231\273\357\270\217/ObsidianAJSON.js" +++ /dev/null @@ -1,95 +0,0 @@ -const { LongTermMemory } = require('./long_term_memory'); -/** - * Class representing a specialized JSON storage system for Obsidian, extending the LongTermMemory class. - * This class handles the loading and saving of collections in a JSON format with specific handling - * for memory optimization and error management. - */ -class ObsidianAJSON extends LongTermMemory { - /** - * Creates an instance of ObsidianAJSON. - * @param {Object} collection - The collection of items to be managed. - */ - constructor(collection) { - super(collection); - this.adapter = this.brain.main.app.vault.adapter; - } - - /** - * Asynchronously loads the collection from a JSON file. - * Parses the JSON file, instantiates items based on their class names, and handles errors such as missing files. - */ - async load() { - console.log("Loading: " + this.file_path); - try { - // replaced reviver b/c it was using too much memory - Object.entries(JSON.parse(`{${await this.adapter.read(this.file_path)}}`)).forEach(([key, value]) => { - this.collection.items[key] = new (this.brain.item_types[value.class_name])(this.brain, value); - // this.collection.keys.push(key); // replaced by getter - }); - console.log("Loaded: " + this.file_name); - } catch (err) { - console.log("Error loading: " + this.file_path); - console.log(err.stack); // stack trace - // Create folder and file if they don't exist - if (err.code === 'ENOENT') { - this.items = {}; - // this.keys = []; // replaced by getter - try { - await this.adapter.mkdir(this.data_path); - await this.adapter.write(this.file_path, ""); - } catch (creationErr) { - console.log("Failed to create folder or file: ", creationErr); - } - } - } - } - - /** - * Saves the collection to a file with a delay to prevent multiple saves at once. - * This method sets up a timeout to delay the actual save operation. - */ - save() { - if(this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = setTimeout(() => { this._save(); }, 10000); - } - - /** - * Internal method to save the collection to a file. - * It checks for conditions to avoid unnecessary saves and handles errors. - * @param {boolean} [force=false] - Forces the save operation regardless of the usual checks. - */ - async _save(force=false) { - if(this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = null; - if(this._saving) return console.log("Already saving: " + this.file_name); - this._saving = true; // prevent multiple saves at once - setTimeout(() => { this._saving = false; }, 10000); // set _saving to false after 10 seconds - const start = Date.now(); - console.log("Saving: " + this.file_name); - try { - // const file_content = JSON.stringify(this.items, this.replacer.bind(this), 2); // pretty print - const file_content = JSON.stringify(this.items, this.replacer.bind(this)); // minified - const new_size = file_content.length; - if(!force && (new_size < 100)) return console.log("File content empty, not saving"); // if file content empty, do not save - const old_size = (await this.adapter.stat(this.file_path))?.size || 0; - if(!force && (new_size < (0.8 * old_size))) return console.log("File content smaller than 80% of original, not saving " + this.file_name ); // if file content smaller than 80% of original, do not save - // replaced slice with substring and removed comma (prefix appends with comma instead of suffix to prevent removal at load) - await this.adapter.write( this.file_path, file_content.substring(1, file_content.length - 1)); - const end = Date.now(); // log time - const time = end - start; - console.log("Saved " + this.file_name + " in " + time + "ms"); - } catch (err) { - console.error("Error saving: " + this.file_name); - console.error(err.stack); - } - this._saving = false; - } - - /** - * Getter for the file name with a custom extension. - * @returns {string} The file name appended with '.ajson'. - */ - get file_name() { return super.file_name + '.ajson'; } -} - -exports.ObsidianAJSON = ObsidianAJSON; \ No newline at end of file diff --git "a/smart-collections/\342\231\273\357\270\217/ScJSON.js" "b/smart-collections/\342\231\273\357\270\217/ScJSON.js" deleted file mode 100644 index e19f2e90..00000000 --- "a/smart-collections/\342\231\273\357\270\217/ScJSON.js" +++ /dev/null @@ -1,66 +0,0 @@ -const fs = require('fs').promises; -const path = require('path'); -const { LongTermMemory } = require('./long_term_memory'); - -class ScJSON extends LongTermMemory { - async load() { - console.log("Loading: " + this.file_path); - try { - // const file_content = await fs.readFile(this.file_path, 'utf8'); - // this.items = JSON.parse(`{${file_content}}`, this.reviver.bind(this)); - (await fs.readFile(this.file_path, 'utf8')).split(",\n").forEach((batch, i) => { - const items = JSON.parse(`{${batch}}`); - Object.entries(items).forEach(([key, value]) => { - this.collection.items[key] = new (this.brain.item_types[value.class_name])(this.brain, value); - // this.collection.keys.push(key); - }); - }); - // this.keys = Object.keys(this.items); // replaced by getter - } catch (err) { - console.log("Error loading: " + this.file_path); - console.log(err.stack); // stack trace - - // Create folder and file if they don't exist - if(err.code === 'ENOENT') { - try { - await fs.mkdir(this.data_path, { recursive: true }); - await fs.writeFile(this.file_path, ""); - this.items = {}; - // this.keys = []; // replaced by getter - } catch (creationErr) { - console.log("Failed to create folder or file: ", creationErr); - } - } - } - } - // wraps _save in timeout to prevent multiple saves at once - save() { - if (this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = setTimeout(() => this._save(), 1000); - } - // saves collection to file - async _save() { - this.save_timeout = null; - // const start = Date.now(); - // console.log("Saving: " + this.file_name); - // try { - // const file_content = JSON.stringify(this.items, this.replacer.bind(this)); - // await fs.writeFile( - // this.file_path, - // file_content.substring(1, file_content.length - 1) - // ); - // } catch (err) { - // console.error("Error saving: " + this.file_name); - // console.error(err.stack); - // return; - // } - // const end = Date.now(); // log time - // const time = end - start; - // console.log("Saved " + this.file_name + " in " + time + "ms"); - // TODO: NOT SAVING IN SMART CONNECT CURRENTLY - console.log("Not saving: " + this.file_name + " in Smart Connect currently"); - } - get file_name() { return super.file_name + '.ajson'; } -} - -exports.ScJSON = ScJSON; diff --git "a/smart-collections/\342\231\273\357\270\217/ScMultiAJSON.js" "b/smart-collections/\342\231\273\357\270\217/ScMultiAJSON.js" deleted file mode 100644 index fa8bd949..00000000 --- "a/smart-collections/\342\231\273\357\270\217/ScMultiAJSON.js" +++ /dev/null @@ -1,115 +0,0 @@ -const { LongTermMemory } = require('./long_term_memory'); -const fs = require('fs').promises; -const path = require('path'); - -/** - * Class representing a specialized form of LongTermMemory that handles multiple .ajson files. - * It extends the LongTermMemory class to manage collections of items stored in .ajson format. - */ -class ScMultiAJSON extends LongTermMemory { - - /** - * Asynchronously loads collection items from .ajson files within the specified data path. - * It ensures that only .ajson files are processed and handles JSON parsing and item instantiation. - */ - async load() { - console.log("Loading collection items"); - const dataPath = this.data_path; - try { - await fs.access(dataPath); - } catch (err) { - await fs.mkdir(dataPath, { recursive: true }); - } - const files = await fs.readdir(dataPath); - for (const fileName of files) { - const filePath = path.join(dataPath, fileName); - if (filePath.endsWith('.ajson')) { - try { - const content = await fs.readFile(filePath, 'utf8'); - const data = JSON.parse(`{${content.endsWith(',') ? content.slice(0, -1) : content}}`); - let pruned = ''; - Object.entries(data).forEach(([key, value]) => { - const entity = new (this.env.item_types[value.class_name])(this.env, value); - this.env[entity.collection_name].items[key] = entity; - pruned += entity.ajson + ',\n'; - }); - await fs.writeFile(filePath, pruned.trim()); - } catch (err) { - console.log("Error loading file: " + filePath); - console.log(err.stack); - } - } - } - console.log("Loaded collection items"); - } - - /** - * Schedules a save operation to prevent multiple saves happening at the same time. - */ - save() { - if (this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = setTimeout(() => { this._save(); }, 10000); - } - - /** - * Asynchronously saves modified collection items to their respective .ajson files. - * @param {boolean} [force=false] - Forces the save operation even if it's currently flagged as saving. - */ - async _save(force = false) { - let saved_ct = 0; - if (this._saving) return console.log("Already saving"); - this._saving = true; - setTimeout(() => { this._saving = false; }, 10000); - const start = Date.now(); - console.log("Saving collection items"); - // ensure data_path exists - if(!(await fs.access(this.data_path))) await this.adapter.mkdir(this.data_path); - const items = Object.values(this.items).filter(i => i.vec && i.changed); - if (items.length === 0) { - this._saving = false; - console.log("Nothing to save"); - return; - } - try { - for (const item of items) { - const itemFilePath = path.join(this.data_path, `${item.multi_ajson_file_name}.ajson`); - await fs.appendFile(itemFilePath, '\n' + item.ajson + ','); - saved_ct++; - } - const end = Date.now(); - const time = end - start; - console.log(`Saved ${saved_ct} collection items in ${time}ms`); - } catch (err) { - console.error("Error saving collection items"); - console.error(err.stack); - } - this._saving = false; - } - - /** - * Validates the save operation by comparing the file sizes of the new and old files. - * @param {string} new_file_path - Path to the new file. - * @param {string} old_file_path - Path to the old file. - * @returns {Promise} - True if the new file size is at least 50% of the old file size, otherwise false. - */ - async validate_save(new_file_path, old_file_path) { - try { - const newStats = await fs.stat(new_file_path); - const oldStats = await fs.stat(old_file_path); - console.log("New file size: " + newStats.size + " bytes"); - console.log("Old file size: " + oldStats.size + " bytes"); - return newStats.size > (oldStats.size * 0.5); - } catch (err) { - console.log("Error validating file sizes:", err); - return false; - } - } - - /** - * Gets the data path for storing .ajson files, appending '/multi' to the base path. - * @returns {string} The data path for .ajson files. - */ - get data_path() { return path.join(super.data_path, 'multi'); } -} - -exports.ScMultiAJSON = ScMultiAJSON; diff --git "a/smart-collections/\342\231\273\357\270\217/idb.js" "b/smart-collections/\342\231\273\357\270\217/idb.js" deleted file mode 100644 index 607aa1a2..00000000 --- "a/smart-collections/\342\231\273\357\270\217/idb.js" +++ /dev/null @@ -1,61 +0,0 @@ -const { LongTermMemory } = require('./long_term_memory'); -const { openDB } = require('idb'); -class IDBLTM extends LongTermMemory { - constructor(collection) { - super(collection); - openDB(this.file_name, 1, { - upgrade: this.upgradeDB.bind(this) - }).then(db => this.db = db); - } - async upgradeDB(db, oldVersion, newVersion, transaction) { - console.log("Upgrading DB", this.file_name); - if (!db.objectStoreNames.contains(this.file_name)) { - db.createObjectStore(this.file_name); - } - } - // clear database - async clear() { - await this.db.clear(this.file_name); - } - async load() { - const time = Date.now(); - while(!this.db) await new Promise(r => setTimeout(r, 100)); - if(!this.db.objectStoreNames.contains(this.file_name)) { - console.log("Collection not found: " + this.file_name); - return; - } - console.log("Getting keys for: " + this.file_name); - const keys = await this.db.getAllKeys(this.file_name); - console.log(keys); - const items = await Promise.all(keys.map(key => this.db.get(this.file_name, key))); - for(let i = 0; i < keys.length; i++) { - this.collection.items[keys[i]] = JSON.parse(items[i], this.reviver.bind(this)); - // this.collection.keys.push(keys[i]); // replaced by getter - } - console.log("Loaded " + this.collection.keys.length + ' items from ' + this.file_name + " in " + (Date.now() - time) + "ms"); - } - // wraps _save in timeout to prevent multiple saves at once - save() { - if(this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = setTimeout(() => { this._save(); }, 10000); - } - async _save(force=false) { - if(this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = null; - if(this._saving) return console.log("Already saving: " + this.file_name); - this._saving = true; - setTimeout(() => { this._saving = false; }, 10000); - const start = Date.now(); - console.log("Saving: " + this.file_name); - const transaction = this.db.transaction(this.file_name, 'readwrite'); - const store = transaction.objectStore(this.file_name); - for(let key in this.items) { - if(!this.items[key]?.vec) continue; - const item = JSON.stringify(this.items[key], this.replacer.bind(this)); - store.put(item, key); - } - await transaction.done; - console.log("Saved " + this.file_name + " in " + (Date.now() - start) + "ms"); - } -} -exports.IDBLTM = IDBLTM; \ No newline at end of file diff --git "a/smart-collections/\342\231\273\357\270\217/long_term_memory.js" "b/smart-collections/\342\231\273\357\270\217/long_term_memory.js" deleted file mode 100644 index c27d3e10..00000000 --- "a/smart-collections/\342\231\273\357\270\217/long_term_memory.js" +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Class representing a long-term memory storage for collections. - */ -class LongTermMemory { - /** - * Creates an instance of LongTermMemory. - * @param {Object} collection - The collection object containing the environment and items. - */ - constructor(collection) { - this.env = collection.env; - this.brain = this.env; - this.collection = collection; - this.save_timeout = null; - } - - /** - * Static method to initialize a LongTermMemory instance using a specific adapter. - * @param {Object} collection - The collection object to be used. - * @param {Function} adapter - The adapter class to be instantiated. - * @returns {LongTermMemory} An instance of the adapter class. - */ - static wake_up(collection, adapter) { - const ltm = new adapter(collection); - return ltm; - } - - /** - * Gets the name of the collection. - * @returns {string} The name of the collection. - */ - get collection_name() { return this.collection.collection_name; } - - /** - * Gets the name of the item in the collection. - * @returns {string} The name of the item. - */ - get item_name() { return this.collection.item_name; } - - /** - * Gets the data path from the environment. - * @returns {string} The data path. - */ - get data_path() { return this.env.data_path; } - - /** - * Gets the file name, defaulting to the collection name if not explicitly set. - * @returns {string} The file name. - */ - get file_name() { return this.collection.file_name || this.collection.collection_name; } - - /** - * Constructs the full file path for the collection's data. - * @returns {string} The full file path. - */ - get file_path() { return this.data_path + '/' + this.file_name; } - - /** - * Gets the items of the collection. - * @returns {Array} The items of the collection. - */ - get items() { return this.collection.items; } - - /** - * Sets the items of the collection. - * @param {Array} items - The new items of the collection. - */ - set items(items) { this.collection.items = items; } - - /** - * Gets the keys of the collection. - * @returns {Array} The keys of the collection. - */ - get keys() { return this.collection.keys; } - - /** - * Placeholder for loading data, to be implemented by subclasses. - */ - async load() { } - - /** - * Default save method, logs a message if not overridden. - */ - save() { if (this.constructor.name !== 'LongTermMemory') console.log("called default, override me"); } - - /** - * Default asynchronous save method, logs a message if not overridden. - */ - async _save() { if (this.constructor.name !== 'LongTermMemory') console.log("called default, override me"); } - - /** - * Revives a value from a key-value pair. - * @param {string} key - The key in the key-value pair. - * @param {*} value - The value in the key-value pair. - * @returns {*} The possibly transformed value. - */ - reviver(key, value) { return this.collection.reviver(key, value); } - - /** - * Replaces a value before it is serialized. - * @param {string} key - The key in the key-value pair. - * @param {*} value - The value in the key-value pair. - * @returns {*} The possibly transformed value. - */ - replacer(key, value) { return this.collection.replacer(key, value); } -} - -// EXPORTS -exports.LongTermMemory = LongTermMemory; \ No newline at end of file diff --git "a/smart-collections/\342\231\273\357\270\217/sqlite_ltm.js" "b/smart-collections/\342\231\273\357\270\217/sqlite_ltm.js" deleted file mode 100644 index 004fc6ca..00000000 --- "a/smart-collections/\342\231\273\357\270\217/sqlite_ltm.js" +++ /dev/null @@ -1,66 +0,0 @@ -const { LongTermMemory } = require('./long_term_memory'); -const fs = require('fs'); -class SQLiteLTM extends LongTermMemory { - constructor(collection) { - super(collection); - this.base_path = this.brain.main.app.vault.adapter.basePath; - // create file if it doesn't exist - console.log("Creating: " + this.file_path); - this.sqlite3 = require('sqlite3'); - if(!fs.existsSync(this.file_path)) fs.writeFileSync(this.file_path, ''); - console.log("Created: " + this.file_path); - this.db = new this.sqlite3.Database(this.file_path, this.sqlite3.OPEN_READWRITE, (err) => { - if (err) { - console.error(err.message); - } else { - console.log('Connected to the SQLite database.'); - } - }); - } - async create_table() { - this.db.run(`CREATE TABLE IF NOT EXISTS ${this.file_name} (key TEXT PRIMARY KEY, value TEXT)`); - } - async load() { - const time = Date.now(); - // create table if it doesn't exist - await this.create_table(); - console.log("Loading: " + this.file_path); - this.db.all(`SELECT * FROM ${this.file_name}`, [], (err, rows) => { - if (err) { - throw err; - } - rows.forEach((row) => { - this.collection.items[row.key] = new (this.brain.item_types[row.class_name])(this.brain, row); - // this.collection.keys.push(row.key); // replaced by getter - }); - // console.log("Loaded: " + this.file_name); - console.log("Loaded " + this.collection.keys.length + ' items from ' + this.file_name + " in " + (Date.now() - time) + "ms"); - }); - } - // wraps _save in timeout to prevent multiple saves at once - save() { - if(this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = setTimeout(() => { this._save(); }, 10000); - } - // saves collection to file - async _save(force=false) { - if(this.save_timeout) clearTimeout(this.save_timeout); - this.save_timeout = null; - if(this._saving) return console.log("Already saving: " + this.file_name); - this._saving = true; // prevent multiple saves at once - setTimeout(() => { this._saving = false; }, 10000); // set _saving to false after 10 seconds - const start = Date.now(); - console.log("Saving: " + this.file_name); - const stmt = this.db.prepare(`INSERT INTO ${this.file_name} (key, value) VALUES (?, ?)`); - for(let key in this.items) { - if(!this.items[key]?.vec) continue; // skip items without vec - stmt.run(key, JSON.stringify(this.items[key], this.replacer.bind(this))); - } - stmt.finalize(); - const end = Date.now(); // log time - const time = end - start; - console.log("Saved " + this.file_name + " in " + time + "ms"); - } - get file_path() { return this.base_path + '/' + this.data_path + '/' + this.file_name + '.sqlite'; } -} -exports.SQLiteLTM = SQLiteLTM; \ No newline at end of file