bitrise-api-cli 0.0.4 → 0.0.6

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.
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Bitrise API CLI [![npm version](https://badge.fury.io/js/bitrise-api-cli.svg)](https://www.npmjs.com/package/bitrise-api-cli)
1
+ # Bitrise API CLI [![npm][npm-image]][npm-url] ![npm][npm-dl-stats]
2
2
 
3
3
  <div align="center">
4
4
  🚀 An unofficial CLI tool to interact with Bitrise API, making artifact downloads a breeze.
@@ -118,3 +118,8 @@ This project is [MIT](LICENSE) licensed.
118
118
  <div align="center">
119
119
  <p>Found this project useful? Give it a ⭐️!</p>
120
120
  </div>
121
+
122
+
123
+ [npm-image]: https://img.shields.io/npm/v/bitrise-api-cli
124
+ [npm-url]: https://www.npmjs.com/package/bitrise-api-cli
125
+ [npm-dl-stats]: https://img.shields.io/npm/dm/bitrise-api-cli
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ app,
4
+ buildContext
5
+ } from "./chunk-SUHWPUKK.js";
6
+ import "./chunk-CF25N4TY.js";
7
+
8
+ // src/cli/bin/bash-complete.ts
9
+ import { proposeCompletions } from "@stricli/core";
10
+ var inputs = process.argv.slice(3);
11
+ if (process.env["COMP_LINE"]?.endsWith(" ")) {
12
+ inputs.push("");
13
+ }
14
+ await proposeCompletions(app, inputs, buildContext(process));
15
+ try {
16
+ for (const { completion } of await proposeCompletions(app, inputs, buildContext(process))) {
17
+ process.stdout.write(`${completion}
18
+ `);
19
+ }
20
+ } catch {
21
+ }
@@ -0,0 +1,6 @@
1
+ // src/cliOptions.types.ts
2
+ var validArtifactTypes = ["android-apk", "ios-ipa"];
3
+
4
+ export {
5
+ validArtifactTypes
6
+ };
@@ -0,0 +1,94 @@
1
+ import {
2
+ validArtifactTypes
3
+ } from "./chunk-CF25N4TY.js";
4
+
5
+ // src/cli/app.ts
6
+ import { buildApplication, buildCommand, buildRouteMap } from "@stricli/core";
7
+
8
+ // package.json
9
+ var name = "bitrise-api-cli";
10
+ var version = "0.0.6";
11
+ var description = "bitrise api CLI wrapper";
12
+
13
+ // src/cli/app.ts
14
+ var downloadCommand = buildCommand({
15
+ loader: async () => import("./impl-ESKLIOQY.js"),
16
+ parameters: {
17
+ flags: {
18
+ artifact: {
19
+ kind: "enum",
20
+ brief: 'bitrise artifact type "ios-ipa" or "android-apk"',
21
+ default: "android-apk",
22
+ values: validArtifactTypes
23
+ },
24
+ debug: {
25
+ kind: "boolean",
26
+ brief: "Number of times to say hello",
27
+ default: false
28
+ },
29
+ slug: {
30
+ kind: "parsed",
31
+ brief: "bitrise app slug (or $BITRISE_APP_SLUG) see bitrise project url to get slug",
32
+ default: process.env["BITRISE_APP_SLUG"],
33
+ parse: String,
34
+ placeholder: "APP_SLUG"
35
+ },
36
+ token: {
37
+ kind: "parsed",
38
+ brief: "bitrise api token (or $BITRISE_API_CLI_TOKEN)",
39
+ default: process.env["BITRISE_API_CLI_TOKEN"],
40
+ parse: String,
41
+ placeholder: "API_TOKEN"
42
+ },
43
+ workflow: {
44
+ kind: "parsed",
45
+ brief: "workflow to get apk from (or $BITRISE_API_CLI_WORKFLOW)",
46
+ default: process.env["BITRISE_API_CLI_WORKFLOW"],
47
+ parse: String,
48
+ placeholder: "WORKFLOW_NAME"
49
+ }
50
+ },
51
+ aliases: {
52
+ a: "artifact",
53
+ d: "debug",
54
+ s: "slug",
55
+ t: "token",
56
+ w: "workflow"
57
+ }
58
+ },
59
+ docs: {
60
+ brief: "Download bitrise artifacts. Most parameters can be set via environment variables."
61
+ }
62
+ });
63
+ var root = buildRouteMap({
64
+ routes: {
65
+ download: downloadCommand
66
+ },
67
+ docs: {
68
+ brief: description
69
+ }
70
+ });
71
+ var app = buildApplication(root, {
72
+ name,
73
+ versionInfo: {
74
+ currentVersion: version
75
+ }
76
+ });
77
+
78
+ // src/cli/context.ts
79
+ import fs from "node:fs";
80
+ import os from "node:os";
81
+ import path from "node:path";
82
+ function buildContext(process2) {
83
+ return {
84
+ process: process2,
85
+ os,
86
+ fs,
87
+ path
88
+ };
89
+ }
90
+
91
+ export {
92
+ app,
93
+ buildContext
94
+ };
package/dist/cli.js ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ app,
4
+ buildContext
5
+ } from "./chunk-SUHWPUKK.js";
6
+ import "./chunk-CF25N4TY.js";
7
+
8
+ // src/cli/bin/cli.ts
9
+ import { run } from "@stricli/core";
10
+ await run(app, process.argv.slice(2), buildContext(process));
@@ -1,19 +1,17 @@
1
- #!/usr/bin/env node
2
-
3
- // src/bin.ts
4
- import { Command } from "commander";
5
-
6
- // src/cliOptions.types.ts
7
- var validArtifactTypes = ["android-apk", "ios-ipa"];
1
+ import {
2
+ validArtifactTypes
3
+ } from "./chunk-CF25N4TY.js";
8
4
 
