or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdconstants-and-utilities.mdfilesystem-abstractions.mdfilesystem-implementations.mdindex.mdpath-handling.md

path-handling.mddocs/

0

# Path Handling

1

2

Cross-platform path manipulation utilities that provide type-safe path operations and conversion between different path formats.

3

4

## Overview

5

6

The @yarnpkg/fslib package provides comprehensive path handling through two main utilities:

7

- `ppath` - Portable path utilities for cross-platform compatibility

8

- `npath` - Native path utilities with platform-specific behavior

9

10

## Core Types

11

12

### Path Types

13

14

```typescript { .api }

15

// Basic path types

16

type PortablePath = string & { readonly __portable_path__: unique symbol };

17

type NativePath = string & { readonly __native_path__: unique symbol };

18

type Filename = string & { readonly __filename__: unique symbol };

19

type Path = PortablePath | NativePath;

20

type FSPath<T> = T | number; // Path or file descriptor

21

22

// Path component types

23

interface ParsedPath<P extends Path> {

24

root: P;

25

dir: P;

26

base: Filename;

27

ext: string;

28

name: string;

29

}

30

31

interface FormatInputPathObject<P extends Path> {

32

root?: P;

33

dir?: P;

34

base?: Filename;

35

ext?: string;

36

name?: string;

37

}

38

```

39

40

## Portable Path Utilities (ppath)

41

42

The `ppath` utility provides cross-platform path operations that always use forward slashes as separators.

43

44

### Basic Operations

45

46

```typescript { .api }

47

import { ppath, type PortablePath } from '@yarnpkg/fslib';

48

49

// Join path segments

50

const joined = ppath.join('/base' as PortablePath, 'sub', 'file.txt');

51

// Result: '/base/sub/file.txt' as PortablePath

52

53

// Resolve to absolute path

54

const resolved = ppath.resolve('/current' as PortablePath, '../relative/path');

55

// Result: '/relative/path' as PortablePath

56

57

// Normalize path

58

const normalized = ppath.normalize('/path/./to/../file.txt' as PortablePath);

59

// Result: '/path/file.txt' as PortablePath

60

```

61

62

### Path Analysis

63

64

```typescript { .api }

65

import { ppath, type PortablePath } from '@yarnpkg/fslib';

66

67

// Check if path is absolute

68

const isAbsolute = ppath.isAbsolute('/absolute/path' as PortablePath);

69

// Result: true

70

71

// Get relative path between two paths

72

const relative = ppath.relative(

73

'/from/directory' as PortablePath,

74

'/to/file.txt' as PortablePath

75

);

76

// Result: '../to/file.txt' as PortablePath

77

78

// Check if one path contains another

79

const contains = ppath.contains(

80

'/parent' as PortablePath,

81

'/parent/child/file.txt' as PortablePath

82

);

83

// Result: true

84

```

85

86

### Path Components

87

88

```typescript { .api }

89

import { ppath, type PortablePath, type Filename } from '@yarnpkg/fslib';

90

91

const filePath = '/path/to/file.txt' as PortablePath;

92

93

// Get directory name

94

const dirname = ppath.dirname(filePath);

95

// Result: '/path/to' as PortablePath

96

97

// Get base name

98

const basename = ppath.basename(filePath);

99

// Result: 'file.txt' as Filename

100

101

const basenameNoExt = ppath.basename(filePath, '.txt');

102

// Result: 'file' as Filename

103

104

// Get file extension

105

const extension = ppath.extname(filePath);

106

// Result: '.txt'

107

```

108

109

### Path Parsing and Formatting

110

111

```typescript { .api }

112

import { ppath, type PortablePath } from '@yarnpkg/fslib';

113

114

// Parse path into components

115

const parsed = ppath.parse('/path/to/file.txt' as PortablePath);

116

// Result: {

117

// root: '/' as PortablePath,

118

// dir: '/path/to' as PortablePath,

119

// base: 'file.txt' as Filename,

120

// ext: '.txt',

121

// name: 'file'

122

// }

123

124

// Format path from components

125

const formatted = ppath.format({

126

dir: '/path/to' as PortablePath,

127

name: 'file',

128

ext: '.txt'

129

});

130

// Result: '/path/to/file.txt' as PortablePath

131

```

132

133

### Working Directory Operations

134

135

```typescript { .api }

136

import { ppath } from '@yarnpkg/fslib';

137

138

// Get current working directory

139

const cwd = ppath.cwd();

140

// Result: Current working directory as PortablePath

141

```

142

143

## Native Path Utilities (npath)

144

145

The `npath` utility provides platform-specific path operations and conversion utilities.

146

147

### Basic Operations

148

149

```typescript { .api }

150

import { npath, type NativePath } from '@yarnpkg/fslib';

151

152

// All standard path operations (same interface as ppath)

153

const joined = npath.join('/base' as NativePath, 'sub', 'file.txt');

154

const resolved = npath.resolve('/current' as NativePath, '../relative/path');

155

const normalized = npath.normalize('/path/./to/../file.txt' as NativePath);

156

```

157

158

### Path Conversion

159

160

```typescript { .api }

161

import { npath, type PortablePath, type NativePath } from '@yarnpkg/fslib';

162

163

// Convert portable path to native path

164

const portablePath = '/path/to/file.txt' as PortablePath;

165

const nativePath = npath.fromPortablePath(portablePath);

166

// On Windows: 'C:\\path\\to\\file.txt' as NativePath

167

// On Unix: '/path/to/file.txt' as NativePath

168

169

// Convert native path to portable path

170

const backToPortable = npath.toPortablePath(nativePath);

171

// Result: '/path/to/file.txt' as PortablePath

172

```

