diff --git a/flightplan/flightplan-tests.ts b/flightplan/flightplan-tests.ts
new file mode 100644
index 000000000..d744be95a
--- /dev/null
+++ b/flightplan/flightplan-tests.ts
@@ -0,0 +1,229 @@
+///
+
+import flightplan = require('flightplan');
+
+// flightplan.target
+// run with `fly staging`
+flightplan.target('staging', {
+ // see: https://github.com/mscdex/ssh2#connection-methods
+ host: 'staging.example.com',
+ username: 'pstadler',
+ agent: 'agent'
+});
+
+// run with `fly production`
+flightplan.target('production', [
+ {
+ host: 'www1.example.com',
+ username: 'pstadler',
+ agent: 'agent'
+ },
+ {
+ host: 'www2.example.com',
+ username: 'pstadler',
+ agent: 'agent'
+ }
+]);
+
+// run with `fly dynamic-hosts`
+flightplan.target('dynamic-hosts', function(done) {
+ done('test');
+});
+
+// with failsafe
+flightplan.target('production', [
+ {
+ host: 'www1.example.com',
+ username: 'pstadler',
+ agent: 'agent'
+ },
+ {
+ host: 'www2.example.com',
+ username: 'pstadler',
+ agent: 'agent',
+ failsafe: true // continue flightplan even if connection to www2 fails
+ }
+]);
+
+// flightplan.local
+flightplan.local(function(local) {
+ local.echo('hello from your localhost.');
+});
+
+// flightplan.remote
+flightplan.remote(function(remote) {
+ remote.echo('hello from the remote host.');
+});
+
+// flightplan.abort
+flightplan.abort('Severe turbulences over the atlantic ocean!');
+
+// transport.exec
+flightplan.local(function(local) {
+ local.echo('Shell.echo() called');
+});
+
+flightplan.remote(function(remote) {
+ remote.echo('SSH.echo() called');
+});
+
+flightplan.remote(function(transport) { // applies to local flights as well
+ // Flightplan specific information
+ console.log(flightplan.runtime.task); // 'default'
+ console.log(flightplan.runtime.target); // 'production'
+ console.log(flightplan.runtime.hosts); // [{ host: 'www1.example.com', port: 22 }, ...]
+ console.log(flightplan.runtime.options.debug); // { debug: true, ... }
+
+ // Flight specific information
+ console.log(transport.runtime); // { host: 'www1.example.com', port: 22 }
+});
+
+
+flightplan.local(function(transport) {
+ // output of `ls -al` is suppressed
+ transport.ls('-al', {silent: true});
+
+ // flightplan continues even if command fails with exit code `1`
+ transport.ls('-al foo', {failsafe: true}); // ls: foo: No such file or directory
+
+ // both options together
+ transport.ls('-al foo', {silent: true, failsafe: true});
+
+ var result = transport.echo('Hello world');
+ console.log(result); // { code: 0, stdout: 'Hello world\n', stderr: null }
+
+ // increase maxBuffer for child_process#exec()
+ transport.ls('-al', {exec: {maxBuffer: 2000*1024}});
+
+ // enable pty for mscdex/ssh2#exec()
+ transport.ls('-al', {exec: {pty: true}});
+});
+
+flightplan.remote(function(transport) {
+ // output of `ls -al` is suppressed
+ transport.ls('-al', {silent: true});
+
+ // flightplan continues even if command fails with exit code `1`
+ transport.ls('-al foo', {failsafe: true}); // ls: foo: No such file or directory
+
+ // both options together
+ transport.ls('-al foo', {silent: true, failsafe: true});
+
+ var result = transport.echo('Hello world');
+ console.log(result); // { code: 0, stdout: 'Hello world\n', stderr: null }
+
+ // increase maxBuffer for child_process#exec()
+ transport.ls('-al', {exec: {maxBuffer: 2000*1024}});
+
+ // enable pty for mscdex/ssh2#exec()
+ transport.ls('-al', {exec: {pty: true}});
+});
+
+// transport.sudo
+flightplan.local(function(transport) {
+ // will run: sudo -u root -i bash -c 'Hello world'
+ transport.sudo('echo Hello world');
+
+ // will run sudo -u www -i bash -c 'Hello world'
+ transport.sudo('echo Hello world', {user: 'www'});
+
+ // further options passed (see `exec()`)
+ transport.sudo('echo Hello world', {user: 'www', silent: true, failsafe: true});
+});
+
+flightplan.remote(function(transport) {
+ // will run: sudo -u root -i bash -c 'Hello world'
+ transport.sudo('echo Hello world');
+
+ // will run sudo -u www -i bash -c 'Hello world'
+ transport.sudo('echo Hello world', {user: 'www'});
+
+ // further options passed (see `exec()`)
+ transport.sudo('echo Hello world', {user: 'www', silent: true, failsafe: true});
+});
+
+// transport.files
+flightplan.local(function(transport) {
+ var files = ['path/to/file1', 'path/to/file2'];
+ transport.transfer(files, '/tmp/foo');
+
+ // use result from a previous command
+ var files2 = transport.git('ls-files', {silent: true}); // get list of files under version control
+ transport.transfer(files2, '/tmp/foo');
+
+ // use zero-terminated result from a previous command
+ var files3 = transport.exec('(git ls-files -z;find node_modules -type f -print0)', {silent: true});
+ transport.transfer(files3, '/tmp/foo');
+
+ // use results from multiple commands
+ var result1 = transport.git('ls-files', {silent: true}).stdout.split('\n');
+ var result2 = transport.find('node_modules -type f', {silent: true}).stdout.split('\n');
+ var files4 = result1.concat(result2);
+ files4.push('path/to/another/file');
+ transport.transfer(files4, '/tmp/foo');
+});
+
+flightplan.remote(function(transport) {
+ var files = ['path/to/file1', 'path/to/file2'];
+ transport.transfer(files, '/tmp/foo');
+
+ // use result from a previous command
+ var files2 = transport.git('ls-files', {silent: true}); // get list of files under version control
+ transport.transfer(files2, '/tmp/foo');
+
+ // use zero-terminated result from a previous command
+ var files3 = transport.exec('(git ls-files -z;find node_modules -type f -print0)', {silent: true});
+ transport.transfer(files3, '/tmp/foo');
+
+ // use results from multiple commands
+ var result1 = transport.git('ls-files', {silent: true}).stdout.split('\n');
+ var result2 = transport.find('node_modules -type f', {silent: true}).stdout.split('\n');
+ var files4 = result1.concat(result2);
+ files4.push('path/to/another/file');
+ transport.transfer(files4, '/tmp/foo');
+});
+
+// transport.prompt
+flightplan.local(function (transport) {
+ var input = transport.prompt('Are you sure you want to continue? [yes]');
+ if(input.indexOf('yes') === -1) {
+ flightplan.abort('User canceled flight');
+ }
+
+ // prompt for password (with UNIX-style hidden input)
+ var password = transport.prompt('Enter your password:', { hidden: true });
+
+ // prompt when deploying to a specific target
+ if(flightplan.runtime.target === 'production') {
+ var input = transport.prompt('Ready for deploying to production? [yes]');
+ if(input.indexOf('yes') === -1) {
+ flightplan.abort('User canceled flight');
+ }
+ }
+});
+
+flightplan.remote(function (transport) {
+ var input = transport.prompt('Are you sure you want to continue? [yes]');
+ if(input.indexOf('yes') === -1) {
+ flightplan.abort('User canceled flight');
+ }
+
+ // prompt for password (with UNIX-style hidden input)
+ var password = transport.prompt('Enter your password:', { hidden: true });
+
+ // prompt when deploying to a specific target
+ if(flightplan.runtime.target === 'production') {
+ var input = transport.prompt('Ready for deploying to production? [yes]');
+ if(input.indexOf('yes') === -1) {
+ flightplan.abort('User canceled flight');
+ }
+ }
+});
+
+// transport.waitFor
+flightplan.local(function (transport) {
+ var result = transport.waitFor(function(done) {
+ done('sent!');
+ });
+ console.log(result); // 'sent!'
+});
diff --git a/flightplan/flightplan.d.ts b/flightplan/flightplan.d.ts
new file mode 100644
index 000000000..6b073d02f
--- /dev/null
+++ b/flightplan/flightplan.d.ts
@@ -0,0 +1,201 @@
+// Type definitions for flightplan v0.6.9
+// Project: https://github.com/pstadler/flightplan
+// Definitions by: Borislav Zhivkov
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
+
+declare var flightplan: FlightplanInterfaces.Flightplan;
+
+declare module FlightplanInterfaces {
+ interface CommandOptions {
+ silent?: boolean;
+ failsafe?: boolean;
+ }
+
+ interface SudoOptions extends CommandOptions {
+ user?: string;
+ }
+
+ interface PromptOptions {
+ hidden?: boolean;
+ required?: boolean;
+ }
+
+ interface CommandResult {
+ code: number;
+ stdout: string;
+ stderr: string;
+ }
+
+ interface Transport {
+ runtime: Host;
+
+ exec(command: string, options?: CommandOptions): CommandResult;
+ exec(command: string, options?: { exec: any }): CommandResult;
+
+ sudo(command: string, options?: SudoOptions): CommandResult;
+ transfer(files: CommandResult, remoteDir: string, options?: CommandOptions): Array;
+ transfer(files: CommandResult[], remoteDir: string, options?: CommandOptions): Array;
+ transfer(files: string[], remoteDir: string, options?: CommandOptions): Array;
+ prompt(message: string, options?: PromptOptions): string;
+ waitFor(fn: (done: (result: any) => void) => void): any;
+
+ with(command: string, fn: () => void): void;
+ with(options: CommandOptions, fn: () => void): void;
+ with(command: string, options: CommandOptions, fn: () => void): void;
+
+ silent(): void;
+ verbose(): void;
+ failsafe(): void;
+ log(message: string): void;
+ debug(message: string): void;
+
+ awk(command: string, options?: CommandOptions): CommandResult;
+ awk(command: string, options?: { exec: any }): CommandResult;
+
+ cat(command: string, options?: CommandOptions): CommandResult;
+ cat(command: string, options?: { exec: any }): CommandResult;
+
+ cd(command: string, options?: CommandOptions): CommandResult;
+ cd(command: string, options?: { exec: any }): CommandResult;
+
+ chgrp(command: string, options?: CommandOptions): CommandResult;
+ chgrp(command: string, options?: { exec: any }): CommandResult;
+
+ chmod(command: string, options?: CommandOptions): CommandResult;
+ chmod(command: string, options?: { exec: any }): CommandResult;
+
+ chown(command: string, options?: CommandOptions): CommandResult;
+ chown(command: string, options?: { exec: any }): CommandResult;
+
+ cp(command: string, options?: CommandOptions): CommandResult;
+ cp(command: string, options?: { exec: any }): CommandResult;
+
+ echo(command: string, options?: CommandOptions): CommandResult;
+ echo(command: string, options?: { exec: any }): CommandResult;
+
+ find(command: string, options?: CommandOptions): CommandResult;
+ find(command: string, options?: { exec: any }): CommandResult;
+
+ ftp(command: string, options?: CommandOptions): CommandResult;
+ ftp(command: string, options?: { exec: any }): CommandResult;
+
+ grep(command: string, options?: CommandOptions): CommandResult;
+ grep(command: string, options?: { exec: any }): CommandResult;
+
+ groups(command: string, options?: CommandOptions): CommandResult;
+ groups(command: string, options?: { exec: any }): CommandResult;
+
+ hostname(command: string, options?: CommandOptions): CommandResult;
+ hostname(command: string, options?: { exec: any }): CommandResult;
+
+ kill(command: string, options?: CommandOptions): CommandResult;
+ kill(command: string, options?: { exec: any }): CommandResult;
+
+ ln(command: string, options?: CommandOptions): CommandResult;
+ ln(command: string, options?: { exec: any }): CommandResult;
+
+ ls(command: string, options?: CommandOptions): CommandResult;
+ ls(command: string, options?: { exec: any }): CommandResult;
+
+ mkdir(command: string, options?: CommandOptions): CommandResult;
+ mkdir(command: string, options?: { exec: any }): CommandResult;
+
+ mv(command: string, options?: CommandOptions): CommandResult;
+ mv(command: string, options?: { exec: any }): CommandResult;
+
+ ps(command: string, options?: CommandOptions): CommandResult;
+ ps(command: string, options?: { exec: any }): CommandResult;
+
+ pwd(command: string, options?: CommandOptions): CommandResult;
+ pwd(command: string, options?: { exec: any }): CommandResult;
+
+ rm(command: string, options?: CommandOptions): CommandResult;
+ rm(command: string, options?: { exec: any }): CommandResult;
+
+ rmdir(command: string, options?: CommandOptions): CommandResult;
+ rmdir(command: string, options?: { exec: any }): CommandResult;
+
+ scp(command: string, options?: CommandOptions): CommandResult;
+ scp(command: string, options?: { exec: any }): CommandResult;
+
+ sed(command: string, options?: CommandOptions): CommandResult;
+ sed(command: string, options?: { exec: any }): CommandResult;
+
+ tail(command: string, options?: CommandOptions): CommandResult;
+ tail(command: string, options?: { exec: any }): CommandResult;
+
+ tar(command: string, options?: CommandOptions): CommandResult;
+ tar(command: string, options?: { exec: any }): CommandResult;
+
+ touch(command: string, options?: CommandOptions): CommandResult;
+ touch(command: string, options?: { exec: any }): CommandResult;
+
+ unzip(command: string, options?: CommandOptions): CommandResult;
+ unzip(command: string, options?: { exec: any }): CommandResult;
+
+ whoami(command: string, options?: CommandOptions): CommandResult;
+ whoami(command: string, options?: { exec: any }): CommandResult;
+
+ zip(command: string, options?: CommandOptions): CommandResult;
+ zip(command: string, options?: { exec: any }): CommandResult;
+
+ git(command: string, options?: CommandOptions): CommandResult;
+ git(command: string, options?: { exec: any }): CommandResult;
+
+ hg(command: string, options?: CommandOptions): CommandResult;
+ hg(command: string, options?: { exec: any }): CommandResult;
+
+ node(command: string, options?: CommandOptions): CommandResult;
+ node(command: string, options?: { exec: any }): CommandResult;
+
+ npm(command: string, options?: CommandOptions): CommandResult;
+ npm(command: string, options?: { exec: any }): CommandResult;
+
+ rsync(command: string, options?: CommandOptions): CommandResult;
+ rsync(command: string, options?: { exec: any }): CommandResult;
+
+ svn(command: string, options?: CommandOptions): CommandResult;
+ svn(command: string, options?: { exec: any }): CommandResult;
+ }
+
+ interface TargetOptions {
+ host: string;
+ username: string;
+ agent: string;
+ failsafe?: boolean;
+ }
+
+ interface Runtime {
+ task: string;
+ target: string;
+ hosts: Host[];
+ options: any;
+ }
+
+ interface Host {
+ host: string;
+ port: number;
+ }
+
+ interface Flightplan {
+ runtime: Runtime;
+
+ local(fn: (transport: Transport) => void): Flightplan;
+ local(task: string, fn: (transport: Transport) => void): Flightplan;
+ local(task: string[], fn: (transport: Transport) => void): Flightplan;
+
+ remote(fn: (transport: Transport) => void): Flightplan;
+ remote(task: string, fn: (transport: Transport) => void): Flightplan;
+ remote(task: string[], fn: (transport: Transport) => void): Flightplan;
+
+ target(name: string, options: TargetOptions): Flightplan;
+ target(name: string, options: TargetOptions[]): Flightplan;
+ target(name: string, fn: (done: (result: any) => void) => void): Flightplan;
+
+ abort(message?: string): void;
+ }
+}
+
+declare module "flightplan" {
+ export = flightplan;
+}