@zeroheight/adoption-cli 2.4.2 → 3.0.0

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,18 +2,19 @@ import React from "react";
2
2
  import { Box, Newline, Text } from "ink";
3
3
  import Spinner from "ink-spinner";
4
4
  import Link from "ink-link";
5
- import { calculateNumberOfComponents } from "../../commands/analyze.utils.js";
5
+ import { calculateNumberOfColors, calculateNumberOfComponents, } from "../../commands/analyze.utils.js";
6
6
  import { readConfig } from "../../common/config.js";
7
- import { submitUsageData } from "../../common/api.js";
7
+ import { submitComponentUsageData, submitTokenLiteralUsageData, } from "../../common/api.js";
8
8
  import { ApiError } from "../../common/errors.js";
9
- export default function NonInteractiveAnalyze({ repoName, onAnalyzeFiles, }) {
9
+ export default function NonInteractiveAnalyze({ repoName, onAnalyzeFiles, onAnalyzeColorUsage, shouldAnalyzeComponentUsage, shouldAnalyzeTokenUsage, }) {
10
10
  const [isSendingData, setIsSendingData] = React.useState(false);
11
11
  const [isAnalyzingFiles, setIsAnalyzingFiles] = React.useState(false);
12
12
  const [isFetchingCredentials, setIsFetchingCredentials] = React.useState(false);
13
13
  const [errorFileLocation, setErrorFileLocation] = React.useState(null);
14
14
  const [errorList, setErrorList] = React.useState([]);
15
15
  const [credentials, setCredentials] = React.useState(null);
16
- const [usage, setUsage] = React.useState(null);
16
+ const [componentUsage, setComponentUsage] = React.useState(null);
17
+ const [colorUsage, setColorUsage] = React.useState(null);
17
18
  async function loadCredentials() {
18
19
  setIsFetchingCredentials(true);
19
20
  try {
@@ -31,13 +32,13 @@ export default function NonInteractiveAnalyze({ repoName, onAnalyzeFiles, }) {
31
32
  }
32
33
  return null;
33
34
  }
34
- async function sendData(result, repoName, credentials) {
35
+ async function sendComponentUsageData(result, repoName, credentials) {
35
36
  setIsSendingData(true);
36
37
  try {
37
- await submitUsageData(result, repoName, credentials);
38
+ await submitComponentUsageData(result, repoName, credentials);
38
39
  }
39
40
  catch (e) {
40
- let errorMessage = "Failed to send data to zeroheight";
41
+ let errorMessage = "Failed to send component usage data to zeroheight";
41
42
  if (e instanceof ApiError) {
42
43
  errorMessage = e.message;
43
44
  }
@@ -47,10 +48,36 @@ export default function NonInteractiveAnalyze({ repoName, onAnalyzeFiles, }) {
47
48
  setIsSendingData(false);
48
49
  }
49
50
  }
50
- async function anaylzeUsage() {
51
+ async function sendTokenUsageData(result, repoName, credentials) {
52
+ setIsSendingData(true);
53
+ try {
54
+ await submitTokenLiteralUsageData(result, repoName, credentials);
55
+ }
56
+ catch (e) {
57
+ let errorMessage = "Failed to send color usage data to zeroheight";
58
+ if (e instanceof ApiError) {
59
+ errorMessage = e.message;
60
+ }
61
+ setErrorList((s) => [...s, errorMessage]);
62
+ }
63
+ finally {
64
+ setIsSendingData(false);
65
+ }
66
+ }
67
+ async function analyzeComponentUsage() {
51
68
  setIsAnalyzingFiles(true);
52
69
  const { errorFile, usage } = await onAnalyzeFiles();
53
- setUsage(usage);
70
+ setComponentUsage(usage);
71
+ if (errorFile) {
72
+ setErrorFileLocation(errorFile);
73
+ }
74
+ setIsAnalyzingFiles(false);
75
+ return usage;
76
+ }
77
+ async function analyzeTokenUsage() {
78
+ setIsAnalyzingFiles(true);
79
+ const { errorFile, usage } = await onAnalyzeColorUsage();
80
+ setColorUsage(usage);
54
81
  if (errorFile) {
55
82
  setErrorFileLocation(errorFile);
56
83
  }
@@ -62,18 +89,25 @@ export default function NonInteractiveAnalyze({ repoName, onAnalyzeFiles, }) {
62
89
  const credentials = await loadCredentials();
63
90
  if (!credentials)
64
91
  return;
65
- const usage = await anaylzeUsage();
66
92
  if (!repoName)
67
93
  return;
68
- await sendData(usage, repoName, credentials);
94
+ if (shouldAnalyzeComponentUsage) {
95
+ const componentUsageMap = await analyzeComponentUsage();
96
+ await sendComponentUsageData(componentUsageMap, repoName, credentials);
97
+ }
98
+ if (shouldAnalyzeTokenUsage) {
99
+ const colorUsageMap = await analyzeTokenUsage();
100
+ await sendTokenUsageData(colorUsageMap, repoName, credentials);
101
+ }
69
102
  })();
70
103
  }, []);
71
104
  if (isAnalyzingFiles || isFetchingCredentials || isSendingData) {
72
105
  return (React.createElement(Text, null,
73
106
  React.createElement(Spinner, { type: "dots" }),
74
- isAnalyzingFiles && React.createElement(Text, null, "Analyzing components"),
107
+ " ",
108
+ isAnalyzingFiles && React.createElement(Text, null, "Analyzing files"),
75
109
  isFetchingCredentials && React.createElement(Text, null, "Loading credentials"),
76
- isSendingData && React.createElement(Text, null, "Sending data to zerohegiht")));
110
+ isSendingData && React.createElement(Text, null, "Sending data to zeroheight")));
77
111
  }
78
112
  if (errorList.length > 0) {
79
113
  return (React.createElement(Box, { flexDirection: "column" },
@@ -115,12 +149,16 @@ export default function NonInteractiveAnalyze({ repoName, onAnalyzeFiles, }) {
115
149
  " ",
116
150
  React.createElement(Text, { italic: true }, "--interactive false")));
117
151
  }
118
- if (!usage) {
152
+ if (!componentUsage && !colorUsage) {
119
153
  return React.createElement(Text, null, "No usage could be found.");
120
154
  }
121
- return (React.createElement(React.Fragment, null, usage && (React.createElement(Text, { color: "green" },
122
- calculateNumberOfComponents(usage),
123
- " components found and sent to",
124
- " ",
125
- React.createElement(Text, { color: "#f63e7c" }, "zeroheight")))));
155
+ return (React.createElement(React.Fragment, null,
156
+ componentUsage && (React.createElement(Text, { color: "green" },
157
+ calculateNumberOfComponents(componentUsage),
158
+ " components found and sent to ",
159
+ React.createElement(Text, { color: "#f63e7c" }, "zeroheight"))),
160
+ colorUsage && (React.createElement(Text, { color: "green" },
161
+ calculateNumberOfColors(colorUsage),
162
+ " usages of raw colors found and sent to ",
163
+ React.createElement(Text, { color: "#f63e7c" }, "zeroheight")))));
126
164
  }
@@ -22,7 +22,9 @@ export default function NoCredentialsOnboarding({ onCheckCredentials, onSaveCred
22
22
  React.createElement(Text, null,
23
23
  "If you need a new auth token, generate them from the",
24
24
  " ",
25
- React.createElement(Link, { url: "https://zeroheight.com/settings/team/developers" }, "Developer Settings")),
25
+ React.createElement(Link, { url: "https://zeroheight.com/settings/team/developers" },
26
+ React.createElement(Text, { underline: true, color: "#f63e7c" }, "Developer Settings"))),
27
+ React.createElement(Newline, null),
26
28
  field === "client" && (React.createElement(Box, null,
27
29
  React.createElement(Text, null, "Client ID: "),
28
30
  React.createElement(TextInput, { onChange: setClient, value: client, onSubmit: (v) => {
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ import { RawColorUsageMap } from "../commands/analyze.js";
3
+ interface ColorUsageTableProps {
4
+ usage: RawColorUsageMap;
5
+ }
6
+ export default function ColorUsageTable({ usage }: ColorUsageTableProps): React.JSX.Element;
7
+ export {};
@@ -0,0 +1,38 @@
1
+ import * as React from "react";
2
+ import { Box, Text } from "ink";
3
+ const colorTypeNameMap = {
4
+ hex: "HEX",
5
+ rgb: "RGB",
6
+ hsla: "HSL",
7
+ oklab: "Oklab",
8
+ hwb: "HWB",
9
+ lab: "LAB",
10
+ lch: "LCH",
11
+ colorSpace: "Color space",
12
+ totalCount: "Total usage",
13
+ };
14
+ export default function ColorUsageTable({ usage }) {
15
+ const rows = Array.from(usage.entries());
16
+ return (React.createElement(Box, { flexDirection: "column" }, rows.map(([filepath, rawColorUsage]) => {
17
+ const rowValues = Object.entries(rawColorUsage);
18
+ return (React.createElement(Box, { key: filepath, flexDirection: "column" },
19
+ React.createElement(Text, { color: "green" }, filepath),
20
+ React.createElement(Box, { flexDirection: "column", marginLeft: 2 },
21
+ React.createElement(Box, { flexDirection: "column", marginLeft: 2 }, rowValues.map(([type, values]) => {
22
+ if (type === "totalCount")
23
+ return null;
24
+ const count = values.length;
25
+ if (count === 0)
26
+ return null;
27
+ const name = colorTypeNameMap[type];
28
+ return (React.createElement(Box, { gap: 2, key: `${type}-${count}` },
29
+ React.createElement(Text, { bold: true },
30
+ name,
31
+ ": "),
32
+ React.createElement(Text, null, count)));
33
+ })),
34
+ React.createElement(Text, { bold: true },
35
+ "Total usage: ",
36
+ rawColorUsage.totalCount))));
37
+ })));
38
+ }
@@ -0,0 +1,9 @@
1
+ import * as React from "react";
2
+ interface LatestVersionInfoProps {
3
+ latestVersion: string;
4
+ }
5
+ /**
6
+ * Rich help banner with info about the latest version
7
+ */
8
+ export default function LatestVersionInfo({ latestVersion, }: LatestVersionInfoProps): React.JSX.Element;
9
+ export {};
@@ -0,0 +1,27 @@
1
+ import * as React from "react";
2
+ import { Box, Text } from "ink";
3
+ import Link from "ink-link";
4
+ import { CURRENT_VERSION } from "../cli.js";
5
+ /**
6
+ * Rich help banner with info about the latest version
7
+ */
8
+ export default function LatestVersionInfo({ latestVersion, }) {
9
+ const isMajorVersionOut = Number(CURRENT_VERSION.split(".")[0]) < Number(latestVersion.split(".")[0]);
10
+ return (React.createElement(React.Fragment, null,
11
+ React.createElement(Box, { borderStyle: "double", paddingLeft: 1, paddingRight: 1, marginBottom: 1, flexDirection: "column" },
12
+ React.createElement(Box, { justifyContent: "center", marginBottom: 1 },
13
+ React.createElement(Text, null, "\uD83D\uDC4B It seems you're not using the latest version of this package")),
14
+ React.createElement(Box, { flexDirection: "column", alignItems: "center", marginBottom: 1 },
15
+ React.createElement(Box, null,
16
+ React.createElement(Text, { color: isMajorVersionOut ? "redBright" : "blueBright", bold: true }, CURRENT_VERSION),
17
+ React.createElement(Text, { bold: true }, ` -> `),
18
+ React.createElement(Text, { color: "green", bold: true }, latestVersion)),
19
+ React.createElement(Box, null,
20
+ React.createElement(Text, null, "Update using: "),
21
+ React.createElement(Text, { bold: true }, "npm i @zeroheight/adoption-cli"))),
22
+ React.createElement(Box, { flexDirection: "column", alignItems: "center" },
23
+ React.createElement(Text, null,
24
+ "For more information on the latest version, check",
25
+ " ",
26
+ React.createElement(Link, { url: "https://www.npmjs.com/package/@zeroheight/adoption-cli" }, "here"))))));
27
+ }
@@ -1,2 +1,5 @@
1
1
  import React from "react";
2
- export default function NonInteractiveTrackPackage(): React.JSX.Element;
2
+ export interface NonInteractiveTrackPackageProps {
3
+ allowedPackages?: string[];
4
+ }
5
+ export default function NonInteractiveTrackPackage({ allowedPackages, }: NonInteractiveTrackPackageProps): React.JSX.Element;
@@ -13,7 +13,7 @@ var Step;
13
13
  Step[Step["MULTIPLE_PACKAGES_FOUND"] = 3] = "MULTIPLE_PACKAGES_FOUND";
14
14
  Step[Step["SINGLE_PACKAGE_FOUND"] = 4] = "SINGLE_PACKAGE_FOUND";
15
15
  })(Step || (Step = {}));
16
- export default function NonInteractiveTrackPackage() {
16
+ export default function NonInteractiveTrackPackage({ allowedPackages, }) {
17
17
  const { exit } = useApp();
18
18
  const [currentStep, setCurrentStep] = React.useState(Step.FINDING_DETAILS);
19
19
  const [errorMessage, setErrorMessage] = React.useState(null);
@@ -22,7 +22,7 @@ export default function NonInteractiveTrackPackage() {
22
22
  const [packageVersion, setPackageVersion] = React.useState(null);
23
23
  async function runTrackPackage() {
24
24
  const config = (await readConfig()) ?? { token: "temp", client: "temp" };
25
- const { files, error } = await getPackageInfo();
25
+ const { files, error } = await getPackageInfo(allowedPackages);
26
26
  try {
27
27
  if (files.length === 1) {
28
28
  const { name, path, version, exports } = files[0];
@@ -83,7 +83,7 @@ export default function NonInteractiveTrackPackage() {
83
83
  " searching for package file...")),
84
84
  currentStep === Step.SINGLE_PACKAGE_FOUND && (React.createElement(React.Fragment, null,
85
85
  React.createElement(Text, null,
86
- React.createElement(Text, { color: "green" }, "Details founds:"),
86
+ React.createElement(Text, { color: "green" }, "Details found:"),
87
87
  " ",
88
88
  packageName,
89
89
  "@",
@@ -5,7 +5,10 @@ export default function ContinuePrompt({ onContinue }) {
5
5
  const [shouldContinueText, setShouldContinueText] = React.useState("");
6
6
  return (React.createElement(Box, null,
7
7
  React.createElement(Text, null,
8
- "Continue? ",
8
+ "Send this data to ",
9
+ React.createElement(Text, { color: "#f63e7c" }, "zeroheight"),
10
+ "?",
11
+ " ",
9
12
  React.createElement(Text, { dimColor: true }, "(Y/n):")),
10
13
  React.createElement(ConfirmInput, { isChecked: true, value: shouldContinueText, onChange: setShouldContinueText, onSubmit: (answer) => {
11
14
  onContinue(answer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeroheight/adoption-cli",
3
- "version": "2.4.2",
3
+ "version": "3.0.0",
4
4
  "license": "ISC",
5
5
  "main": "dist/cli.js",
6
6
  "bin": {