or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

directory-operations.mdindex.mdpackage-import-linking.mdtarball-processing.mdworker-pool.md

package-import-linking.mddocs/

0

# Package Import and Linking

1

2

Import packages from the CAFS store and create symbolic links for module resolution in Node.js projects.

3

4

## Capabilities

5

6

### Import Package

7

8

Imports a package from the CAFS store to a target directory using various import methods. This operation is limited to 4 concurrent operations for optimal performance.

9

10

```typescript { .api }

11

/**

12

* Imports a package using the worker pool with concurrency limit

13

* @param opts - Import configuration options (excludes 'type' from LinkPkgMessage)

14

* @returns Promise resolving to import results with build status

15

*/

16

function importPackage(opts: Omit<LinkPkgMessage, 'type'>): Promise<ImportPackageResult>;

17

18

interface LinkPkgMessage {

19

type: 'link';

20

/** Store directory path where package files are located */

21

storeDir: string;

22

/** Import method to use for package installation */

23

packageImportMethod?: 'auto' | 'hardlink' | 'copy' | 'clone' | 'clone-or-copy';

24

/** Package files response containing file metadata */

25

filesResponse: PackageFilesResponse;

26

/** Optional cache key for side effects */

27

sideEffectsCacheKey?: string | undefined;

28

/** Target directory where package should be installed */

29

targetDir: string;

30

/** Whether the package requires a build step */

31

requiresBuild?: boolean;

32

/** Force import even if target already exists */

33

force: boolean;

34

/** Keep existing modules directory */

35

keepModulesDir?: boolean;

36

/** Disable relinking of local directory dependencies */

37

disableRelinkLocalDirDeps?: boolean;

38

}

39

40

interface ImportPackageResult {

41

/** Whether the package was built during import */

42

isBuilt: boolean;

43

/** Actual import method used (may differ from requested method) */

44

importMethod: string | undefined;

45

}

46

```

47

48

**Usage Examples:**

49

50

```typescript

51

import { importPackage } from "@pnpm/worker";

52

53

// Basic package import with auto method selection

54

const result = await importPackage({

55

storeDir: "/path/to/pnpm/store",

56

filesResponse: {

57

/* PackageFilesResponse data */

58

},

59

targetDir: "/project/node_modules/lodash",

60

force: false

61

});

62

63

console.log("Package imported with method:", result.importMethod);

64

console.log("Package was built:", result.isBuilt);

65

66

// Import with specific method and build requirements

67

const buildResult = await importPackage({

68

storeDir: "/path/to/store",

69

packageImportMethod: "hardlink",

70

filesResponse: packageFiles,

71

targetDir: "/project/node_modules/native-package",

72

requiresBuild: true,

73

force: true,

74

keepModulesDir: true

75

});

76

```

77

78

### Symlink All Modules

79

80

Creates symbolic links for all modules in dependencies. This is typically used for setting up module resolution after package import.

81

82

```typescript { .api }

83

/**

84

* Creates symbolic links for all modules in dependencies

85

* @param opts - Symlinking configuration options (excludes 'type' from SymlinkAllModulesMessage)

86

* @returns Promise resolving to symlinking results

87

*/

88

function symlinkAllModules(opts: Omit<SymlinkAllModulesMessage, 'type'>): Promise<ImportPackageResult>;

89

90

interface SymlinkAllModulesMessage {

91

type: 'symlinkAllModules';

92

/** Array of dependencies to create symlinks for */

93

deps: Array<{

94

/** Child dependencies mapping alias to package directory */

95

children: Record<string, string>;

96

/** Modules directory path */

97

modules: string;

98

/** Dependency name */

99

name: string;

100

}>;

101

}

102

```

103

104

**Usage Examples:**

105

106

```typescript

107

import { symlinkAllModules } from "@pnpm/worker";

108

109

// Create symlinks for multiple dependencies

110

const symlinkResult = await symlinkAllModules({

111

deps: [

112

{

113

name: "express",

114

modules: "/project/node_modules",

115

children: {

116

"body-parser": "/store/body-parser/1.19.0",

117

"cookie-parser": "/store/cookie-parser/1.4.5",

118

"debug": "/store/debug/4.3.2"

119

}

120

},

121

{

122

name: "lodash",

123

modules: "/project/node_modules",

124

children: {}

125

}

126

]

127

});

128

129

console.log("Symlinks created successfully");

130

```