9
5
  // src/bitrise/env.ts
10
6
  var ENV = {
7
+ debug: false,
11
8
  appSlug: "",
12
9
  token: "",
13
10
  workflow: "",
14
11
  artifactType: "android-apk"
15
12
  };
16
13
  var saveOptions = (options) => {
14
+ ENV.debug = options.debug;
17
15
  ENV.appSlug = options.slug;
18
16
  ENV.token = options.token;
19
17
  ENV.workflow = options.workflow;
@@ -1435,28 +1433,17 @@ var api = {
1435
1433
  builds: () => new BuildsApi(getApiConfig())
1436
1434
  };
1437
1435
 
1436
+ // src/helper/debugLog.ts
1437
+ var debugLog = (label, data) => console.log(`${label}: ${JSON.stringify(data, void 0, 2)}`);
1438
+
1438
1439
  // src/bitrise/fetchArtifact.ts
1439
1440
  var fetchArtifact = async ({ artifactSlug, buildSlug }) => {
1440
1441
  const { data } = await api.buildArtifact().artifactShow({ appSlug: ENV.appSlug, artifactSlug, buildSlug });
1441
1442
  if (!data) throw new Error("buildArtifact().artifactShow returned no data");
1443
+ if (ENV.debug) debugLog("artifact", data);
1442
1444
  return data;
1443
1445
  };
1444
1446
 
1445
- // src/helper/formatBytes.ts
1446
- var decimals = 0;
1447
- var formatBytes = (bytes) => {
1448
- if (bytes === 0) return "0 Bytes";
1449
- const k = 1024;
1450
- const dm = decimals || 2;
1451
- const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
1452
- const i = Math.floor(Math.log(bytes) / Math.log(k));
1453
- const formattedSize = Number.parseFloat((bytes / k ** i).toFixed(dm));
1454
- return `${formattedSize} ${sizes[i]}`;
1455
- };
1456
-
1457
- // src/downloadLatestArtifacts.ts
1458
- import { oraPromise } from "ora";
1459
-
1460
1447
  // src/bitrise/fetchArtifactList.ts
1461
1448
  var fetchArtifactList = async (buildSlug) => {
1462
1449
  const { data } = await api.buildArtifact().artifactList({ appSlug: ENV.appSlug, buildSlug });
@@ -1468,32 +1455,51 @@ var fetchArtifactByType = async (buildSlug) => {
1468
1455
  const artifactMetadata = artifactInfo.find((artifact) => artifact.artifactType === ENV.artifactType);
1469
1456
  if (!artifactMetadata || !artifactMetadata.slug)
1470
1457
  throw new Error(`Found no ${ENV.artifactType} in build Slug: ${buildSlug}`);
1458
+ if (ENV.debug) debugLog("artifactMetadata", artifactMetadata);
1471
1459
  return artifactMetadata;
1472
1460
  };
1473
1461
 
1474
- // src/helper/debugLog.ts
1475
- var debugLog = (label, data) => console.log(`${label}: ${JSON.stringify(data, void 0, 2)}`);
1476
-
1477
1462
  // src/bitrise/fetchBuilds.ts
1478
1463
  var getAllBuilds = async () => {
1479
1464
  const { data } = await api.builds().buildList({ appSlug: ENV.appSlug, status: 1 });
1480
1465
  if (!data) throw Error("no build data");
1481
1466
  return data;
1482
1467
  };
1483
- var getLatestBuild = async (options) => {
1468
+ var getLatestBuild = async () => {
1484
1469
  const builds = await getAllBuilds();
1485
1470
  const latestBuild = builds.find((build) => build.triggeredWorkflow === ENV.workflow);
1486
1471
  if (!latestBuild) throw `Found no build with the workflow: "${ENV.workflow}"`;
1487
- if (options.debug) debugLog("latestBuild", latestBuild);
1472
+ if (ENV.debug) debugLog("latestBuild", latestBuild);
1488
1473
  return latestBuild;
1489
1474
  };
1490
1475
 
1476
+ // src/helper/formatBytes.ts
1477
+ var decimals = 0;
1478
+ var formatBytes = (bytes) => {
1479
+ if (bytes === 0) return "0 Bytes";
1480
+ const k = 1024;
1481
+ const dm = decimals || 2;
1482
+ const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
1483
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
1484
+ const formattedSize = Number.parseFloat((bytes / k ** i).toFixed(dm));
1485
+ return `${formattedSize} ${sizes[i]}`;
1486
+ };
1487
+
1488
+ // src/downloadLatestArtifacts.ts
1489
+ import { oraPromise } from "ora";
1490
+
1491
1491
  // src/helper/downloadFile.ts
1492
1492
  import { createWriteStream } from "node:fs";
1493
1493
  import { get } from "node:https";
1494
1494
  import { pipeline } from "node:stream/promises";
1495
1495
  import { URL } from "node:url";
1496
+
1497
+ // src/helper/formatTime.ts
1498
+ var formatTime = (timeMs) => `${(timeMs / 1e3).toFixed(1)}s`;
1499
+
1500
+ // src/helper/downloadFile.ts
1496
1501
  var downloadFile = async (fileUrl, outputLocationPath) => {
1502
+ const startTime = Date.now();
1497
1503
  const url = new URL(fileUrl);
1498
1504
  const response = await new Promise((resolve, reject) => {
1499
1505
  get(url, (res) => {
@@ -1505,54 +1511,40 @@ var downloadFile = async (fileUrl, outputLocationPath) => {
1505
1511
  }).on("error", reject);
1506
1512
  });
1507
1513
  await pipeline(response, createWriteStream(outputLocationPath));
1514
+ return { duration: formatTime(Date.now() - startTime) };
1508
1515
  };
1509
1516
 
1510
1517
  // src/downloadLatestArtifacts.ts
1511
1518
  var downloadLatestArtifacts = async (options) => {
1512
1519
  saveOptions(options);
1513
1520
  if (!isEnvValid()) return process.exit(1);
1514
- const latestBuild = await oraPromise(getLatestBuild(options), {
1521
+ const latestBuild = await oraPromise(getLatestBuild(), {
1515
1522
  text: "fetching latest build",
1516
1523
  failText: (error) => `fetching latest build failed with error: ${error}`
1517
1524
  });
1518
- if (!latestBuild.slug) {
1519
- console.log("Latest build contained no Slug");
1520
- return process.exit(1);
1521
- }
1525
+ if (!latestBuild.slug) throw Error("Latest build contained no Slug");
1522
1526
  const artifactMetadata = await oraPromise(fetchArtifactByType(latestBuild.slug), {
1523
1527
  text: "fetching artifact list",
1524
1528
  failText: (error) => `fetching artifact list failed with error: ${error}`
1525
1529
  });
1526
- if (options.debug) debugLog("artifactMetadata", artifactMetadata);
1527
- if (!artifactMetadata || !artifactMetadata.slug) return process.exit(1);
1530
+ if (!artifactMetadata.slug || !artifactMetadata.title) throw Error("Artifact was Invalid");
1528
1531
  const artifact = await oraPromise(
1529
- fetchArtifact({
1530
- artifactSlug: artifactMetadata.slug,
1531
- buildSlug: latestBuild.slug
1532
- }),
1532
+ fetchArtifact({ artifactSlug: artifactMetadata.slug, buildSlug: latestBuild.slug }),
1533
1533
  { text: "fetching artifact metadata" }
1534
1534
  );
1535
- if (options.debug) debugLog("artifact", artifact);
1536
- if (!artifact || !artifact.expiringDownloadUrl || !artifactMetadata.title) {
1537
- console.log("Artifact is missing data");
1538
- return process.exit(1);
1539
- }
1535
+ if (!artifact.expiringDownloadUrl) throw Error("Artifact is missing expiringDownloadUrl");
1540
1536
  const fileSize = formatBytes(artifact.fileSizeBytes ?? 0);
1541
1537
  await oraPromise(downloadFile(artifact.expiringDownloadUrl, artifactMetadata.title), {
1542
- text: `downloading apk file (${fileSize})`
1538
+ text: `downloading apk file (${fileSize})`,
1539
+ successText: ({ duration }) => `downloading apk file took ${duration}`
1543
1540
  });
1544
1541
  };
1545
1542
 
1546
- // src/bin.ts
1547
- var program = new Command();
1548
- program.version("0.0.4");
1549
- program.command("download").option("-t, --token <TOKEN>", "bitrise api token (or $BITRISE_API_CLI_TOKEN)", process.env.BITRISE_API_CLI_TOKEN).option(
1550
- "-w, --workflow <WORKFLOW_NAME>",
1551
- "workflow to get apk from (or $BITRISE_API_CLI_WORKFLOW)",
1552
- process.env.BITRISE_API_CLI_WORKFLOW
1553
- ).option(
1554
- "-s, --slug <APP_SLUG>",
1555
- "bitrise app slug (or $BITRISE_APP_SLUG) see bitrise project url to get slug",
1556
- process.env.BITRISE_APP_SLUG
1557
- ).option("-a, --artifact <ARTIFACT_TYPE>", 'bitrise artifact type "ios-ipa" or "android-apk"', "android-apk").option("-d, --debug", "output extra debugging", false).description("Download bitrise artifacts").action((options) => downloadLatestArtifacts(options).catch(() => process.exit(1)));
1558
- program.parse(process.argv);
1543
+ // src/cli/impl.ts
1544
+ async function impl_default(flags) {
1545
+ if (flags.debug) console.log(JSON.stringify(flags, null, 2));
1546
+ return downloadLatestArtifacts(flags);
1547
+ }
1548
+ export {
1549
+ impl_default as default
1550
+ };
package/package.json CHANGED
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "name": "bitrise-api-cli",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "bitrise api CLI wrapper",
5
5
  "module": "index",
6
6
  "type": "module",
7
7
  "bin": {
8
- "bitrise-api-cli": "./dist/bin.js"
8
+ "bitrise-api-cli": "./dist/cli.js",
9
+ "__bitrise-api-cli_bash_complete": "dist/bash-complete.js"
9
10
  },
10
- "keywords": ["bitrise", "bitriseio"],
11
+ "keywords": ["bitrise", "bitriseio", "apk", "downloader"],
11
12
  "license": "MIT",
12
- "main": "dist/bin.js",
13
+ "main": "dist/cli.js",
13
14
  "files": ["dist"],
14
15
  "scripts": {
15
16
  "build": "tsup",
16
- "build:dev": "tsup --watch",
17
+ "build:dev": "tsup --watch --clean false",
17
18
  "lint": "bunx biome check --fix",
18
19
  "lint:CI": "bunx biome check",
19
20
  "typecheck": "tsc",
@@ -22,14 +23,15 @@
22
23
  "prepublishOnly": "bun i && bun run lint:CI && tsc && bun run build"
23
24
  },
24
25
  "dependencies": {
25
- "commander": "13.1.0",
26
+ "@stricli/core": "1.1.1",
27
+ "@stricli/auto-complete": "1.1.1",
26
28
  "ora": "8.2.0"
27
29
  },
28
30
  "devDependencies": {
29
31
  "@biomejs/biome": "1.9.4",
30
32
  "@openapitools/openapi-generator-cli": "2.16.3",
31
33
  "@types/bun": "latest",
32
- "tsup": "8.3.5",
34
+ "tsup": "8.3.6",
33
35
  "typescript": "5.7.3"
34
36
  }
35
37
  }