| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | const log = require('./log'); | 
					
						
							|  |  |  | const dataDir = require('./data_dir'); | 
					
						
							|  |  |  | const fs = require('fs'); | 
					
						
							|  |  |  | const sqlite = require('sqlite'); | 
					
						
							|  |  |  | const resourceDir = require('./resource_dir'); | 
					
						
							|  |  |  | const appInfo = require('./app_info'); | 
					
						
							|  |  |  | const sql = require('./sql'); | 
					
						
							| 
									
										
										
										
											2018-04-02 22:33:54 -04:00
										 |  |  | const cls = require('./cls'); | 
					
						
							| 
									
										
										
										
											2018-07-24 20:35:03 +02:00
										 |  |  | const optionService = require('./options'); | 
					
						
							|  |  |  | const Option = require('../entities/option'); | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | async function createConnection() { | 
					
						
							|  |  |  |     return await sqlite.open(dataDir.DOCUMENT_PATH, {Promise}); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | let dbReadyResolve = null; | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  | const dbReady = new Promise(async (resolve, reject) => { | 
					
						
							| 
									
										
										
										
											2018-07-22 19:56:20 +02:00
										 |  |  |     dbReadyResolve = resolve; | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  |     // no need to create new connection now since DB stays the same all the time
 | 
					
						
							|  |  |  |     const db = await createConnection(); | 
					
						
							|  |  |  |     sql.setDbConnection(db); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-22 19:56:20 +02:00
										 |  |  |     initDbConnection(); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 08:12:36 +02:00
										 |  |  | async function schemaExists() { | 
					
						
							|  |  |  |     const tableResults = await sql.getRows("SELECT name FROM sqlite_master WHERE type='table' AND name='options'"); | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-22 19:56:20 +02:00
										 |  |  |     return tableResults.length === 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-07-21 08:55:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 08:12:36 +02:00
										 |  |  | async function isDbInitialized() { | 
					
						
							|  |  |  |     if (!await schemaExists()) { | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const initialized = await sql.getValue("SELECT value FROM options WHERE name = 'initialized'"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 20:35:03 +02:00
										 |  |  |     // !initialized may be removed in the future, required only for migration
 | 
					
						
							|  |  |  |     return !initialized || initialized === 'true'; | 
					
						
							| 
									
										
										
										
											2018-07-24 08:12:36 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-22 19:56:20 +02:00
										 |  |  | async function initDbConnection() { | 
					
						
							|  |  |  |     await cls.init(async () => { | 
					
						
							| 
									
										
										
										
											2018-07-22 22:21:16 +02:00
										 |  |  |         if (!await isDbInitialized()) { | 
					
						
							| 
									
										
										
										
											2018-09-10 19:09:05 +02:00
										 |  |  |             log.info("DB not initialized, please visit setup page to see instructions on how to initialize Trilium."); | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-03 22:15:28 -04:00
										 |  |  |             return; | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-04-03 22:15:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 20:35:03 +02:00
										 |  |  |         await sql.execute("PRAGMA foreign_keys = ON"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-03 22:15:28 -04:00
										 |  |  |         if (!await isDbUpToDate()) { | 
					
						
							| 
									
										
										
										
											2018-06-10 15:49:22 -04:00
										 |  |  |             // avoiding circular dependency
 | 
					
						
							|  |  |  |             const migrationService = require('./migration'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             await migrationService.migrate(); | 
					
						
							| 
									
										
										
										
											2018-04-03 22:15:28 -04:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-22 19:56:20 +02:00
										 |  |  |         log.info("DB ready."); | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  |         dbReadyResolve(); | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2018-07-22 19:56:20 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-21 08:55:24 +02:00
										 |  |  | async function createInitialDatabase(username, password) { | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  |     log.info("Creating initial database ..."); | 
					
						
							| 
									
										
										
										
											2018-04-02 22:33:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 08:12:36 +02:00
										 |  |  |     if (await isDbInitialized()) { | 
					
						
							|  |  |  |         throw new Error("DB is already initialized"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-02 22:33:54 -04:00
										 |  |  |     const schema = fs.readFileSync(resourceDir.DB_INIT_DIR + '/schema.sql', 'UTF-8'); | 
					
						
							| 
									
										
										
										
											2018-11-16 14:36:50 +01:00
										 |  |  |     const demoFile = fs.readFileSync(resourceDir.DB_INIT_DIR + '/demo.tar'); | 
					
						
							| 
									
										
										
										
											2018-04-02 22:33:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-07 13:03:16 -04:00
										 |  |  |     await sql.transactional(async () => { | 
					
						
							| 
									
										
										
										
											2018-04-02 22:33:54 -04:00
										 |  |  |         await sql.executeScript(schema); | 
					
						
							| 
									
										
										
										
											2018-11-16 14:36:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const Note = require("../entities/note"); | 
					
						
							|  |  |  |         const Branch = require("../entities/branch"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const rootNote = await new Note({ | 
					
						
							|  |  |  |             noteId: 'root', | 
					
						
							|  |  |  |             title: 'root', | 
					
						
							|  |  |  |             content: '', | 
					
						
							|  |  |  |             type: 'text', | 
					
						
							|  |  |  |             mime: 'text/html' | 
					
						
							|  |  |  |         }).save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await new Branch({ | 
					
						
							|  |  |  |             branchId: 'root', | 
					
						
							|  |  |  |             noteId: 'root', | 
					
						
							|  |  |  |             parentNoteId: 'none', | 
					
						
							|  |  |  |             isExpanded: true, | 
					
						
							|  |  |  |             notePosition: 0 | 
					
						
							|  |  |  |         }).save(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const tarImportService = require("./import/tar"); | 
					
						
							|  |  |  |         await tarImportService.importTar(demoFile, rootNote); | 
					
						
							| 
									
										
										
										
											2018-04-02 22:33:54 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         const startNoteId = await sql.getValue("SELECT noteId FROM branches WHERE parentNoteId = 'root' AND isDeleted = 0 ORDER BY notePosition"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  |         const optionsInitService = require('./options_init'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await optionsInitService.initDocumentOptions(); | 
					
						
							|  |  |  |         await optionsInitService.initSyncedOptions(username, password); | 
					
						
							| 
									
										
										
										
											2018-07-24 08:12:36 +02:00
										 |  |  |         await optionsInitService.initNotSyncedOptions(true, startNoteId); | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-02 22:33:54 -04:00
										 |  |  |         await require('./sync_table').fillAllSyncRows(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  |     log.info("Schema and initial content generated."); | 
					
						
							| 
									
										
										
										
											2018-04-02 22:33:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-22 19:56:20 +02:00
										 |  |  |     await initDbConnection(); | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 08:30:41 +02:00
										 |  |  | async function createDatabaseForSync(options, syncServerHost = '', syncProxy = '') { | 
					
						
							| 
									
										
										
										
											2018-07-24 20:35:03 +02:00
										 |  |  |     log.info("Creating database for sync"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (await isDbInitialized()) { | 
					
						
							|  |  |  |         throw new Error("DB is already initialized"); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const schema = fs.readFileSync(resourceDir.DB_INIT_DIR + '/schema.sql', 'UTF-8'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await sql.transactional(async () => { | 
					
						
							|  |  |  |         await sql.executeScript(schema); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-17 18:11:03 +02:00
										 |  |  |         await require('./options_init').initNotSyncedOptions(false, 'root', syncServerHost, syncProxy); | 
					
						
							| 
									
										
										
										
											2018-07-24 20:35:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         // document options required for sync to kick off
 | 
					
						
							|  |  |  |         for (const opt of options) { | 
					
						
							|  |  |  |             await new Option(opt).save(); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     log.info("Schema and not synced options generated."); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | async function isDbUpToDate() { | 
					
						
							| 
									
										
										
										
											2018-04-02 21:47:46 -04:00
										 |  |  |     const dbVersion = parseInt(await sql.getValue("SELECT value FROM options WHERE name = 'dbVersion'")); | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-02 21:47:46 -04:00
										 |  |  |     const upToDate = dbVersion >= appInfo.dbVersion; | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (!upToDate) { | 
					
						
							| 
									
										
										
										
											2018-04-02 21:47:46 -04:00
										 |  |  |         log.info("App db version is " + appInfo.dbVersion + ", while db version is " + dbVersion + ". Migration needed."); | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return upToDate; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 20:35:03 +02:00
										 |  |  | async function dbInitialized() { | 
					
						
							|  |  |  |     await optionService.setOption('initialized', 'true'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     await initDbConnection(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 20:00:24 +01:00
										 |  |  | dbReady.then(async () => { | 
					
						
							|  |  |  |     log.info("DB size: " + await sql.getValue("SELECT page_count * page_size / 1000 as size FROM pragma_page_count(), pragma_page_size()") + " KB"); | 
					
						
							|  |  |  | }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | module.exports = { | 
					
						
							|  |  |  |     dbReady, | 
					
						
							| 
									
										
										
										
											2018-07-24 08:12:36 +02:00
										 |  |  |     schemaExists, | 
					
						
							| 
									
										
										
										
											2018-07-22 19:56:20 +02:00
										 |  |  |     isDbInitialized, | 
					
						
							|  |  |  |     initDbConnection, | 
					
						
							| 
									
										
										
										
											2018-07-21 08:55:24 +02:00
										 |  |  |     isDbUpToDate, | 
					
						
							| 
									
										
										
										
											2018-07-23 21:15:32 +02:00
										 |  |  |     createInitialDatabase, | 
					
						
							| 
									
										
										
										
											2018-07-24 20:35:03 +02:00
										 |  |  |     createDatabaseForSync, | 
					
						
							|  |  |  |     dbInitialized | 
					
						
							| 
									
										
										
										
											2018-04-02 21:25:20 -04:00
										 |  |  | }; |