2022-11-01 17:28:14 +02:00
const BaseCommand = require ( './base-command' ) . default ;
2020-11-07 17:59:37 +02:00
const { _ , setLocale } = require ( '@joplin/lib/locale' ) ;
2017-11-03 02:09:34 +02:00
const { app } = require ( './app.js' ) ;
2019-12-28 23:48:34 +02:00
const fs = require ( 'fs-extra' ) ;
2020-11-07 17:59:37 +02:00
const Setting = require ( '@joplin/lib/models/Setting' ) . default ;
2017-07-10 22:03:46 +02:00
class Command extends BaseCommand {
usage ( ) {
2017-07-28 20:13:07 +02:00
return 'config [name] [value]' ;
2017-07-10 22:03:46 +02:00
}
description ( ) {
2019-07-30 09:35:42 +02:00
return _ ( 'Gets or sets a config value. If [value] is not provided, it will show the value of [name]. If neither [name] nor [value] is provided, it will list the current configuration.' ) ;
2017-07-10 22:03:46 +02:00
}
2017-07-24 21:47:01 +02:00
options ( ) {
2020-01-25 00:28:54 +02:00
return [
[ '-v, --verbose' , _ ( 'Also displays unset and hidden config variables.' ) ] ,
[ '--export' , 'Writes all settings to STDOUT as JSON including secure variables.' ] ,
[ '--import' , 'Reads in JSON formatted settings from STDIN.' ] ,
[ '--import-file <file>' , 'Reads in settings from <file>. <file> must contain valid JSON.' ] ,
] ;
2017-07-24 21:47:01 +02:00
}
2019-12-28 23:48:34 +02:00
async _ _importSettings ( inputStream ) {
return new Promise ( ( resolve , reject ) => {
// being defensive and not attempting to settle twice
let isSettled = false ;
const chunks = [ ] ;
2017-07-24 21:47:01 +02:00
2019-12-28 23:48:34 +02:00
inputStream . on ( 'readable' , ( ) => {
let chunk ;
while ( ( chunk = inputStream . read ( ) ) !== null ) {
chunks . push ( chunk ) ;
}
} ) ;
inputStream . on ( 'end' , ( ) => {
2020-03-14 01:46:14 +02:00
const json = chunks . join ( '' ) ;
2019-12-28 23:48:34 +02:00
let settingsObj ;
try {
settingsObj = JSON . parse ( json ) ;
2023-02-16 12:55:24 +02:00
} catch ( error ) {
2019-12-28 23:48:34 +02:00
isSettled = true ;
2023-02-16 12:55:24 +02:00
return reject ( new Error ( ` Invalid JSON passed to config --import: \n ${ error . message } . ` ) ) ;
2019-12-28 23:48:34 +02:00
}
if ( settingsObj ) {
Object . entries ( settingsObj )
. forEach ( ( [ key , value ] ) => {
Setting . setValue ( key , value ) ;
} ) ;
}
if ( ! isSettled ) {
isSettled = true ;
resolve ( ) ;
}
} ) ;
inputStream . on ( 'error' , ( error ) => {
if ( ! isSettled ) {
isSettled = true ;
reject ( error ) ;
}
} ) ;
} ) ;
}
2017-07-10 22:03:46 +02:00
async action ( args ) {
2017-08-22 19:57:35 +02:00
const verbose = args . options . verbose ;
2019-12-28 23:48:34 +02:00
const isExport = args . options . export ;
const isImport = args . options . import || args . options . importFile ;
const importFile = args . options . importFile ;
2017-07-24 20:58:11 +02:00
2020-05-21 10:14:33 +02:00
const renderKeyValue = name => {
2018-01-28 19:35:20 +02:00
const md = Setting . settingMetadata ( name ) ;
2018-01-09 22:25:31 +02:00
let value = Setting . value ( name ) ;
if ( typeof value === 'object' || Array . isArray ( value ) ) value = JSON . stringify ( value ) ;
2018-11-02 21:22:49 +02:00
if ( md . secure && value ) value = '********' ;
2018-01-28 19:35:20 +02:00
2017-07-24 20:58:11 +02:00
if ( Setting . isEnum ( name ) ) {
2017-08-22 19:57:35 +02:00
return _ ( '%s = %s (%s)' , name , value , Setting . enumOptionsDoc ( name ) ) ;
2017-07-24 20:58:11 +02:00
} else {
return _ ( '%s = %s' , name , value ) ;
}
2019-07-30 09:35:42 +02:00
} ;
2017-07-24 20:58:11 +02:00
2019-12-28 23:48:34 +02:00
if ( isExport || ( ! isImport && ! args . value ) ) {
2020-03-14 01:46:14 +02:00
const keys = Setting . keys ( ! verbose , 'cli' ) ;
2017-11-12 02:44:26 +02:00
keys . sort ( ) ;
2019-12-28 23:48:34 +02:00
if ( isExport ) {
const resultObj = keys . reduce ( ( acc , key ) => {
const value = Setting . value ( key ) ;
if ( ! verbose && ! value ) return acc ;
acc [ key ] = value ;
return acc ;
} , { } ) ;
// Printing the object in "pretty" format so it's easy to read/edit
this . stdout ( JSON . stringify ( resultObj , null , 2 ) ) ;
} else if ( ! args . name ) {
for ( let i = 0 ; i < keys . length ; i ++ ) {
const value = Setting . value ( keys [ i ] ) ;
if ( ! verbose && ! value ) continue ;
this . stdout ( renderKeyValue ( keys [ i ] ) ) ;
}
} else {
this . stdout ( renderKeyValue ( args . name ) ) ;
2017-07-10 22:03:46 +02:00
}
2019-12-28 23:48:34 +02:00
2020-01-25 00:28:54 +02:00
app ( ) . gui ( ) . showConsole ( ) ;
app ( ) . gui ( ) . maximizeConsole ( ) ;
2019-12-28 23:48:34 +02:00
2017-07-10 22:03:46 +02:00
return ;
}
2019-12-28 23:48:34 +02:00
if ( isImport ) {
let fileStream = process . stdin ;
if ( importFile ) {
fileStream = fs . createReadStream ( importFile , { autoClose : true } ) ;
}
await this . _ _importSettings ( fileStream ) ;
} else {
Setting . setValue ( args . name , args . value ) ;
2017-07-10 22:03:46 +02:00
}
2017-07-18 20:49:47 +02:00
2022-07-23 09:31:32 +02:00
if ( args . name === 'locale' ) {
2017-07-18 20:49:47 +02:00
setLocale ( Setting . value ( 'locale' ) ) ;
}
2017-07-10 22:03:46 +02:00
await Setting . saveAll ( ) ;
}
}
2019-07-30 09:35:42 +02:00
module . exports = Command ;