mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-11-04 07:01:31 +08:00 
			
		
		
		
	script to generate large documents, closes #55
This commit is contained in:
		
							parent
							
								
									42dd8d4754
								
							
						
					
					
						commit
						abfc64af95
					
				
							
								
								
									
										28
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										28
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "trilium",
 | 
					  "name": "trilium",
 | 
				
			||||||
  "version": "0.9.1-beta",
 | 
					  "version": "0.9.2",
 | 
				
			||||||
  "lockfileVersion": 1,
 | 
					  "lockfileVersion": 1,
 | 
				
			||||||
  "requires": true,
 | 
					  "requires": true,
 | 
				
			||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
@ -7121,6 +7121,32 @@
 | 
				
			|||||||
        "js-tokens": "3.0.2"
 | 
					        "js-tokens": "3.0.2"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "lorem-ipsum": {
 | 
				
			||||||
 | 
					      "version": "1.0.4",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-1.0.4.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha1-MLcqOx4ZH1UGKvjH36spGuT72RI=",
 | 
				
			||||||
 | 
					      "dev": true,
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "optimist": "0.3.7"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "optimist": {
 | 
				
			||||||
 | 
					          "version": "0.3.7",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=",
 | 
				
			||||||
 | 
					          "dev": true,
 | 
				
			||||||
 | 
					          "requires": {
 | 
				
			||||||
 | 
					            "wordwrap": "0.0.3"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "wordwrap": {
 | 
				
			||||||
 | 
					          "version": "0.0.3",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=",
 | 
				
			||||||
 | 
					          "dev": true
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "loud-rejection": {
 | 
					    "loud-rejection": {
 | 
				
			||||||
      "version": "1.6.0",
 | 
					      "version": "1.6.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
 | 
				
			||||||
 | 
				
			|||||||
@ -66,6 +66,7 @@
 | 
				
			|||||||
    "electron-compile": "^6.4.2",
 | 
					    "electron-compile": "^6.4.2",
 | 
				
			||||||
    "electron-packager": "^11.1.0",
 | 
					    "electron-packager": "^11.1.0",
 | 
				
			||||||
    "electron-prebuilt-compile": "2.0.0-beta.5",
 | 
					    "electron-prebuilt-compile": "2.0.0-beta.5",
 | 
				
			||||||
 | 
					    "lorem-ipsum": "^1.0.4",
 | 
				
			||||||
    "tape": "^4.9.0",
 | 
					    "tape": "^4.9.0",
 | 
				
			||||||
    "xo": "^0.18.0"
 | 
					    "xo": "^0.18.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
const Entity = require('./entity');
 | 
					const Entity = require('./entity');
 | 
				
			||||||
const dateUtils = require('../services/date_utils');
 | 
					const dateUtils = require('../services/date_utils');
 | 
				
			||||||
const repository = require('../services/repository');
 | 
					const repository = require('../services/repository');
 | 
				
			||||||
 | 
					const sql = require('../services/sql');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Branch extends Entity {
 | 
					class Branch extends Entity {
 | 
				
			||||||
    static get tableName() { return "branches"; }
 | 
					    static get tableName() { return "branches"; }
 | 
				
			||||||
@ -12,9 +13,14 @@ class Branch extends Entity {
 | 
				
			|||||||
        return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
 | 
					        return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    beforeSaving() {
 | 
					    async beforeSaving() {
 | 
				
			||||||
        super.beforeSaving();
 | 
					        super.beforeSaving();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.notePosition === undefined) {
 | 
				
			||||||
 | 
					            const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [this.parentNoteId]);
 | 
				
			||||||
 | 
					            this.notePosition = maxNotePos === null ? 0 : maxNotePos + 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!this.isDeleted) {
 | 
					        if (!this.isDeleted) {
 | 
				
			||||||
            this.isDeleted = false;
 | 
					            this.isDeleted = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@ async function showDialog() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    await $autoComplete.autocomplete({
 | 
					    await $autoComplete.autocomplete({
 | 
				
			||||||
        source: await utils.stopWatch("building autocomplete", autocompleteService.getAutocompleteItems),
 | 
					        source: await utils.stopWatch("building autocomplete", autocompleteService.getAutocompleteItems),
 | 
				
			||||||
        minLength: 0
 | 
					        minLength: 1
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -46,6 +46,10 @@ async function getAutocompleteItems(parentNoteId, notePath, titlePath) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (parentNoteId === 'root') {
 | 
				
			||||||
 | 
					        console.log(`Generated ${autocompleteItems.length} autocomplete items`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return autocompleteItems;
 | 
					    return autocompleteItems;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -8,8 +8,8 @@ const notes = require('../../services/notes');
 | 
				
			|||||||
const repository = require('../../services/repository');
 | 
					const repository = require('../../services/repository');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Code in this file deals with moving and cloning note tree rows. Relationship between note and parent note is unique
 | 
					 * Code in this file deals with moving and cloning branches. Relationship between note and parent note is unique
 | 
				
			||||||
 * for not deleted note trees. There may be multiple deleted note-parent note relationships.
 | 
					 * for not deleted branches. There may be multiple deleted note-parent note relationships.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function moveBranchToParent(req) {
 | 
					async function moveBranchToParent(req) {
 | 
				
			||||||
@ -49,7 +49,7 @@ async function moveBranchBeforeNote(req) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // we don't change dateModified so other changes are prioritized in case of conflict
 | 
					    // we don't change dateModified so other changes are prioritized in case of conflict
 | 
				
			||||||
    // also we would have to sync all those modified note trees otherwise hash checks would fail
 | 
					    // also we would have to sync all those modified branches otherwise hash checks would fail
 | 
				
			||||||
    await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition >= ? AND isDeleted = 0",
 | 
					    await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition >= ? AND isDeleted = 0",
 | 
				
			||||||
        [beforeNote.parentNoteId, beforeNote.notePosition]);
 | 
					        [beforeNote.parentNoteId, beforeNote.notePosition]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -77,7 +77,7 @@ async function moveBranchAfterNote(req) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // we don't change dateModified so other changes are prioritized in case of conflict
 | 
					    // we don't change dateModified so other changes are prioritized in case of conflict
 | 
				
			||||||
    // also we would have to sync all those modified note trees otherwise hash checks would fail
 | 
					    // also we would have to sync all those modified branches otherwise hash checks would fail
 | 
				
			||||||
    await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
 | 
					    await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
 | 
				
			||||||
        [afterNote.parentNoteId, afterNote.notePosition]);
 | 
					        [afterNote.parentNoteId, afterNote.notePosition]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,64 +1,20 @@
 | 
				
			|||||||
"use strict";
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const sql = require('../../services/sql');
 | 
					const cloningService = require('../../services/cloning');
 | 
				
			||||||
const syncTable = require('../../services/sync_table');
 | 
					 | 
				
			||||||
const tree = require('../../services/tree');
 | 
					 | 
				
			||||||
const Branch = require('../../entities/branch');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function cloneNoteToParent(req) {
 | 
					async function cloneNoteToParent(req) {
 | 
				
			||||||
    const noteId = req.params.noteId;
 | 
					    const noteId = req.params.noteId;
 | 
				
			||||||
    const parentNoteId = req.params.parentNoteId;
 | 
					    const parentNoteId = req.params.parentNoteId;
 | 
				
			||||||
    const prefix = req.body.prefix;
 | 
					    const prefix = req.body.prefix;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const validationResult = await tree.validateParentChild(parentNoteId, noteId);
 | 
					    return await cloningService.cloneNoteToParent(noteId, parentNoteId, prefix);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!validationResult.success) {
 | 
					 | 
				
			||||||
        return validationResult;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const maxNotePos = await sql.getValue('SELECT MAX(notePosition) FROM branches WHERE parentNoteId = ? AND isDeleted = 0', [parentNoteId]);
 | 
					 | 
				
			||||||
    const newNotePos = maxNotePos === null ? 0 : maxNotePos + 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const branch = await new Branch({
 | 
					 | 
				
			||||||
        noteId: noteId,
 | 
					 | 
				
			||||||
        parentNoteId: parentNoteId,
 | 
					 | 
				
			||||||
        prefix: prefix,
 | 
					 | 
				
			||||||
        notePosition: newNotePos,
 | 
					 | 
				
			||||||
        isExpanded: 0
 | 
					 | 
				
			||||||
    }).save();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await sql.execute("UPDATE branches SET isExpanded = 1 WHERE noteId = ?", [parentNoteId]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return { success: true };
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function cloneNoteAfter(req) {
 | 
					async function cloneNoteAfter(req) {
 | 
				
			||||||
    const noteId = req.params.noteId;
 | 
					    const noteId = req.params.noteId;
 | 
				
			||||||
    const afterBranchId = req.params.afterBranchId;
 | 
					    const afterBranchId = req.params.afterBranchId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const afterNote = await tree.getBranch(afterBranchId);
 | 
					    return await cloningService.cloneNoteAfter(noteId, afterBranchId);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    const validationResult = await tree.validateParentChild(afterNote.parentNoteId, noteId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!validationResult.result) {
 | 
					 | 
				
			||||||
        return validationResult;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // we don't change dateModified so other changes are prioritized in case of conflict
 | 
					 | 
				
			||||||
    // also we would have to sync all those modified note trees otherwise hash checks would fail
 | 
					 | 
				
			||||||
    await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
 | 
					 | 
				
			||||||
        [afterNote.parentNoteId, afterNote.notePosition]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await syncTable.addNoteReorderingSync(afterNote.parentNoteId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const branch = await new Branch({
 | 
					 | 
				
			||||||
        noteId: noteId,
 | 
					 | 
				
			||||||
        parentNoteId: afterNote.parentNoteId,
 | 
					 | 
				
			||||||
        notePosition: afterNote.notePosition + 1,
 | 
					 | 
				
			||||||
        isExpanded: 0
 | 
					 | 
				
			||||||
    }).save();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return { success: true };
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
 | 
				
			|||||||
@ -110,17 +110,17 @@ async function importNotes(files, parentNoteId) {
 | 
				
			|||||||
            file.data = file.data.toString("UTF-8");
 | 
					            file.data = file.data.toString("UTF-8");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const noteId = await noteService.createNote(parentNoteId, file.meta.title, file.data, {
 | 
					        const {note} = await noteService.createNote(parentNoteId, file.meta.title, file.data, {
 | 
				
			||||||
            type: file.meta.type,
 | 
					            type: file.meta.type,
 | 
				
			||||||
            mime: file.meta.mime
 | 
					            mime: file.meta.mime
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const label of file.meta.labels) {
 | 
					        for (const label of file.meta.labels) {
 | 
				
			||||||
            await labelService.createLabel(noteId, label.name, label.value);
 | 
					            await labelService.createLabel(note.noteId, label.name, label.value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (file.children.length > 0) {
 | 
					        if (file.children.length > 0) {
 | 
				
			||||||
            await importNotes(file.children, noteId);
 | 
					            await importNotes(file.children, note.noteId);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -20,13 +20,13 @@ async function saveSearchToNote(req) {
 | 
				
			|||||||
        searchString: req.params.searchString
 | 
					        searchString: req.params.searchString
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const noteId = await noteService.createNote('root', 'Search note', noteContent, {
 | 
					    const {note} = await noteService.createNote('root', 'Search note', noteContent, {
 | 
				
			||||||
        json: true,
 | 
					        json: true,
 | 
				
			||||||
        type: 'search',
 | 
					        type: 'search',
 | 
				
			||||||
        mime: "application/json"
 | 
					        mime: "application/json"
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return { noteId };
 | 
					    return { noteId: note.noteId };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										56
									
								
								src/services/cloning.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/services/cloning.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const sql = require('./sql');
 | 
				
			||||||
 | 
					const syncTable = require('./sync_table');
 | 
				
			||||||
 | 
					const tree = require('./tree');
 | 
				
			||||||
 | 
					const Branch = require('../entities/branch');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function cloneNoteToParent(noteId, parentNoteId, prefix) {
 | 
				
			||||||
 | 
					    const validationResult = await tree.validateParentChild(parentNoteId, noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!validationResult.success) {
 | 
				
			||||||
 | 
					        return validationResult;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await new Branch({
 | 
				
			||||||
 | 
					        noteId: noteId,
 | 
				
			||||||
 | 
					        parentNoteId: parentNoteId,
 | 
				
			||||||
 | 
					        prefix: prefix,
 | 
				
			||||||
 | 
					        isExpanded: 0
 | 
				
			||||||
 | 
					    }).save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await sql.execute("UPDATE branches SET isExpanded = 1 WHERE noteId = ?", [parentNoteId]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return { success: true };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function cloneNoteAfter(noteId, afterBranchId) {
 | 
				
			||||||
 | 
					    const afterNote = await tree.getBranch(afterBranchId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const validationResult = await tree.validateParentChild(afterNote.parentNoteId, noteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!validationResult.result) {
 | 
				
			||||||
 | 
					        return validationResult;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // we don't change dateModified so other changes are prioritized in case of conflict
 | 
				
			||||||
 | 
					    // also we would have to sync all those modified branches otherwise hash checks would fail
 | 
				
			||||||
 | 
					    await sql.execute("UPDATE branches SET notePosition = notePosition + 1 WHERE parentNoteId = ? AND notePosition > ? AND isDeleted = 0",
 | 
				
			||||||
 | 
					        [afterNote.parentNoteId, afterNote.notePosition]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await syncTable.addNoteReorderingSync(afterNote.parentNoteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await new Branch({
 | 
				
			||||||
 | 
					        noteId: noteId,
 | 
				
			||||||
 | 
					        parentNoteId: afterNote.parentNoteId,
 | 
				
			||||||
 | 
					        notePosition: afterNote.notePosition + 1,
 | 
				
			||||||
 | 
					        isExpanded: 0
 | 
				
			||||||
 | 
					    }).save();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return { success: true };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = {
 | 
				
			||||||
 | 
					    cloneNoteToParent,
 | 
				
			||||||
 | 
					    cloneNoteAfter
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -105,7 +105,7 @@ async function runAllChecks() {
 | 
				
			|||||||
            LEFT JOIN notes USING(noteId) 
 | 
					            LEFT JOIN notes USING(noteId) 
 | 
				
			||||||
          WHERE 
 | 
					          WHERE 
 | 
				
			||||||
            notes.noteId IS NULL`,
 | 
					            notes.noteId IS NULL`,
 | 
				
			||||||
        "Missing notes records for following note tree ID > note ID", errorList);
 | 
					        "Missing notes records for following branch ID > note ID", errorList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await runCheck(`
 | 
					    await runCheck(`
 | 
				
			||||||
          SELECT 
 | 
					          SELECT 
 | 
				
			||||||
@ -116,7 +116,7 @@ async function runAllChecks() {
 | 
				
			|||||||
          WHERE 
 | 
					          WHERE 
 | 
				
			||||||
            notes.isDeleted = 1 
 | 
					            notes.isDeleted = 1 
 | 
				
			||||||
            AND branches.isDeleted = 0`,
 | 
					            AND branches.isDeleted = 0`,
 | 
				
			||||||
        "Note tree is not deleted even though main note is deleted for following note tree IDs", errorList);
 | 
					        "Note tree is not deleted even though main note is deleted for following branch IDs", errorList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await runCheck(`
 | 
					    await runCheck(`
 | 
				
			||||||
          SELECT 
 | 
					          SELECT 
 | 
				
			||||||
@ -128,7 +128,7 @@ async function runAllChecks() {
 | 
				
			|||||||
            AND child.parentNoteId != 'root'
 | 
					            AND child.parentNoteId != 'root'
 | 
				
			||||||
            AND (SELECT COUNT(*) FROM branches AS parent WHERE parent.noteId = child.parentNoteId 
 | 
					            AND (SELECT COUNT(*) FROM branches AS parent WHERE parent.noteId = child.parentNoteId 
 | 
				
			||||||
                                                                 AND parent.isDeleted = 0) = 0`,
 | 
					                                                                 AND parent.isDeleted = 0) = 0`,
 | 
				
			||||||
        "All parent note trees are deleted but child note tree is not for these child note tree IDs", errorList);
 | 
					        "All parent branches are deleted but child note tree is not for these child note tree IDs", errorList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // we do extra JOIN to eliminate orphan notes without note tree (which are reported separately)
 | 
					    // we do extra JOIN to eliminate orphan notes without note tree (which are reported separately)
 | 
				
			||||||
    await runCheck(`
 | 
					    await runCheck(`
 | 
				
			||||||
@ -140,7 +140,7 @@ async function runAllChecks() {
 | 
				
			|||||||
          WHERE
 | 
					          WHERE
 | 
				
			||||||
            (SELECT COUNT(*) FROM branches WHERE notes.noteId = branches.noteId AND branches.isDeleted = 0) = 0
 | 
					            (SELECT COUNT(*) FROM branches WHERE notes.noteId = branches.noteId AND branches.isDeleted = 0) = 0
 | 
				
			||||||
            AND notes.isDeleted = 0
 | 
					            AND notes.isDeleted = 0
 | 
				
			||||||
    `, 'No undeleted note trees for note IDs', errorList);
 | 
					    `, 'No undeleted branches for note IDs', errorList);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await runCheck(`
 | 
					    await runCheck(`
 | 
				
			||||||
          SELECT 
 | 
					          SELECT 
 | 
				
			||||||
 | 
				
			|||||||
@ -83,7 +83,7 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {})
 | 
				
			|||||||
        noteData.mime = "application/json";
 | 
					        noteData.mime = "application/json";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const {note} = await createNewNote(parentNoteId, noteData);
 | 
					    const {note, branch} = await createNewNote(parentNoteId, noteData);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (extraOptions.labels) {
 | 
					    if (extraOptions.labels) {
 | 
				
			||||||
        for (const labelName in extraOptions.labels) {
 | 
					        for (const labelName in extraOptions.labels) {
 | 
				
			||||||
@ -91,7 +91,7 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {})
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return note.noteId;
 | 
					    return {note, branch};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function protectNoteRecursively(note, protect) {
 | 
					async function protectNoteRecursively(note, protect) {
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,9 @@ async function createConnection() {
 | 
				
			|||||||
    return await sqlite.open(dataDir.DOCUMENT_PATH, {Promise});
 | 
					    return await sqlite.open(dataDir.DOCUMENT_PATH, {Promise});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let schemaReadyResolve = null;
 | 
				
			||||||
 | 
					const schemaReady = new Promise((resolve, reject) => schemaReadyResolve = resolve);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let dbReadyResolve = null;
 | 
					let dbReadyResolve = null;
 | 
				
			||||||
const dbReady = new Promise((resolve, reject) => {
 | 
					const dbReady = new Promise((resolve, reject) => {
 | 
				
			||||||
    cls.init(async () => {
 | 
					    cls.init(async () => {
 | 
				
			||||||
@ -29,19 +32,20 @@ const dbReady = new Promise((resolve, reject) => {
 | 
				
			|||||||
        if (tableResults.length !== 1) {
 | 
					        if (tableResults.length !== 1) {
 | 
				
			||||||
            await createInitialDatabase();
 | 
					            await createInitialDatabase();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            if (!await isUserInitialized()) {
 | 
					 | 
				
			||||||
                log.info("Login/password not initialized. DB not ready.");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return;
 | 
					        schemaReadyResolve();
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!await isDbUpToDate()) {
 | 
					        if (!await isUserInitialized()) {
 | 
				
			||||||
                return;
 | 
					            log.info("Login/password not initialized. DB not ready.");
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            resolve(db);
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!await isDbUpToDate()) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        resolve(db);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -97,6 +101,7 @@ async function isUserInitialized() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    dbReady,
 | 
					    dbReady,
 | 
				
			||||||
 | 
					    schemaReady,
 | 
				
			||||||
    isUserInitialized,
 | 
					    isUserInitialized,
 | 
				
			||||||
    setDbReadyAsResolved,
 | 
					    setDbReadyAsResolved,
 | 
				
			||||||
    isDbUpToDate
 | 
					    isDbUpToDate
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,7 @@ async function updateBranch(entity, sourceId) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            await syncTableService.addBranchSync(entity.branchId, sourceId);
 | 
					            await syncTableService.addBranchSync(entity.branchId, sourceId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            log.info("Update/sync note tree " + entity.branchId);
 | 
					            log.info("Update/sync branch " + entity.branchId);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										74
									
								
								src/tools/generate_document.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/tools/generate_document.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					const fs = require('fs');
 | 
				
			||||||
 | 
					const dataDir = require('../services/data_dir');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fs.unlinkSync(dataDir.DOCUMENT_PATH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require('../entities/entity_constructor');
 | 
				
			||||||
 | 
					const optionService = require('../services/options');
 | 
				
			||||||
 | 
					const sqlInit = require('../services/sql_init');
 | 
				
			||||||
 | 
					const myScryptService = require('../services/my_scrypt');
 | 
				
			||||||
 | 
					const passwordEncryptionService = require('../services/password_encryption');
 | 
				
			||||||
 | 
					const utils = require('../services/utils');
 | 
				
			||||||
 | 
					const noteService = require('../services/notes');
 | 
				
			||||||
 | 
					const cls = require('../services/cls');
 | 
				
			||||||
 | 
					const cloningService = require('../services/cloning');
 | 
				
			||||||
 | 
					const loremIpsum = require('lorem-ipsum');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function setUserNamePassword() {
 | 
				
			||||||
 | 
					    const username = "test";
 | 
				
			||||||
 | 
					    const password = "test";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await optionService.setOption('username', username);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await optionService.setOption('passwordVerificationSalt', utils.randomSecureToken(32));
 | 
				
			||||||
 | 
					    await optionService.setOption('passwordDerivedKeySalt', utils.randomSecureToken(32));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const passwordVerificationKey = utils.toBase64(await myScryptService.getVerificationHash(password));
 | 
				
			||||||
 | 
					    await optionService.setOption('passwordVerificationHash', passwordVerificationKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await passwordEncryptionService.setDataKey(password, utils.randomSecureToken(16));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sqlInit.setDbReadyAsResolved();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const noteCount = parseInt(process.argv[2]);
 | 
				
			||||||
 | 
					const notes = ['root'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getRandomParentNoteId() {
 | 
				
			||||||
 | 
					    const index = Math.floor(Math.random() * notes.length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return notes[index];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function start() {
 | 
				
			||||||
 | 
					    await setUserNamePassword();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (let i = 0; i < noteCount; i++) {
 | 
				
			||||||
 | 
					        const title = loremIpsum({ count: 1, units: 'sentences', sentenceLowerBound: 1, sentenceUpperBound: 10 });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const paragraphCount = Math.floor(Math.random() * Math.random() * 100);
 | 
				
			||||||
 | 
					        const content = loremIpsum({ count: paragraphCount, units: 'paragraphs', sentenceLowerBound: 1, sentenceUpperBound: 15,
 | 
				
			||||||
 | 
					            paragraphLowerBound: 3, paragraphUpperBound: 10, format: 'html' });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const {note} = await noteService.createNote(getRandomParentNoteId(), title, content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        console.log(`Created note ${i}: ${title}`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        notes.push(note.noteId);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // we'll create clones for 20% of notes
 | 
				
			||||||
 | 
					    for (let i = 0; i < (noteCount / 5); i++) {
 | 
				
			||||||
 | 
					        const noteIdToClone = getRandomParentNoteId();
 | 
				
			||||||
 | 
					        const parentNoteId = getRandomParentNoteId();
 | 
				
			||||||
 | 
					        const prefix = Math.random() > 0.8 ? "prefix" : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const result = await cloningService.cloneNoteToParent(noteIdToClone, parentNoteId, prefix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        console.log(`Cloning ${i}:`, result.success ? "succeeded" : "FAILED");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    process.exit(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sqlInit.schemaReady.then(cls.wrap(start));
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user