173

174

## Path Constants

175

176

### Portable Path Constants

177

178

```typescript { .api }

179

import { PortablePath } from '@yarnpkg/fslib';

180

181

// Root path

182

const root = PortablePath.root; // '/' as PortablePath

183

184

// Current directory

185

const dot = PortablePath.dot; // '.' as PortablePath

186

187

// Parent directory

188

const parent = PortablePath.parent; // '..' as PortablePath

189

```

190

191

### Filename Constants

192

193

```typescript { .api }

194

import { Filename } from '@yarnpkg/fslib';

195

196

// Common directory and file names

197

const home = Filename.home; // '~' as Filename

198

const nodeModules = Filename.nodeModules; // 'node_modules' as Filename

199

const packageJson = Filename.manifest; // 'package.json' as Filename

200

const yarnLock = Filename.lockfile; // 'yarn.lock' as Filename

201

202

// Yarn-specific files

203

const virtual = Filename.virtual; // '__virtual__' as Filename

204

const pnpCjs = Filename.pnpCjs; // '.pnp.cjs' as Filename

205

const pnpData = Filename.pnpData; // '.pnp.data.json' as Filename

206

const pnpLoader = Filename.pnpEsmLoader; // '.pnp.loader.mjs' as Filename

207

const yarnrc = Filename.rc; // '.yarnrc.yml' as Filename

208

const env = Filename.env; // '.env' as Filename

209

```

210

211

## Advanced Path Operations

212

213

### Generic Path Conversion

214

215

```typescript { .api }

216

import { convertPath, ppath, npath, type PortablePath, type NativePath } from '@yarnpkg/fslib';

217

218

// Convert between path types using utilities

219

const nativePath = '/some/path' as NativePath;

220

const portablePath = convertPath(ppath, nativePath);

221

// Result: '/some/path' as PortablePath

222

223

const backToNative = convertPath(npath, portablePath);

224

// Result: '/some/path' as NativePath (or platform-specific format)

225

```

226

227

### Path Validation and Safety

228

229

```typescript { .api }

230

import { ppath, type PortablePath } from '@yarnpkg/fslib';

231

232

// Check if path is contained within another path (security)

233

function isPathSafe(basePath: PortablePath, targetPath: PortablePath): boolean {

234

const resolved = ppath.resolve(basePath, targetPath);

235

return ppath.contains(basePath, resolved);

236

}

237

238

// Usage

239

const isAllowed = isPathSafe(

240

'/safe/directory' as PortablePath,

241

'relative/path/to/file.txt' as PortablePath

242

);

243

```

244

245

### Working with Path Collections

246

247

```typescript { .api }

248

import { ppath, type PortablePath } from '@yarnpkg/fslib';

249

250

// Find common ancestor path

251

function findCommonPath(paths: PortablePath[]): PortablePath {

252

if (paths.length === 0) return '/' as PortablePath;

253

254

let common = paths[0];

255

for (const path of paths.slice(1)) {

256

while (!ppath.contains(common, path) && !ppath.contains(path, common)) {

257

common = ppath.dirname(common);

258

}

259

}

260

return common;

261

}

262

263

// Usage

264

const commonPath = findCommonPath([

265

'/project/src/components/Button.tsx' as PortablePath,

266

'/project/src/utils/helpers.ts' as PortablePath,

267

'/project/src/types/index.ts' as PortablePath

268

]);

269

// Result: '/project/src' as PortablePath

270

```

271

272

## Integration Examples

273

274

### File System Integration

275

276

```typescript { .api }

277

import { xfs, ppath, type PortablePath } from '@yarnpkg/fslib';

278

279

// Combine path utilities with filesystem operations

280

async function processFileTree(basePath: PortablePath): Promise<void> {

281

const files = await xfs.readdirPromise(basePath, { withFileTypes: true });

282

283

for (const file of files) {

284

const fullPath = ppath.join(basePath, file.name);

285

286

if (file.isDirectory()) {

287

console.log(`Directory: ${ppath.relative(ppath.cwd(), fullPath)}`);

288

await processFileTree(fullPath);

289

} else {

290

const ext = ppath.extname(fullPath);

291

console.log(`File: ${file.name} (${ext})`);

292

}

293

}

294

}

295

```

296

297

### Cross-Platform Path Handling

298

299

```typescript { .api }

300

import { npath, ppath, type PortablePath, type NativePath } from '@yarnpkg/fslib';

301

302

// Handle paths from different sources

303

function normalizePath(inputPath: string): PortablePath {

304

// Assume input might be native or portable

305

try {

306

// Try to treat as native path and convert

307

const asNative = inputPath as NativePath;

308

return npath.toPortablePath(asNative);

309

} catch {

310

// Already portable or invalid

311

return ppath.normalize(inputPath as PortablePath);

312

}

313

}

314

315

// Usage with various input formats

316

const paths = [

317

'/unix/style/path',

318

'C:\\Windows\\Style\\Path',

319

'./relative/path',

320

'../parent/directory'

321

];

322

323

const normalized = paths.map(normalizePath);

324

```

325

326

## Related Documentation

327

328

- [Filesystem Abstractions](./filesystem-abstractions.md) - Core filesystem interfaces that use these path types

329

- [Filesystem Implementations](./filesystem-implementations.md) - Concrete filesystems working with paths

330

- [Advanced Features](./advanced-features.md) - Advanced operations using path utilities