@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.
- package/CHANGELOG.md +24 -0
- package/README.md +49 -10
- package/dist/cli.js +6 -4
- package/dist/commands/monitor-repo.d.ts +9 -0
- package/dist/commands/monitor-repo.js +36 -0
- package/dist/commands/monitor-repo.utils.d.ts +31 -0
- package/dist/commands/monitor-repo.utils.js +81 -0
- package/dist/commands/track-package.d.ts +5 -1
- package/dist/commands/track-package.js +15 -5
- package/dist/commands/track-package.utils.d.ts +8 -14
- package/dist/commands/track-package.utils.js +24 -15
- package/dist/common/api.d.ts +30 -2
- package/dist/common/api.js +13 -1
- package/dist/common/types/package-file.d.ts +8 -0
- package/dist/common/types/package-file.js +1 -0
- package/dist/components/analyze/analyze.js +16 -3
- package/dist/components/auth/auth.js +16 -2
- package/dist/components/auth/no-credentials-onboarding.d.ts +2 -1
- package/dist/components/auth/no-credentials-onboarding.js +13 -3
- package/dist/components/monitor-repo/monitor-repo.d.ts +2 -0
- package/dist/components/monitor-repo/monitor-repo.js +9 -0
- package/dist/components/monitor-repo/non-interactive-monitor-repo.d.ts +6 -0
- package/dist/components/monitor-repo/non-interactive-monitor-repo.js +112 -0
- package/dist/components/track-package/non-interactive-track-package.d.ts +2 -0
- package/dist/components/track-package/non-interactive-track-package.js +113 -0
- package/dist/components/track-package/track-package.js +119 -11
- package/dist/lockfile-parsers/lock-parser.d.ts +9 -0
- package/dist/lockfile-parsers/lock-parser.js +5 -0
- package/dist/lockfile-parsers/npm-lock-parser.d.ts +6 -0
- package/dist/lockfile-parsers/npm-lock-parser.js +54 -0
- package/dist/lockfile-parsers/pnpm-lock-parser.d.ts +6 -0
- package/dist/lockfile-parsers/pnpm-lock-parser.js +45 -0
- package/dist/lockfile-parsers/yarn-lock-parser.d.ts +6 -0
- package/dist/lockfile-parsers/yarn-lock-parser.js +67 -0
- 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
|
|
5
|
+
import Spinner from "ink-spinner";
|
|
6
6
|
import ConfirmInput from "../ui/confirm-input.js";
|
|
7
|
-
|
|
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
|
-
|
|
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,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,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,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["
|
|
12
|
-
Step[Step["
|
|
13
|
-
Step[Step["
|
|
14
|
-
Step[Step["
|
|
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
|
-
|
|
29
|
-
|
|
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 {
|
|
54
|
-
if (
|
|
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.
|
|
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.
|
|
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
|
|
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,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,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;
|