@zeroheight/adoption-cli 0.4.4 → 1.1.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.
Files changed (35) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +49 -10
  3. package/dist/cli.js +6 -4
  4. package/dist/commands/monitor-repo.d.ts +9 -0
  5. package/dist/commands/monitor-repo.js +36 -0
  6. package/dist/commands/monitor-repo.utils.d.ts +31 -0
  7. package/dist/commands/monitor-repo.utils.js +81 -0
  8. package/dist/commands/track-package.d.ts +5 -1
  9. package/dist/commands/track-package.js +15 -5
  10. package/dist/commands/track-package.utils.d.ts +8 -14
  11. package/dist/commands/track-package.utils.js +24 -15
  12. package/dist/common/api.d.ts +30 -2
  13. package/dist/common/api.js +13 -1
  14. package/dist/common/types/package-file.d.ts +8 -0
  15. package/dist/common/types/package-file.js +1 -0
  16. package/dist/components/analyze/analyze.js +16 -3
  17. package/dist/components/auth/auth.js +16 -2
  18. package/dist/components/auth/no-credentials-onboarding.d.ts +2 -1
  19. package/dist/components/auth/no-credentials-onboarding.js +13 -3
  20. package/dist/components/monitor-repo/monitor-repo.d.ts +2 -0
  21. package/dist/components/monitor-repo/monitor-repo.js +9 -0
  22. package/dist/components/monitor-repo/non-interactive-monitor-repo.d.ts +6 -0
  23. package/dist/components/monitor-repo/non-interactive-monitor-repo.js +112 -0
  24. package/dist/components/track-package/non-interactive-track-package.d.ts +2 -0
  25. package/dist/components/track-package/non-interactive-track-package.js +113 -0
  26. package/dist/components/track-package/track-package.js +119 -11
  27. package/dist/lockfile-parsers/lock-parser.d.ts +9 -0
  28. package/dist/lockfile-parsers/lock-parser.js +5 -0
  29. package/dist/lockfile-parsers/npm-lock-parser.d.ts +6 -0
  30. package/dist/lockfile-parsers/npm-lock-parser.js +54 -0
  31. package/dist/lockfile-parsers/pnpm-lock-parser.d.ts +6 -0
  32. package/dist/lockfile-parsers/pnpm-lock-parser.js +45 -0
  33. package/dist/lockfile-parsers/yarn-lock-parser.d.ts +6 -0
  34. package/dist/lockfile-parsers/yarn-lock-parser.js +67 -0
  35. package/package.json +7 -4
@@ -2,13 +2,19 @@ import * as React from "react";
2
2
  import { Box, Newline, Text } from "ink";
3
3
  import TextInput from "ink-text-input";
4
4
  import Link from "ink-link";
5
- import CredentialsPreview from "./credentials-preview.js";
5
+ import Spinner from "ink-spinner";
6
6
  import ConfirmInput from "../ui/confirm-input.js";
