-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathjavascript_bun.js
More file actions
122 lines (100 loc) · 3.24 KB
/
Copy pathjavascript_bun.js
File metadata and controls
122 lines (100 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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
import fs from 'node:fs'
import path from 'node:path'
import { parse } from 'jsonc-parser';
import Base_javascript from './base_javascript.js';
export default class Javascript_bun extends Base_javascript {
_lockFileName() {
return "bun.lock";
}
_cmdName() {
return "bun";
}
_listCmdArgs() {
throw new Error("not supported by Bun");
}
_updateLockFileCmdArgs() {
return ['install', '--lockfile-only'];
}
_buildDependencyTree(includeTransitive, opts = {}) {
this._version();
const manifestDir = path.dirname(this._getManifest().manifestPath);
const lockDir = this._findLockFileDir(manifestDir, opts) || manifestDir;
this._createLockFile(lockDir);
const lockContent = fs.readFileSync(path.join(lockDir, 'bun.lock'), 'utf-8');
const lockData = parse(lockContent);
const packages = lockData.packages || {};
const memberName = this._getManifest().name;
const workspaceEntry = this.#findWorkspaceEntry(lockData, lockDir, manifestDir, memberName);
const directDeps = workspaceEntry?.dependencies || {};
const tree = { name: memberName, version: this._getManifest().version, dependencies: {} };
const visited = new Set();
for (const depName of Object.keys(directDeps)) {
const resolved = this.#resolvePackage(depName, '', packages);
if (resolved) {
tree.dependencies[depName] = this.#buildNode(depName, resolved, packages, includeTransitive, visited);
}
}
return tree;
}
#findWorkspaceEntry(lockData, lockDir, manifestDir, memberName) {
const workspaces = lockData.workspaces || {};
const relPath = path.relative(lockDir, path.resolve(manifestDir));
if (!relPath || relPath === '.') {
return workspaces[''] || {};
}
const normalised = relPath.split(path.sep).join('/');
if (workspaces[normalised]) {
return workspaces[normalised];
}
for (const [wsPath, entry] of Object.entries(workspaces)) {
if (entry.name === memberName && wsPath !== '') {
return entry;
}
}
return workspaces[''] || {};
}
#resolvePackage(depName, parentKey, packages) {
if (parentKey) {
const scopedKey = `${parentKey}/${depName}`;
if (packages[scopedKey]) {
return packages[scopedKey];
}
}
return packages[depName] || null;
}
#buildNode(depName, resolved, packages, includeTransitive, visited) {
const resolvedId = Array.isArray(resolved) ? resolved[0] : resolved;
const version = this.#extractVersion(resolvedId);
const node = { version };
if (!includeTransitive) {
return node;
}
const metadata = Array.isArray(resolved) ? (resolved[2] || {}) : {};
const subDeps = metadata.dependencies || {};
if (Object.keys(subDeps).length > 0) {
const visitKey = `${depName}@${version}`;
if (visited.has(visitKey)) {
return node;
}
visited.add(visitKey);
node.dependencies = {};
for (const subName of Object.keys(subDeps)) {
const subResolved = this.#resolvePackage(subName, depName, packages);
if (subResolved) {
node.dependencies[subName] = this.#buildNode(subName, subResolved, packages, true, visited);
}
}
}
return node;
}
#extractVersion(resolvedId) {
if (typeof resolvedId !== 'string') {
return '0.0.0';
}
const atIdx = resolvedId.lastIndexOf('@');
if (atIdx > 0) {
return resolvedId.substring(atIdx + 1);
}
return '0.0.0';
}
}