@zeroheight/adoption-cli 2.1.0 → 2.2.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,5 +1,13 @@
1
1
  # Release notes
2
2
 
3
+ ## [2.2.1](https://www.npmjs.com/package/@zeroheight/adoption-cli/v/2.2.1) - 13th November 2024
4
+
5
+ - Handle API throttling
6
+
7
+ ## [2.2.0](https://www.npmjs.com/package/@zeroheight/adoption-cli/v/2.2.0) - 8th November 2024
8
+
9
+ - Include export names in package file as part of component analyzing
10
+
3
11
  ## [2.1.0](https://www.npmjs.com/package/@zeroheight/adoption-cli/v/2.1.0) - 8th November 2024
4
12
 
5
13
  - Start collecting component property usage data as part of component analyzing
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("2.1.0")
15
+ .version("2.2.1")
16
16
  .addHelpText("before", output)
17
17
  .addCommand(analyzeCommand())
18
18
  .addCommand(authCommand())
@@ -8,3 +8,7 @@ export declare function getPackageInfo(): Promise<{
8
8
  files: PackageFile[];
9
9
  error: string | null;
10
10
  }>;
11
+ /**
12
+ * Transform exports object into fully qualified aliases
13
+ */
14
+ export declare function getAliasesFromExports(packageName: string, exports?: PackageFile["exports"]): string[];
@@ -21,10 +21,12 @@ export async function getPackageInfo() {
21
21
  try {
22
22
  const packageFiles = await Promise.all(files.map(async (file) => {
23
23
  const fileContents = await readFile(file, "utf-8");
24
+ const parsedPackage = JSON.parse(fileContents);
24
25
  return {
25
- name: JSON.parse(fileContents).name,
26
+ name: parsedPackage.name,
26
27
  path: `.${files[0]?.split(base).pop()}`,
27
- version: JSON.parse(fileContents).version,
28
+ version: parsedPackage.version,
29
+ exports: parsedPackage.exports,
28
30
  };
29
31
  }));
30
32
  return {
@@ -39,3 +41,13 @@ export async function getPackageInfo() {
39
41
  };
40
42
  }
41
43
  }
44
+ /**
45
+ * Transform exports object into fully qualified aliases
46
+ */
47
+ export function getAliasesFromExports(packageName, exports) {
48
+ if (!exports)
49
+ return [];
50
+ return Object.keys(exports)
51
+ .map((path) => joinPath(packageName, path))
52
+ .filter((name) => name !== packageName);
53
+ }
@@ -39,7 +39,7 @@ interface PackageDetailsSuccessResponse {
39
39
  updated_at: string;
40
40
  };
41
41
  }
