or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

arborist.mdedges.mdindex.mdlinks.mdshrinkwrap.mdtree-navigation.md

links.mddocs/

0

# Symbolic Links

1

2

The Link class extends Node to represent symbolic links within node_modules directories. Links delegate dependency resolution to their targets while maintaining their own position in the tree structure.

3

4

## Capabilities

5

6

### Constructor

7

8

Creates a new Link instance representing a symbolic link.

9

10

```javascript { .api }

11

/**

12

* Create a new symbolic link node

13

* @param options - Link configuration options

14

*/

15

constructor(options?: LinkOptions): Link;

16

17

interface LinkOptions extends NodeOptions {

18

/** Link target node */

19

target?: Node;

20

/** Real path to link target (required) */

21

realpath: string;

22

/** Is store link */

23

isStoreLink?: boolean;

24

}

25

```

26

27

**Usage Example:**

28

29

```javascript

30

const { Link } = require('@npmcli/arborist');

31

32

// Create a link to a target node

33

const link = new Link({

34

name: 'my-package',

35

parent: rootNode,

36

realpath: '/path/to/actual/package',

37

target: targetNode

38

});

39

```

40

41

### Link-Specific Properties

42

43

Properties that distinguish links from regular nodes.

44

45

```javascript { .api }

46

interface LinkSpecificProperties {

47

/** Always true for Link instances */

48

isLink: true;

49

/** Target node that the link points to */

50

target: Node;

51

/** Relative path to target (computed property) */

52

resolved: string;

53

/** Is store link */

54

isStoreLink: boolean;

55

/** Always empty Map (read-only) */

56

children: Map<string, Node>;

57

}

58

```

59

60

**Usage Examples:**

61

62

```javascript

63

// Check if node is a link

64

if (node.isLink) {

65

console.log(`Link target: ${node.target.name}@${node.target.version}`);

66

console.log(`Target path: ${node.target.path}`);

67

console.log(`Resolved path: ${node.resolved}`);

68

}

69

70

// Links have no direct children

71

console.log(`Link children count: ${node.children.size}`); // Always 0

72

73

// Access target's children instead

74

console.log(`Target children: ${Array.from(node.target.children.keys())}`);

75

```

76

77

### Target Delegation

78

79

Links delegate certain operations to their targets, particularly dependency resolution.

80

81

```javascript { .api }

82

/**

83

* Links inherit most Node methods but delegate resolution to target

84

* Dependencies are resolved from target location, not link location

85

*/

86

interface LinkDelegation {

87

/** Delegates to target.resolve() */

88

resolve(name: string): Node | undefined;

89

/** Target's package.json content */

90

package: object;

91

/** Target's version */

92

version: string;

93

/** Target's dependency edges */

94

edgesOut: Map<string, Edge>;

95

}

96

```

97

98

**Usage Example:**

99

100

```javascript

101

// Resolution happens from target location

102

const dependency = link.resolve('express');

103

// This is equivalent to:

104

const dependency2 = link.target.resolve('express');

105

106

// Package information comes from target

107

console.log(`Link package name: ${link.package.name}`);

108

console.log(`Link version: ${link.version}`);

109

110

// Dependencies come from target

111

console.log(`Link dependencies: ${Array.from(link.edgesOut.keys())}`);

112

```

113

114

### Path Resolution

115

116

Links maintain their own path while pointing to a target with a different path.

117

118

```javascript { .api }

119

interface LinkPathResolution {

120

/** Path to the link itself */

121

path: string;

122

/** Real path to the target */

123

realpath: string;

124

/** Computed relative path from link to target */

125

resolved: string;

126

}

127

```

128

129

**Usage Example:**

130

131

```javascript

132

console.log(`Link path: ${link.path}`); // e.g. /proj/node_modules/pkg

133

console.log(`Target path: ${link.realpath}`); // e.g. /proj/packages/pkg

134

console.log(`Resolved path: ${link.resolved}`); // e.g. ../../packages/pkg

135

```

136

137

### Store Links

138

139

Special type of links used for package stores and global installations.

140

141

```javascript { .api }

142

/**

143

* Store links are special links used in package stores

144

* @param isStoreLink - Whether this is a store link

145

*/

146

interface StoreLinkProperties {

147

/** Is this a store link */

148

isStoreLink: boolean;

149

}

150

```

