@zeroheight/adoption-cli 1.2.0 → 2.0.1

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/CHANGELOG.md CHANGED
@@ -1,9 +1,23 @@
1
1
  # Release notes
2
2
 
3
+ ## [2.0.1](https://www.npmjs.com/package/@zeroheight/adoption-cli/v/2.0.1) - 21st October 2024
4
+
5
+ - Update help text and link
6
+
7
+ ## [2.0.0](https://www.npmjs.com/package/@zeroheight/adoption-cli/v/2.0.0) - 21st October 2024
8
+
9
+ - Use new API endpoints
10
+
11
+ ## [1.2.1](https://www.npmjs.com/package/@zeroheight/adoption-cli/v/1.2.1) - 18th October 2024
12
+
13
+ - Update error handling internally
14
+
3
15
  ## [1.2.0](https://www.npmjs.com/package/@zeroheight/adoption-cli/v/1.2.0) - 17th October 2024
16
+
4
17
  - Support scoped packages in Yarn lockfiles
5
18
 
6
19
  ## [1.1.0](https://www.npmjs.com/package/@zeroheight/adoption-cli/v/1.1.0) - 17th October 2024
20
+
7
21
  - Validate authentication credentials on set up
8
22
 
9
23
  ## [1.0.0](https://www.npmjs.com/package/@zeroheight/adoption-cli/v/1.0.0) - 16th October 2024
package/dist/cli.js CHANGED
@@ -12,7 +12,7 @@ const { output, cleanup } = render(React.createElement(HelpInfo, null));
12
12
  program
13
13
  .name("zh-adoption")
14
14
  .description("CLI for measuring design system usage usage in your products")
15
- .version("1.2.0")
15
+ .version("2.0.1")
16
16
  .addHelpText("before", output)
17
17
  .addCommand(analyzeCommand())
18
18
  .addCommand(authCommand())
@@ -1,23 +1,82 @@
1
1
  import { RawUsageMap } from "../commands/analyze.js";
2
2
  import { Credentials } from "./config.js";
3
+ export declare enum ResponseStatus {
4
+ Success = "success",
5
+ Error = "error",
6
+ Fail = "fail"
7
+ }
3
8
  /**
4
9
  * Open API V2 Response format
5
10
  */
