User storage and settings, more cli

This commit is contained in:
Nick Farina
2015-07-11 09:12:01 -07:00
parent c8d729c732
commit 6afff4f3e4
4 changed files with 136 additions and 27 deletions

View File

@@ -1,6 +1,7 @@
import Server from './server';
import program from 'commander';
import { HOMEBRIDGE_VERSION } from '../homebridge';
import { Server } from './server';
import { Provider } from './provider';
export default function() {
@@ -11,14 +12,59 @@ export default function() {
// Run the HomeBridge server
program
.command('server')
.description('Run the HomeBridge server')
.action((options) => new Server(options).run());
.description('Run the HomeBridge server.')
.action(runServer);
program
.command('providers')
.description('List installed providers.')
.action(listInstalledProviders);
program
.command('setup [provider]')
.description('Sets up a new HomeBridge provider or re-configures an existing one.')
.action(setupProvider);
// Parse options and execute HomeBridge
program.parse(process.argv);
// Display help by default if no commands or options given
if (!process.argv.slice(2).length) {
program.outputHelp();
program.help();
}
}
function runServer(options) {
// get all installed providers
let providers:Array<Provider> = Provider.installed();
// load and validate providers - check for valid package.json, etc.
try {
this.providerModules = providers.map((provider) => provider.load());
}
catch (err) {
console.log(err.message);
process.exit(1);
}
}
function listInstalledProviders(options) {
Provider.installed().forEach((provider) => console.log(provider.name));
}
function setupProvider(providerName, options) {
// if you didn't specify a provider, print help
if (!providerName) {
console.log("You must specify the name of the provider to setup. Type 'homebridge providers' to list the providers currently installed.");
program.help();
}
try {
let provider = new Provider(providerName);
}
catch (err) {
}
}

View File

@@ -1,6 +1,7 @@
import path from 'path';
import fs from 'fs';
import semver from 'semver';
import { User } from './user';
import { HOMEBRIDGE_VERSION } from '../homebridge';
// This class represents a HomeBridge Provider that may or may not be installed.
@@ -11,11 +12,16 @@ export class Provider {
}
get path():string {
return path.join(Provider.installedProvidersDir, this.name);
return path.join(User.providersPath, this.name);
}
load():object {
// does this provider exist at all?
if (!fs.existsSync(this.path)) {
throw new Error(`Provider ${this.name} was not found. Make sure a directory matching the name '${this.name}' exists in your ~/.homebridge/providers folder.`)
}
// check for a package.json
let pjsonPath:string = path.join(this.path, "package.json");
let pjson:object = null;
@@ -52,6 +58,21 @@ export class Provider {
// try to require() it
let loadedProvider:object = require(mainPath);
// pull out the configuration data, if any
let providerConfig = loadedProvider.config;
// verify that all required values are present
if (providerConfig) {
for (let key:string in providerConfig) {
let configParams:object = providerConfig[key];
if (configParams.required && !User.config.get(`${this.name}-${key}`)) {
throw new Error(`Provider ${this.name} requires the config value ${key} to be set.`);
}
}
}
return loadedProvider;
}
@@ -59,12 +80,12 @@ export class Provider {
static installed():Array<Provider> {
let providers:Array<Provider> = [];
let names:Array<string> = fs.readdirSync(Provider.installedProvidersDir);
let names:Array<string> = fs.readdirSync(User.providersPath);
for (let name:string of names) {
// reconstruct full path
let fullPath:string = path.join(Provider.installedProvidersDir, name);
let fullPath:string = path.join(User.providersPath, name);
// we only care about directories
if (!fs.statSync(fullPath).isDirectory()) continue;
@@ -74,16 +95,4 @@ export class Provider {
return providers;
}
//
// Private utility functions
//
static get userDir():string {
return process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
}
static get installedProvidersDir():string {
return path.join(Provider.userDir, ".homebridge/providers");
}
}

View File

@@ -1,14 +1,12 @@
import { Provider } from './provider';
import { User, Config } from './user';
export default class Server {
export class Server {
constructor(providers:object) {
this.providers = providers; // providers[name] = loaded provider JS module
}
run() {
// get all installed providers
let providers:Array<Provider> = Provider.installed();
// validate providers - check for valid package.json, etc.
providers.forEach((provider) => provider.load());
console.log(`Loaded ${providers.length} providers.`);
}
}

56
lib/homebridge/user.js Normal file
View File

@@ -0,0 +1,56 @@
import path from 'path';
import fs from 'fs';
//
// Manages user settings and storage locations.
//
// global cached config
let config:Config;
export class User {
static get config():Config {
return config || (config = new Config());
}
static get storagePath():string {
let home = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
return path.join(home, ".homebridge");
}
static get configPath():string {
return path.join(User.storagePath, "config.json");
}
static get providersPath():string {
return path.join(User.storagePath, "providers");
}
}
export class Config {
constructor(data:object = {}) {
this.data = data;
}
get(key:string) {
return this.data[key];
}
set(key:string, value:object) {
this.data[key] = value;
}
static load():Config {
// load up the previous config if found
if (fs.existsSync(User.configPath))
return new Config(JSON.parse(fs.readFileSync(User.configPath)));
else
return new Config(); // empty initial config
}
save() {
fs.writeFileSync(User.configPath, JSON.stringify(this.data));
}
}