@revopush/code-push-cli 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,26 +2,33 @@
2
2
  // Licensed under the MIT License.
3
3
 
4
4
  import AccountManager = require("./management-sdk");
5
+
5
6
  const childProcess = require("child_process");
6
7
  import debugCommand from "./commands/debug";
7
8
  import * as fs from "fs";
8
9
  import * as chalk from "chalk";
10
+
9
11
  const g2js = require("gradle-to-js/lib/parser");
10
12
  import * as moment from "moment";
13
+
11
14
  const opener = require("opener");
12
15
  import * as os from "os";
13
16
  import * as path from "path";
17
+
14
18
  const plist = require("plist");
15
19
  const progress = require("progress");
16
20
  const prompt = require("prompt");
17
21
  import * as Q from "q";
22
+
18
23
  const rimraf = require("rimraf");
19
24
  import * as semver from "semver";
25
+
20
26
  const Table = require("cli-table");
21
27
  const which = require("which");
22
28
  import wordwrap = require("wordwrap");
23
29
  import * as cli from "../script/types/cli";
24
30
  import sign from "./sign";
31
+
25
32
  const xcode = require("xcode");
26
33
  import {
27
34
  AccessKey,
@@ -38,23 +45,15 @@ import {
38
45
  Session,
39
46
  UpdateMetrics,
40
47
  } from "../script/types";
41
- import {
42
- getAndroidHermesEnabled,
43
- getiOSHermesEnabled,
44
- runHermesEmitBinaryCommand,
45
- isValidVersion
46
- } from "./react-native-utils";
47
- import {
48
- fileDoesNotExistOrIsDirectory,
49
- isBinaryOrZip,
50
- fileExists
51
- } from "./utils/file-utils";
48
+ import { getAndroidHermesEnabled, getiOSHermesEnabled, runHermesEmitBinaryCommand, isValidVersion } from "./react-native-utils";
49
+ import { fileDoesNotExistOrIsDirectory, isBinaryOrZip, fileExists } from "./utils/file-utils";
52
50
 
53
- const configFilePath: string = path.join(process.env.LOCALAPPDATA || process.env.HOME, ".code-push.config");
51
+ const configFilePath: string = path.join(process.env.LOCALAPPDATA || process.env.HOME, ".revopush.config");
54
52
  const emailValidator = require("email-validator");
55
53
  const packageJson = require("../../package.json");
56
54
  const parseXml = Q.denodeify(require("xml2js").parseString);
57
55
  import Promise = Q.Promise;
56
+
58
57
  const properties = require("properties");
59
58
 
60
59
  const CLI_HEADERS: Headers = {
@@ -290,7 +289,7 @@ function deleteFolder(folderPath: string): Promise<void> {
290
289
  }
291
290
 
292
291
  function deploymentAdd(command: cli.IDeploymentAddCommand): Promise<void> {
293
- return sdk.addDeployment(command.appName, command.deploymentName).then((deployment: Deployment): void => {
292
+ return sdk.addDeployment(command.appName, command.deploymentName, command.key).then((deployment: Deployment): void => {
294
293
  log(
295
294
  'Successfully added the "' +
296
295
  command.deploymentName +
@@ -454,7 +453,7 @@ export function execute(command: cli.ICommand) {
454
453
 
455
454
  if (!connectionInfo) {
456
455
  throw new Error(
457
- "You are not currently logged in. Run the 'code-push-standalone login' command to authenticate with the CodePush server."
456
+ "You are not currently logged in. Run the 'revopush login' command to authenticate with the CodePush server."
458
457
  );
459
458
  }
460
459
 
@@ -573,13 +572,10 @@ function getTotalActiveFromDeploymentMetrics(metrics: DeploymentMetrics): number
573
572
  }
574
573
 
575
574
  function initiateExternalAuthenticationAsync(action: string, serverUrl?: string): void {
576
- const message: string =
577
- `A browser is being launched to authenticate your account. Follow the instructions ` +
578
- `it displays to complete your ${action === "register" ? "registration" : action}.`;
579
-
580
- log(message);
581
575
  const hostname: string = os.hostname();
582
- const url: string = `${serverUrl || AccountManager.SERVER_URL}/auth/${action}?hostname=${hostname}`;
576
+ const url: string = `${serverUrl || AccountManager.APP_SERVER_URL}/cli-login?hostname=${hostname}`;
577
+ log("Opening your browser...");
578
+ log(`Visit ${url} and enter the code`);
583
579
  opener(url);
584
580
  }
585
581
 
@@ -591,21 +587,21 @@ function link(command: cli.ILinkCommand): Promise<void> {
591
587
  function login(command: cli.ILoginCommand): Promise<void> {
592
588
  // Check if one of the flags were provided.
593
589
  if (command.accessKey) {
594
- sdk = getSdk(command.accessKey, CLI_HEADERS, command.serverUrl);
590
+ sdk = getSdk(command.accessKey, CLI_HEADERS, command.apiServerUrl);
595
591
  return sdk.isAuthenticated().then((isAuthenticated: boolean): void => {
596
592
  if (isAuthenticated) {
597
- serializeConnectionInfo(command.accessKey, /*preserveAccessKeyOnLogout*/ true, command.serverUrl);
593
+ serializeConnectionInfo(command.accessKey, /*preserveAccessKeyOnLogout*/ true, command.apiServerUrl);
598
594
  } else {
599
595
  throw new Error("Invalid access key.");
600
596
  }
601
597
  });
602
598
  } else {
603
- return loginWithExternalAuthentication("login", command.serverUrl);
599
+ return loginWithExternalAuthentication("login", command.apiServerUrl, command.appServerUrl);
604
600
  }
605
601
  }
606
602
 
607
- function loginWithExternalAuthentication(action: string, serverUrl?: string): Promise<void> {
608
- initiateExternalAuthenticationAsync(action, serverUrl);
603
+ function loginWithExternalAuthentication(action: string, apiServerUrl?: string, appServerUrl?: string): Promise<void> {
604
+ initiateExternalAuthenticationAsync(action, appServerUrl);
609
605
  log(""); // Insert newline
610
606
 
611
607
  return requestAccessKey().then((accessKey: string): Promise<void> => {
@@ -614,11 +610,11 @@ function loginWithExternalAuthentication(action: string, serverUrl?: string): Pr
614
610
  return;
615
611
  }
616
612
 
617
- sdk = getSdk(accessKey, CLI_HEADERS, serverUrl);
613
+ sdk = getSdk(accessKey, CLI_HEADERS, apiServerUrl);
618
614
 
619
615
  return sdk.isAuthenticated().then((isAuthenticated: boolean): void => {
620
616
  if (isAuthenticated) {
621
- serializeConnectionInfo(accessKey, /*preserveAccessKeyOnLogout*/ false, serverUrl);
617
+ serializeConnectionInfo(accessKey, /*preserveAccessKeyOnLogout*/ false, apiServerUrl);
622
618
  } else {
623
619
  throw new Error("Invalid access key.");
624
620
  }
@@ -1081,11 +1077,7 @@ function getAppVersionFromXcodeProject(command: cli.IReleaseReactCommand, projec
1081
1077
  }
1082
1078
 
1083
1079
  const xcodeProj = xcode.project(resolvedPbxprojFile).parseSync();
1084
- const marketingVersion = xcodeProj.getBuildProperty(
1085
- "MARKETING_VERSION",
1086
- command.buildConfigurationName,
1087
- command.xcodeTargetName
1088
- );
1080
+ const marketingVersion = xcodeProj.getBuildProperty("MARKETING_VERSION", command.buildConfigurationName, command.xcodeTargetName);
1089
1081
  if (!isValidVersion(marketingVersion)) {
1090
1082
  throw new Error(
1091
1083
  `The "MARKETING_VERSION" key in the "${resolvedPbxprojFile}" file needs to specify a valid semver string, containing both a major and minor version (e.g. 1.3.2, 1.1).`
@@ -1353,9 +1345,9 @@ export const releaseReact = (command: cli.IReleaseReactCommand): Promise<void> =
1353
1345
  )
1354
1346
  .then(async () => {
1355
1347
  const isHermesEnabled =
1356
- command.useHermes ||
1357
- (platform === "android" && (await getAndroidHermesEnabled(command.gradleFile))) || // Check if we have to run hermes to compile JS to Byte Code if Hermes is enabled in build.gradle and we're releasing an Android build
1358
- (platform === "ios" && (await getiOSHermesEnabled(command.podFile))); // Check if we have to run hermes to compile JS to Byte Code if Hermes is enabled in Podfile and we're releasing an iOS build
1348
+ command.useHermes ||
1349
+ (platform === "android" && (await getAndroidHermesEnabled(command.gradleFile))) || // Check if we have to run hermes to compile JS to Byte Code if Hermes is enabled in build.gradle and we're releasing an Android build
1350
+ (platform === "ios" && (await getiOSHermesEnabled(command.podFile))); // Check if we have to run hermes to compile JS to Byte Code if Hermes is enabled in Podfile and we're releasing an iOS build
1359
1351
 
1360
1352
  if (isHermesEnabled) {
1361
1353
  log(chalk.cyan("\nRunning hermes compiler...\n"));
@@ -1521,7 +1513,7 @@ function sessionList(command: cli.ISessionListCommand): Promise<void> {
1521
1513
 
1522
1514
  function sessionRemove(command: cli.ISessionRemoveCommand): Promise<void> {
1523
1515
  if (os.hostname() === command.machineName) {
1524
- throw new Error("Cannot remove the current login session via this command. Please run 'code-push-standalone logout' instead.");
1516
+ throw new Error("Cannot remove the current login session via this command. Please run 'revopush logout' instead.");
1525
1517
  } else {
1526
1518
  return confirm().then((wasConfirmed: boolean): Promise<void> => {
1527
1519
  if (wasConfirmed) {
@@ -9,7 +9,7 @@ import parseDuration = require("parse-duration");
9
9
 
10
10
  const packageJson = require("../../package.json");
11
11
  const ROLLOUT_PERCENTAGE_REGEX: RegExp = /^(100|[1-9][0-9]|[1-9])%?$/;
12
- const USAGE_PREFIX = "Usage: code-push-standalone";
12
+ const USAGE_PREFIX = "Usage: revopush";
13
13
 
14
14
  // Command categories are: access-key, app, release, deployment, deployment-key, login, logout, register
15
15
  let isValidCommandCategory = false;
@@ -20,13 +20,19 @@ let wasHelpShown = false;
20
20
  export function showHelp(showRootDescription?: boolean): void {
21
21
  if (!wasHelpShown) {
22
22
  if (showRootDescription) {
23
- console.log(chalk.cyan(" _____ __ " + chalk.green(" ___ __ ")));
24
- console.log(chalk.cyan(" / ___/__ ___/ /__" + chalk.green(" / _ \\__ _____ / / ")));
25
- console.log(chalk.cyan("/ /__/ _ \\/ _ / -_)" + chalk.green(" ___/ // (_-</ _ \\")));
26
- console.log(chalk.cyan("\\___/\\___/\\_,_/\\__/" + chalk.green("_/ \\_,_/___/_//_/")) + " CLI v" + packageJson.version);
27
- console.log(chalk.cyan("======================================"));
28
- console.log("");
29
- console.log("CodePush is a service that enables you to deploy mobile app updates directly to your users' devices.\n");
23
+ console.log(
24
+ chalk.blue(`
25
+ ____ ____ _
26
+ | _ \\ _____ _____ | _ \\ _ _ ___| |__
27
+ | |_) / _ \\ \\ / / _ \\| |_) | | | / __| '_ \\
28
+ | _ < __/\\ V / (_) | __/| |_| \\__ \\ | | |
29
+ |_| \\_\\___| \\_/ \\___/|_| \\__,_|___/_| |_| CLI v${packageJson.version}
30
+ ============================================`)
31
+ );
32
+ console.log(
33
+ "Revopush is a service that enables you to deploy mobile app updates directly to your users' devices. " +
34
+ "Visit our website https://revopush.org/ \n"
35
+ );
30
36
  }
31
37
 
32
38
  yargs.showHelp();
@@ -322,6 +328,7 @@ yargs
322
328
  .command("list", "Lists the apps associated with your account", (yargs: yargs.Argv) => appList("list", yargs))
323
329
  .command("ls", "Lists the apps associated with your account", (yargs: yargs.Argv) => appList("ls", yargs))
324
330
  .command("transfer", "Transfer the ownership of an app to another account", (yargs: yargs.Argv) => {
331
+ isValidCommand = true;
325
332
  yargs
326
333
  .usage(USAGE_PREFIX + " app transfer <appName> <email>")
327
334
  .demand(/*count*/ 2, /*max*/ 2) // Require exactly two non-option arguments
@@ -376,7 +383,14 @@ yargs
376
383
  yargs
377
384
  .usage(USAGE_PREFIX + " deployment add <appName> <deploymentName>")
378
385
  .demand(/*count*/ 2, /*max*/ 2) // Require exactly two non-option arguments
379
- .example("deployment add MyApp MyDeployment", 'Adds deployment "MyDeployment" to app "MyApp"');
386
+ .example("deployment add MyApp MyDeployment", 'Adds deployment "MyDeployment" to app "MyApp"')
387
+ .example("deployment add MyApp MyDeployment -k abc123", 'Adds deployment key "abc123"')
388
+ .option("key", {
389
+ alias: "k",
390
+ demand: false,
391
+ description: "Specify deployment key",
392
+ type: "string",
393
+ });
380
394
 
381
395
  addCommonConfiguration(yargs);
382
396
  })
@@ -405,23 +419,23 @@ yargs
405
419
 
406
420
  addCommonConfiguration(yargs);
407
421
  })
408
- .command("link", "Link an additional authentication provider (e.g. GitHub) to an existing CodePush account", (yargs: yargs.Argv) => {
409
- isValidCommandCategory = true;
410
- isValidCommand = true;
411
- yargs
412
- .usage(USAGE_PREFIX + " link")
413
- .demand(/*count*/ 0, /*max*/ 1) //set 'max' to one to allow usage of serverUrl undocument parameter for testing
414
- .example("link", "Links an account on the CodePush server")
415
- .check((argv: any, aliases: { [aliases: string]: string }): any => isValidCommand); // Report unrecognized, non-hyphenated command category.
422
+ /* .command("link", "Link an additional authentication provider (e.g. GitHub) to an existing CodePush account", (yargs: yargs.Argv) => {
423
+ isValidCommandCategory = true;
424
+ isValidCommand = true;
425
+ yargs
426
+ .usage(USAGE_PREFIX + " link")
427
+ .demand(/!*count*!/ 0, /!*max*!/ 1) //set 'max' to one to allow usage of serverUrl undocument parameter for testing
428
+ .example("link", "Links an account on the CodePush server")
429
+ .check((argv: any, aliases: { [aliases: string]: string }): any => isValidCommand); // Report unrecognized, non-hyphenated command category.
416
430
 
417
- addCommonConfiguration(yargs);
418
- })
431
+ addCommonConfiguration(yargs);
432
+ })*/
419
433
  .command("login", "Authenticate with the CodePush server in order to begin managing your apps", (yargs: yargs.Argv) => {
420
434
  isValidCommandCategory = true;
421
435
  isValidCommand = true;
422
436
  yargs
423
437
  .usage(USAGE_PREFIX + " login [options]")
424
- .demand(/*count*/ 0, /*max*/ 1) //set 'max' to one to allow usage of serverUrl undocument parameter for testing
438
+ .demand(/*count*/ 0, /*max*/ 2) //set 'max' to one to allow usage of serverUrl undocument parameter for testing
425
439
  .example("login", "Logs in to the CodePush server")
426
440
  .example("login --accessKey mykey", 'Logs in on behalf of the user who owns and created the access key "mykey"')
427
441
  .option("accessKey", {
@@ -786,15 +800,14 @@ yargs
786
800
  alias: "pod",
787
801
  default: null,
788
802
  demand: false,
789
- description: "Path to the cocopods config file (iOS only).",
803
+ description: "Path to the cocopods config file (iOS only).",
790
804
  type: "string",
791
805
  })
792
806
  .option("extraHermesFlags", {
793
807
  alias: "hf",
794
808
  default: [],
795
809
  demand: false,
796
- description:
797
- "Flags that get passed to Hermes, JavaScript to bytecode compiler. Can be specified multiple times.",
810
+ description: "Flags that get passed to Hermes, JavaScript to bytecode compiler. Can be specified multiple times.",
798
811
  type: "array",
799
812
  })
800
813
  .option("privateKeyPath", {
@@ -815,14 +828,16 @@ yargs
815
828
  alias: "xt",
816
829
  default: undefined,
817
830
  demand: false,
818
- description: "Name of target (PBXNativeTarget) which specifies the binary version you want to target this release at (iOS only)",
831
+ description:
832
+ "Name of target (PBXNativeTarget) which specifies the binary version you want to target this release at (iOS only)",
819
833
  type: "string",
820
834
  })
821
835
  .option("buildConfigurationName", {
822
836
  alias: "c",
823
837
  default: undefined,
824
838
  demand: false,
825
- description: "Name of build configuration which specifies the binary version you want to target this release at. For example, 'Debug' or 'Release' (iOS only)",
839
+ description:
840
+ "Name of build configuration which specifies the binary version you want to target this release at. For example, 'Debug' or 'Release' (iOS only)",
826
841
  type: "string",
827
842
  })
828
843
  .check((argv: any, aliases: { [aliases: string]: string }): any => {
@@ -1045,6 +1060,9 @@ export function createCommand(): cli.ICommand {
1045
1060
 
1046
1061
  deploymentAddCommand.appName = arg2;
1047
1062
  deploymentAddCommand.deploymentName = arg3;
1063
+ if (argv["key"]) {
1064
+ deploymentAddCommand.key = argv["key"] as any;
1065
+ }
1048
1066
  }
1049
1067
  break;
1050
1068
 
@@ -1112,19 +1130,20 @@ export function createCommand(): cli.ICommand {
1112
1130
  }
1113
1131
  break;
1114
1132
 
1115
- case "link":
1116
- cmd = <cli.ILinkCommand>{
1117
- type: cli.CommandType.link,
1118
- serverUrl: getServerUrl(arg1),
1119
- };
1120
- break;
1133
+ /* case "link":
1134
+ cmd = <cli.ILinkCommand>{
1135
+ type: cli.CommandType.link,
1136
+ serverUrl: getServerUrl(arg1),
1137
+ };
1138
+ break;*/
1121
1139
 
1122
1140
  case "login":
1123
1141
  cmd = { type: cli.CommandType.login };
1124
1142
 
1125
1143
  const loginCommand = <cli.ILoginCommand>cmd;
1126
1144
 
1127
- loginCommand.serverUrl = getServerUrl(arg1);
1145
+ loginCommand.apiServerUrl = getServerUrl(arg1);
1146
+ loginCommand.appServerUrl = getServerUrl(arg2);
1128
1147
  loginCommand.accessKey = argv["accessKey"] as any;
1129
1148
  break;
1130
1149
 
@@ -58,7 +58,8 @@ class AccountManager {
58
58
  OWNER: "Owner",
59
59
  COLLABORATOR: "Collaborator",
60
60
  };
61
- public static SERVER_URL = "http://localhost:3000";
61
+ public static API_SERVER_URL = "https://api.revopush.org";
62
+ public static APP_SERVER_URL = "https://app.revopush.org";
62
63
 
63
64
  private static API_VERSION: number = 2;
64
65
 
@@ -77,7 +78,7 @@ class AccountManager {
77
78
 
78
79
  this._accessKey = accessKey;
79
80
  this._customHeaders = customHeaders;
80
- this._serverUrl = serverUrl || AccountManager.SERVER_URL;
81
+ this._serverUrl = serverUrl || AccountManager.API_SERVER_URL;
81
82
  }
82
83
 
83
84
  public get accessKey(): string {
@@ -253,8 +254,8 @@ class AccountManager {
253
254
  }
254
255
 
255
256
  // Deployments
256
- public addDeployment(appName: string, deploymentName: string): Promise<Deployment> {
257
- const deployment = <Deployment>{ name: deploymentName };
257
+ public addDeployment(appName: string, deploymentName: string, deploymentKey?: string): Promise<Deployment> {
258
+ const deployment = <Deployment>{ name: deploymentName, key: deploymentKey };
258
259
  return this.post(urlEncode([`/apps/${appName}/deployments/`]), JSON.stringify(deployment), /*expectResponseBody=*/ true).then(
259
260
  (res: JsonResponse) => res.body.deployment
260
261
  );
@@ -107,6 +107,7 @@ export interface IDebugCommand extends ICommand {
107
107
  export interface IDeploymentAddCommand extends ICommand {
108
108
  appName: string;
109
109
  deploymentName: string;
110
+ key?: string;
110
111
  default: boolean;
111
112
  }
112
113
 
@@ -144,7 +145,8 @@ export interface ILinkCommand extends ICommand {
144
145
  }
145
146
 
146
147
  export interface ILoginCommand extends ICommand {
147
- serverUrl?: string;
148
+ apiServerUrl?: string;
149
+ appServerUrl?: string;
148
150
  accessKey: string;
149
151
  }
150
152
 
package/.idea/cli.iml DELETED
@@ -1,9 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <module type="JAVA_MODULE" version="4">
3
- <component name="NewModuleRootManager" inherit-compiler-output="true">
4
- <exclude-output />
5
- <content url="file://$MODULE_DIR$" />
6
- <orderEntry type="inheritedJdk" />
7
- <orderEntry type="sourceFolder" forTests="false" />
8
- </component>
9
- </module>
@@ -1,6 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <profile version="1.0">
3
- <option name="myName" value="Project Default" />
4
- <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
5
- </profile>
6
- </component>
package/.idea/misc.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectRootManager">
4
- <output url="file://$PROJECT_DIR$/out" />
5
- </component>
6
- </project>
package/.idea/modules.xml DELETED
@@ -1,8 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="ProjectModuleManager">
4
- <modules>
5
- <module fileurl="file://$PROJECT_DIR$/.idea/cli.iml" filepath="$PROJECT_DIR$/.idea/cli.iml" />
6
- </modules>
7
- </component>
8
- </project>
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="PrettierConfiguration">
4
- <option name="myConfigurationMode" value="AUTOMATIC" />
5
- </component>
6
- </project>
package/.idea/vcs.xml DELETED
@@ -1,6 +0,0 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <project version="4">
3
- <component name="VcsDirectoryMappings">
4
- <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
5
- </component>
6
- </project>