131

132

### Read Package From CAFS

133

134

Reads package metadata and files from the content-addressable file system store, with optional integrity verification.

135

136

```typescript { .api }

137

/**

138

* Reads package from content-addressable file system store

139

* @param storeDir - Store directory path

140

* @param verifyStoreIntegrity - Whether to verify file integrity

141

* @param filesIndexFile - Path to files index file

142

* @param readManifest - Whether to read package manifest

143

* @returns Promise resolving to package read results

144

*/

145

function readPkgFromCafs(

146

storeDir: string,

147

verifyStoreIntegrity: boolean,

148

filesIndexFile: string,

149

readManifest?: boolean

150

): Promise<ReadPkgFromCafsResult>;

151

152

interface ReadPkgFromCafsResult {

153

/** Whether integrity verification passed */

154

verified: boolean;

155

/** Package files index metadata */

156

pkgFilesIndex: PackageFilesIndex;

157

/** Package manifest if requested and available */

158

manifest?: DependencyManifest;

159

/** Whether the package requires a build step */

160

requiresBuild: boolean;

161

}

162

```

163

164

**Usage Examples:**

165

166

```typescript

167

import { readPkgFromCafs } from "@pnpm/worker";

168

169

// Read package with integrity verification

170

const packageData = await readPkgFromCafs(

171

"/path/to/pnpm/store",

172

true, // verify integrity

173

"/path/to/package/index.json",

174

true // read manifest

175

);

176

177

if (packageData.verified) {

178

console.log("Package integrity verified");

179

console.log("Package name:", packageData.manifest?.name);

180

console.log("Requires build:", packageData.requiresBuild);

181

} else {

182

console.log("Package integrity check failed - refetch required");

183

}

184

185

// Quick read without verification

186

const quickRead = await readPkgFromCafs(

187

"/path/to/store",

188

false, // skip verification

189

"/path/to/index.json"

190

);

191

```

192

193

## Import Methods

194

195

The `packageImportMethod` parameter supports several strategies:

196

197

### Auto (Default)

198

Automatically selects the best method based on the environment and file system capabilities.

199

200

### Hardlink

201

Creates hard links to files in the store. Most efficient but requires same file system.

202

203

### Copy

204

Copies files from store to target. Slower but works across file systems.

205

206

### Clone

207

Uses copy-on-write cloning when supported by the file system (e.g., APFS, Btrfs).

208

209

### Clone-or-Copy

210

Attempts cloning first, falls back to copying if cloning is not supported.

211

212

## Error Handling

213

214

### ExFAT Drive Detection

215

216

On Windows, the library detects exFAT drives which don't support symlinks:

217

218

```typescript

219

// Error handling for exFAT drives

220

try {

221

await symlinkAllModules({

222

deps: [/* dependencies */]

223

});

224

} catch (error) {

225

if (error.code === 'EISDIR' && error.message.includes('exFAT')) {

226

console.error('ExFAT drive detected - symlinks not supported');

227

console.log('Consider setting node-linker to "hoisted"');

228

}

229

}

230

```

231

232

### Concurrent Import Limits

233

234

The `importPackage` function automatically limits concurrent operations to 4 for optimal performance. This prevents file system overwhelming during large installations.

235

236

## Package Files Response

237

238

The `PackageFilesResponse` interface contains metadata about package files stored in CAFS:

239

240

```typescript { .api }

241

interface PackageFilesResponse {

242

/** File integrity information and metadata */

243

files: Record<string, FileInfo>;

244

/** Additional package metadata */

245

[key: string]: any;

246

}

247

248

interface FileInfo {

249

/** File integrity hash */

250

integrity: string;

251

/** File permissions mode */

252

mode: number;

253

/** File size in bytes */

254

size: number;

255

/** Timestamp when file was last checked */

256

checkedAt?: number;

257

}

258

```