42
- export declare function submitPackageDetails(name: string, path: string, version: string, credentials: Credentials): Promise<APIResponse<PackageDetailsSuccessResponse, {}, {}>>;
42
+ export declare function submitPackageDetails(name: string, path: string, version: string, aliases: string[], credentials: Credentials): Promise<APIResponse<PackageDetailsSuccessResponse, {}, {}>>;
43
43
  interface MonitoredRepoDetailsSuccess {
44
44
  monitored_repository: {
45
45
  id: number;
@@ -13,11 +13,12 @@ export function getZeroheightURL() {
13
13
  return new URL("https://zeroheight.com");
14
14
  }
15
15
  }
16
- export async function submitPackageDetails(name, path, version, credentials) {
16
+ export async function submitPackageDetails(name, path, version, aliases, credentials) {
17
17
  return post("/design_system_packages", {
18
18
  name,
19
19
  path,
20
20
  latest_version: version,
21
+ aliases,
21
22
  }, credentials);
22
23
  }
23
24
  export async function submitMonitoredRepoDetails(name, version, lockfilePath, packages, credentials) {
@@ -51,25 +52,40 @@ async function post(path, body, credentials) {
51
52
  body: JSON.stringify(body),
52
53
  });
53
54
  }
55
+ async function sleep(ms) {
56
+ return new Promise((resolve) => setTimeout(resolve, ms));
57
+ }
54
58
  async function request(path, credentials, init) {
55
59
  const url = getZeroheightURL();
56
60
  url.pathname = API_PATH + path;
57
61
  if (process.env["NODE_ENV"] === "dev") {
58
62
  process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
59
63
  }
60
- const response = await fetch(url, {
61
- ...init,
62
- headers: {
63
- "X-API-CLIENT-NAME": "cli",
64
- "X-API-CLIENT": credentials.client,
65
- "X-API-KEY": credentials.token,
66
- "Content-Type": "application/json",
67
- },
68
- });
69
- if (response.status === 401) {
70
- throw new Error("Unauthorized");
64
+ const maxRetries = 3;
65
+ let retries = 0;
66
+ while (retries < maxRetries) {
67
+ const response = await fetch(url, {
68
+ ...init,
69
+ headers: {
70
+ "X-API-CLIENT-NAME": "cli",
71
+ "X-API-CLIENT": credentials.client,
72
+ "X-API-KEY": credentials.token,
73
+ "Content-Type": "application/json",
74
+ },
75
+ });
76
+ if (response.status === 401) {
77
+ throw new Error("Unauthorized");
78
+ }
79
+ else if (response.status === 429) {
80
+ retries++;
81
+ const responseData = await response.json();
82
+ const waitTime = responseData.data.reset_time * 1000 - Date.now();
83
+ await sleep(waitTime);
84
+ continue;
85
+ }
86
+ return await response.json();
71
87
  }
72
- return await response.json();
88
+ throw new Error(`Request failed after ${maxRetries} retries`);
73
89
  }
74
90
  export function mergeUsageProps(newProps, currentProps) {
75
91
  if (!currentProps)
@@ -5,4 +5,9 @@ export interface PackageFile {
5
5
  name: string;
6
6
  path: string;
7
7
  version: string;
8
+ exports?: Record<string, Partial<{
9
+ import: string;
10
+ require: string;
11
+ types: string;
12
+ }> | string>;
8
13
  }
@@ -2,7 +2,7 @@ import React from "react";
2
2
  import { Newline, Text, useApp } from "ink";
3
3
  import Spinner from "ink-spinner";
4
4
  import { readConfig } from "../../common/config.js";
5
- import { getPackageInfo } from "../../commands/track-package.utils.js";
5
+ import { getAliasesFromExports, getPackageInfo, } from "../../commands/track-package.utils.js";
6
6
  import { ResponseStatus, submitPackageDetails } from "../../common/api.js";
7
7
  var Step;
8
8
  (function (Step) {
@@ -24,11 +24,12 @@ export default function NonInteractiveTrackPackage() {
24
24
  const { files, error } = await getPackageInfo();
25
25
  try {
26
26
  if (files.length === 1) {
27
- const { name, path, version } = files[0];
27
+ const { name, path, version, exports } = files[0];
28
28
  setPackageName(name);
29
29
  setPackageVersion(version);
30
30
  setCurrentStep(Step.SINGLE_PACKAGE_FOUND);
31
- const response = await submitPackageDetails(name, path, version, {
31
+ const aliases = getAliasesFromExports(name, exports);
32
+ const response = await submitPackageDetails(name, path, version, aliases, {
32
33
  token: config.token,
33
34
  client: config.client,
34
35
  });
@@ -46,7 +47,8 @@ export default function NonInteractiveTrackPackage() {
46
47
  setPackageFiles(files);
47
48
  setCurrentStep(Step.MULTIPLE_PACKAGES_FOUND);
48
49
  await Promise.all(files.map(async (pack) => {
49
- await submitPackageDetails(pack.name, pack.path, pack.version, {
50
+ const aliases = getAliasesFromExports(pack.name, pack.exports);
51
+ await submitPackageDetails(pack.name, pack.path, pack.version, aliases, {
50
52
  token: config.token,
51
53
  client: config.client,
52
54
  });
@@ -5,7 +5,7 @@ import SelectInput from "ink-select-input";
5
5
  import Spinner from "ink-spinner";
6
6
  import ConfirmInput from "../ui/confirm-input.js";
7
7
  import { readConfig } from "../../common/config.js";
8
- import { getPackageInfo } from "../../commands/track-package.utils.js";
8
+ import { getAliasesFromExports, getPackageInfo, } from "../../commands/track-package.utils.js";
9
9
  import { submitPackageDetails } from "../../common/api.js";
10
10
  var Step;
11
11
  (function (Step) {
@@ -28,12 +28,13 @@ export default function TrackPackage() {
28
28
  const [packageName, setPackageName] = React.useState(null);
29
29
  const [packagePath, setPackagePath] = React.useState(null);
30
30
  const [packageVersion, setPackageVersion] = React.useState(null);
31
+ const [packageAliases, setPackageAliases] = React.useState([]);
31
32
  const [shouldSend, setShouldSend] = React.useState("");
32
33
  const [shouldMultiSelect, setShouldMultiSelect] = React.useState("");
33
34
  const [packageSelection, setPackageSelection] = React.useState([]);
34
35
  const [selectedFileLabels, setSelectedFileLabels] = React.useState([]);
35
- async function submitPackage(name, path, version) {
36
- await submitPackageDetails(name, path, version, credentials);
36
+ async function submitPackage(name, path, version, aliases) {
37
+ await submitPackageDetails(name, path, version, aliases, credentials);
37
38
  }
38
39
  async function sendData() {
39
40
  setCurrentStep(Step.SENDING_DETAILS);
@@ -42,18 +43,20 @@ export default function TrackPackage() {
42
43
  const packagesToSend = packageFiles.filter((p) => selectedFileLabels.includes(`${p.name}@${p.version}`));
43
44
  if (packagesToSend.length > 0) {
44
45
  await Promise.all(packagesToSend.map(async (pack) => {
45
- submitPackage(pack.name, pack.path, pack.version);
46
+ const aliases = getAliasesFromExports(pack.name, pack.exports);
47
+ submitPackage(pack.name, pack.path, pack.version, aliases);
46
48
  }));
47
49
  }
48
50
  else {
49
51
  await Promise.all(packageFiles.map(async (pack) => {
50
- submitPackage(pack.name, pack.path, pack.version);
52
+ const aliases = getAliasesFromExports(pack.name, pack.exports);
53
+ submitPackage(pack.name, pack.path, pack.version, aliases);
51
54
  }));
52
55
  }
53
56
  setCurrentStep(Step.COMPLETE);
54
57
  }
55
58
  else {
56
- await submitPackage(packageName, packagePath, packageVersion);
59
+ await submitPackage(packageName, packagePath, packageVersion, packageAliases);
57
60
  setCurrentStep(Step.COMPLETE);
58
61
  }
59
62
  }
@@ -101,10 +104,11 @@ export default function TrackPackage() {
101
104
  }
102
105
  const { files, error } = await getPackageInfo();
103
106
  if (files.length === 1) {
104
- const { name, path, version } = files[0];
107
+ const { name, path, version, exports } = files[0];
105
108
  setPackageName(name);
106
109
  setPackagePath(path);
107
110
  setPackageVersion(version);
111
+ setPackageAliases(getAliasesFromExports(name, exports));
108
112
  setCurrentStep(Step.SINGLE_PACKAGE_FOUND);
109
113
  }
110
114
  else if (files.length > 1) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroheight/adoption-cli",
3
- "version": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "license": "ISC",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {