From 0d1658579d709587256991412065bd61ae73d11b Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Wed, 2 Mar 2016 17:16:39 -0800 Subject: [PATCH 01/11] Throw an error if the SDK is constructed without an access key --- sdk/script/account-manager.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdk/script/account-manager.ts b/sdk/script/account-manager.ts index 602fb8af..33e9fc61 100644 --- a/sdk/script/account-manager.ts +++ b/sdk/script/account-manager.ts @@ -68,6 +68,8 @@ export class AccountManager { private _userAgent: string; constructor(accessKey: string, userAgent?: string, serverUrl?: string) { + if (!accessKey) throw new Error("An access key must be specified."); + this._accessKey = accessKey; this._userAgent = userAgent; this._serverUrl = serverUrl || AccountManager.SERVER_URL; From f3163fd6c14924184408708d94351ccb677ab034 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Wed, 2 Mar 2016 17:17:29 -0800 Subject: [PATCH 02/11] Add a 'customHeaders' property to the SDK so that X-CodePush-CLI-Version can be set --- cli/script/command-executor.ts | 12 +++++++----- sdk/script/account-manager.ts | 21 +++++++++++++-------- sdk/test/management-sdk.ts | 2 +- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/cli/script/command-executor.ts b/cli/script/command-executor.ts index 9fca9d45..63faa8e3 100644 --- a/cli/script/command-executor.ts +++ b/cli/script/command-executor.ts @@ -23,16 +23,18 @@ import wordwrap = require("wordwrap"); import * as cli from "../definitions/cli"; import { AcquisitionStatus } from "code-push/script/acquisition-sdk"; -import { AccessKey, Account, AccountManager, App, CollaboratorMap, CollaboratorProperties, Deployment, DeploymentMetrics, Package, Permissions, UpdateMetrics } from "code-push"; +import { AccessKey, Account, AccountManager, App, CollaboratorMap, CollaboratorProperties, Deployment, DeploymentMetrics, Headers, Package, Permissions, UpdateMetrics } from "code-push"; var configFilePath: string = path.join(process.env.LOCALAPPDATA || process.env.HOME, ".code-push.config"); var emailValidator = require("email-validator"); var packageJson = require("../package.json"); var progress = require("progress"); import Promise = Q.Promise; -var userAgent: string = packageJson.name + "/" + packageJson.version; const ACTIVE_METRICS_KEY: string = "Active"; +const CLI_HEADERS: Headers = { + "X-CodePush-CLI-Version": packageJson.version +}; const DOWNLOADED_METRICS_KEY: string = "Downloaded"; interface NameToCountMap { @@ -393,7 +395,7 @@ export function execute(command: cli.ICommand): Promise { throw new Error("You are not currently logged in. Run the 'code-push login' command to authenticate with the CodePush server."); } - sdk = new AccountManager(connectionInfo.accessKey, userAgent, connectionInfo.customServerUrl); + sdk = new AccountManager(connectionInfo.accessKey, CLI_HEADERS, connectionInfo.customServerUrl); break; } @@ -515,7 +517,7 @@ function initiateExternalAuthenticationAsync(action: string, serverUrl?: string) function login(command: cli.ILoginCommand): Promise { // Check if one of the flags were provided. if (command.accessKey) { - sdk = new AccountManager(command.accessKey, userAgent, command.serverUrl); + sdk = new AccountManager(command.accessKey, CLI_HEADERS, command.serverUrl); return sdk.isAuthenticated() .then((isAuthenticated: boolean): void => { if (isAuthenticated) { @@ -539,7 +541,7 @@ function loginWithExternalAuthentication(action: string, serverUrl?: string): Pr return; } - sdk = new AccountManager(accessKey, userAgent, serverUrl); + sdk = new AccountManager(accessKey, CLI_HEADERS, serverUrl); return sdk.isAuthenticated() .then((isAuthenticated: boolean): void => { diff --git a/sdk/script/account-manager.ts b/sdk/script/account-manager.ts index 33e9fc61..9f2ced94 100644 --- a/sdk/script/account-manager.ts +++ b/sdk/script/account-manager.ts @@ -40,8 +40,10 @@ interface PackageToUpload { isMandatory: boolean; } +export type Headers = { [headerName: string]: string }; + interface JsonResponse { - header: { [headerName: string]: string }; + headers: Headers; body?: any; } @@ -65,13 +67,13 @@ export class AccountManager { private _accessKey: string; private _serverUrl: string; - private _userAgent: string; + private _customHeaders: Headers; - constructor(accessKey: string, userAgent?: string, serverUrl?: string) { + constructor(accessKey: string, customHeaders?: Headers, serverUrl?: string) { if (!accessKey) throw new Error("An access key must be specified."); this._accessKey = accessKey; - this._userAgent = userAgent; + this._customHeaders = customHeaders; this._serverUrl = serverUrl || AccountManager.SERVER_URL; } @@ -315,7 +317,7 @@ export class AccountManager { reject({ message: `Could not parse response: ${res.text}`, statusCode: res.status }); } else { resolve({ - header: res.header, + headers: res.header, body: body }); } @@ -343,11 +345,14 @@ export class AccountManager { } private attachCredentials(request: superagent.Request): void { + if (this._customHeaders) { + for (var headerName in this._customHeaders) { + request.set(headerName, this._customHeaders[headerName]); + } + } + request.set("Accept", `application/vnd.code-push.v${AccountManager.API_VERSION}+json`); request.set("Authorization", `Bearer ${this._accessKey}`); - if (this._userAgent) { - request.set("User-Agent", this._userAgent); - } request.set("X-CodePush-SDK-Version", packageJson.version); } } diff --git a/sdk/test/management-sdk.ts b/sdk/test/management-sdk.ts index fb2ee8fd..1b967a87 100644 --- a/sdk/test/management-sdk.ts +++ b/sdk/test/management-sdk.ts @@ -11,7 +11,7 @@ var manager: AccountManager; describe("Management SDK", () => { beforeEach(() => { - manager = new AccountManager(/*accessKey=*/ "dummyAccessKey", /*userAgent=*/ "unit-test/1.0.0", /*serverUrl=*/ "http://localhost"); + manager = new AccountManager(/*accessKey=*/ "dummyAccessKey", /*customHeaders=*/ null, /*serverUrl=*/ "http://localhost"); }); after(() => { From ea5fac26ef5e6e8ac4480c0cfba2bfb23316ec1f Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Thu, 3 Mar 2016 16:02:55 -0800 Subject: [PATCH 03/11] Rename SDK methods to make verbiage consistent --- cli/script/command-executor.ts | 22 +++++++++++----------- cli/test/cli.ts | 12 ++++++------ sdk/script/account-manager.ts | 28 ++++++++++++++-------------- sdk/test/management-sdk.ts | 16 ++++++++-------- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/cli/script/command-executor.ts b/cli/script/command-executor.ts index 63faa8e3..5f2279ad 100644 --- a/cli/script/command-executor.ts +++ b/cli/script/command-executor.ts @@ -225,7 +225,7 @@ function addCollaborator(command: cli.ICollaboratorAddCommand): Promise { function listCollaborators(command: cli.ICollaboratorListCommand): Promise { throwForInvalidOutputFormat(command.format); - return sdk.getCollaboratorsList(command.appName) + return sdk.getCollaborators(command.appName) .then((retrievedCollaborators: CollaboratorMap): void => { printCollaboratorsList(command.format, retrievedCollaborators); }); @@ -337,12 +337,12 @@ function deploymentHistory(command: cli.IDeploymentHistoryCommand): Promise([ sdk.getAccountInfo(), - sdk.getPackageHistory(command.appName, command.deploymentName), + sdk.getDeploymentHistory(command.appName, command.deploymentName), sdk.getDeploymentMetrics(command.appName, command.deploymentName) ]) - .spread((account: Account, packageHistory: Package[], metrics: DeploymentMetrics): void => { + .spread((account: Account, deploymentHistory: Package[], metrics: DeploymentMetrics): void => { var totalActive: number = getTotalActiveFromDeploymentMetrics(metrics); - packageHistory.forEach((packageObject: Package) => { + deploymentHistory.forEach((packageObject: Package) => { if (metrics[packageObject.label]) { (packageObject).metrics = { active: metrics[packageObject.label].active, @@ -353,7 +353,7 @@ function deploymentHistory(command: cli.IDeploymentHistoryCommand): PromisepackageHistory, account.email); + printDeploymentHistory(command, deploymentHistory, account.email); }); } @@ -653,9 +653,9 @@ function printDeploymentList(command: cli.IDeploymentListCommand, deployments: D } } -function printDeploymentHistory(command: cli.IDeploymentHistoryCommand, packageHistory: PackageWithMetrics[], currentUserEmail: string): void { +function printDeploymentHistory(command: cli.IDeploymentHistoryCommand, deploymentHistory: PackageWithMetrics[], currentUserEmail: string): void { if (command.format === "json") { - printJson(packageHistory); + printJson(deploymentHistory); } else if (command.format === "table") { var headers = ["Label", "Release Time", "App Version", "Mandatory"]; if (command.displayAuthor) { @@ -665,7 +665,7 @@ function printDeploymentHistory(command: cli.IDeploymentHistoryCommand, packageH headers.push("Description", "Install Metrics"); printTable(headers, (dataSource: any[]) => { - packageHistory.forEach((packageObject: Package) => { + deploymentHistory.forEach((packageObject: Package) => { var releaseTime: string = formatDate(packageObject.uploadTime); var releaseSource: string; if (packageObject.releaseMethod === "Promote") { @@ -834,7 +834,7 @@ function register(command: cli.IRegisterCommand): Promise { } function promote(command: cli.IPromoteCommand): Promise { - return sdk.promotePackage(command.appName, command.sourceDeploymentName, command.destDeploymentName) + return sdk.promote(command.appName, command.sourceDeploymentName, command.destDeploymentName) .then((): void => { log("Successfully promoted the \"" + command.sourceDeploymentName + "\" deployment of the \"" + command.appName + "\" app to the \"" + command.destDeploymentName + "\" deployment."); }); @@ -909,7 +909,7 @@ export var release = (command: cli.IReleaseCommand): Promise => { return getPackageFilePromise .then((file: IPackageFile): Promise => { - return sdk.releasePackage(command.appName, command.deploymentName, file.path, command.description, command.appStoreVersion, command.mandatory, uploadProgress) + return sdk.release(command.appName, command.deploymentName, file.path, command.description, command.appStoreVersion, command.mandatory, uploadProgress) .then((): void => { log("Successfully released an update containing the \"" + command.package + "\" " + (isSingleFilePackage ? "file" : "directory") + " to the \"" + command.deploymentName + "\" deployment of the \"" + command.appName + "\" app."); @@ -997,7 +997,7 @@ function rollback(command: cli.IRollbackCommand): Promise { return; } - return sdk.rollbackPackage(command.appName, command.deploymentName, command.targetRelease || undefined) + return sdk.rollback(command.appName, command.deploymentName, command.targetRelease || undefined) .then((): void => { log("Successfully performed a rollback on the \"" + command.deploymentName + "\" deployment of the \"" + command.appName + "\" app."); }); diff --git a/cli/test/cli.ts b/cli/test/cli.ts index 2311deed..e687c798 100644 --- a/cli/test/cli.ts +++ b/cli/test/cli.ts @@ -91,7 +91,7 @@ export class SdkStub { }]); } - public getPackageHistory(appId: string, deploymentId: string): Promise { + public getDeploymentHistory(appId: string, deploymentId: string): Promise { return Q([ { description: null, @@ -136,7 +136,7 @@ export class SdkStub { }); } - public getCollaboratorsList(app: codePush.App): Promise { + public getCollaborators(app: codePush.App): Promise { return Q({ "a@a.com": { permission: "Owner", @@ -633,11 +633,11 @@ describe("CLI", () => { displayAuthor: false }; - var getPackageHistory: Sinon.SinonSpy = sandbox.spy(cmdexec.sdk, "getPackageHistory"); + var getDeploymentHistory: Sinon.SinonSpy = sandbox.spy(cmdexec.sdk, "getDeploymentHistory"); cmdexec.execute(command) .done((): void => { - sinon.assert.calledOnce(getPackageHistory); + sinon.assert.calledOnce(getDeploymentHistory); sinon.assert.calledOnce(log); assert.equal(log.args[0].length, 1); @@ -881,7 +881,7 @@ describe("CLI", () => { }) .done(); }); - + it("release-react defaults bundle name to \"index.android.bundle\" if not provided and platform is \"android\"", (done: MochaDone): void => { var command: cli.IReleaseReactCommand = { type: cli.CommandType.releaseReact, @@ -915,7 +915,7 @@ describe("CLI", () => { }) .done(); }); - + it("release-react generates sourcemaps", (done: MochaDone): void => { var bundleName = "bundle.js"; var command: cli.IReleaseReactCommand = { diff --git a/sdk/script/account-manager.ts b/sdk/script/account-manager.ts index 9f2ced94..e40ace5b 100644 --- a/sdk/script/account-manager.ts +++ b/sdk/script/account-manager.ts @@ -165,7 +165,7 @@ export class AccountManager { } // Collaborators - public getCollaboratorsList(appName: string): Promise { + public getCollaborators(appName: string): Promise { return this.get(urlEncode `/apps/${appName}/collaborators`) .then((res: JsonResponse) => res.body.collaborators); } @@ -197,11 +197,6 @@ export class AccountManager { .then((res: JsonResponse) => res.body.deployment); } - public getDeploymentMetrics(appName: string, deploymentName: string): Promise { - return this.get(urlEncode `/apps/${appName}/deployments/${deploymentName}/metrics`) - .then((res: JsonResponse) => res.body.metrics); - } - public updateDeployment(appName: string, deploymentName: string, infoToChange: Deployment): Promise { return this.patch(urlEncode `/apps/${appName}/deployments/${deploymentName}`, JSON.stringify(infoToChange)) .then(() => null); @@ -212,7 +207,17 @@ export class AccountManager { .then(() => null); } - public releasePackage(appName: string, deploymentName: string, fileOrPath: File | string, description: string, appVersion: string, isMandatory: boolean = false, uploadProgressCallback?: (progress: number) => void): Promise { + public getDeploymentMetrics(appName: string, deploymentName: string): Promise { + return this.get(urlEncode `/apps/${appName}/deployments/${deploymentName}/metrics`) + .then((res: JsonResponse) => res.body.metrics); + } + + public getDeploymentHistory(appName: string, deploymentName: string): Promise { + return this.get(urlEncode `/apps/${appName}/deployments/${deploymentName}/history`) + .then((res: JsonResponse) => res.body.history); + } + + public release(appName: string, deploymentName: string, fileOrPath: File | string, description: string, appVersion: string, isMandatory: boolean = false, uploadProgressCallback?: (progress: number) => void): Promise { return Promise((resolve, reject, notify) => { var packageInfo: PackageToUpload = this.generatePackageInfo(description, appVersion, isMandatory); var request: superagent.Request = superagent.post(this._serverUrl + urlEncode `/apps/${appName}/deployments/${deploymentName}/release`); @@ -257,21 +262,16 @@ export class AccountManager { }); } - public promotePackage(appName: string, sourceDeploymentName: string, destDeploymentName: string): Promise { + public promote(appName: string, sourceDeploymentName: string, destDeploymentName: string): Promise { return this.post(urlEncode `/apps/${appName}/deployments/${sourceDeploymentName}/promote/${destDeploymentName}`, /*requestBody=*/ null, /*expectResponseBody=*/ false) .then(() => null); } - public rollbackPackage(appName: string, deploymentName: string, targetRelease?: string): Promise { + public rollback(appName: string, deploymentName: string, targetRelease?: string): Promise { return this.post(urlEncode `/apps/${appName}/deployments/${deploymentName}/rollback/${targetRelease || ``}`, /*requestBody=*/ null, /*expectResponseBody=*/ false) .then(() => null); } - public getPackageHistory(appName: string, deploymentName: string): Promise { - return this.get(urlEncode `/apps/${appName}/deployments/${deploymentName}/packageHistory`) - .then((res: JsonResponse) => res.body.packageHistory); - } - private get(endpoint: string, expectResponseBody: boolean = true): Promise { return this.makeApiRequest("get", endpoint, /*requestBody=*/ null, expectResponseBody, /*contentType=*/ null); } diff --git a/sdk/test/management-sdk.ts b/sdk/test/management-sdk.ts index 1b967a87..89efb04e 100644 --- a/sdk/test/management-sdk.ts +++ b/sdk/test/management-sdk.ts @@ -174,20 +174,20 @@ describe("Management SDK", () => { }, rejectHandler); }); - it("getPackageHistory handles success response with no packages", (done: MochaDone) => { - mockReturn(JSON.stringify({ packageHistory: [] }), 200); + it("getDeploymentHistory handles success response with no packages", (done: MochaDone) => { + mockReturn(JSON.stringify({ history: [] }), 200); - manager.getPackageHistory("appName", "deploymentName").done((obj: any) => { + manager.getDeploymentHistory("appName", "deploymentName").done((obj: any) => { assert.ok(obj); assert.equal(obj.length, 0); done(); }, rejectHandler); }); - it("getPackageHistory handles success response with two packages", (done: MochaDone) => { - mockReturn(JSON.stringify({ packageHistory: [ { label: "v1" }, { label: "v2" } ] }), 200); + it("getDeploymentHistory handles success response with two packages", (done: MochaDone) => { + mockReturn(JSON.stringify({ history: [ { label: "v1" }, { label: "v2" } ] }), 200); - manager.getPackageHistory("appName", "deploymentName").done((obj: any) => { + manager.getDeploymentHistory("appName", "deploymentName").done((obj: any) => { assert.ok(obj); assert.equal(obj.length, 2); assert.equal(obj[0].label, "v1"); @@ -196,10 +196,10 @@ describe("Management SDK", () => { }, rejectHandler); }); - it("getPackageHistory handles error response", (done: MochaDone) => { + it("getDeploymentHistory handles error response", (done: MochaDone) => { mockReturn("", 404); - manager.getPackageHistory("appName", "deploymentName").done((obj: any) => { + manager.getDeploymentHistory("appName", "deploymentName").done((obj: any) => { throw new Error("Call should not complete successfully"); }, (error: Error) => done()); }); From 243f7b394256e7ff98a82a5b89b69fb7245f28a7 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Thu, 3 Mar 2016 16:41:41 -0800 Subject: [PATCH 04/11] Remove defunct files and rename 'account-manager.ts' to 'management-sdk.ts' for consistency --- sdk/script/index.ts | 2 +- .../{account-manager.ts => management-sdk.ts} | 0 sdk/script/samples/acquisition-native-stub.ts | 27 ---------- sdk/script/samples/typescript-acquisition.ts | 52 ------------------- sdk/test/management-sdk.ts | 2 +- 5 files changed, 2 insertions(+), 81 deletions(-) rename sdk/script/{account-manager.ts => management-sdk.ts} (100%) delete mode 100644 sdk/script/samples/acquisition-native-stub.ts delete mode 100644 sdk/script/samples/typescript-acquisition.ts diff --git a/sdk/script/index.ts b/sdk/script/index.ts index 98546db8..dc68a5b9 100644 --- a/sdk/script/index.ts +++ b/sdk/script/index.ts @@ -1 +1 @@ -export * from "./account-manager"; +export * from "./management-sdk"; diff --git a/sdk/script/account-manager.ts b/sdk/script/management-sdk.ts similarity index 100% rename from sdk/script/account-manager.ts rename to sdk/script/management-sdk.ts diff --git a/sdk/script/samples/acquisition-native-stub.ts b/sdk/script/samples/acquisition-native-stub.ts deleted file mode 100644 index 202d3a85..00000000 --- a/sdk/script/samples/acquisition-native-stub.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - ******************************************************* - * * - * Copyright (C) Microsoft. All rights reserved. * - * * - ******************************************************* - */ - -import * as Acquisition from "../acquisition-sdk"; -export * from "../acquisition-sdk"; - -export interface NativeSample { - // constructor(configuration: Configuration): void; - - beforeApply(callback: Acquisition.Callback): void; - afterApply(callback: Acquisition.Callback): void; - - queryUpdate(callback: Acquisition.Callback): void; - download(session: Acquisition.RemotePackage, callback?: Acquisition.Callback): void; - abort(session: Acquisition.RemotePackage, callback?: Acquisition.Callback): void; - apply(newPackage: Acquisition.LocalPackage, callback?: Acquisition.Callback): void; - - getCurrentPackage(callback?: Acquisition.Callback): void; -} - -export var NativeImplementation: { new (configuration: Acquisition.Configuration): NativeSample }; - diff --git a/sdk/script/samples/typescript-acquisition.ts b/sdk/script/samples/typescript-acquisition.ts deleted file mode 100644 index 18fa7a88..00000000 --- a/sdk/script/samples/typescript-acquisition.ts +++ /dev/null @@ -1,52 +0,0 @@ -import Acquisition = require("./acquisition-native-stub"); - -class MyApp { - private static AppStoreScriptVersion = "1.5"; - private static AppUpdateTimeoutMs = 30 * 60 * 1000; - private static ServerUrl = "http://localhost:7127/"; - - private _acquisition: Acquisition.NativeSample; - - constructor() { - this._acquisition = new Acquisition.NativeImplementation({ appVersion: "1.0.0", clientUniqueId: "203ff986-f335-4e94-8e79-ee404231218d", deploymentKey: "fa3s34a5s6d7f8we9a9r", serverUrl: MyApp.ServerUrl }); - } - - public onAppStartup(): void { - this.registerLifecycleEvents(); - this.getLatestApp(); - window.setInterval(() => this.getLatestApp(), MyApp.AppUpdateTimeoutMs); - } - - private registerLifecycleEvents(): void { - this._acquisition.beforeApply((error: Error, newPackageInfo: Acquisition.LocalPackage) => { - if (newPackageInfo.label.charAt(0) > "1") { - // Migrate user data - } - }); - - this._acquisition.afterApply((error: Error, oldPackageInfo: Acquisition.LocalPackage) => { - if (oldPackageInfo.label.charAt(0) < "1") { - // Display dialog to user about changes - return Q.Promise((resolve: () => void) => { - resolve(); - }); - } - }); - } - - private getLatestApp(): void { - this._acquisition.queryUpdate((error: Error, remotePackage: Acquisition.RemotePackage) => this.downloadAndApplyPackage(remotePackage)); - } - - private downloadAndApplyPackage(remotePackage: Acquisition.RemotePackage): void { - if (remotePackage) { - this._acquisition.download(remotePackage, (error: Error, localPackage: Acquisition.LocalPackage) => this.applyPackage(localPackage)); - } - } - - private applyPackage(localPackage: Acquisition.LocalPackage): void { - if (localPackage) { - this._acquisition.apply(localPackage); - } - } -} diff --git a/sdk/test/management-sdk.ts b/sdk/test/management-sdk.ts index 89efb04e..72ed0b41 100644 --- a/sdk/test/management-sdk.ts +++ b/sdk/test/management-sdk.ts @@ -3,7 +3,7 @@ import * as assert from "assert"; import * as Q from "q"; -import { AccountManager } from "../script/account-manager"; +import { AccountManager } from "../script/management-sdk"; var request = require("superagent"); From 1c1e251229547c76d33bfa6507591f131df23c86 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Fri, 4 Mar 2016 13:26:10 -0800 Subject: [PATCH 05/11] Split SDK types into a separate file --- cli/script/command-executor.ts | 6 +++--- cli/test/cli.ts | 2 +- sdk/script/management-sdk.ts | 24 ++++++------------------ sdk/script/types.ts | 8 ++++++++ 4 files changed, 18 insertions(+), 22 deletions(-) create mode 100644 sdk/script/types.ts diff --git a/cli/script/command-executor.ts b/cli/script/command-executor.ts index 5f2279ad..371db68b 100644 --- a/cli/script/command-executor.ts +++ b/cli/script/command-executor.ts @@ -22,8 +22,8 @@ import * as yazl from "yazl"; import wordwrap = require("wordwrap"); import * as cli from "../definitions/cli"; -import { AcquisitionStatus } from "code-push/script/acquisition-sdk"; -import { AccessKey, Account, AccountManager, App, CollaboratorMap, CollaboratorProperties, Deployment, DeploymentMetrics, Headers, Package, Permissions, UpdateMetrics } from "code-push"; +import { AccountManager } from "code-push"; +import { AccessKey, Account, App, CollaboratorMap, CollaboratorProperties, Deployment, DeploymentMetrics, Headers, Package, UpdateMetrics } from "code-push/script/types"; var configFilePath: string = path.join(process.env.LOCALAPPDATA || process.env.HOME, ".code-push.config"); var emailValidator = require("email-validator"); @@ -603,7 +603,7 @@ function printAppList(format: string, apps: App[], deploymentLists: string[][]): } function getCollaboratorDisplayName(email: string, collaboratorProperties: CollaboratorProperties): string { - return (collaboratorProperties.permission === Permissions.Owner) ? email + chalk.magenta(" (" + Permissions.Owner + ")") : email; + return (collaboratorProperties.permission === AccountManager.PERMISSIONS.OWNER) ? email + chalk.magenta(" (Owner)") : email; } function printCollaboratorsList(format: string, collaborators: CollaboratorMap): void { diff --git a/cli/test/cli.ts b/cli/test/cli.ts index e687c798..591d4475 100644 --- a/cli/test/cli.ts +++ b/cli/test/cli.ts @@ -3,7 +3,7 @@ import * as sinon from "sinon"; import Q = require("q"); import * as path from "path"; import Promise = Q.Promise; -import * as codePush from "code-push"; +import * as codePush from "code-push/script/types"; import * as cli from "../definitions/cli"; import * as cmdexec from "../script/command-executor"; import * as os from "os"; diff --git a/sdk/script/management-sdk.ts b/sdk/script/management-sdk.ts index e40ace5b..ce8f1c19 100644 --- a/sdk/script/management-sdk.ts +++ b/sdk/script/management-sdk.ts @@ -4,6 +4,8 @@ import crypto = require("crypto"); import Promise = Q.Promise; import superagent = require("superagent"); +import { AccessKey, Account, App, CodePushError, CollaboratorMap, CollaboratorProperties, Deployment, DeploymentMetrics, Headers, Package, UpdateMetrics } from "./types"; + var packageJson = require("../../package.json"); declare var fs: any; @@ -18,30 +20,12 @@ if (typeof window === "undefined") { } } -// Aliasing UpdateMetrics as IUpdateMetrics & CollaboratorProperties as ICollaboratorProperties to deal with TypeScript issue that removes unused imports. -import { AccessKey, Account, App, CollaboratorMap, CollaboratorProperties as ICollaboratorProperties, Deployment, DeploymentMetrics, Package, UpdateMetrics as IUpdateMetrics } from "rest-definitions"; -export { AccessKey, Account, App, CollaboratorMap, Deployment, DeploymentMetrics, Package }; -export type UpdateMetrics = IUpdateMetrics; -export type CollaboratorProperties = ICollaboratorProperties; - -export module Permissions { - export const Owner = "Owner"; - export const Collaborator = "Collaborator"; -} - -export interface CodePushError { - message?: string; - statusCode?: number; -} - interface PackageToUpload { description: string; appVersion: string; isMandatory: boolean; } -export type Headers = { [headerName: string]: string }; - interface JsonResponse { headers: Headers; body?: any; @@ -61,6 +45,10 @@ function urlEncode(strings: string[], ...values: string[]): string { } export class AccountManager { + public static PERMISSIONS = { + OWNER: "Owner", + COLLABORATOR: "Collaborator" + }; public static SERVER_URL = "https://codepush-management.azurewebsites.net"; private static API_VERSION: number = 2; diff --git a/sdk/script/types.ts b/sdk/script/types.ts new file mode 100644 index 00000000..7b4bc44e --- /dev/null +++ b/sdk/script/types.ts @@ -0,0 +1,8 @@ +export { AccessKey, Account, App, CollaboratorMap, CollaboratorProperties, Deployment, DeploymentMetrics, Package, UpdateMetrics } from "rest-definitions"; + +export interface CodePushError { + message?: string; + statusCode?: number; +} + +export type Headers = { [headerName: string]: string }; From 0f78a75f1ae8f25172849dc0977748afcced9399 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Fri, 4 Mar 2016 13:30:56 -0800 Subject: [PATCH 06/11] Make AccountManager the default export from the SDK --- cli/script/command-executor.ts | 2 +- cli/script/command-parser.ts | 3 +-- sdk/script/index.ts | 3 ++- sdk/script/management-sdk.ts | 4 +++- sdk/test/management-sdk.ts | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cli/script/command-executor.ts b/cli/script/command-executor.ts index 371db68b..c9e7b525 100644 --- a/cli/script/command-executor.ts +++ b/cli/script/command-executor.ts @@ -1,5 +1,6 @@ /// +import AccountManager = require("code-push"); import * as base64 from "base-64"; import * as chalk from "chalk"; var childProcess = require("child_process"); @@ -22,7 +23,6 @@ import * as yazl from "yazl"; import wordwrap = require("wordwrap"); import * as cli from "../definitions/cli"; -import { AccountManager } from "code-push"; import { AccessKey, Account, App, CollaboratorMap, CollaboratorProperties, Deployment, DeploymentMetrics, Headers, Package, UpdateMetrics } from "code-push/script/types"; var configFilePath: string = path.join(process.env.LOCALAPPDATA || process.env.HOME, ".code-push.config"); diff --git a/cli/script/command-parser.ts b/cli/script/command-parser.ts index eb6a403f..dbfbfef2 100644 --- a/cli/script/command-parser.ts +++ b/cli/script/command-parser.ts @@ -1,5 +1,4 @@ -import { AccountManager } from "code-push"; -import * as yargs from "yargs"; +import * as yargs from "yargs"; import * as cli from "../definitions/cli"; import * as chalk from "chalk"; import * as updateNotifier from "update-notifier"; diff --git a/sdk/script/index.ts b/sdk/script/index.ts index dc68a5b9..d8806c3d 100644 --- a/sdk/script/index.ts +++ b/sdk/script/index.ts @@ -1 +1,2 @@ -export * from "./management-sdk"; +import AccountManager = require("./management-sdk"); +export = AccountManager; diff --git a/sdk/script/management-sdk.ts b/sdk/script/management-sdk.ts index ce8f1c19..a8c16c39 100644 --- a/sdk/script/management-sdk.ts +++ b/sdk/script/management-sdk.ts @@ -44,7 +44,7 @@ function urlEncode(strings: string[], ...values: string[]): string { return result; } -export class AccountManager { +class AccountManager { public static PERMISSIONS = { OWNER: "Owner", COLLABORATOR: "Collaborator" @@ -344,3 +344,5 @@ export class AccountManager { request.set("X-CodePush-SDK-Version", packageJson.version); } } + +export = AccountManager; diff --git a/sdk/test/management-sdk.ts b/sdk/test/management-sdk.ts index 72ed0b41..31137d2f 100644 --- a/sdk/test/management-sdk.ts +++ b/sdk/test/management-sdk.ts @@ -3,7 +3,7 @@ import * as assert from "assert"; import * as Q from "q"; -import { AccountManager } from "../script/management-sdk"; +import AccountManager = require("../script/management-sdk"); var request = require("superagent"); From 49788d6ecb1c2d282f4edcbaa166d6fbafc4ba34 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Mon, 7 Mar 2016 14:44:52 -0800 Subject: [PATCH 07/11] Fix bug where package.json was being pulled from source directory instead of bin directory --- sdk/script/management-sdk.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/script/management-sdk.ts b/sdk/script/management-sdk.ts index a8c16c39..1c0414df 100644 --- a/sdk/script/management-sdk.ts +++ b/sdk/script/management-sdk.ts @@ -6,7 +6,7 @@ import superagent = require("superagent"); import { AccessKey, Account, App, CodePushError, CollaboratorMap, CollaboratorProperties, Deployment, DeploymentMetrics, Headers, Package, UpdateMetrics } from "./types"; -var packageJson = require("../../package.json"); +var packageJson = require("../package.json"); declare var fs: any; From 1fd132a70fe0d9e96c15053258d872347bc93b77 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Mon, 7 Mar 2016 15:19:54 -0800 Subject: [PATCH 08/11] Rename/reorder SDK variables for consistency with CLI commands --- cli/script/command-executor.ts | 4 ++-- sdk/script/management-sdk.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/script/command-executor.ts b/cli/script/command-executor.ts index c9e7b525..4a7e73cc 100644 --- a/cli/script/command-executor.ts +++ b/cli/script/command-executor.ts @@ -603,7 +603,7 @@ function printAppList(format: string, apps: App[], deploymentLists: string[][]): } function getCollaboratorDisplayName(email: string, collaboratorProperties: CollaboratorProperties): string { - return (collaboratorProperties.permission === AccountManager.PERMISSIONS.OWNER) ? email + chalk.magenta(" (Owner)") : email; + return (collaboratorProperties.permission === AccountManager.AppPermission.OWNER) ? email + chalk.magenta(" (Owner)") : email; } function printCollaboratorsList(format: string, collaborators: CollaboratorMap): void { @@ -909,7 +909,7 @@ export var release = (command: cli.IReleaseCommand): Promise => { return getPackageFilePromise .then((file: IPackageFile): Promise => { - return sdk.release(command.appName, command.deploymentName, file.path, command.description, command.appStoreVersion, command.mandatory, uploadProgress) + return sdk.release(command.appName, command.deploymentName, file.path, command.appStoreVersion, command.description, command.mandatory, uploadProgress) .then((): void => { log("Successfully released an update containing the \"" + command.package + "\" " + (isSingleFilePackage ? "file" : "directory") + " to the \"" + command.deploymentName + "\" deployment of the \"" + command.appName + "\" app."); diff --git a/sdk/script/management-sdk.ts b/sdk/script/management-sdk.ts index 1c0414df..66bd35fc 100644 --- a/sdk/script/management-sdk.ts +++ b/sdk/script/management-sdk.ts @@ -45,7 +45,7 @@ function urlEncode(strings: string[], ...values: string[]): string { } class AccountManager { - public static PERMISSIONS = { + public static AppPermission = { OWNER: "Owner", COLLABORATOR: "Collaborator" }; @@ -205,9 +205,9 @@ class AccountManager { .then((res: JsonResponse) => res.body.history); } - public release(appName: string, deploymentName: string, fileOrPath: File | string, description: string, appVersion: string, isMandatory: boolean = false, uploadProgressCallback?: (progress: number) => void): Promise { + public release(appName: string, deploymentName: string, fileOrPath: File | string, targetBinaryVersion: string, description: string, isMandatory: boolean = false, uploadProgressCallback?: (progress: number) => void): Promise { return Promise((resolve, reject, notify) => { - var packageInfo: PackageToUpload = this.generatePackageInfo(description, appVersion, isMandatory); + var packageInfo: PackageToUpload = this.generatePackageInfo(description, targetBinaryVersion, isMandatory); var request: superagent.Request = superagent.post(this._serverUrl + urlEncode `/apps/${appName}/deployments/${deploymentName}/release`); this.attachCredentials(request); From 423182fde1d03f635b28461dc1ee243d12e4d3b4 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Mon, 7 Mar 2016 15:26:01 -0800 Subject: [PATCH 09/11] Remove the updateAccountInfo() method from the SDK --- sdk/script/management-sdk.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sdk/script/management-sdk.ts b/sdk/script/management-sdk.ts index 66bd35fc..cc09076e 100644 --- a/sdk/script/management-sdk.ts +++ b/sdk/script/management-sdk.ts @@ -115,11 +115,6 @@ class AccountManager { .then((res: JsonResponse) => res.body.account); } - public updateAccountInfo(accountInfoToChange: Account): Promise { - return this.patch(urlEncode `/account`, JSON.stringify(accountInfoToChange)) - .then(() => null); - } - // Apps public getApps(): Promise { return this.get(urlEncode `/apps`) From 6bee85114e3acf258f0c0161e5a4eefecab12b83 Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Mon, 7 Mar 2016 16:17:00 -0800 Subject: [PATCH 10/11] updateApp()->renameApp() and updateDeployment()->renameDeployment() to match SDK --- cli/script/command-executor.ts | 4 ++-- cli/test/cli.ts | 12 ++++++------ sdk/script/management-sdk.ts | 8 ++++---- sdk/test/management-sdk.ts | 10 +++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/cli/script/command-executor.ts b/cli/script/command-executor.ts index 4a7e73cc..7987d3b2 100644 --- a/cli/script/command-executor.ts +++ b/cli/script/command-executor.ts @@ -184,7 +184,7 @@ function appRemove(command: cli.IAppRemoveCommand): Promise { } function appRename(command: cli.IAppRenameCommand): Promise { - return sdk.updateApp(command.currentAppName, { name: command.newAppName }) + return sdk.renameApp(command.currentAppName, command.newAppName) .then((): void => { log("Successfully renamed the \"" + command.currentAppName + "\" app to \"" + command.newAppName + "\"."); }); @@ -326,7 +326,7 @@ function deploymentRemove(command: cli.IDeploymentRemoveCommand): Promise } function deploymentRename(command: cli.IDeploymentRenameCommand): Promise { - return sdk.updateDeployment(command.appName, command.currentDeploymentName, { name: command.newDeploymentName }) + return sdk.renameDeployment(command.appName, command.currentDeploymentName, command.newDeploymentName) .then((): void => { log("Successfully renamed the \"" + command.currentDeploymentName + "\" deployment to \"" + command.newDeploymentName + "\" for the \"" + command.appName + "\" app."); }); diff --git a/cli/test/cli.ts b/cli/test/cli.ts index 591d4475..75efc32b 100644 --- a/cli/test/cli.ts +++ b/cli/test/cli.ts @@ -169,7 +169,7 @@ export class SdkStub { return Q(null); } - public updateApp(app: codePush.App): Promise { + public renameApp(app: codePush.App): Promise { return Q(null); } @@ -177,7 +177,7 @@ export class SdkStub { return Q(null); } - public updateDeployment(appId: string, deployment: codePush.Deployment): Promise { + public renameDeployment(appId: string, deployment: codePush.Deployment): Promise { return Q(null); } } @@ -402,11 +402,11 @@ describe("CLI", () => { newAppName: "c" }; - var updateApp: Sinon.SinonSpy = sandbox.spy(cmdexec.sdk, "updateApp"); + var renameApp: Sinon.SinonSpy = sandbox.spy(cmdexec.sdk, "renameApp"); cmdexec.execute(command) .done((): void => { - sinon.assert.calledOnce(updateApp); + sinon.assert.calledOnce(renameApp); sinon.assert.calledOnce(log); sinon.assert.calledWithExactly(log, "Successfully renamed the \"a\" app to \"c\"."); @@ -612,11 +612,11 @@ describe("CLI", () => { newDeploymentName: "c" }; - var updateDeployment: Sinon.SinonSpy = sandbox.spy(cmdexec.sdk, "updateDeployment"); + var renameDeployment: Sinon.SinonSpy = sandbox.spy(cmdexec.sdk, "renameDeployment"); cmdexec.execute(command) .done((): void => { - sinon.assert.calledOnce(updateDeployment); + sinon.assert.calledOnce(renameDeployment); sinon.assert.calledOnce(log); sinon.assert.calledWithExactly(log, "Successfully renamed the \"Staging\" deployment to \"c\" for the \"a\" app."); diff --git a/sdk/script/management-sdk.ts b/sdk/script/management-sdk.ts index cc09076e..79fd2e05 100644 --- a/sdk/script/management-sdk.ts +++ b/sdk/script/management-sdk.ts @@ -137,8 +137,8 @@ class AccountManager { .then(() => null); } - public updateApp(appName: string, infoToChange: App): Promise { - return this.patch(urlEncode `/apps/${appName}`, JSON.stringify(infoToChange)) + public renameApp(oldAppName: string, newAppName: string): Promise { + return this.patch(urlEncode `/apps/${oldAppName}`, JSON.stringify({ name: newAppName })) .then(() => null); } @@ -180,8 +180,8 @@ class AccountManager { .then((res: JsonResponse) => res.body.deployment); } - public updateDeployment(appName: string, deploymentName: string, infoToChange: Deployment): Promise { - return this.patch(urlEncode `/apps/${appName}/deployments/${deploymentName}`, JSON.stringify(infoToChange)) + public renameDeployment(appName: string, oldDeploymentName: string, newDeploymentName: string): Promise { + return this.patch(urlEncode `/apps/${appName}/deployments/${oldDeploymentName}`, JSON.stringify({ name: newDeploymentName })) .then(() => null); } diff --git a/sdk/test/management-sdk.ts b/sdk/test/management-sdk.ts index 31137d2f..6761d563 100644 --- a/sdk/test/management-sdk.ts +++ b/sdk/test/management-sdk.ts @@ -25,13 +25,13 @@ describe("Management SDK", () => { var methodsWithErrorHandling: any[] = [ manager.addApp.bind(manager, "appName"), manager.getApp.bind(manager, "appName"), - manager.updateApp.bind(manager, "appName", {}), + manager.renameApp.bind(manager, "appName", {}), manager.removeApp.bind(manager, "appName"), manager.addDeployment.bind(manager, "appName", "deploymentName"), manager.getDeployment.bind(manager, "appName", "deploymentName"), manager.getDeployments.bind(manager, "appName"), - manager.updateDeployment.bind(manager, "appName", "deploymentName", { name: "newDeploymentName" }), + manager.renameDeployment.bind(manager, "appName", "deploymentName", { name: "newDeploymentName" }), manager.removeDeployment.bind(manager, "appName", "deploymentName"), ]; @@ -114,7 +114,7 @@ describe("Management SDK", () => { it("updateApp handles success response", (done: MochaDone) => { mockReturn(JSON.stringify({ apps: [] }), 200, {}); - manager.updateApp("appName", {}).done((obj: any) => { + manager.renameApp("appName", "newAppName").done((obj: any) => { assert.ok(!obj); done(); }, rejectHandler); @@ -156,10 +156,10 @@ describe("Management SDK", () => { }, rejectHandler); }); - it("updateDeployment handles success response", (done: MochaDone) => { + it("renameDeployment handles success response", (done: MochaDone) => { mockReturn(JSON.stringify({ apps: [] }), 200, {}); - manager.updateDeployment("appName", "deploymentName", { name: "newDeploymentName" }).done((obj: any) => { + manager.renameDeployment("appName", "deploymentName", "newDeploymentName").done((obj: any) => { assert.ok(!obj); done(); }, rejectHandler); From a89a979c7005c2df282ec3c5bb02dcf5a81c568f Mon Sep 17 00:00:00 2001 From: Richard Hua Date: Mon, 7 Mar 2016 16:47:01 -0800 Subject: [PATCH 11/11] Make 'description' parameter of release() method optional --- sdk/script/management-sdk.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/script/management-sdk.ts b/sdk/script/management-sdk.ts index 79fd2e05..eef46748 100644 --- a/sdk/script/management-sdk.ts +++ b/sdk/script/management-sdk.ts @@ -200,7 +200,7 @@ class AccountManager { .then((res: JsonResponse) => res.body.history); } - public release(appName: string, deploymentName: string, fileOrPath: File | string, targetBinaryVersion: string, description: string, isMandatory: boolean = false, uploadProgressCallback?: (progress: number) => void): Promise { + public release(appName: string, deploymentName: string, fileOrPath: File | string, targetBinaryVersion: string, description?: string, isMandatory: boolean = false, uploadProgressCallback?: (progress: number) => void): Promise { return Promise((resolve, reject, notify) => { var packageInfo: PackageToUpload = this.generatePackageInfo(description, targetBinaryVersion, isMandatory); var request: superagent.Request = superagent.post(this._serverUrl + urlEncode `/apps/${appName}/deployments/${deploymentName}/release`);