6
- interface APIResponse<T> {
7
- status: string;
11
+ interface BaseResponse<T> {
12
+ status: ResponseStatus;
8
13
  message: string;
9
14
  data: T;
10
15
  }
16
+ interface SuccessResponse<T> extends BaseResponse<T> {
17
+ status: ResponseStatus.Success;
18
+ }
19
+ interface FailResponse<T> extends BaseResponse<T> {
20
+ status: ResponseStatus.Fail;
21
+ }
22
+ interface ErrorResponse<T> extends BaseResponse<T> {
23
+ status: ResponseStatus.Error;
24
+ }
25
+ export type APIResponse<S = {}, F = {}, E = {}> = SuccessResponse<S> | FailResponse<F> | ErrorResponse<E>;
11
26
  export declare function getZeroheightURL(): URL;
12
- export declare function submitPackageDetails(name: string, path: string, version: string, credentials: Credentials): Promise<APIResponse<any>>;
27
+ interface PackageDetailsSuccessResponse {
28
+ design_system_packages: {
29
+ id: number;
30
+ name: string;
31
+ path: string;
32
+ latest_version: string;
33
+ source: string;
34
+ repository_id: number | null;
35
+ team_id: number | null;
36
+ project_id: number | null;
37
+ created_at: string;
38
+ updated_at: string;
39
+ };
40
+ }
41
+ export declare function submitPackageDetails(name: string, path: string, version: string, credentials: Credentials): Promise<APIResponse<PackageDetailsSuccessResponse, {}, {}>>;
42
+ interface MonitoredRepoDetailsSuccess {
43
+ monitored_repository: {
44
+ id: number;
45
+ lock_file_path: string;
46
+ repository_id: number;
47
+ team_id: number | null;
48
+ project_id: number | null;
49
+ created_at: string;
50
+ updated_at: string;
51
+ name: string;
52
+ source: string;
53
+ };
54
+ }
13
55
  export declare function submitMonitoredRepoDetails(name: string, version: string, lockfilePath: string, packages: {
14
56
  name: string;
15
57
  version: string;
16
- }[], credentials: Credentials): Promise<APIResponse<{
17
- errors: string[];
18
- }>>;
19
- export declare function submitUsageData(usage: RawUsageMap, repoName: string, credentials: Credentials): Promise<any>;
20
- export declare function getExistingRepoNames(credentials: Credentials): Promise<string[]>;
58
+ }[], credentials: Credentials): Promise<APIResponse<MonitoredRepoDetailsSuccess>>;
59
+ interface ComponentUsageDetailsSuccess {
60
+ component_usage: {
61
+ id: number;
62
+ usage: {
63
+ name: string;
64
+ count: number;
65
+ package: string;
66
+ files: string[];
67
+ }[];
68
+ team_id: number | null;
69
+ project_id: number | null;
70
+ created_at: string;
71
+ updated_at: string;
72
+ repo_name: string;
73
+ };
74
+ }
75
+ export declare function submitUsageData(usage: RawUsageMap, repoName: string, credentials: Credentials): Promise<APIResponse<ComponentUsageDetailsSuccess>>;
76
+ interface RepoNamesSuccss {
77
+ repo_names: string[];
78
+ }
79
+ export declare function getExistingRepoNames(credentials: Credentials): Promise<APIResponse<RepoNamesSuccss>>;
21
80
  interface AuthTokensResponse {
22
81
  scopes: string[];
23
82
  email: string;
@@ -30,5 +89,5 @@ interface AuthTokensResponse {
30
89
  name: string;
31
90
  };
32
91
  }
33
- export declare function getAuthDetails(credentials: Credentials): Promise<AuthTokensResponse>;
92
+ export declare function getAuthDetails(credentials: Credentials): Promise<APIResponse<AuthTokensResponse>>;
34
93
  export {};