7
- export default function NoCredentialsOnboarding({ onSaveCredentials, configPath, }) {
7
+ import CredentialsPreview from "./credentials-preview.js";
8
+ export default function NoCredentialsOnboarding({ onCheckCredentials, onSaveCredentials, configPath, }) {
8
9
  const [client, setClient] = React.useState("");
9
10
  const [token, setToken] = React.useState("");
10
11
  const [shouldWrite, setShouldWrite] = React.useState("");
11
12
  const [field, setField] = React.useState("client");
13
+ const handleCheckCredentials = async () => {
14
+ setField("authenticating");
15
+ await onCheckCredentials(client, token);
16
+ setField("write");
17
+ };
12
18
  const handleWriteCredentials = async (answer) => {
13
19
  await onSaveCredentials(answer, client.trim(), token.trim());
14
20
  };
@@ -29,8 +35,12 @@ export default function NoCredentialsOnboarding({ onSaveCredentials, configPath,
29
35
  React.createElement(TextInput, { onChange: setToken, value: token, onSubmit: (v) => {
30
36
  if (v.trim().length === 0)
31
37
  return;
32
- setField("write");
38
+ handleCheckCredentials();
33
39
  } }))),
40
+ field === "authenticating" && (React.createElement(Text, null,
41
+ React.createElement(Text, { color: "green" },
42
+ React.createElement(Spinner, { type: "dots" })),
43
+ " checking authentication details...")),
34
44
  field === "write" && (React.createElement(Box, { flexDirection: "column" },
35
45
  React.createElement(CredentialsPreview, { client: client, token: token }),
36
46
  React.createElement(Text, null,
@@ -0,0 +1,2 @@
1
+ import React from "react";
2
+ export default function MonitorRepo(): React.JSX.Element;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import { Text } from "ink";
3
+ import { findLockfiles } from "../../commands/monitor-repo.utils.js";
4
+ export default function MonitorRepo() {
5
+ React.useEffect(() => {
6
+ findLockfiles();
7
+ }, []);
8
+ return React.createElement(Text, null, "Monitor Repo");
9
+ }
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ interface NonInteractiveMonitorRepoProps {
3
+ packageDirs?: string[];
4
+ }
5
+ export default function NonInteractiveMonitorRepo({ packageDirs, }: NonInteractiveMonitorRepoProps): React.JSX.Element;
6
+ export {};
@@ -0,0 +1,112 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import Spinner from "ink-spinner";
4
+ import { join as joinPath } from "path";
5
+ import { findLockfiles, getPackageMeta, groupByBasename, parseLockfile, } from "../../commands/monitor-repo.utils.js";
6
+ import { findPackageFiles } from "../../commands/track-package.utils.js";
7
+ import { submitMonitoredRepoDetails } from "../../common/api.js";
8
+ import { readConfig } from "../../common/config.js";
9
+ import YarnLockParser from "../../lockfile-parsers/yarn-lock-parser.js";
10
+ var Step;
11
+ (function (Step) {
12
+ Step[Step["COMPLETE"] = 0] = "COMPLETE";
13
+ Step[Step["ERRORED"] = 1] = "ERRORED";
14
+ Step[Step["FINDING_DETAILS"] = 2] = "FINDING_DETAILS";
15
+ Step[Step["SENDING_DATA"] = 3] = "SENDING_DATA";
16
+ })(Step || (Step = {}));
17
+ export default function NonInteractiveMonitorRepo({ packageDirs, }) {
18
+ const [errorMessage, setErrorMessage] = React.useState(); // Global error message
19
+ const [repoStatus, setRepoStatus] = React.useState({});
20
+ function updateRepoStatus(name, step, error) {
21
+ // If any error ocurred, return error so pipes failing
22
+ if (error) {
23
+ process.exitCode = 1;
24
+ }
25
+ setRepoStatus((s) => ({ ...s, [name]: { ...s[name], step, error } }));
26
+ }
27
+ async function scanLockfiles() {
28
+ const base = process.cwd();
29
+ let lockfiles = [];
30
+ let packageFiles = [];
31
+ if (packageDirs) {
32
+ packageFiles = (await Promise.all(packageDirs.map(findLockfiles))).flat();
33
+ lockfiles = (await Promise.all(packageDirs.map(findPackageFiles))).flat();
34
+ }
35
+ else {
36
+ packageFiles = await findPackageFiles();
37
+ lockfiles = await findLockfiles();
38
+ }
39
+ const groupedFiles = groupByBasename([...lockfiles, ...packageFiles]);
40
+ const config = await readConfig();
41
+ if (Object.keys(groupedFiles).length === 0) {
42
+ setErrorMessage("No NPM packages found");
43
+ return;
44
+ }
45
+ // Package file should be in same directory as lockfile, iterate through to send as pairs
46
+ for (const [directory, files] of Object.entries(groupedFiles)) {
47
+ const lockfile = files.filter((f) => f !== "package.json").at(0);
48
+ if (!lockfile)
49
+ continue;
50
+ let packageMeta;
51
+ try {
52
+ packageMeta = await getPackageMeta(joinPath(directory, "package.json"));
53
+ }
54
+ catch (e) {
55
+ // package.json doesn't exist or is invalid, skip pair
56
+ continue;
57
+ }
58
+ updateRepoStatus(packageMeta.name, Step.FINDING_DETAILS);
59
+ const parser = await parseLockfile(joinPath(directory, lockfile));
60
+ let parsedPackages = parser.packages;
61
+ // Exclude self-named packages (may be used for linking and workspaces)
62
+ if (parser instanceof YarnLockParser) {
63
+ parsedPackages = parser.packages.filter((p) => p.name !== packageMeta.name);
64
+ }
65
+ //TODO: not sure if we want `./` or not, maybe better to leave off for compatibility with windows?
66
+ const relativeLockfilePath = joinPath(directory.split(base).pop() ?? "", lockfile);
67
+ if (!config) {
68
+ setErrorMessage("No credentials, must authenticate to send data to zeroheight.");
69
+ continue;
70
+ }
71
+ try {
72
+ updateRepoStatus(packageMeta.name, Step.SENDING_DATA);
73
+ const response = await submitMonitoredRepoDetails(packageMeta.name, packageMeta.version, relativeLockfilePath, parsedPackages, {
74
+ token: config.token,
75
+ client: config.client,
76
+ });
77
+ if (response.status === "success") {
78
+ updateRepoStatus(packageMeta.name, Step.COMPLETE);
79
+ }
80
+ else {
81
+ updateRepoStatus(packageMeta.name, Step.ERRORED, response.message);
82
+ }
83
+ }
84
+ catch (e) {
85
+ updateRepoStatus(packageMeta.name, Step.ERRORED, "Failed to send data to zeroheight");
86
+ }
87
+ }
88
+ }
89
+ React.useEffect(() => {
90
+ scanLockfiles();
91
+ }, []);
92
+ return (React.createElement(React.Fragment, null,
93
+ Object.entries(repoStatus).map(([name, { step, error }]) => (React.createElement(Box, { key: name, flexDirection: "column" },
94
+ step === Step.FINDING_DETAILS && (React.createElement(Text, null,
95
+ React.createElement(Text, { color: "green" },
96
+ React.createElement(Spinner, { type: "dots" })),
97
+ `${name} - searching for package details...`)),
98
+ step === Step.SENDING_DATA && (React.createElement(Text, null,
99
+ React.createElement(Text, { color: "green" },
100
+ React.createElement(Spinner, { type: "dots" })),
101
+ `${name} - sending data to zeroheight...`)),
102
+ step === Step.COMPLETE && (React.createElement(Text, null,
103
+ React.createElement(Text, { color: "green" }, "Success: "),
104
+ `${name} - sent to your zeroheight account`)),
105
+ step === Step.ERRORED && (React.createElement(Text, null,
106
+ React.createElement(Text, { color: "red" }, "Error: "),
107
+ `${name} - ${error}`))))),
108
+ errorMessage && (React.createElement(Text, null,
109
+ React.createElement(Text, { color: "red" }, "Error:"),
110
+ " ",
111
+ errorMessage))));
112
+ }
@@ -0,0 +1,2 @@
1
+ import React from "react";
2
+ export default function NonInteractiveTrackPackage(): React.JSX.Element;
@@ -0,0 +1,113 @@
1
+ import React from "react";
2
+ import { Newline, Text, useApp } from "ink";
3
+ import Spinner from "ink-spinner";
4
+ import { readConfig } from "../../common/config.js";
5
+ import { getPackageInfo } from "../../commands/track-package.utils.js";
6
+ import { submitPackageDetails } from "../../common/api.js";
7
+ var Step;
8
+ (function (Step) {
9
+ Step[Step["COMPLETE"] = 0] = "COMPLETE";
10
+ Step[Step["ERRORED"] = 1] = "ERRORED";
11
+ Step[Step["FINDING_DETAILS"] = 2] = "FINDING_DETAILS";
12
+ Step[Step["MULTIPLE_PACKAGES_FOUND"] = 3] = "MULTIPLE_PACKAGES_FOUND";
13
+ Step[Step["SINGLE_PACKAGE_FOUND"] = 4] = "SINGLE_PACKAGE_FOUND";
14
+ })(Step || (Step = {}));
15
+ export default function NonInteractiveTrackPackage() {
16
+ const { exit } = useApp();
17
+ const [currentStep, setCurrentStep] = React.useState(Step.FINDING_DETAILS);
18
+ const [errorMessage, setErrorMessage] = React.useState(null);
19
+ const [packageFiles, setPackageFiles] = React.useState([]);
20
+ const [packageName, setPackageName] = React.useState(null);
21
+ const [packageVersion, setPackageVersion] = React.useState(null);
22
+ async function runTrackPackage() {
23
+ const config = (await readConfig()) ?? { token: "temp", client: "temp" };
24
+ const { files, error } = await getPackageInfo();
25
+ try {
26
+ if (files.length === 1) {
27
+ const { name, path, version } = files[0];
28
+ setPackageName(name);
29
+ setPackageVersion(version);
30
+ setCurrentStep(Step.SINGLE_PACKAGE_FOUND);
31
+ const response = await submitPackageDetails(name, path, version, {
32
+ token: config.token,
33
+ client: config.client,
34
+ });
35
+ if (response.status === "error") {
36
+ setErrorMessage(response.message);
37
+ setCurrentStep(Step.ERRORED);
38
+ exit();
39
+ }
40
+ else {
41
+ setCurrentStep(Step.COMPLETE);
42
+ exit();
43
+ }
44
+ }
45
+ else if (files.length > 1) {
46
+ setPackageFiles(files);
47
+ setCurrentStep(Step.MULTIPLE_PACKAGES_FOUND);
48
+ await Promise.all(files.map(async (pack) => {
49
+ await submitPackageDetails(pack.name, pack.path, pack.version, {
50
+ token: config.token,
51
+ client: config.client,
52
+ });
53
+ }));
54
+ }
55
+ else {
56
+ setErrorMessage(error);
57
+ setCurrentStep(Step.ERRORED);
58
+ exit();
59
+ }
60
+ setCurrentStep(Step.COMPLETE);
61
+ exit();
62
+ }
63
+ catch (e) {
64
+ const errorMessage = e.message === "Unauthorized"
65
+ ? "Unauthorized. Please reset your authentication by running: zh-adoption auth"
66
+ : "Failed to send data to zeroheight";
67
+ setErrorMessage(errorMessage);
68
+ setCurrentStep(Step.ERRORED);
69
+ exit();
70
+ }
71
+ }
72
+ React.useEffect(() => {
73
+ runTrackPackage();
74
+ }, []);
75
+ return (React.createElement(React.Fragment, null,
76
+ currentStep === Step.FINDING_DETAILS && (React.createElement(Text, null,
77
+ React.createElement(Text, { color: "green" },
78
+ React.createElement(Spinner, { type: "dots" })),
79
+ " searching for package file...")),
80
+ currentStep === Step.SINGLE_PACKAGE_FOUND && (React.createElement(React.Fragment, null,
81
+ React.createElement(Text, null,
82
+ React.createElement(Text, { color: "green" }, "Details founds:"),
83
+ " ",
84
+ packageName,
85
+ "@",
86
+ packageVersion),
87
+ React.createElement(Newline, null),
88
+ React.createElement(Text, null,
89
+ React.createElement(Text, { color: "green" },
90
+ React.createElement(Spinner, { type: "dots" })),
91
+ " sending to zeroheight..."))),
92
+ currentStep === Step.MULTIPLE_PACKAGES_FOUND && (React.createElement(React.Fragment, null,
93
+ React.createElement(Text, { color: "green" },
94
+ packageFiles.length,
95
+ " packages found"),
96
+ React.createElement(Newline, null),
97
+ React.createElement(Text, null,
98
+ React.createElement(Text, { color: "green" },
99
+ React.createElement(Spinner, { type: "dots" })),
100
+ " sending to zeroheight..."))),
101
+ currentStep === Step.COMPLETE && (React.createElement(Text, null,
102
+ "Complete -",
103
+ " ",
104
+ packageFiles.length > 1
105
+ ? `details for ${packageFiles.length} packages`
106
+ : "package details",
107
+ " ",
108
+ "sent to your zeroheight account")),
109
+ currentStep === Step.ERRORED && (React.createElement(Text, null,
110
+ React.createElement(Text, { color: "red" }, "Error:"),
111
+ " ",
112
+ errorMessage))));
113
+ }
@@ -1,5 +1,7 @@
1
1
  import React from "react";
2
2
  import { Box, Newline, Text, useApp } from "ink";
3
+ import { Checkbox } from "ink-checkbox";
4
+ import SelectInput from "ink-select-input";
3
5
  import Spinner from "ink-spinner";
4
6
  import ConfirmInput from "../ui/confirm-input.js";
5
7
  import { readConfig } from "../../common/config.js";
@@ -8,25 +10,52 @@ import { submitPackageDetails } from "../../common/api.js";
8
10
  var Step;
9
11
  (function (Step) {
10
12
  Step[Step["COMPLETE"] = 0] = "COMPLETE";
11
- Step[Step["DETAILS_FOUND"] = 1] = "DETAILS_FOUND";
12
- Step[Step["ERRORED"] = 2] = "ERRORED";
13
- Step[Step["FINDING_DETAILS"] = 3] = "FINDING_DETAILS";
14
- Step[Step["SENDING_DETAILS"] = 4] = "SENDING_DETAILS";
13
+ Step[Step["ERRORED"] = 1] = "ERRORED";
14
+ Step[Step["FINDING_DETAILS"] = 2] = "FINDING_DETAILS";
15
+ Step[Step["MULTIPLE_PACKAGES_FOUND"] = 3] = "MULTIPLE_PACKAGES_FOUND";
16
+ Step[Step["MULTIPLE_PACKAGES_SELECT"] = 4] = "MULTIPLE_PACKAGES_SELECT";
17
+ Step[Step["SENDING_DETAILS"] = 5] = "SENDING_DETAILS";
18
+ Step[Step["SHOULD_SEND_ALL"] = 6] = "SHOULD_SEND_ALL";
19
+ Step[Step["SHOULD_SENDING_DETAILS"] = 7] = "SHOULD_SENDING_DETAILS";
20
+ Step[Step["SINGLE_PACKAGE_FOUND"] = 8] = "SINGLE_PACKAGE_FOUND";
15
21
  })(Step || (Step = {}));
16
22
  export default function TrackPackage() {
17
23
  const { exit } = useApp();
18
24
  const [currentStep, setCurrentStep] = React.useState(Step.FINDING_DETAILS);
19
25
  const [credentials, setCredentials] = React.useState(null);
20
26
  const [errorMessage, setErrorMessage] = React.useState(null);
27
+ const [packageFiles, setPackageFiles] = React.useState([]);
21
28
  const [packageName, setPackageName] = React.useState(null);
22
29
  const [packagePath, setPackagePath] = React.useState(null);
23
30
  const [packageVersion, setPackageVersion] = React.useState(null);
24
31
  const [shouldSend, setShouldSend] = React.useState("");
32
+ const [shouldMultiSelect, setShouldMultiSelect] = React.useState("");
33
+ const [packageSelection, setPackageSelection] = React.useState([]);
34
+ const [selectedFileLabels, setSelectedFileLabels] = React.useState([]);
35
+ async function submitPackage(name, path, version) {
36
+ await submitPackageDetails(name, path, version, credentials);
37
+ }
25
38
  async function sendData() {
26
39
  setCurrentStep(Step.SENDING_DETAILS);
27
40
  try {
28
- await submitPackageDetails(packageName, packagePath, packageVersion, credentials);
29
- setCurrentStep(Step.COMPLETE);
41
+ if (packageFiles.length > 0) {
42
+ const packagesToSend = packageFiles.filter((p) => selectedFileLabels.includes(`${p.name}@${p.version}`));
43
+ if (packagesToSend.length > 0) {
44
+ await Promise.all(packagesToSend.map(async (pack) => {
45
+ submitPackage(pack.name, pack.path, pack.version);
46
+ }));
47
+ }
48
+ else {
49
+ await Promise.all(packageFiles.map(async (pack) => {
50
+ submitPackage(pack.name, pack.path, pack.version);
51
+ }));
52
+ }
53
+ setCurrentStep(Step.COMPLETE);
54
+ }
55
+ else {
56
+ await submitPackage(packageName, packagePath, packageVersion);
57
+ setCurrentStep(Step.COMPLETE);
58
+ }
30
59
  }
31
60
  catch (e) {
32
61
  const errorMessage = e.message === "Unauthorized"
@@ -44,18 +73,51 @@ export default function TrackPackage() {
44
73
  return sendData();
45
74
  exit();
46
75
  };
76
+ const handleShowMultiSelect = (shouldShow) => {
77
+ if (shouldShow) {
78
+ setCurrentStep(Step.MULTIPLE_PACKAGES_SELECT);
79
+ }
80
+ else {
81
+ setCurrentStep(Step.SHOULD_SEND_ALL);
82
+ }
83
+ };
84
+ const handlePackageSelected = ({ label, }) => {
85
+ if (label === "Continue?") {
86
+ if (selectedFileLabels.length > 0)
87
+ setCurrentStep(Step.SHOULD_SENDING_DETAILS);
88
+ }
89
+ else if (selectedFileLabels.includes(label)) {
90
+ setSelectedFileLabels(selectedFileLabels.filter((f) => f !== label));
91
+ }
92
+ else {
93
+ setSelectedFileLabels([...selectedFileLabels, label]);
94
+ }
95
+ };
47
96
  React.useEffect(() => {
48
97
  (async () => {
49
98
  const config = await readConfig();
50
99
  if (config) {
51
100
  setCredentials({ token: config.token, client: config.client });
52
101
  }
53
- const { name, path, version, error } = await getPackageInfo();
54
- if (name && path && version) {
102
+ const { files, error } = await getPackageInfo();
103
+ if (files.length === 1) {
104
+ const { name, path, version } = files[0];
55
105
  setPackageName(name);
56
106
  setPackagePath(path);
57
107
  setPackageVersion(version);
58
- setCurrentStep(Step.DETAILS_FOUND);
108
+ setCurrentStep(Step.SINGLE_PACKAGE_FOUND);
109
+ }
110
+ else if (files.length > 1) {
111
+ const filesAsItems = files.map((f) => ({
112
+ label: `${f.name}@${f.version}`,
113
+ value: `${f.name}@${f.version}`,
114
+ }));
115
+ setPackageSelection([
116
+ ...filesAsItems,
117
+ { label: "Continue?", value: "continue" },
118
+ ]);
119
+ setPackageFiles(files);
120
+ setCurrentStep(Step.MULTIPLE_PACKAGES_FOUND);
59
121
  }
60
122
  else {
61
123
  setErrorMessage(error);
@@ -69,7 +131,7 @@ export default function TrackPackage() {
69
131
  React.createElement(Text, { color: "green" },
70
132
  React.createElement(Spinner, { type: "dots" })),
71
133
  " Searching for package file..."));
72
- case Step.DETAILS_FOUND:
134
+ case Step.SINGLE_PACKAGE_FOUND:
73
135
  return (React.createElement(Box, { flexDirection: "column" },
74
136
  React.createElement(Text, null,
75
137
  React.createElement(Text, { color: "green" }, "Details founds:"),
@@ -82,13 +144,51 @@ export default function TrackPackage() {
82
144
  "Send to zeroheight? ",
83
145
  React.createElement(Text, { dimColor: true }, "(Y/n):")),
84
146
  React.createElement(ConfirmInput, { isChecked: true, onChange: setShouldSend, onSubmit: handleSendToZh, value: shouldSend })));
147
+ case Step.MULTIPLE_PACKAGES_FOUND:
148
+ return (React.createElement(Box, { flexDirection: "column" },
149
+ React.createElement(Text, null,
150
+ React.createElement(Text, { color: "green" },
151
+ packageFiles.length,
152
+ " package files found")),
153
+ React.createElement(Newline, null),
154
+ React.createElement(Text, null,
155
+ "Select specific package to send? ",
156
+ React.createElement(Text, { dimColor: true }, "(Y/n):")),
157
+ React.createElement(ConfirmInput, { isChecked: true, onChange: setShouldMultiSelect, onSubmit: handleShowMultiSelect, value: shouldMultiSelect })));
158
+ case Step.MULTIPLE_PACKAGES_SELECT:
159
+ return (React.createElement(React.Fragment, null,
160
+ React.createElement(Box, { marginBottom: 1 },
161
+ React.createElement(Text, null, "Select packages (use the arrow keys/return key)")),
162
+ React.createElement(SelectInput, { items: packageSelection, onSelect: handlePackageSelected, itemComponent: (props) => (React.createElement(FileItem, { ...props, selectedFileLabels: selectedFileLabels })) })));
163
+ case Step.SHOULD_SENDING_DETAILS:
164
+ return (React.createElement(Box, { flexDirection: "column" },
165
+ React.createElement(Text, null,
166
+ React.createElement(Text, { color: "green" },
167
+ selectedFileLabels.length,
168
+ " ",
169
+ selectedFileLabels.length > 1 ? "packages" : "package",
170
+ " selected")),
171
+ React.createElement(Newline, null),
172
+ React.createElement(Text, null,
173
+ "Send to zeroheight? ",
174
+ React.createElement(Text, { dimColor: true }, "(Y/n):")),
175
+ React.createElement(ConfirmInput, { isChecked: true, onChange: setShouldSend, onSubmit: handleSendToZh, value: shouldSend })));
176
+ case Step.SHOULD_SEND_ALL:
177
+ return (React.createElement(Box, { flexDirection: "column" },
178
+ React.createElement(Text, null,
179
+ "Send ",
180
+ packageFiles.length,
181
+ " packages to zeroheight?",
182
+ " ",
183
+ React.createElement(Text, { dimColor: true }, "(Y/n):")),
184
+ React.createElement(ConfirmInput, { isChecked: true, onChange: setShouldSend, onSubmit: handleSendToZh, value: shouldSend })));
85
185
  case Step.SENDING_DETAILS:
86
186
  return (React.createElement(Text, null,
87
187
  React.createElement(Text, { color: "green" },
88
188
  React.createElement(Spinner, { type: "dots" })),
89
189
  " Sending details to zeroheight..."));
90
190
  case Step.COMPLETE:
91
- return (React.createElement(Text, null, "Complete - details sent to your zeroheight account"));
191
+ return React.createElement(Text, null, "Complete - details sent to your zeroheight account");
92
192
  case Step.ERRORED:
93
193
  return (React.createElement(Text, null,
94
194
  React.createElement(Text, { color: "red" }, "Error:"),
@@ -98,3 +198,11 @@ export default function TrackPackage() {
98
198
  return React.createElement(Text, null, "Done");
99
199
  }
100
200
  }
201
+ function FileItem({ isSelected, label, selectedFileLabels, }) {
202
+ if (label === "Continue?") {
203
+ return React.createElement(Text, { color: "Blue" }, label);
204
+ }
205
+ return (React.createElement(React.Fragment, null,
206
+ React.createElement(Checkbox, { label: label, focused: !!isSelected, checked: selectedFileLabels.includes(label) }),
207
+ React.createElement(Newline, null)));
208
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Parse lock file to get common properties
3
+ */
4
+ export declare abstract class LockParser {
5
+ abstract readonly packages: {
6
+ name: string;
7
+ version: string;
8
+ }[];
9
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Parse lock file to get common properties
3
+ */
4
+ export class LockParser {
5
+ }
@@ -0,0 +1,6 @@
1
+ import { LockParser } from "./lock-parser.js";
2
+ export default class NPMLockParser extends LockParser {
3
+ #private;
4
+ packages: LockParser["packages"];
5
+ constructor(lockContent: string);
6
+ }
@@ -0,0 +1,54 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
6
+ var _NPMLockParser_instances, _NPMLockParser_parseV1, _NPMLockParser_parseV2, _NPMLockParser_parseV3, _NPMLockParser_sanitizeName;
7
+ import { LockParser } from "./lock-parser.js";
8
+ class NPMLockParser extends LockParser {
9
+ constructor(lockContent) {
10
+ super();
11
+ _NPMLockParser_instances.add(this);
12
+ Object.defineProperty(this, "packages", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: void 0
17
+ });
18
+ const data = JSON.parse(lockContent);
19
+ switch (data.lockfileVersion) {
20
+ case 1:
21
+ this.packages = __classPrivateFieldGet(this, _NPMLockParser_instances, "m", _NPMLockParser_parseV1).call(this, data);
22
+ break;
23
+ case 2:
24
+ this.packages = __classPrivateFieldGet(this, _NPMLockParser_instances, "m", _NPMLockParser_parseV2).call(this, data);
25
+ break;
26
+ case 3:
27
+ default:
28
+ this.packages = __classPrivateFieldGet(this, _NPMLockParser_instances, "m", _NPMLockParser_parseV3).call(this, data);
29
+ }
30
+ }
31
+ }
32
+ _NPMLockParser_instances = new WeakSet(), _NPMLockParser_parseV1 = function _NPMLockParser_parseV1(data) {
33
+ return Object.entries(data.dependencies).map(([key, properties]) => ({
34
+ name: __classPrivateFieldGet(this, _NPMLockParser_instances, "m", _NPMLockParser_sanitizeName).call(this, key),
35
+ version: properties.version,
36
+ }));
37
+ }, _NPMLockParser_parseV2 = function _NPMLockParser_parseV2(data) {
38
+ const out = Object.entries(data.packages)
39
+ .map(([key, properties]) => ({
40
+ name: __classPrivateFieldGet(this, _NPMLockParser_instances, "m", _NPMLockParser_sanitizeName).call(this, key),
41
+ version: properties.version,
42
+ }))
43
+ .filter((p) => p.name && p.version); // Remove nameless and versionless packages
44
+ return out;
45
+ }, _NPMLockParser_parseV3 = function _NPMLockParser_parseV3(data) {
46
+ return __classPrivateFieldGet(this, _NPMLockParser_instances, "m", _NPMLockParser_parseV2).call(this, data);
47
+ }, _NPMLockParser_sanitizeName = function _NPMLockParser_sanitizeName(name) {
48
+ const nodeModulePath = "node_modules/";
49
+ if (name.startsWith(nodeModulePath)) {
50
+ return name.slice(nodeModulePath.length);
51
+ }
52
+ return name;
53
+ };
54
+ export default NPMLockParser;
@@ -0,0 +1,6 @@
1
+ import { LockParser } from "./lock-parser.js";
2
+ export default class PNPMLockParser extends LockParser {
3
+ #private;
4
+ packages: LockParser["packages"];
5
+ constructor(lockContent: string);
6
+ }
@@ -0,0 +1,45 @@
1
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
2
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
3
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
4
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
5
+ };
6
+ var _PNPMLockParser_instances, _PNPMLockParser_parseV5, _PNPMLockParser_parseV6;
7
+ import { parse as parseYAML } from "yaml";
8
+ import { LockParser } from "./lock-parser.js";
9
+ class PNPMLockParser extends LockParser {
10
+ constructor(lockContent) {
11
+ super();
12
+ _PNPMLockParser_instances.add(this);
13
+ Object.defineProperty(this, "packages", {
14
+ enumerable: true,
15
+ configurable: true,
16
+ writable: true,
17
+ value: void 0
18
+ });
19
+ this.packages = [];
20
+ const data = parseYAML(lockContent);
21
+ const majorLockfileVersion = parseInt(data.lockfileVersion, 10);
22
+ if (majorLockfileVersion < 6) {
23
+ this.packages = __classPrivateFieldGet(this, _PNPMLockParser_instances, "m", _PNPMLockParser_parseV5).call(this, data);
24
+ }
25
+ else {
26
+ this.packages = __classPrivateFieldGet(this, _PNPMLockParser_instances, "m", _PNPMLockParser_parseV6).call(this, data);
27
+ }
28
+ }
29
+ }
30
+ _PNPMLockParser_instances = new WeakSet(), _PNPMLockParser_parseV5 = function _PNPMLockParser_parseV5(data) {
31
+ return Object.entries(data.dependencies)
32
+ .map(([name, version]) => ({
33
+ name,
34
+ version,
35
+ }))
36
+ .filter((p) => p.name && p.version);
37
+ }, _PNPMLockParser_parseV6 = function _PNPMLockParser_parseV6(data) {
38
+ return Object.keys(data.packages)
39
+ .map((packagePair) => {
40
+ const [name, version] = packagePair.split("@");
41
+ return { name, version };
42
+ })
43
+ .filter((p) => p.name && p.version);
44
+ };
45
+ export default PNPMLockParser;
@@ -0,0 +1,6 @@
1
+ import { LockParser } from "./lock-parser.js";
2
+ export default class YarnLockParser extends LockParser {
3
+ #private;
4
+ packages: LockParser["packages"];
5
+ constructor(lockContent: string);
6
+ }