import * as fs from 'fs' ; import * as path from 'path' ; import * as os from 'os' ; import { isCallsignSSID , isCallsign , isSSID } from './utils' ; import { Keystore } from './Keystore' ; export interface Config { readonly version : number ; callsign : string ; ssid : number ; keystoreFile : string ; kissPort : string ; kissBaud : number ; feedbackDebounce : number ; signingKey ? : string ; } export const defaultChattervoxDir = path . join ( os . homedir ( ) , '.chattervox' ) ; export const defaultConfigPath = path . join ( defaultChattervoxDir , 'config.json' ) ; export const defaultKeystorePath = path . join ( defaultChattervoxDir , 'keystore.json' ) ; export const defaultConfig = { version : 3 , callsign : 'N0CALL' , ssid : 0 , keystoreFile : defaultKeystorePath , kissPort : 'kiss://localhost:8001' , kissBaud : 9600 , feedbackDebounce : 20 * 1000 , } ; function param { Config } config param { string } configPath returns export function save ( config , configPath ? ) { validate ( config ) ; const path = typeof configPath === 'string' ? configPath : defaultConfigPath ; fs . writeFileSync ( path , JSON . stringify ( config , null , 4 ) ) ; } function param { string } configPath returns export function load ( configPath ? ) { const path = typeof configPath === 'string' ? configPath : defaultConfigPath ; const conf = JSON . parse ( fs . readFileSync ( path ) . toString ( 'utf8' ) ) ; if ( migrate ( conf ) ) save ( conf , configPath ) ; validate ( conf ) ; return conf ; } function param { Config } config returns export function migrate ( config ) { let changed = false ; if ( typeof config . feedbackDebounce === 'undefined' ) { config . feedbackDebounce = defaultConfig . feedbackDebounce ; changed = true ; } return changed ; } function param { string } configPath returns export function exists ( configPath ? ) { const path = typeof configPath === 'string' ? configPath : defaultConfigPath ; return fs . existsSync ( path ) ; } function param config throws export function validate ( config ) { if ( typeof config !== 'object' ) { throw TypeError ( 'config is not an object' ) ; } else if ( typeof config . version !== 'number' ) { throw TypeError ( 'version must be a number type' ) ; } else if ( typeof config . callsign !== 'string' ) { throw TypeError ( 'callsign must be a string type' ) ; } else if ( isCallsignSSID ( config . callsign ) ) { throw TypeError ( 'callsign must be a valid callsign excluding an SSID' ) ; } else if ( ! isCallsign ( config . callsign ) ) { throw TypeError ( 'callsign must be a valid callsign' ) ; } else if ( ! isSSID ( config . ssid ) ) { throw TypeError ( 'ssid must be a number between 0 and 15' ) ; } else if ( typeof config . kissPort !== 'string' ) { throw TypeError ( 'kissPort must be a string type' ) ; } else if ( typeof config . kissBaud !== 'number' ) { throw TypeError ( 'kissBaud must be a number type' ) ; } else if ( typeof config . keystoreFile !== 'string' ) { throw TypeError ( 'keystoreFile must be a string type' ) ; } else if ( typeof config . signingKey !== 'undefined' && config . signingKey !== null && typeof config . signingKey !== 'string' ) { throw TypeError ( 'signingKey must be a string or null if it is defined' ) ; } else if ( config . feedbackDebounce !== null && typeof config . feedbackDebounce !== 'number' ) { throw TypeError ( 'feedbackDebounce must be a number or null' ) ; } } function export function init ( ) { if ( ! fs . existsSync ( defaultChattervoxDir ) ) { fs . mkdirSync ( defaultChattervoxDir ) ; } if ( ! exists ( defaultConfigPath ) ) { save ( defaultConfig ) ; } if ( ! exists ( defaultKeystorePath ) ) { new Keystore ( defaultKeystorePath ) ; } }