2017-06-25 18:30:44 +02:00
#!/usr/bin/env node
2017-06-22 23:52:27 +02:00
require ( 'source-map-support' ) . install ( ) ;
require ( 'babel-plugin-transform-runtime' ) ;
2017-06-24 20:06:28 +02:00
import { FileApi } from 'lib/file-api.js' ;
import { FileApiDriverOneDrive } from 'lib/file-api-driver-onedrive.js' ;
import { Database } from 'lib/database.js' ;
import { DatabaseDriverNode } from 'lib/database-driver-node.js' ;
import { BaseModel } from 'lib/base-model.js' ;
import { Folder } from 'lib/models/folder.js' ;
2017-06-25 09:35:59 +02:00
import { BaseItem } from 'lib/models/base-item.js' ;
2017-06-24 20:06:28 +02:00
import { Note } from 'lib/models/note.js' ;
import { Setting } from 'lib/models/setting.js' ;
import { Synchronizer } from 'lib/synchronizer.js' ;
import { Logger } from 'lib/logger.js' ;
import { uuid } from 'lib/uuid.js' ;
2017-06-22 23:52:27 +02:00
import { sprintf } from 'sprintf-js' ;
2017-06-24 19:40:03 +02:00
import { importEnex } from 'import-enex' ;
2017-06-25 13:39:42 +02:00
import { filename , basename } from 'lib/path-utils.js' ;
2017-06-24 20:06:28 +02:00
import { _ } from 'lib/locale.js' ;
2017-06-22 23:52:27 +02:00
import os from 'os' ;
import fs from 'fs-extra' ;
2017-06-23 23:32:24 +02:00
process . on ( 'unhandledRejection' , ( reason , p ) => {
2017-06-26 00:20:07 +02:00
console . error ( 'Unhandled promise rejection' , p , 'reason:' , reason ) ;
2017-06-23 23:32:24 +02:00
} ) ;
2017-06-26 00:20:07 +02:00
const packageJson = require ( './package.json' ) ;
2017-06-24 19:40:03 +02:00
2017-06-26 00:20:07 +02:00
let profileDir = os . homedir ( ) + '/.config/' + Setting . value ( 'appName' ) ;
let currentFolder = null ;
let commands = [ ] ;
let database _ = null ;
2017-06-22 23:52:27 +02:00
let synchronizer _ = null ;
2017-06-26 00:20:07 +02:00
let logger = new Logger ( ) ;
let dbLogger = new Logger ( ) ;
let syncLogger = new Logger ( ) ;
commands . push ( {
usage : 'root' ,
options : [
[ '-p, --profile <filePath>' , 'Sets the profile path directory.' ] ,
] ,
action : function ( args , end ) {
let p = args . profile || args . p ;
if ( p ) profileDir = p ;
end ( ) ;
} ,
} ) ;
2017-06-24 19:40:03 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'version' ,
description : 'Displays version information' ,
action : function ( args , end ) {
this . log ( packageJson . name + ' ' + packageJson . version ) ;
end ( ) ;
} ,
} ) ;
2017-06-24 19:40:03 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'mkbook <notebook>' ,
aliases : [ 'mkdir' ] ,
description : 'Creates a new notebook' ,
action : function ( args , end ) {
Folder . save ( { title : args [ 'notebook' ] } ) . catch ( ( error ) => {
this . log ( error ) ;
} ) . then ( ( folder ) => {
switchCurrentFolder ( folder ) ;
end ( ) ;
} ) ;
} ,
} ) ;
2017-06-24 19:40:03 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'mknote <note-title>' ,
aliases : [ 'touch' ] ,
description : 'Creates a new note' ,
action : function ( args , end ) {
if ( ! currentFolder ) {
this . log ( 'Notes can only be created within a notebook.' ) ;
end ( ) ;
return ;
}
2017-06-24 19:40:03 +02:00
2017-06-26 00:20:07 +02:00
let note = {
title : args [ 'note-title' ] ,
parent _id : currentFolder . id ,
} ;
Note . save ( note ) . catch ( ( error ) => {
this . log ( error ) ;
} ) . then ( ( note ) => {
end ( ) ;
} ) ;
} ,
} ) ;
2017-06-24 19:40:03 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'use <notebook>' ,
aliases : [ 'cd' ] ,
description : 'Switches to [notebook] - all further operations will happen within this notebook.' ,
action : async function ( args , end ) {
let folderTitle = args [ 'notebook' ] ;
2017-06-25 14:49:46 +02:00
2017-06-26 00:20:07 +02:00
let folder = await Folder . loadByField ( 'title' , folderTitle ) ;
if ( ! folder ) return cmdError ( this , _ ( 'Invalid folder title: %s' , folderTitle ) , end ) ;
switchCurrentFolder ( folder ) ;
end ( ) ;
} ,
autocomplete : autocompleteFolders ,
} ) ;
2017-06-25 14:49:46 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'set <item-title> <prop-name> [prop-value]' ,
description : 'Sets the given <prop-name> of the given item.' ,
action : function ( args , end ) {
let promise = null ;
let title = args [ 'item-title' ] ;
let propName = args [ 'prop-name' ] ;
let propValue = args [ 'prop-value' ] ;
if ( ! propValue ) propValue = '' ;
2017-06-25 14:49:46 +02:00
2017-06-26 00:20:07 +02:00
if ( ! currentFolder ) {
promise = Folder . loadByField ( 'title' , title ) ;
} else {
promise = Folder . loadNoteByField ( currentFolder . id , 'title' , title ) ;
}
2017-06-24 19:40:03 +02:00
2017-06-26 00:20:07 +02:00
promise . then ( ( item ) => {
if ( ! item ) {
this . log ( _ ( 'No item with title "%s" found.' , title ) ) ;
end ( ) ;
return ;
}
2017-06-24 19:40:03 +02:00
2017-06-26 00:20:07 +02:00
let newItem = {
id : item . id ,
type _ : item . type _ ,
} ;
newItem [ propName ] = propValue ;
let ItemClass = BaseItem . itemClass ( ) ;
return ItemClass . save ( newItem ) ;
} ) . catch ( ( error ) => {
this . log ( error ) ;
} ) . then ( ( ) => {
end ( ) ;
} ) ;
} ,
autocomplete : autocompleteItems ,
} ) ;
2017-06-24 19:40:03 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'cat <item-title>' ,
description : 'Displays the given item data.' ,
action : function ( args , end ) {
let title = args [ 'item-title' ] ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
let promise = null ;
if ( ! currentFolder ) {
promise = Folder . loadByField ( 'title' , title ) ;
} else {
promise = Folder . loadNoteByField ( currentFolder . id , 'title' , title ) ;
}
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
promise . then ( ( item ) => {
if ( ! item ) {
this . log ( _ ( 'No item with title "%s" found.' , title ) ) ;
end ( ) ;
return ;
}
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
if ( ! currentFolder ) {
this . log ( Folder . serialize ( item ) ) ;
} else {
this . log ( Note . serialize ( item ) ) ;
}
} ) . catch ( ( error ) => {
this . log ( error ) ;
} ) . then ( ( ) => {
end ( ) ;
} ) ;
} ,
autocomplete : autocompleteItems ,
} ) ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'rm <pattern>' ,
description : 'Deletes the given item. For a notebook, all the notes within that notebook will be deleted. Use `rm ../<notebook>` to delete a notebook.' ,
action : async function ( args , end ) {
let pattern = args [ 'pattern' ] ;
let itemType = null ;
if ( pattern . indexOf ( '*' ) < 0 ) { // Handle it as a simple title
if ( pattern . substr ( 0 , 3 ) == '../' ) {
itemType = BaseModel . MODEL _TYPE _FOLDER ;
pattern = pattern . substr ( 3 ) ;
2017-06-22 23:52:27 +02:00
} else {
2017-06-26 00:20:07 +02:00
itemType = BaseModel . MODEL _TYPE _NOTE ;
2017-06-22 23:52:27 +02:00
}
2017-06-26 00:20:07 +02:00
let item = await BaseItem . loadItemByField ( itemType , 'title' , pattern ) ;
if ( ! item ) return cmdError ( this , _ ( 'No item with title "%s" found.' , pattern ) , end ) ;
await BaseItem . deleteItem ( itemType , item . id ) ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
if ( currentFolder && currentFolder . id == item . id ) {
let f = await Folder . defaultFolder ( ) ;
switchCurrentFolder ( f ) ;
}
} else { // Handle it as a glob pattern
let notes = await Note . previews ( currentFolder . id , { titlePattern : pattern } ) ;
if ( ! notes . length ) return cmdError ( this , _ ( 'No note matches this pattern: "%s"' , pattern ) , end ) ;
let ok = await cmdPromptConfirm ( this , _ ( '%d notes match this pattern. Delete them?' , notes . length ) ) ;
if ( ok ) {
for ( let i = 0 ; i < notes . length ; i ++ ) {
await Note . delete ( notes [ i ] . id ) ;
}
}
2017-06-22 23:52:27 +02:00
}
2017-06-26 00:20:07 +02:00
end ( ) ;
} ,
autocomplete : autocompleteItems ,
} ) ;
2017-06-23 23:32:24 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'mv <pattern> <notebook>' ,
description : 'Moves the notes matching <pattern> to <notebook>.' ,
action : async function ( args , end ) {
let pattern = args [ 'pattern' ] ;
2017-06-25 12:41:03 +02:00
2017-06-26 00:20:07 +02:00
let folder = await Folder . loadByField ( 'title' , args [ 'notebook' ] ) ;
if ( ! folder ) return cmdError ( this , _ ( 'No folder with title "%s"' , args [ 'notebook' ] ) , end ) ;
let notes = await Note . previews ( currentFolder . id , { titlePattern : pattern } ) ;
if ( ! notes . length ) return cmdError ( this , _ ( 'No note matches this pattern: "%s"' , pattern ) , end ) ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
for ( let i = 0 ; i < notes . length ; i ++ ) {
await Note . save ( { id : notes [ i ] . id , parent _id : folder . id } ) ;
2017-06-22 23:52:27 +02:00
}
2017-06-26 00:20:07 +02:00
end ( ) ;
} ,
autocomplete : autocompleteItems ,
} ) ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'ls [pattern]' ,
description : 'Displays the notes in [notebook]. Use `ls ..` to display the list of notebooks.' ,
options : [
[ '-n, --lines <num>' , 'Displays only the first top <num> lines.' ] ,
[ '-s, --sort <field>' , 'Sorts the item by <field> (eg. title, updated_time, created_time).' ] ,
[ '-r, --reverse' , 'Reverses the sorting order.' ] ,
[ '-t, --type <type>' , 'Displays only the items of the specific type(s). Can be `n` for notes, `t` for todos, or `nt` for notes and todos (eg. `-tt` would display only the todos, while `-ttd` would display notes and todos.' ] ,
] ,
action : async function ( args , end ) {
let pattern = args [ 'pattern' ] ;
let suffix = '' ;
let items = [ ] ;
let options = args . options ;
let queryOptions = { } ;
if ( options . lines ) queryOptions . limit = options . lines ;
if ( options . sort ) {
queryOptions . orderBy = options . sort ;
queryOptions . orderByDir = 'ASC' ;
2017-06-22 23:52:27 +02:00
}
2017-06-26 00:20:07 +02:00
if ( options . reverse === true ) queryOptions . orderByDir = queryOptions . orderByDir == 'ASC' ? 'DESC' : 'ASC' ;
queryOptions . caseInsensitive = true ;
if ( options . type ) {
queryOptions . itemTypes = [ ] ;
if ( options . type . indexOf ( 'n' ) >= 0 ) queryOptions . itemTypes . push ( 'note' ) ;
if ( options . type . indexOf ( 't' ) >= 0 ) queryOptions . itemTypes . push ( 'todo' ) ;
}
if ( pattern ) queryOptions . titlePattern = pattern ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
if ( pattern == '..' ) {
items = await Folder . all ( queryOptions ) ;
suffix = '/' ;
2017-06-22 23:52:27 +02:00
} else {
2017-06-26 00:20:07 +02:00
items = await Note . previews ( currentFolder . id , queryOptions ) ;
2017-06-22 23:52:27 +02:00
}
2017-06-26 00:20:07 +02:00
for ( let i = 0 ; i < items . length ; i ++ ) {
let item = items [ i ] ;
let line = '' ;
if ( ! ! item . is _todo ) {
line += sprintf ( '[%s] ' , ! ! item . todo _completed ? 'X' : ' ' ) ;
2017-06-22 23:52:27 +02:00
}
2017-06-26 00:20:07 +02:00
line += item . title + suffix ;
this . log ( line ) ;
}
2017-06-22 23:52:27 +02:00
2017-06-25 09:35:59 +02:00
end ( ) ;
2017-06-26 00:20:07 +02:00
} ,
autocomplete : autocompleteFolders ,
} ) ;
2017-06-25 09:35:59 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'sync' ,
description : 'Synchronizes with remote storage.' ,
action : function ( args , end ) {
synchronizer ( 'onedrive' ) . then ( ( s ) => {
return s . start ( ) ;
} ) . catch ( ( error ) => {
logger . error ( error ) ;
} ) . then ( ( ) => {
end ( ) ;
2017-06-25 13:39:42 +02:00
} ) ;
2017-06-26 00:20:07 +02:00
} ,
} ) ;
2017-06-25 13:39:42 +02:00
2017-06-26 00:20:07 +02:00
commands . push ( {
usage : 'import-enex <file> [notebook]' ,
description : _ ( 'Imports en Evernote notebook file (.enex file).' ) ,
options : [
[ '--fuzzy-matching' , 'For debugging purposes. Do not use.' ] ,
] ,
action : async function ( args , end ) {
let filePath = args . file ;
let folder = null ;
let folderTitle = args [ 'notebook' ] ;
if ( folderTitle ) {
folder = await Folder . loadByField ( 'title' , folderTitle ) ;
if ( ! folder ) return cmdError ( this , _ ( 'Folder does not exists: "%s"' , folderTitle ) , end ) ;
} else {
folderTitle = filename ( filePath ) ;
folderTitle = _ ( 'Imported - %s' , folderTitle ) ;
let inc = 0 ;
while ( true ) {
let t = folderTitle + ( inc ? ' (' + inc + ')' : '' ) ;
let f = await Folder . loadByField ( 'title' , t ) ;
if ( ! f ) {
folderTitle = t ;
break ;
}
inc ++ ;
}
2017-06-22 23:52:27 +02:00
}
2017-06-26 00:20:07 +02:00
let ok = await cmdPromptConfirm ( this , _ ( 'File "%s" will be imported into notebook "%s". Continue?' , basename ( filePath ) , folderTitle ) )
if ( ! ok ) {
end ( ) ;
return ;
2017-06-22 23:52:27 +02:00
}
2017-06-26 21:03:01 +02:00
let redrawnCalled = false ;
2017-06-26 00:20:07 +02:00
let options = {
fuzzyMatching : args . options [ 'fuzzy-matching' ] === true ,
2017-06-26 21:03:01 +02:00
onProgress : ( progressState ) => {
let line = sprintf ( _ ( 'Found: %d. Imported: %d.' , progressState . loaded , progressState . imported ) ) ;
redrawnCalled = true ;
vorpal . ui . redraw ( line ) ;
} ,
onError : ( error ) => {
let s = error . trace ? error . trace : error . toString ( ) ;
this . log ( s ) ;
} ,
2017-06-26 00:20:07 +02:00
}
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
folder = ! folder ? await Folder . save ( { title : folderTitle } ) : folder ;
this . log ( _ ( 'Importing notes...' ) ) ;
await importEnex ( folder . id , filePath , options ) ;
2017-06-26 21:03:01 +02:00
if ( redrawnCalled ) vorpal . ui . redraw . done ( ) ;
this . log ( _ ( 'Done.' ) ) ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
end ( ) ;
} ,
} ) ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
function commandByName ( name ) {
for ( let i = 0 ; i < commands . length ; i ++ ) {
let c = commands [ i ] ;
let n = c . usage . split ( ' ' ) ;
n = n [ 0 ] ;
if ( n == name ) return c ;
if ( c . aliases && c . aliases . indexOf ( name ) >= 0 ) return c ;
}
return null ;
}
2017-06-25 12:41:03 +02:00
2017-06-26 00:20:07 +02:00
function execCommand ( name , args ) {
return new Promise ( ( resolve , reject ) => {
let cmd = commandByName ( name ) ;
if ( ! cmd ) {
reject ( new Error ( 'Unknown command: ' + name ) ) ;
} else {
cmd . action ( args , function ( ) {
resolve ( ) ;
} ) ;
}
2017-06-25 12:41:03 +02:00
} ) ;
2017-06-26 00:20:07 +02:00
}
2017-06-25 12:41:03 +02:00
2017-06-26 00:20:07 +02:00
async function synchronizer ( remoteBackend ) {
if ( synchronizer _ ) return synchronizer _ ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
let fileApi = null ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
if ( remoteBackend == 'onedrive' ) {
const CLIENT _ID = 'e09fc0de-c958-424f-83a2-e56a721d331b' ;
const CLIENT _SECRET = 'JA3cwsqSGHFtjMwd5XoF5L5' ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
let driver = new FileApiDriverOneDrive ( CLIENT _ID , CLIENT _SECRET ) ;
let auth = Setting . value ( 'sync.onedrive.auth' ) ;
if ( auth ) {
auth = JSON . parse ( auth ) ;
} else {
auth = await driver . api ( ) . oauthDance ( ) ;
Setting . setValue ( 'sync.onedrive.auth' , JSON . stringify ( auth ) ) ;
}
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
driver . api ( ) . setAuth ( auth ) ;
driver . api ( ) . on ( 'authRefreshed' , ( a ) => {
Setting . setValue ( 'sync.onedrive.auth' , JSON . stringify ( a ) ) ;
} ) ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
let appDir = await driver . api ( ) . appDirectory ( ) ;
logger . info ( 'App dir: ' + appDir ) ;
fileApi = new FileApi ( appDir , driver ) ;
fileApi . setLogger ( logger ) ;
} else {
throw new Error ( 'Unknown backend: ' + remoteBackend ) ;
}
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
synchronizer _ = new Synchronizer ( database _ , fileApi ) ;
synchronizer _ . setLogger ( syncLogger ) ;
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
return synchronizer _ ;
}
2017-06-25 09:52:25 +02:00
2017-06-26 00:20:07 +02:00
// let s = await synchronizer('onedrive');
// await synchronizer_.start();
// return;
2017-06-25 09:52:25 +02:00
2017-06-26 00:20:07 +02:00
function switchCurrentFolder ( folder ) {
if ( ! folder ) throw new Error ( _ ( 'No active folder is defined.' ) ) ;
2017-06-25 09:52:25 +02:00
2017-06-26 00:20:07 +02:00
currentFolder = folder ;
Setting . setValue ( 'activeFolderId' , folder . id ) ;
updatePrompt ( ) ;
}
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
function promptString ( ) {
let path = '~' ;
if ( currentFolder ) {
path += '/' + currentFolder . title ;
}
return 'joplin:' + path + '$ ' ;
}
2017-06-25 16:40:42 +02:00
2017-06-26 00:20:07 +02:00
function updatePrompt ( ) {
vorpal . delimiter ( promptString ( ) ) ;
}
2017-06-25 16:40:42 +02:00
2017-06-26 00:20:07 +02:00
// For now, to go around this issue: https://github.com/dthree/vorpal/issues/114
function quotePromptArg ( s ) {
if ( s . indexOf ( ' ' ) >= 0 ) {
return '"' + s + '"' ;
}
return s ;
}
2017-06-25 16:40:42 +02:00
2017-06-26 00:20:07 +02:00
function autocompleteFolders ( ) {
return Folder . all ( ) . then ( ( folders ) => {
let output = [ ] ;
for ( let i = 0 ; i < folders . length ; i ++ ) {
output . push ( quotePromptArg ( folders [ i ] . title ) ) ;
}
output . push ( '..' ) ;
output . push ( '.' ) ;
return output ;
2017-06-25 16:40:42 +02:00
} ) ;
2017-06-26 00:20:07 +02:00
}
2017-06-25 16:40:42 +02:00
2017-06-26 00:20:07 +02:00
function autocompleteItems ( ) {
let promise = null ;
if ( ! currentFolder ) {
promise = Folder . all ( ) ;
} else {
promise = Note . previews ( currentFolder . id ) ;
}
2017-06-25 09:35:59 +02:00
2017-06-26 00:20:07 +02:00
return promise . then ( ( items ) => {
let output = [ ] ;
for ( let i = 0 ; i < items . length ; i ++ ) {
output . push ( quotePromptArg ( items [ i ] . title ) ) ;
}
return output ;
2017-06-22 23:52:27 +02:00
} ) ;
2017-06-26 00:20:07 +02:00
}
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
function cmdError ( commandInstance , msg , end ) {
commandInstance . log ( msg ) ;
end ( ) ;
}
2017-06-22 23:52:27 +02:00
2017-06-26 00:20:07 +02:00
function cmdPromptConfirm ( commandInstance , message ) {
return new Promise ( ( resolve , reject ) => {
let options = {
type : 'confirm' ,
name : 'ok' ,
default : false , // This needs to be false so that, when pressing Ctrl+C, the prompt returns false
message : message ,
} ;
commandInstance . prompt ( options , ( result ) => {
if ( result . ok ) {
resolve ( true ) ;
2017-06-25 13:39:42 +02:00
} else {
2017-06-26 00:20:07 +02:00
resolve ( false ) ;
2017-06-25 13:39:42 +02:00
}
2017-06-26 00:20:07 +02:00
} ) ;
} ) ;
}
2017-06-25 13:39:42 +02:00
2017-06-26 00:20:07 +02:00
// Handles the initial arguments passed to main script and
// route them to the "root" command.
function handleStartArgs ( argv ) {
return new Promise ( ( resolve , reject ) => {
if ( argv && argv . length >= 3 && argv [ 2 ] [ 0 ] == '-' ) {
const startParams = vorpal . parse ( argv , { use : 'minimist' } ) ;
const cmd = commandByName ( 'root' ) ;
cmd . action ( startParams , ( ) => { resolve ( ) ; } ) ;
} else {
// TODO
resolve ( ) ;
}
} ) ;
}
2017-06-25 13:39:42 +02:00
2017-06-26 00:20:07 +02:00
process . stdin . on ( 'keypress' , ( _ , key ) => {
if ( key && key . name === 'return' ) {
updatePrompt ( ) ;
}
2017-06-25 13:39:42 +02:00
2017-06-26 00:20:07 +02:00
if ( key . name === 'tab' ) {
vorpal . ui . imprint ( ) ;
vorpal . log ( vorpal . ui . input ( ) ) ;
}
} ) ;
2017-06-25 13:39:42 +02:00
2017-06-26 00:20:07 +02:00
const vorpal = require ( 'vorpal' ) ( ) ;
2017-06-25 13:39:42 +02:00
2017-06-26 00:20:07 +02:00
async function main ( ) {
// console.info('DELETING ALL DATA');
// await db.exec('DELETE FROM notes');
// await db.exec('DELETE FROM changes');
// await db.exec('DELETE FROM folders');
// await db.exec('DELETE FROM resources');
// await db.exec('DELETE FROM deleted_items');
// await db.exec('DELETE FROM tags');
// await db.exec('DELETE FROM note_tags');
// let folder1 = await Folder.save({ title: 'test1' });
// let folder2 = await Folder.save({ title: 'test2' });
// await importEnex(folder1.id, '/mnt/c/Users/Laurent/Desktop/Laurent.enex');
// return;
2017-06-24 19:40:03 +02:00
2017-06-25 09:35:59 +02:00
2017-06-26 00:20:07 +02:00
// let testglob = await Note.glob('title', 'La *', {
// fields: ['title', 'updated_time'],
// });
// console.info(testglob);
2017-06-25 09:35:59 +02:00
for ( let commandIndex = 0 ; commandIndex < commands . length ; commandIndex ++ ) {
let c = commands [ commandIndex ] ;
2017-06-26 00:20:07 +02:00
if ( c . usage == 'root' ) continue ;
2017-06-22 23:52:27 +02:00
let o = vorpal . command ( c . usage , c . description ) ;
2017-06-25 09:35:59 +02:00
if ( c . options ) {
for ( let i = 0 ; i < c . options . length ; i ++ ) {
let options = c . options [ i ] ;
if ( options . length == 2 ) o . option ( options [ 0 ] , options [ 1 ] ) ;
if ( options . length == 3 ) o . option ( options [ 0 ] , options [ 1 ] , options [ 2 ] ) ;
}
}
if ( c . aliases ) {
for ( let i = 0 ; i < c . aliases . length ; i ++ ) {
o . alias ( c . aliases [ i ] ) ;
}
2017-06-22 23:52:27 +02:00
}
if ( c . autocomplete ) {
o . autocomplete ( {
data : c . autocomplete ,
} ) ;
}
o . action ( c . action ) ;
}
2017-06-25 09:35:59 +02:00
vorpal . history ( 'net.cozic.joplin' ) ; // Enables persistent history
2017-06-26 00:20:07 +02:00
await handleStartArgs ( process . argv ) ;
const resourceDir = profileDir + '/resources' ;
Setting . setConstant ( 'profileDir' , profileDir ) ;
Setting . setConstant ( 'resourceDir' , resourceDir ) ;
await fs . mkdirp ( profileDir , 0o755 ) ;
await fs . mkdirp ( resourceDir , 0o755 ) ;
logger . addTarget ( 'file' , { path : profileDir + '/log.txt' } ) ;
logger . setLevel ( Logger . LEVEL _DEBUG ) ;
dbLogger . addTarget ( 'file' , { path : profileDir + '/log-database.txt' } ) ;
dbLogger . setLevel ( Logger . LEVEL _DEBUG ) ;
syncLogger . addTarget ( 'file' , { path : profileDir + '/log-sync.txt' } ) ;
syncLogger . setLevel ( Logger . LEVEL _DEBUG ) ;
logger . info ( sprintf ( 'Starting %s %s...' , packageJson . name , packageJson . version ) ) ;
logger . info ( 'Profile directory: ' + profileDir ) ;
database _ = new Database ( new DatabaseDriverNode ( ) ) ;
database _ . setLogger ( dbLogger ) ;
await database _ . open ( { name : profileDir + '/database.sqlite' } ) ;
BaseModel . db _ = database _ ;
await Setting . load ( ) ;
2017-06-25 12:41:03 +02:00
let activeFolderId = Setting . value ( 'activeFolderId' ) ;
let activeFolder = null ;
if ( activeFolderId ) activeFolder = await Folder . load ( activeFolderId ) ;
if ( ! activeFolder ) activeFolder = await Folder . defaultFolder ( ) ;
2017-06-25 16:40:42 +02:00
if ( activeFolder ) await execCommand ( 'cd' , { 'notebook' : activeFolder . title } ) ; // Use execCommand() so that no history entry is created
2017-06-25 09:35:59 +02:00
2017-06-22 23:52:27 +02:00
vorpal . delimiter ( promptString ( ) ) . show ( ) ;
}
main ( ) . catch ( ( error ) => {
console . error ( 'Fatal error: ' , error ) ;
} ) ;