@@ -1,3 +1,10 @@
1
+ const API_PATH = "/open_api/v2";
2
+ export var ResponseStatus;
3
+ (function (ResponseStatus) {
4
+ ResponseStatus["Success"] = "success";
5
+ ResponseStatus["Error"] = "error";
6
+ ResponseStatus["Fail"] = "fail";
7
+ })(ResponseStatus || (ResponseStatus = {}));
1
8
  export function getZeroheightURL() {
2
9
  if (process.env["NODE_ENV"] === "dev") {
3
10
  return new URL("https://zeroheight.dev");
@@ -7,14 +14,14 @@ export function getZeroheightURL() {
7
14
  }
8
15
  }
9
16
  export async function submitPackageDetails(name, path, version, credentials) {
10
- return post("/open_api/v2/design_system_packages", {
17
+ return post("/design_system_packages", {
11
18
  name,
12
19
  path,
13
20
  latest_version: version,
14
21
  }, credentials);
15
22
  }
16
23
  export async function submitMonitoredRepoDetails(name, version, lockfilePath, packages, credentials) {
17
- return post("/open_api/v2/monitored_repositories", {
24
+ return post("/monitored_repositories", {
18
25
  name,
19
26
  lock_file_path: lockfilePath,
20
27
  packages,
@@ -22,17 +29,16 @@ export async function submitMonitoredRepoDetails(name, version, lockfilePath, pa
22
29
  }, credentials);
23
30
  }
24
31
  export async function submitUsageData(usage, repoName, credentials) {
25
- return post("/open_api/v1/component_usages", {
32
+ return post("/component_usages", {
26
33
  repo_name: repoName,
27
34
  usage: transformUsageByName(usage),
28
35
  }, credentials);
29
36
  }
30
- export function getExistingRepoNames(credentials) {
31
- return get("/open_api/v1/component_usages/repo_names", credentials);
37
+ export async function getExistingRepoNames(credentials) {
38
+ return get("/component_usages/repo_names", credentials);
32
39
  }
33
40
  export async function getAuthDetails(credentials) {
34
- const response = await get("/open_api/v2/auth_tokens", credentials);
35
- return response.data;
41
+ return get("/auth_tokens", credentials);
36
42
  }
37
43
  async function get(path, credentials) {
38
44
  return request(path, credentials, {
@@ -47,7 +53,7 @@ async function post(path, body, credentials) {
47
53
  }
48
54
  async function request(path, credentials, init) {
49
55
  const url = getZeroheightURL();
50
- url.pathname = path;
56
+ url.pathname = API_PATH + path;
51
57
  if (process.env["NODE_ENV"] === "dev") {
52
58
  process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
53
59
  }
@@ -8,7 +8,7 @@ import NoCredentialsOnboarding from "../auth/no-credentials-onboarding.js";
8
8
  import RepoNamePrompt from "../repo-name-prompt.js";
9
9
  import UsageTable from "../usage-table.js";
10
10
  import { configPath, writeConfig, readConfig, } from "../../common/config.js";
11
- import { getAuthDetails, getZeroheightURL, submitUsageData, } from "../../common/api.js";
11
+ import { ResponseStatus, getAuthDetails, getZeroheightURL, submitUsageData, } from "../../common/api.js";
12
12
  import { calculateNumberOfComponents } from "../../commands/analyze.utils.js";
13
13
  export default function Analyze({ onAnalyzeFiles, dryRun, repoName, }) {
14
14
  const { exit } = useApp();
@@ -49,8 +49,11 @@ export default function Analyze({ onAnalyzeFiles, dryRun, repoName, }) {
49
49
  setIsSendingData(true);
50
50
  try {
51
51
  await submitUsageData(result, repoName, credentials);
52
- const authDetails = await getAuthDetails(credentials);
53
- const projectId = authDetails.project?.id;
52
+ const authDetailsResponse = await getAuthDetails(credentials);
53
+ if (authDetailsResponse.status !== ResponseStatus.Success) {
54
+ throw new Error("Failed to get credentials");
55
+ }
56
+ const projectId = authDetailsResponse.data.project?.id;
54
57
  const resourceURL = getZeroheightURL();
55
58
  resourceURL.pathname = projectId
56
59
  ? `/project/${projectId}/adoption/`
@@ -1,24 +1,24 @@
1
1
  import * as React from "react";
2
- import { Box, Newline, Text } from "ink";
2
+ import { Box, Text } from "ink";
3
3
  import Link from "ink-link";
4
4
  /**
5
5
  * Rich help banner with link to help center docs
6
6
  */
7
7
  export default function HelpInfo() {
8
8
  return (React.createElement(React.Fragment, null,
9
- React.createElement(Box, { borderStyle: "double", padding: 2, margin: 1, flexDirection: "column" },
10
- React.createElement(Box, { justifyContent: "center" },
9
+ React.createElement(Box, { borderStyle: "double", paddingLeft: 1, paddingRight: 1, marginBottom: 1, flexDirection: "column" },
10
+ React.createElement(Box, { justifyContent: "center", marginBottom: 1 },
11
11
  React.createElement(Text, { bold: true }, "Welcome \uD83D\uDC4B")),
12
- React.createElement(Newline, null),
13
- React.createElement(Text, null,
14
- "Get started with the",
15
- " ",
16
- React.createElement(Text, { color: "#f63e7c", bold: true }, "zeroheight"),
17
- " ",
18
- "measurement CLI and start tracking your component usage."),
12
+ React.createElement(Box, { marginBottom: 1 },
13
+ React.createElement(Text, null,
14
+ "Get started with the",
15
+ " ",
16
+ React.createElement(Text, { color: "#f63e7c", bold: true }, "zeroheight"),
17
+ " ",
18
+ "measurement CLI and start tracking your design system's adoption.")),
19
19
  React.createElement(Text, null,
20
20
  "For more information on how to set this up, check",
21
21
  " ",
22
- React.createElement(Link, { url: "https://zeroheight.com/help/article/component-usage/" }, "here"),
22
+ React.createElement(Link, { url: "https://zeroheight.com/help/article/adoption-private-beta-overview/" }, "here"),
23
23
  "."))));
24
24
  }
@@ -4,7 +4,7 @@ import Spinner from "ink-spinner";
4
4
  import { join as joinPath } from "path";
5
5
  import { findLockfiles, getPackageMeta, groupByBasename, parseLockfile, } from "../../commands/monitor-repo.utils.js";
6
6
  import { findPackageFiles } from "../../commands/track-package.utils.js";
7
- import { submitMonitoredRepoDetails } from "../../common/api.js";
7
+ import { ResponseStatus, submitMonitoredRepoDetails, } from "../../common/api.js";
8
8
  import { readConfig } from "../../common/config.js";
9
9
  import YarnLockParser from "../../lockfile-parsers/yarn-lock-parser.js";
10
10
  var Step;
@@ -74,7 +74,7 @@ export default function NonInteractiveMonitorRepo({ packageDirs, }) {
74
74
  token: config.token,
75
75
  client: config.client,
76
76
  });
77
- if (response.status === "success") {
77
+ if (response.status === ResponseStatus.Success) {
78
78
  updateRepoStatus(packageMeta.name, Step.COMPLETE);
79
79
  }
80
80
  else {
@@ -3,7 +3,7 @@ import { Box, Text } from "ink";
3
3
  import Spinner from "ink-spinner";
4
4
  import SelectInput from "ink-select-input";
5
5
  import { readConfig } from "../common/config.js";
6
- import { getExistingRepoNames } from "../common/api.js";
6
+ import { ResponseStatus, getExistingRepoNames } from "../common/api.js";
7
7
  import TextInput from "ink-text-input";
8
8
  var RepoNamePromptState;
9
9
  (function (RepoNamePromptState) {
@@ -18,7 +18,11 @@ export default function RepoNamePrompt({ credentials, onRepoNameSelected, }) {
18
18
  const [repoName, setRepoName] = React.useState("");
19
19
  async function loadRepoNames(credentials) {
20
20
  try {
21
- const names = await getExistingRepoNames(credentials);
21
+ const repoNamesResponse = await getExistingRepoNames(credentials);
22
+ if (repoNamesResponse.status !== ResponseStatus.Success) {
23
+ throw new Error("Failed to get repo names");
24
+ }
25
+ const names = repoNamesResponse.data.repo_names;
22
26
  setRepoNames(names);
23
27
  if (names.length === 0) {
24
28
  setState(RepoNamePromptState.ENTER_REPO_NAME);
@@ -3,7 +3,7 @@ import { Newline, Text, useApp } from "ink";
3
3
  import Spinner from "ink-spinner";
4
4
  import { readConfig } from "../../common/config.js";
5
5
  import { getPackageInfo } from "../../commands/track-package.utils.js";
6
- import { submitPackageDetails } from "../../common/api.js";
6
+ import { ResponseStatus, submitPackageDetails } from "../../common/api.js";
7
7
  var Step;
8
8
  (function (Step) {
9
9
  Step[Step["COMPLETE"] = 0] = "COMPLETE";
@@ -32,13 +32,13 @@ export default function NonInteractiveTrackPackage() {
32
32
  token: config.token,
33
33
  client: config.client,
34
34
  });
35
- if (response.status === "error") {
36
- setErrorMessage(response.message);
37
- setCurrentStep(Step.ERRORED);
35
+ if (response.status === ResponseStatus.Success) {
36
+ setCurrentStep(Step.COMPLETE);
38
37
  exit();
39
38
  }
40
39
  else {
41
- setCurrentStep(Step.COMPLETE);
40
+ setErrorMessage(response.message);
41
+ setCurrentStep(Step.ERRORED);
42
42
  exit();
43
43
  }
44
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroheight/adoption-cli",
3
- "version": "1.2.0",
3
+ "version": "2.0.1",
4
4
  "license": "ISC",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {