login, logout

This commit is contained in:
Joao Moreno 2015-09-18 19:35:25 +02:00
parent d09d6178ff
commit 854e73e592
7 changed files with 127 additions and 15 deletions

View file

@ -15,7 +15,9 @@
"glob": "^5.0.14",
"lodash": "^3.10.1",
"minimist": "^1.2.0",
"osenv": "^0.1.3",
"q": "^1.4.1",
"read": "^1.0.7",
"tmp": "0.0.27",
"vso-node-api": "^0.4.2",
"yazl": "^2.2.2"

66
src/login.ts Normal file
View file

@ -0,0 +1,66 @@
import * as fs from 'fs';
import * as path from 'path';
import { Promise, nfcall, resolve, reject } from 'q';
import { home } from 'osenv';
import read = require('read');
const credentialsPath = path.join(home(), '.vsce');
interface ICredentials {
account: string;
publisher: string;
pat: string;
}
function readCredentials(): Promise<ICredentials> {
return nfcall<string>(fs.readFile, credentialsPath, 'utf8')
.catch<string>(err => err.code !== 'ENOENT' ? reject(err) : resolve('null'))
.then<ICredentials>(credentialsStr => {
try {
return resolve(JSON.parse(credentialsStr));
} catch (e) {
return reject(`Error parsing credentials: ${ credentialsPath }`);
}
});
}
function writeCredentials(credentials: ICredentials): Promise<ICredentials> {
return nfcall<void>(fs.writeFile, credentialsPath, JSON.stringify(credentials))
.then(() => credentials);
}
function clearCredentials(): Promise<void> {
return nfcall<void>(fs.unlink, credentialsPath);
}
function promptForCredentials(): Promise<ICredentials> {
return nfcall<string>(read, { prompt: 'Account name:' }).spread(account => {
return nfcall<string>(read, { prompt: 'Publisher:' }).spread(publisher => {
return nfcall<string>(read, { prompt: 'Personal Access Token:', silent: true, replace: '*' })
.spread(pat => ({ account, publisher, pat }));
});
});
}
export function getCredentials(): Promise<ICredentials> {
return login(false);
}
export function login(relogin = true): Promise<ICredentials> {
return readCredentials()
.then(credentials => {
if (!credentials || !relogin) {
return resolve(credentials);
}
console.log(`Existing credentials found: { account: ${ credentials.account }, publisher: ${ credentials.publisher } }`);
return nfcall<string>(read, { prompt: 'Do you want to overwrite existing credentials? [y/N] ' })
.spread<ICredentials>(answer => /^y$/i.test(answer) ? promptForCredentials() : credentials);
})
.then(credentials => credentials || promptForCredentials())
.then(writeCredentials);
}
export function logout(): Promise<any> {
return clearCredentials();
}

View file

@ -2,6 +2,7 @@ import * as minimist from 'minimist';
import { pack } from './package';
import { publish } from './publish';
import { fatal } from './util';
import { login, logout } from './login';
const packagejson = require('../package.json');
interface ICommand {
@ -13,6 +14,8 @@ function helpCommand(args: minimist.ParsedArgs): boolean {
Commands:
package [vsix path] Packages the extension into a .vsix package
login Logs in to the extension service
logout Logs out of the extension service
publish [pat] Publishes the extension
Global options:
@ -26,16 +29,23 @@ VSCode Extension Manager v${ packagejson.version }`
}
function command(args: minimist.ParsedArgs): boolean {
switch (args._[0]) {
case 'package':
pack(args._[1]).then(({ packagePath }) => console.log(`Package created: ${ packagePath }`), fatal);
return true;
case 'publish':
publish(args._[1]).catch(fatal);
return true;
default:
return false;
const promise = (() => {
switch (args._[0]) {
case 'package': return pack(args._[1]);
case 'login': return login();
case 'logout': return logout();
case 'publish': return publish(args._[1]);
}
return null;
})();
if (promise) {
promise.catch(fatal);
return true;
}
return false;
}
module.exports = function (argv: string[]): void {

View file

@ -101,9 +101,9 @@ export function pack(packagePath?: string, cwd = process.cwd()): Promise<IPackag
return readManifest(cwd)
.then(validateManifest)
.then(manifest => {
return writeVsix(cwd, manifest, packagePath).then(packagePath => ({
manifest,
packagePath
}));
return writeVsix(cwd, manifest, packagePath).then(packagePath => {
console.log(`Package created: ${ packagePath }`);
return { manifest, packagePath };
});
});
};
}

View file

@ -1,4 +1,10 @@
export function fatal(message: string, ...args: any[]) {
import { Promise } from 'q';
export function fatal(message: any, ...args: any[]) {
if (message instanceof Error && /^cancell?ed$/i.test(message.message)) {
return;
}
console.error('Error:', message, ...args);
process.exit(1);
}

3
typings/osenv/osenv.d.ts vendored Normal file
View file

@ -0,0 +1,3 @@
declare module "osenv" {
export function home(): string;
}

25
typings/read/read.d.ts vendored Normal file
View file

@ -0,0 +1,25 @@
declare module "read" {
import { Readable, Writable } from 'stream';
function read(options: read.Options, callback: read.Callback): void;
module read {
interface Options {
prompt?: string;
silent?: boolean;
replace?: string;
timeout?: number;
default?: string;
edit?: boolean;
terminal?: boolean;
input?: Readable;
output?: Writable;
}
interface Callback {
(error: Error, result: string, isDefault: boolean): void;
}
}
export = read;
}