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