lllink 1.25.4 → 1.25.5

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 (2) hide show
  1. package/package.json +1 -1
  2. package/dist/index.mjs +0 -269
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lllink",
3
- "version": "1.25.4",
3
+ "version": "1.25.5",
4
4
  "type": "module",
5
5
  "module": "dist",
6
6
  "exports": {
package/dist/index.mjs DELETED
@@ -1,269 +0,0 @@
1
- #!/usr/bin/env bun
2
- import { cp, mkdir, readFile, readdir, rename, rm, stat, symlink } from "node:fs/promises";
3
- import { homedir } from "node:os";
4
- import { join, relative, resolve } from "node:path";
5
- if (typeof Bun === "undefined") {
6
- console.error(`Must run in Bun due to using ~ resolutions`);
7
- process.exit(1);
8
- }
9
- const IGNORE_DIR = "node_modules";
10
- async function findLocalPackages(rootDir) {
11
- const results = {};
12
- async function recurse(dir) {
13
- let entries;
14
- try {
15
- entries = await readdir(dir);
16
- } catch {
17
- return;
18
- }
19
- await Promise.all(entries.map(async entry => {
20
- if (entry === IGNORE_DIR) return;
21
- const fullPath = join(dir, entry);
22
- let entryStat;
23
- try {
24
- entryStat = await stat(fullPath);
25
- } catch {
26
- return;
27
- }
28
- if (entryStat.isDirectory()) {
29
- const pkgJsonPath = join(fullPath, "package.json");
30
- try {
31
- const pkgJsonStat = await stat(pkgJsonPath);
32
- if (pkgJsonStat.isFile()) {
33
- const raw = await readFile(pkgJsonPath, "utf-8");
34
- const pkgData = JSON.parse(raw);
35
- if (pkgData.name && !pkgData.name.startsWith("@types/")) {
36
- results[pkgData.name] = fullPath;
37
- }
38
- }
39
- } catch {
40
- await recurse(fullPath);
41
- }
42
- }
43
- }));
44
- }
45
- await recurse(rootDir);
46
- return results;
47
- }
48
- async function linkPackages(externalPackages) {
49
- const backupDir = join(process.cwd(), "node_modules", ".cache", "lllink", "moved");
50
- await mkdir(backupDir, {
51
- recursive: true
52
- });
53
- for (const pkgName of Object.keys(externalPackages)) {
54
- const localPath = join(process.cwd(), "node_modules", ...pkgName.split("/"));
55
- try {
56
- const existingStat = await stat(localPath);
57
- if (existingStat) {
58
- await cp(localPath, join(backupDir, pkgName.replace("/", "__")), {
59
- recursive: true,
60
- dereference: true
61
- });
62
- }
63
- const externalPath = externalPackages[pkgName];
64
- if (externalPath) {
65
- console.info(`symlink ${relative(process.cwd(), localPath)} to ${externalPath.replace(homedir(), "~")}`);
66
- await rm(localPath, {
67
- recursive: true,
68
- force: true
69
- }).catch(() => {});
70
- await symlink(externalPath, localPath);
71
- }
72
- } catch {}
73
- }
74
- }
75
- async function undoLinks() {
76
- const backupDir = join(process.cwd(), "node_modules", ".cache", "lllink", "moved");
77
- let movedItems;
78
- try {
79
- movedItems = await readdir(backupDir);
80
- } catch {
81
- console.info("Nothing to undo.");
82
- return;
83
- }
84
- for (const item of movedItems) {
85
- const originalName = item.replace("__", "/");
86
- const nmPath = join(process.cwd(), "node_modules", ...originalName.split("/"));
87
- await rm(nmPath, {
88
- recursive: true,
89
- force: true
90
- }).catch(() => {});
91
- await rename(join(backupDir, item), nmPath).catch(() => {});
92
- console.info(`Restored: ${originalName}`);
93
- }
94
- }
95
- async function checkAllPackageVersionsAligned(workspaceDirs, packagesToCheck) {
96
- const allPackageVersions = [];
97
- const allDirs = [process.cwd(), ...workspaceDirs];
98
- const allDepsToCheck = /* @__PURE__ */new Set();
99
- for (const pkgName of Object.keys(packagesToCheck)) {
100
- allDepsToCheck.add(pkgName);
101
- }
102
- for (const [pkgName, pkgPath] of Object.entries(packagesToCheck)) {
103
- const deps = await getPackageDependencies(pkgPath);
104
- for (const dep of deps) {
105
- allDepsToCheck.add(dep);
106
- }
107
- }
108
- for (const workspaceDir of allDirs) {
109
- const resolved = resolve(workspaceDir);
110
- const workspaceName = workspaceDir === process.cwd() ? "current" : workspaceDir.split("/").pop() || workspaceDir;
111
- const packages = await collectSpecificNodeModulePackages(resolved, workspaceName, allDepsToCheck);
112
- allPackageVersions.push(...packages);
113
- }
114
- const packageGroups = {};
115
- for (const pkg of allPackageVersions) {
116
- if (!packageGroups[pkg.name]) {
117
- packageGroups[pkg.name] = [];
118
- }
119
- packageGroups[pkg.name].push(pkg);
120
- }
121
- const mismatches = [];
122
- for (const [pkgName, versions] of Object.entries(packageGroups)) {
123
- const versionsByWorkspace = {};
124
- for (const version of versions) {
125
- versionsByWorkspace[version.workspace] = version.version;
126
- }
127
- const uniqueVersions = new Set(Object.values(versionsByWorkspace));
128
- if (uniqueVersions.size > 1) {
129
- const uniqueVersionsArray = Object.entries(versionsByWorkspace).map(([workspace, version]) => ({
130
- name: pkgName,
131
- version,
132
- workspace,
133
- path: versions.find(v => v.workspace === workspace)?.path || ""
134
- }));
135
- mismatches.push({
136
- name: pkgName,
137
- versions: uniqueVersionsArray
138
- });
139
- }
140
- }
141
- if (mismatches.length === 0) {
142
- console.info("\u2713 All package versions are aligned across workspaces!");
143
- return true;
144
- }
145
- console.info(`
146
- \u274C Found ${mismatches.length} packages with mismatched versions, this may cause issues linking:
147
- `);
148
- for (const {
149
- name,
150
- versions
151
- } of mismatches) {
152
- console.info(`Package: ${name}`);
153
- for (const version of versions) {
154
- console.info(` ${version.workspace}: ${version.version}`);
155
- }
156
- console.info("");
157
- }
158
- return false;
159
- }
160
- async function getPackageDependencies(packagePath) {
161
- const dependencies = /* @__PURE__ */new Set();
162
- try {
163
- const pkgJsonPath = join(packagePath, "package.json");
164
- const raw = await readFile(pkgJsonPath, "utf-8");
165
- const pkgData = JSON.parse(raw);
166
- const depTypes = ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
167
- for (const depType of depTypes) {
168
- if (pkgData[depType]) {
169
- for (const depName of Object.keys(pkgData[depType])) {
170
- if (!depName.startsWith("@types/")) {
171
- dependencies.add(depName);
172
- }
173
- }
174
- }
175
- }
176
- } catch {}
177
- return Array.from(dependencies);
178
- }
179
- async function collectSpecificNodeModulePackages(workspaceDir, workspaceName, packagesToFind) {
180
- const packages = [];
181
- const nodeModulesPath = join(workspaceDir, "node_modules");
182
- async function recurseNodeModules(dir, depth = 0) {
183
- if (depth > 10) return;
184
- let entries;
185
- try {
186
- entries = await readdir(dir);
187
- } catch {
188
- return;
189
- }
190
- for (const entry of entries) {
191
- const fullPath = join(dir, entry);
192
- let entryStat;
193
- try {
194
- entryStat = await stat(fullPath);
195
- } catch {
196
- continue;
197
- }
198
- if (entryStat.isDirectory()) {
199
- if (entry.startsWith("@")) {
200
- await recurseNodeModules(fullPath, depth + 1);
201
- } else if (entry !== ".bin" && entry !== ".cache") {
202
- const pkgJsonPath = join(fullPath, "package.json");
203
- try {
204
- const pkgJsonStat = await stat(pkgJsonPath);
205
- if (pkgJsonStat.isFile()) {
206
- const raw = await readFile(pkgJsonPath, "utf-8");
207
- const pkgData = JSON.parse(raw);
208
- if (pkgData.name && pkgData.version && packagesToFind.has(pkgData.name) && !pkgData.name.startsWith("@types/")) {
209
- packages.push({
210
- name: pkgData.name,
211
- version: pkgData.version,
212
- workspace: workspaceName,
213
- path: fullPath
214
- });
215
- }
216
- }
217
- } catch {
218
- const nestedNodeModules = join(fullPath, "node_modules");
219
- try {
220
- const nestedStat = await stat(nestedNodeModules);
221
- if (nestedStat.isDirectory()) {
222
- await recurseNodeModules(nestedNodeModules, depth + 1);
223
- }
224
- } catch {}
225
- }
226
- }
227
- }
228
- }
229
- }
230
- try {
231
- await recurseNodeModules(nodeModulesPath);
232
- } catch {}
233
- return packages;
234
- }
235
- async function main() {
236
- const args = process.argv.slice(2);
237
- if (args.includes("--unlink")) {
238
- await undoLinks();
239
- process.exit(0);
240
- }
241
- const workspaceDirs = args.filter(arg => !arg.startsWith("--"));
242
- if (args.length === 0) {
243
- console.info("No workspace directories provided.");
244
- process.exit(0);
245
- }
246
- const allLocalPackages = {};
247
- for (const workspaceDir of workspaceDirs) {
248
- const resolved = resolve(workspaceDir);
249
- const found = await findLocalPackages(resolved);
250
- Object.assign(allLocalPackages, found);
251
- }
252
- if (!(await checkAllPackageVersionsAligned(workspaceDirs, allLocalPackages))) {
253
- if (args.includes("--check")) {
254
- process.exit(1);
255
- }
256
- } else {
257
- if (args.includes("--check")) {
258
- return;
259
- }
260
- }
261
- await linkPackages(allLocalPackages);
262
- console.info(`
263
- \u2713 linked ${Object.keys(allLocalPackages).length} packages`);
264
- }
265
- main().catch(err => {
266
- console.error("Error:", err);
267
- process.exit(1);
268
- });
269
- //# sourceMappingURL=index.mjs.map