@uxf/scripts 11.107.0 → 11.109.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/README.md +50 -0
- package/bin/uxf-dependencies-check.ts +11 -0
- package/package.json +9 -9
- package/bin/uxf-dependencies-check.js +0 -8
- package/src/uxf-dependencies-check/cli.js +0 -32
- package/src/uxf-dependencies-check/index.js +0 -106
- package/src/uxf-dependencies-check/uxf-dependencies-check.test.js +0 -111
package/README.md
CHANGED
|
@@ -63,6 +63,56 @@ notify-push:
|
|
|
63
63
|
- uxf-push-notifier --google-chat-webhook-url=$GOOGLE_CHAT_WEBHOOK
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
## uxf-dependencies-check
|
|
67
|
+
|
|
68
|
+
All-in-one dependency health check for projects using `@uxf/*` packages. Runs two checks:
|
|
69
|
+
|
|
70
|
+
1. **Version conflict detection** — parses the lock file and reports dependencies of `@uxf/*` packages that resolve to multiple versions
|
|
71
|
+
2. **Peer dependency check** — verifies that all `peerDependencies` of installed `@uxf/*` packages are present and version-matched
|
|
72
|
+
|
|
73
|
+
Supports **yarn**, **npm**, **pnpm**, and **bun**. The package manager is auto-detected from the lock file.
|
|
74
|
+
|
|
75
|
+
Requires `tsx` or another tool to execute typescript (typically already available in your project's `devDependencies`).
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
Usage:
|
|
79
|
+
uxf-dependencies-check [options]
|
|
80
|
+
|
|
81
|
+
Options:
|
|
82
|
+
--fix Auto-install missing/mismatched peer dependencies
|
|
83
|
+
--dry-run Show what would be installed without changes
|
|
84
|
+
-e, --exclude Packages to ignore in conflict check [array]
|
|
85
|
+
-h, --help Show help [boolean]
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Build-time dependencies (`yargs`, `fast-glob`) are automatically ignored in the conflict check.
|
|
89
|
+
|
|
90
|
+
### Examples
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Run both checks (exits with code 1 if issues found)
|
|
94
|
+
npx tsx -dependencies-check
|
|
95
|
+
|
|
96
|
+
# Auto-install missing peer deps
|
|
97
|
+
npx tsx uxf-dependencies-check --fix
|
|
98
|
+
|
|
99
|
+
# Preview what would be installed
|
|
100
|
+
npx tsx uxf-dependencies-check --dry-run
|
|
101
|
+
|
|
102
|
+
# Ignore specific packages in conflict check
|
|
103
|
+
npx tsx uxf-dependencies-check --exclude lodash dayjs
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### What it checks
|
|
107
|
+
|
|
108
|
+
- Parses the lock file (yarn.lock / package-lock.json / pnpm-lock.yaml / bun.lock) to detect version conflicts
|
|
109
|
+
- Scans all `@uxf/*` packages in your `dependencies` / `devDependencies`
|
|
110
|
+
- Reads each package's `peerDependencies` from `node_modules`
|
|
111
|
+
- Skips `@uxf/*`, `react`, `react-dom`, and `next` (you manage these yourself)
|
|
112
|
+
- Reports missing dependencies and version mismatches
|
|
113
|
+
- Distinguishes between prod and dev dependencies — peer deps required only by `devDependencies` are installed with `-D`
|
|
114
|
+
- With `--fix`, auto-installs missing peer deps using the detected package manager
|
|
115
|
+
|
|
66
116
|
## uxf-lunch
|
|
67
117
|
|
|
68
118
|
```bash
|
package/package.json
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uxf/scripts",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.109.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"uxf-audit": "bin/uxf-audit.js",
|
|
8
8
|
"uxf-claude-sync": "bin/uxf-claude-sync.js",
|
|
9
|
+
"uxf-dependencies-check": "bin/uxf-dependencies-check.ts",
|
|
10
|
+
"uxf-i18n-namespaces-gen": "bin/uxf-i18n-namespaces-gen.js",
|
|
9
11
|
"uxf-lunch": "bin/uxf-lunch.js",
|
|
10
|
-
"uxf-dependencies-check": "bin/uxf-dependencies-check.js",
|
|
11
12
|
"uxf-push-notifier": "bin/uxf-push-notifier.js",
|
|
12
13
|
"uxf-release": "bin/uxf-release.js",
|
|
13
14
|
"uxf-sitemap-check": "bin/uxf-sitemap-check.js",
|
|
14
15
|
"uxf-sitemap-meta-export": "bin/uxf-sitemap-meta-export.js",
|
|
15
|
-
"uxf-i18n-namespaces-gen": "bin/uxf-i18n-namespaces-gen.js",
|
|
16
16
|
"uxf-unused": "bin/uxf-unused.js"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "",
|
|
20
|
-
"
|
|
20
|
+
"run:mr-notifier": "GOOGLE_WEBHOOK_URL=<<TODO>> GITLAB_TOKEN=<<TODO>> CI_SERVER_URL=https://gitlab.uxf.cz node ./bin/uxf-merge-requests-notifier.js",
|
|
21
21
|
"test": "./node_modules/.bin/eslint ./bin",
|
|
22
|
-
"
|
|
22
|
+
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
23
23
|
},
|
|
24
24
|
"publishConfig": {
|
|
25
25
|
"access": "public"
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"node": ">=24"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"axios": "1.13.4",
|
|
36
|
+
"axios": "^1.13.4",
|
|
37
37
|
"cheerio": "1.2.0",
|
|
38
|
-
"dayjs": "1.11.19",
|
|
38
|
+
"dayjs": "^1.11.19",
|
|
39
39
|
"fast-glob": "3.3.3",
|
|
40
40
|
"got": "14.6.6",
|
|
41
41
|
"madge": "8.0.0",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@types/node": "24",
|
|
48
48
|
"@types/react": "18.3.27",
|
|
49
49
|
"@types/react-dom": "18.3.7",
|
|
50
|
-
"@uxf/core": "11.
|
|
51
|
-
"@uxf/ui": "11.
|
|
50
|
+
"@uxf/core": "11.108.0",
|
|
51
|
+
"@uxf/ui": "11.108.0"
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const { checkUxfDependencies } = require("./index");
|
|
2
|
-
const { argv } = require("process");
|
|
3
|
-
|
|
4
|
-
module.exports = async () => {
|
|
5
|
-
const cli = require("yargs")()
|
|
6
|
-
.command("$0", "UXF Dependencies Check", (yargs) => {
|
|
7
|
-
yargs.demandCommand(0, 0).usage(`
|
|
8
|
-
Usage:
|
|
9
|
-
uxf-dependencies-check [options]`);
|
|
10
|
-
})
|
|
11
|
-
.option("e", {
|
|
12
|
-
alias: "exclude",
|
|
13
|
-
array: true,
|
|
14
|
-
default: [],
|
|
15
|
-
describe: "Seznam balíčků, které budou ignorovány",
|
|
16
|
-
})
|
|
17
|
-
.strict(false)
|
|
18
|
-
.exitProcess(false);
|
|
19
|
-
|
|
20
|
-
try {
|
|
21
|
-
const { help, exclude } = cli.parse(argv.slice(2));
|
|
22
|
-
|
|
23
|
-
if (Boolean(help)) {
|
|
24
|
-
return 0;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
await checkUxfDependencies(new Set(exclude));
|
|
28
|
-
} catch (e) {
|
|
29
|
-
console.error(e);
|
|
30
|
-
return 1;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
const fs = require("fs");
|
|
2
|
-
const path = require("path");
|
|
3
|
-
|
|
4
|
-
const yarnLockPath = path.resolve(process.cwd(), "yarn.lock");
|
|
5
|
-
const packageJsonPath = path.resolve(process.cwd(), "package.json");
|
|
6
|
-
|
|
7
|
-
async function parseLockFile() {
|
|
8
|
-
const YAML = await import("yaml");
|
|
9
|
-
|
|
10
|
-
const content = fs.readFileSync(yarnLockPath, "utf8");
|
|
11
|
-
return YAML.parse(content);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function parsePackageJson() {
|
|
15
|
-
const content = fs.readFileSync(packageJsonPath, "utf8");
|
|
16
|
-
return JSON.parse(content);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function extractPackageName(key) {
|
|
20
|
-
const match = key.match(/^(@[^/]+\/[^@]+|[^@]+)@/);
|
|
21
|
-
return match ? match[1] : null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function findUxfPackagesInDependencies(lockData, packageJson) {
|
|
25
|
-
const declaredDependencies = new Set(Object.keys(packageJson.dependencies || {}));
|
|
26
|
-
|
|
27
|
-
const uxfPackages = [];
|
|
28
|
-
|
|
29
|
-
for (const key of Object.keys(lockData)) {
|
|
30
|
-
const name = extractPackageName(key);
|
|
31
|
-
if (name?.startsWith("@uxf/") && declaredDependencies.has(name)) {
|
|
32
|
-
uxfPackages.push(key);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return uxfPackages;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function collectDirectDependencies(packageKeys, lockData) {
|
|
40
|
-
const found = {};
|
|
41
|
-
|
|
42
|
-
for (const key of packageKeys) {
|
|
43
|
-
const entry = lockData[key];
|
|
44
|
-
if (!entry) continue;
|
|
45
|
-
|
|
46
|
-
const dependencies = entry.dependencies || {};
|
|
47
|
-
|
|
48
|
-
for (const depName in dependencies) {
|
|
49
|
-
const matchingKeys = Object.keys(lockData).filter((lockKey) => extractPackageName(lockKey) === depName);
|
|
50
|
-
|
|
51
|
-
for (const matchKey of matchingKeys) {
|
|
52
|
-
const depEntry = lockData[matchKey];
|
|
53
|
-
if (!depEntry || !depEntry.version) continue;
|
|
54
|
-
|
|
55
|
-
if (!found[depName]) {
|
|
56
|
-
found[depName] = new Set();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
found[depName].add(depEntry.version);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return found;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function checkMultipleVersions(dependencyMap, excludedPackages = new Set()) {
|
|
68
|
-
const conflicts = [];
|
|
69
|
-
|
|
70
|
-
for (const [name, versions] of Object.entries(dependencyMap)) {
|
|
71
|
-
if (excludedPackages.has(name)) continue;
|
|
72
|
-
if (versions.size > 1) {
|
|
73
|
-
conflicts.push({ name, versions: Array.from(versions) });
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return conflicts;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async function checkUxfDependencies(excludedPackages = new Set()) {
|
|
81
|
-
const lockData = await parseLockFile();
|
|
82
|
-
const packageJson = parsePackageJson();
|
|
83
|
-
|
|
84
|
-
const uxfPackages = findUxfPackagesInDependencies(lockData, packageJson);
|
|
85
|
-
const dependencies = collectDirectDependencies(uxfPackages, lockData);
|
|
86
|
-
|
|
87
|
-
const conflicts = checkMultipleVersions(dependencies, excludedPackages);
|
|
88
|
-
|
|
89
|
-
if (conflicts.length > 0) {
|
|
90
|
-
console.log("Následující balíčky mají více verzí v závislostech UXF balíčků:");
|
|
91
|
-
for (const { name, versions } of conflicts) {
|
|
92
|
-
console.log(`- ${name}: ${versions.join(", ")}`);
|
|
93
|
-
}
|
|
94
|
-
process.exit(1);
|
|
95
|
-
} else {
|
|
96
|
-
console.log("Všechny závislosti UXF balíčků mají jednotnou verzi.");
|
|
97
|
-
process.exit(0);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
module.exports = {
|
|
102
|
-
findUxfPackagesInDependencies,
|
|
103
|
-
collectDirectDependencies,
|
|
104
|
-
checkMultipleVersions,
|
|
105
|
-
checkUxfDependencies,
|
|
106
|
-
};
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
const { findUxfPackagesInDependencies, collectDirectDependencies, checkMultipleVersions } = require("./index"); // Adjust the path if needed
|
|
2
|
-
|
|
3
|
-
describe("findUxfPackagesInDependencies", () => {
|
|
4
|
-
const lockData = {
|
|
5
|
-
"@uxf/button@^1.0.0": {},
|
|
6
|
-
"@uxf/form@^2.1.0": {},
|
|
7
|
-
"react@^17.0.0": {},
|
|
8
|
-
"lodash@^4.17.0": {},
|
|
9
|
-
"classnames@^2.3.1": {},
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const packageJson = {
|
|
13
|
-
dependencies: {
|
|
14
|
-
"@uxf/button": "^1.0.0",
|
|
15
|
-
"@uxf/form": "^2.1.0",
|
|
16
|
-
react: "^17.0.0",
|
|
17
|
-
},
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
it("returns @uxf/* packages that are in package.json dependencies", () => {
|
|
21
|
-
const result = findUxfPackagesInDependencies(lockData, packageJson);
|
|
22
|
-
expect(result).toEqual(["@uxf/button@^1.0.0", "@uxf/form@^2.1.0"]);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
describe("collectDirectDependencies", () => {
|
|
27
|
-
const lockData = {
|
|
28
|
-
"@uxf/button@^1.0.0": {
|
|
29
|
-
dependencies: {
|
|
30
|
-
react: "^17.0.0",
|
|
31
|
-
lodash: "^4.17.0",
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
"@uxf/form@^2.1.0": {
|
|
35
|
-
dependencies: {
|
|
36
|
-
react: "^17.0.1", // different version range
|
|
37
|
-
classnames: "^2.3.1",
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
"react@^17.0.0": {
|
|
41
|
-
version: "17.0.2",
|
|
42
|
-
},
|
|
43
|
-
"react@^17.0.1": {
|
|
44
|
-
version: "17.0.1",
|
|
45
|
-
},
|
|
46
|
-
"lodash@^4.17.0": {
|
|
47
|
-
version: "4.17.21",
|
|
48
|
-
},
|
|
49
|
-
"classnames@^2.3.1": {
|
|
50
|
-
version: "2.3.1",
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
const packageKeys = ["@uxf/button@^1.0.0", "@uxf/form@^2.1.0"];
|
|
55
|
-
|
|
56
|
-
it("collects direct dependencies of multiple UXF packages with shared and unique deps", () => {
|
|
57
|
-
const result = collectDirectDependencies(packageKeys, lockData);
|
|
58
|
-
|
|
59
|
-
expect(result).toEqual({
|
|
60
|
-
react: new Set(["17.0.2", "17.0.1"]),
|
|
61
|
-
lodash: new Set(["4.17.21"]),
|
|
62
|
-
classnames: new Set(["2.3.1"]),
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("handles empty dependencies gracefully", () => {
|
|
67
|
-
const lockData = {
|
|
68
|
-
"@uxf/empty@1.0.0": {},
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const result = collectDirectDependencies(["@uxf/empty@1.0.0"], lockData);
|
|
72
|
-
expect(result).toEqual({});
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe("checkMultipleVersions", () => {
|
|
77
|
-
it("returns empty array when all packages have a single version", () => {
|
|
78
|
-
const deps = {
|
|
79
|
-
react: new Set(["17.0.2"]),
|
|
80
|
-
lodash: new Set(["4.17.21"]),
|
|
81
|
-
};
|
|
82
|
-
expect(checkMultipleVersions(deps)).toEqual([]);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("returns conflicts when a package has multiple versions", () => {
|
|
86
|
-
const deps = {
|
|
87
|
-
react: new Set(["17.0.2", "18.0.0"]),
|
|
88
|
-
lodash: new Set(["4.17.21"]),
|
|
89
|
-
};
|
|
90
|
-
const conflicts = checkMultipleVersions(deps);
|
|
91
|
-
expect(conflicts).toHaveLength(1);
|
|
92
|
-
expect(conflicts[0].name).toBe("react");
|
|
93
|
-
expect(conflicts[0].versions).toEqual(expect.arrayContaining(["17.0.2", "18.0.0"]));
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it("excludes packages that are in the excludedPackages set", () => {
|
|
97
|
-
const deps = {
|
|
98
|
-
react: new Set(["17.0.2", "18.0.0"]),
|
|
99
|
-
};
|
|
100
|
-
const result = checkMultipleVersions(deps, new Set(["react"]));
|
|
101
|
-
expect(result).toEqual([]);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it("returns multiple conflicts when several packages have version mismatches", () => {
|
|
105
|
-
const deps = {
|
|
106
|
-
react: new Set(["17.0.2", "18.0.0"]),
|
|
107
|
-
lodash: new Set(["4.17.0", "4.17.21"]),
|
|
108
|
-
};
|
|
109
|
-
expect(checkMultipleVersions(deps)).toHaveLength(2);
|
|
110
|
-
});
|
|
111
|
-
});
|