@bigbinary/neeto-audit-frontend 1.0.8 → 1.0.9
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/dist/index.js +65 -24
- package/package.json +1 -1
- package/src/constants/index.js +14 -0
- package/src/utils/index.js +10 -7
- package/src/verifiers/currentNodeVersion/index.js +7 -2
- package/src/verifiers/eslint/index.js +15 -6
- package/src/verifiers/husky/index.js +9 -4
- package/src/verifiers/prettier/index.js +11 -3
- package/src/verifiers/recommendedPackageVersions/index.js +5 -4
package/dist/index.js
CHANGED
|
@@ -18233,6 +18233,20 @@ var simpleGit = gitInstanceFactory;
|
|
|
18233
18233
|
|
|
18234
18234
|
const PACKAGE_JSON_PATH = path$1.resolve("./package.json");
|
|
18235
18235
|
|
|
18236
|
+
const STATUSES = {
|
|
18237
|
+
PASS: "PASS",
|
|
18238
|
+
FAIL: "FAIL",
|
|
18239
|
+
SKIPPED: "SKIPPED",
|
|
18240
|
+
};
|
|
18241
|
+
|
|
18242
|
+
const NANO_TYPE_MAP = {
|
|
18243
|
+
nano: "nano",
|
|
18244
|
+
frontend: "frontend",
|
|
18245
|
+
extension: "extension",
|
|
18246
|
+
editor: "frontend",
|
|
18247
|
+
molecules: "frontend",
|
|
18248
|
+
};
|
|
18249
|
+
|
|
18236
18250
|
const run$1 = require$$1$1.promisify(exec);
|
|
18237
18251
|
|
|
18238
18252
|
const execute = async (command, debug) => {
|
|
@@ -18257,10 +18271,10 @@ const renderErrors = (errors = [], isAutoFixFlagPresent = false) => {
|
|
|
18257
18271
|
const getResults = async ({ verifiers, debug }) => {
|
|
18258
18272
|
let errors = [];
|
|
18259
18273
|
const results = verifiers.map(async ([name, verifier]) => {
|
|
18260
|
-
const { isSuccess = false, error } = await verifier(debug);
|
|
18274
|
+
const { isSuccess = false, error, status } = await verifier(debug);
|
|
18261
18275
|
!isSuccess && errors.push(error);
|
|
18262
18276
|
|
|
18263
|
-
return { name, isSuccess };
|
|
18277
|
+
return { name, isSuccess, status };
|
|
18264
18278
|
});
|
|
18265
18279
|
|
|
18266
18280
|
const allResults = await Promise.all(results);
|
|
@@ -18440,10 +18454,10 @@ const runVerifiers = async ({ verifiers, autoFix, debug }) => {
|
|
|
18440
18454
|
const { results, errors } = await getResults({ verifiers, autoFix, debug });
|
|
18441
18455
|
const isErrorPresent = isNotEmpty(errors);
|
|
18442
18456
|
|
|
18443
|
-
results.map(({ name, isSuccess }) => {
|
|
18457
|
+
results.map(({ name, isSuccess, status }) => {
|
|
18444
18458
|
const resultText = isSuccess
|
|
18445
|
-
? chalk$1.bgGreen.black(
|
|
18446
|
-
: chalk$1.bgRed.black(
|
|
18459
|
+
? chalk$1.bgGreen.black(status)
|
|
18460
|
+
: chalk$1.bgRed.black(status);
|
|
18447
18461
|
console.log(resultText, name);
|
|
18448
18462
|
});
|
|
18449
18463
|
|
|
@@ -18477,7 +18491,10 @@ const getNanoType = async () => {
|
|
|
18477
18491
|
|
|
18478
18492
|
const projectName = projectGitName.split(".git").at(0);
|
|
18479
18493
|
|
|
18480
|
-
return
|
|
18494
|
+
return {
|
|
18495
|
+
type: NANO_TYPE_MAP[last$2(split$1("-", projectName))],
|
|
18496
|
+
repoName: projectName,
|
|
18497
|
+
};
|
|
18481
18498
|
};
|
|
18482
18499
|
|
|
18483
18500
|
const getPackageJson = async (debug) => {
|
|
@@ -18525,10 +18542,14 @@ const currentNodeVersion = async (debug) => {
|
|
|
18525
18542
|
patch >= REQUIRED_NODE_VERSION.patch;
|
|
18526
18543
|
|
|
18527
18544
|
if (!isSuccess) {
|
|
18528
|
-
return {
|
|
18545
|
+
return {
|
|
18546
|
+
error: "There is a mismatch in the node version.",
|
|
18547
|
+
status: STATUSES.FAIL,
|
|
18548
|
+
fix,
|
|
18549
|
+
};
|
|
18529
18550
|
}
|
|
18530
18551
|
|
|
18531
|
-
return { isSuccess };
|
|
18552
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
18532
18553
|
};
|
|
18533
18554
|
|
|
18534
18555
|
const ESLINT_DESTINATION_DIRECTORY = path$1.resolve("./");
|
|
@@ -18536,11 +18557,15 @@ const ESLINT_DESTINATION_DIRECTORY = path$1.resolve("./");
|
|
|
18536
18557
|
const NANOS_TO_OVERRIDE = ["nano", "extension"];
|
|
18537
18558
|
|
|
18538
18559
|
const eslint = async (debug) => {
|
|
18539
|
-
const
|
|
18560
|
+
const { type, repoName } = await getNanoType();
|
|
18540
18561
|
|
|
18541
|
-
|
|
18542
|
-
|
|
18543
|
-
|
|
18562
|
+
// neeto-molecules has different ESLint rules disabled. This does not match other frontend packages.
|
|
18563
|
+
// So, decided to skip this check instead of adding a different config check just for a single repo.
|
|
18564
|
+
if (repoName === "neeto-molecules") {
|
|
18565
|
+
return { isSuccess: true, status: STATUSES.SKIPPED };
|
|
18566
|
+
}
|
|
18567
|
+
|
|
18568
|
+
const eslintCommonSource = NANOS_TO_OVERRIDE.includes(type) ? type : "common";
|
|
18544
18569
|
|
|
18545
18570
|
const eslintSourceDirectory = path$1.resolve(
|
|
18546
18571
|
`./node_modules/@bigbinary/neeto-audit-frontend/common/eslint/${eslintCommonSource}`
|
|
@@ -18565,10 +18590,14 @@ const eslint = async (debug) => {
|
|
|
18565
18590
|
const isSuccess = eslintFiles.every(identity$1);
|
|
18566
18591
|
|
|
18567
18592
|
if (!isSuccess) {
|
|
18568
|
-
return {
|
|
18593
|
+
return {
|
|
18594
|
+
error: "ESLint and its related files are not present.",
|
|
18595
|
+
status: STATUSES.FAIL,
|
|
18596
|
+
fix,
|
|
18597
|
+
};
|
|
18569
18598
|
}
|
|
18570
18599
|
|
|
18571
|
-
return { isSuccess };
|
|
18600
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
18572
18601
|
};
|
|
18573
18602
|
|
|
18574
18603
|
const HUSKY_SOURCE_DIRECTORY = path$1.resolve(
|
|
@@ -18584,9 +18613,9 @@ const HUSKY_DESTINATION_DIRECTORY = path$1.resolve("./.husky");
|
|
|
18584
18613
|
const HUSKY_GIT_IGNORE_PATH = path$1.resolve("./.husky/.gitignore");
|
|
18585
18614
|
|
|
18586
18615
|
const husky = async (debug) => {
|
|
18587
|
-
const
|
|
18616
|
+
const { type } = await getNanoType();
|
|
18588
18617
|
|
|
18589
|
-
const nanoSourceDirectory = `${HUSKY_SOURCE_DIRECTORY}/${
|
|
18618
|
+
const nanoSourceDirectory = `${HUSKY_SOURCE_DIRECTORY}/${type}`;
|
|
18590
18619
|
|
|
18591
18620
|
const fix = async (debug) => {
|
|
18592
18621
|
await createOrReplaceDirectoryFiles({
|
|
@@ -18630,18 +18659,28 @@ const husky = async (debug) => {
|
|
|
18630
18659
|
const isSuccess = huskyFiles.every(identity$1);
|
|
18631
18660
|
|
|
18632
18661
|
if (!isSuccess) {
|
|
18633
|
-
return {
|
|
18662
|
+
return {
|
|
18663
|
+
error: "Some husky helper files are not present.",
|
|
18664
|
+
status: STATUSES.FAIL,
|
|
18665
|
+
fix,
|
|
18666
|
+
};
|
|
18634
18667
|
}
|
|
18635
18668
|
|
|
18636
|
-
return { isSuccess };
|
|
18669
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
18637
18670
|
};
|
|
18638
18671
|
|
|
18639
18672
|
const PRETTIER_DESTINATION_PATH = path$1.resolve("./");
|
|
18640
18673
|
|
|
18641
18674
|
const prettier = async (debug) => {
|
|
18642
|
-
const
|
|
18675
|
+
const { type, repoName } = await getNanoType();
|
|
18676
|
+
|
|
18677
|
+
// neeto-molecules uses custom tailwind plugins for styles. This does not match other frontend packages.
|
|
18678
|
+
// So, decided to skip this check instead of adding a different config check just for a single repo.
|
|
18679
|
+
if (repoName === "neeto-molecules") {
|
|
18680
|
+
return { isSuccess: true, status: STATUSES.SKIPPED };
|
|
18681
|
+
}
|
|
18643
18682
|
|
|
18644
|
-
const prettierCommonSource =
|
|
18683
|
+
const prettierCommonSource = type === "extension" ? type : "common";
|
|
18645
18684
|
|
|
18646
18685
|
const prettierSourceDirectory = path$1.resolve(
|
|
18647
18686
|
`./node_modules/@bigbinary/neeto-audit-frontend/common/prettier/${prettierCommonSource}`
|
|
@@ -18668,11 +18707,12 @@ const prettier = async (debug) => {
|
|
|
18668
18707
|
if (!isSuccess) {
|
|
18669
18708
|
return {
|
|
18670
18709
|
error: "There are some discrepancy in the prettier configurations.",
|
|
18710
|
+
status: STATUSES.FAIL,
|
|
18671
18711
|
fix,
|
|
18672
18712
|
};
|
|
18673
18713
|
}
|
|
18674
18714
|
|
|
18675
|
-
return { isSuccess };
|
|
18715
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
18676
18716
|
};
|
|
18677
18717
|
|
|
18678
18718
|
const DEPENDENCIES$4 = {};
|
|
@@ -18967,11 +19007,11 @@ const getInstallationCommands = (recommendPackages, packagesToUpdate) =>
|
|
|
18967
19007
|
const recommendedPackageVersions = async (debug) => {
|
|
18968
19008
|
const packageJson = await getPackageJson(debug);
|
|
18969
19009
|
|
|
18970
|
-
const
|
|
19010
|
+
const { type } = await getNanoType();
|
|
18971
19011
|
|
|
18972
19012
|
const recommendedVersions = mergeDeepRight$1(
|
|
18973
19013
|
recommendedDependencies["common"],
|
|
18974
|
-
recommendedDependencies[
|
|
19014
|
+
recommendedDependencies[type]
|
|
18975
19015
|
);
|
|
18976
19016
|
|
|
18977
19017
|
const packagesToUpdate = getOutdatedPackages(
|
|
@@ -19011,11 +19051,12 @@ const recommendedPackageVersions = async (debug) => {
|
|
|
19011
19051
|
if (!isSuccess) {
|
|
19012
19052
|
return {
|
|
19013
19053
|
error: "The dependency packages are not using the recommended versions.",
|
|
19054
|
+
status: STATUSES.FAIL,
|
|
19014
19055
|
fix,
|
|
19015
19056
|
};
|
|
19016
19057
|
}
|
|
19017
19058
|
|
|
19018
|
-
return { isSuccess };
|
|
19059
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
19019
19060
|
};
|
|
19020
19061
|
|
|
19021
19062
|
const verifiers = [
|
package/package.json
CHANGED
package/src/constants/index.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
1
|
import path from "path";
|
|
2
2
|
|
|
3
3
|
export const PACKAGE_JSON_PATH = path.resolve("./package.json");
|
|
4
|
+
|
|
5
|
+
export const STATUSES = {
|
|
6
|
+
PASS: "PASS",
|
|
7
|
+
FAIL: "FAIL",
|
|
8
|
+
SKIPPED: "SKIPPED",
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const NANO_TYPE_MAP = {
|
|
12
|
+
nano: "nano",
|
|
13
|
+
frontend: "frontend",
|
|
14
|
+
extension: "extension",
|
|
15
|
+
editor: "frontend",
|
|
16
|
+
molecules: "frontend",
|
|
17
|
+
};
|
package/src/utils/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { identity, last, split } from "ramda";
|
|
|
10
10
|
import { simpleGit } from "simple-git";
|
|
11
11
|
import util from "util";
|
|
12
12
|
|
|
13
|
-
import { PACKAGE_JSON_PATH } from "../constants";
|
|
13
|
+
import { NANO_TYPE_MAP, PACKAGE_JSON_PATH } from "../constants";
|
|
14
14
|
|
|
15
15
|
const run = util.promisify(exec);
|
|
16
16
|
|
|
@@ -36,10 +36,10 @@ const renderErrors = (errors = [], isAutoFixFlagPresent = false) => {
|
|
|
36
36
|
const getResults = async ({ verifiers, debug }) => {
|
|
37
37
|
let errors = [];
|
|
38
38
|
const results = verifiers.map(async ([name, verifier]) => {
|
|
39
|
-
const { isSuccess = false, error } = await verifier(debug);
|
|
39
|
+
const { isSuccess = false, error, status } = await verifier(debug);
|
|
40
40
|
!isSuccess && errors.push(error);
|
|
41
41
|
|
|
42
|
-
return { name, isSuccess };
|
|
42
|
+
return { name, isSuccess, status };
|
|
43
43
|
});
|
|
44
44
|
|
|
45
45
|
const allResults = await Promise.all(results);
|
|
@@ -219,10 +219,10 @@ export const runVerifiers = async ({ verifiers, autoFix, debug }) => {
|
|
|
219
219
|
const { results, errors } = await getResults({ verifiers, autoFix, debug });
|
|
220
220
|
const isErrorPresent = isNotEmpty(errors);
|
|
221
221
|
|
|
222
|
-
results.map(({ name, isSuccess }) => {
|
|
222
|
+
results.map(({ name, isSuccess, status }) => {
|
|
223
223
|
const resultText = isSuccess
|
|
224
|
-
? chalk.bgGreen.black(
|
|
225
|
-
: chalk.bgRed.black(
|
|
224
|
+
? chalk.bgGreen.black(status)
|
|
225
|
+
: chalk.bgRed.black(status);
|
|
226
226
|
console.log(resultText, name);
|
|
227
227
|
});
|
|
228
228
|
|
|
@@ -256,7 +256,10 @@ export const getNanoType = async () => {
|
|
|
256
256
|
|
|
257
257
|
const projectName = projectGitName.split(".git").at(0);
|
|
258
258
|
|
|
259
|
-
return
|
|
259
|
+
return {
|
|
260
|
+
type: NANO_TYPE_MAP[last(split("-", projectName))],
|
|
261
|
+
repoName: projectName,
|
|
262
|
+
};
|
|
260
263
|
};
|
|
261
264
|
|
|
262
265
|
export const getPackageJson = async (debug) => {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NVMRC_FILE_PATH, REQUIRED_NODE_VERSION } from "./constants";
|
|
2
2
|
import { createOrReplaceFile, getFileContent } from "../../utils";
|
|
3
3
|
import { getSemVer } from "./utils";
|
|
4
|
+
import { STATUSES } from "../../constants";
|
|
4
5
|
|
|
5
6
|
const currentNodeVersion = async (debug) => {
|
|
6
7
|
const fix = async (debug) => {
|
|
@@ -28,10 +29,14 @@ const currentNodeVersion = async (debug) => {
|
|
|
28
29
|
patch >= REQUIRED_NODE_VERSION.patch;
|
|
29
30
|
|
|
30
31
|
if (!isSuccess) {
|
|
31
|
-
return {
|
|
32
|
+
return {
|
|
33
|
+
error: "There is a mismatch in the node version.",
|
|
34
|
+
status: STATUSES.FAIL,
|
|
35
|
+
fix,
|
|
36
|
+
};
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
return { isSuccess };
|
|
39
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
35
40
|
};
|
|
36
41
|
|
|
37
42
|
export default currentNodeVersion;
|
|
@@ -7,13 +7,18 @@ import {
|
|
|
7
7
|
identicalDirectoryFiles,
|
|
8
8
|
} from "../../utils";
|
|
9
9
|
import { ESLINT_DESTINATION_DIRECTORY, NANOS_TO_OVERRIDE } from "./constants";
|
|
10
|
+
import { STATUSES } from "../../constants";
|
|
10
11
|
|
|
11
12
|
const eslint = async (debug) => {
|
|
12
|
-
const
|
|
13
|
+
const { type, repoName } = await getNanoType();
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
// neeto-molecules has different ESLint rules disabled. This does not match other frontend packages.
|
|
16
|
+
// So, decided to skip this check instead of adding a different config check just for a single repo.
|
|
17
|
+
if (repoName === "neeto-molecules") {
|
|
18
|
+
return { isSuccess: true, status: STATUSES.SKIPPED };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const eslintCommonSource = NANOS_TO_OVERRIDE.includes(type) ? type : "common";
|
|
17
22
|
|
|
18
23
|
const eslintSourceDirectory = path.resolve(
|
|
19
24
|
`./node_modules/@bigbinary/neeto-audit-frontend/common/eslint/${eslintCommonSource}`
|
|
@@ -38,10 +43,14 @@ const eslint = async (debug) => {
|
|
|
38
43
|
const isSuccess = eslintFiles.every(identity);
|
|
39
44
|
|
|
40
45
|
if (!isSuccess) {
|
|
41
|
-
return {
|
|
46
|
+
return {
|
|
47
|
+
error: "ESLint and its related files are not present.",
|
|
48
|
+
status: STATUSES.FAIL,
|
|
49
|
+
fix,
|
|
50
|
+
};
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
return { isSuccess };
|
|
53
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
45
54
|
};
|
|
46
55
|
|
|
47
56
|
export default eslint;
|
|
@@ -12,11 +12,12 @@ import {
|
|
|
12
12
|
HUSKY_SOURCE_DIRECTORY,
|
|
13
13
|
HUSKY_COMMON_SOURCE_DIRECTORY,
|
|
14
14
|
} from "./constants";
|
|
15
|
+
import { STATUSES } from "../../constants";
|
|
15
16
|
|
|
16
17
|
const husky = async (debug) => {
|
|
17
|
-
const
|
|
18
|
+
const { type } = await getNanoType();
|
|
18
19
|
|
|
19
|
-
const nanoSourceDirectory = `${HUSKY_SOURCE_DIRECTORY}/${
|
|
20
|
+
const nanoSourceDirectory = `${HUSKY_SOURCE_DIRECTORY}/${type}`;
|
|
20
21
|
|
|
21
22
|
const fix = async (debug) => {
|
|
22
23
|
await createOrReplaceDirectoryFiles({
|
|
@@ -60,10 +61,14 @@ const husky = async (debug) => {
|
|
|
60
61
|
const isSuccess = huskyFiles.every(identity);
|
|
61
62
|
|
|
62
63
|
if (!isSuccess) {
|
|
63
|
-
return {
|
|
64
|
+
return {
|
|
65
|
+
error: "Some husky helper files are not present.",
|
|
66
|
+
status: STATUSES.FAIL,
|
|
67
|
+
fix,
|
|
68
|
+
};
|
|
64
69
|
}
|
|
65
70
|
|
|
66
|
-
return { isSuccess };
|
|
71
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
67
72
|
};
|
|
68
73
|
|
|
69
74
|
export default husky;
|
|
@@ -7,11 +7,18 @@ import {
|
|
|
7
7
|
identicalDirectoryFiles,
|
|
8
8
|
} from "../../utils";
|
|
9
9
|
import { PRETTIER_DESTINATION_PATH } from "./constants";
|
|
10
|
+
import { STATUSES } from "../../constants";
|
|
10
11
|
|
|
11
12
|
const prettier = async (debug) => {
|
|
12
|
-
const
|
|
13
|
+
const { type, repoName } = await getNanoType();
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
// neeto-molecules uses custom tailwind plugins for styles. This does not match other frontend packages.
|
|
16
|
+
// So, decided to skip this check instead of adding a different config check just for a single repo.
|
|
17
|
+
if (repoName === "neeto-molecules") {
|
|
18
|
+
return { isSuccess: true, status: STATUSES.SKIPPED };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const prettierCommonSource = type === "extension" ? type : "common";
|
|
15
22
|
|
|
16
23
|
const prettierSourceDirectory = path.resolve(
|
|
17
24
|
`./node_modules/@bigbinary/neeto-audit-frontend/common/prettier/${prettierCommonSource}`
|
|
@@ -38,11 +45,12 @@ const prettier = async (debug) => {
|
|
|
38
45
|
if (!isSuccess) {
|
|
39
46
|
return {
|
|
40
47
|
error: "There are some discrepancy in the prettier configurations.",
|
|
48
|
+
status: STATUSES.FAIL,
|
|
41
49
|
fix,
|
|
42
50
|
};
|
|
43
51
|
}
|
|
44
52
|
|
|
45
|
-
return { isSuccess };
|
|
53
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
46
54
|
};
|
|
47
55
|
|
|
48
56
|
export default prettier;
|
|
@@ -2,7 +2,7 @@ import { existsBy, isNotEmpty } from "@bigbinary/neeto-commons-frontend/pure";
|
|
|
2
2
|
import { mergeDeepRight, objOf } from "ramda";
|
|
3
3
|
|
|
4
4
|
import recommendedDependencies from "../../../common/recommendedDependencies";
|
|
5
|
-
import { PACKAGE_JSON_PATH } from "../../constants";
|
|
5
|
+
import { PACKAGE_JSON_PATH, STATUSES } from "../../constants";
|
|
6
6
|
import {
|
|
7
7
|
createOrReplaceFile,
|
|
8
8
|
execute,
|
|
@@ -18,11 +18,11 @@ import {
|
|
|
18
18
|
const recommendedPackageVersions = async (debug) => {
|
|
19
19
|
const packageJson = await getPackageJson(debug);
|
|
20
20
|
|
|
21
|
-
const
|
|
21
|
+
const { type } = await getNanoType();
|
|
22
22
|
|
|
23
23
|
const recommendedVersions = mergeDeepRight(
|
|
24
24
|
recommendedDependencies["common"],
|
|
25
|
-
recommendedDependencies[
|
|
25
|
+
recommendedDependencies[type]
|
|
26
26
|
);
|
|
27
27
|
|
|
28
28
|
const packagesToUpdate = getOutdatedPackages(
|
|
@@ -62,11 +62,12 @@ const recommendedPackageVersions = async (debug) => {
|
|
|
62
62
|
if (!isSuccess) {
|
|
63
63
|
return {
|
|
64
64
|
error: "The dependency packages are not using the recommended versions.",
|
|
65
|
+
status: STATUSES.FAIL,
|
|
65
66
|
fix,
|
|
66
67
|
};
|
|
67
68
|
}
|
|
68
69
|
|
|
69
|
-
return { isSuccess };
|
|
70
|
+
return { isSuccess, status: STATUSES.PASS };
|
|
70
71
|
};
|
|
71
72
|
|
|
72
73
|
export default recommendedPackageVersions;
|