151

152

**Usage Example:**

153

154

```javascript

155

// Check if this is a store link

156

if (link.isStoreLink) {

157

console.log('This is a store link (global or cached package)');

158

}

159

160

// Create a store link

161

const storeLink = new Link({

162

name: 'global-package',

163

realpath: '/usr/local/lib/node_modules/global-package',

164

target: globalPackageNode,

165

isStoreLink: true

166

});

167

```

168

169

## Key Differences from Node

170

171

### Children Handling

172

173

Links cannot have direct children - their children map is always empty.

174

175

```javascript

176

// Regular node can have children

177

const regularNode = new Node({ name: 'parent' });

178

regularNode.children.set('child', childNode); // Works

179

180

// Link cannot have children

181

const link = new Link({ name: 'link', target: targetNode });

182

link.children.set('child', childNode); // children remains empty

183

console.log(link.children.size); // Always 0

184

```

185

186

### Dependency Resolution

187

188

Dependencies are resolved from the target's location, not the link's location.

189

190

```javascript

191

// If link is at /project/node_modules/my-package

192

// But target is at /project/packages/my-package

193

// Resolution happens from /project/packages/my-package

194

const resolved = link.resolve('dependency');

195

// Uses Node.js resolution from target location

196

```

197

198

### Tree Structure

199

200

Links maintain their position in the tree while delegating content to targets.

201

202

```javascript

203

// Link has its own parent/location

204

console.log(`Link parent: ${link.parent.name}`);

205

console.log(`Link location: ${link.location}`);

206

207

// But content comes from target

208

console.log(`Package content: ${link.package.name}`);

209

console.log(`Dependencies: ${Array.from(link.edgesOut.keys())}`);

210

211

// Target might be elsewhere in tree or outside tree entirely

212

console.log(`Target parent: ${link.target.parent?.name || 'none'}`);

213

```

214

215

## Common Use Cases

216

217

### Workspace Links

218

219

Links between packages in a monorepo workspace.

220

221

```javascript

222

// Package A depends on Package B in same workspace

223

const workspaceLink = new Link({

224

name: 'package-b',

225

parent: packageANode,

226

realpath: '/workspace/packages/package-b',

227

target: packageBNode

228

});

229

```

230

231

### Global Package Links

232

233

Links to globally installed packages.

234

235

```javascript

236

// Global CLI tool linked into project

237

const globalLink = new Link({

238

name: 'some-cli',

239

parent: rootNode,

240

realpath: '/usr/local/lib/node_modules/some-cli',

241

target: globalCliNode,

242

isStoreLink: true

243

});

244

```

245

246

### Development Links

247

248

Links created during development (e.g., `npm link`).

249

250

```javascript

251

// Development package linked for testing

252

const devLink = new Link({

253

name: 'my-dev-package',

254

parent: testProjectNode,

255

realpath: '/home/dev/my-dev-package',

256

target: devPackageNode

257

});

258

```

259

260

### Store Cache Links

261

262

Links to packages in a content-addressable store.

263

264

```javascript

265

// Package from content store

266

const cacheLink = new Link({

267

name: 'cached-package',

268

parent: rootNode,

269

realpath: '/cache/store/abc123/node_modules/cached-package',

270

target: cachedPackageNode,

271

isStoreLink: true

272

});

273

```

274

275

## Working with Links

276

277

### Detecting Links

278

279

```javascript

280

// Check if a node is a link

281

if (node.isLink) {

282

console.log('This is a symbolic link');

283

console.log(`Points to: ${node.target.path}`);

284

} else {

285

console.log('This is a regular package');

286

}

287

```

288

289

### Following Links

290

291

```javascript

292

// Get the actual package content

293

const actualPackage = node.isLink ? node.target : node;

294

console.log(`Actual package: ${actualPackage.name}@${actualPackage.version}`);

295

```

296

297

### Finding Link Sources

298

299

```javascript

300

// Find what links to a target

301

if (node.linksIn.size > 0) {

302

console.log(`This package has ${node.linksIn.size} links pointing to it:`);

303

for (const link of node.linksIn) {

304

console.log(` - ${link.location} -> ${node.location}`);

305

}

306

}

307

```