or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-interface.mdindex.mdpackage-management.mdpatch-application.mdpatch-creation.mdrebase-operations.mdutility-apis.md

utility-apis.mddocs/

0

# Utility APIs

1

2

Supporting utilities for path handling, file operations, state management, and type definitions used throughout the patch-package ecosystem. These utilities provide cross-platform compatibility, type safety, and robust error handling.

3

4

## Capabilities

5

6

### Core Type Definitions

7

8

Fundamental data structures used throughout patch-package.

9

10

```typescript { .api }

11

/**

12

* Core package details interface

13

*/

14

interface PackageDetails {

15

/** Human-readable package path specifier */

16

humanReadablePathSpecifier: string;

17

/** Package path specifier */

18

pathSpecifier: string;

19

/** File system path to package */

20

path: string;

21

/** Package name */

22

name: string;

23

/** Whether package is nested */

24

isNested: boolean;

25

/** Array of package names in hierarchy */

26

packageNames: string[];

27

}

28

29

/**

30

* Extended package details with patch information

31

*/

32

interface PatchedPackageDetails extends PackageDetails {

33

/** Package version */

34

version: string;

35

/** Patch file name */

36

patchFilename: string;

37

/** Development dependency only */

38

isDevOnly: boolean;

39

/** Optional sequence name */

40

sequenceName?: string;

41

/** Optional sequence number */

42

sequenceNumber?: number;

43

}

44

```

45

46

### Package Detail Parsing

47

48

Functions for parsing and extracting package information from various string formats.

49

50

```typescript { .api }

51

/**

52

* Parse package name and version from string

53

* @param str - String containing package info

54

* @returns Parsed name and version info or null if invalid

55

*/

56

function parseNameAndVersion(str: string): ParsedNameVersion | null;

57

58

interface ParsedNameVersion {

59

packageName: string;

60

version: string;

61

sequenceName?: string;

62

sequenceNumber?: number;

63

}

64

65

/**

66

* Extract package details from patch filename

67

* @param patchFilename - Patch file name

68

* @returns Package details or null if invalid filename

69

*/

70

function getPackageDetailsFromPatchFilename(patchFilename: string): PatchedPackageDetails | null;

71

72

/**

73

* Parse package details from CLI string

74

* @param specifier - Package specifier string

75

* @returns Package details or null if invalid

76

*/

77

function getPatchDetailsFromCliString(specifier: string): PackageDetails | null;

78

```

79

80

**Usage Examples:**

81

82

```typescript

83

import {

84

parseNameAndVersion,

85

getPackageDetailsFromPatchFilename,

86

getPatchDetailsFromCliString

87

} from "patch-package/dist/PackageDetails";

88

89

// Parse version info

90

const nameVersion = parseNameAndVersion("lodash+4.17.21++001_security-fix");

91

// Returns: { packageName: "lodash", version: "4.17.21", sequenceName: "security-fix", sequenceNumber: 1 }

92

93

// Extract from patch filename

94

const patchDetails = getPackageDetailsFromPatchFilename("react+17.0.2.patch");

95

96

// Parse CLI input

97

const cliDetails = getPatchDetailsFromCliString("@types/node");

98

```

99

100

## Cross-Platform Path Utilities

101

102

### Path Operations

103

104

Cross-platform path handling utilities that work consistently across Windows, macOS, and Linux.

105

106

```typescript { .api }

107

/**

108

* Cross-platform path joining

109

* @param args - Path segments to join

110

* @returns Joined path with correct separators

111

*/

112

function join(...args: string[]): string;

113

114

/**

115

* Cross-platform path resolution

116

* @param args - Path segments to resolve

117

* @returns Absolute resolved path

118

*/

119

function resolve(...args: string[]): string;

120

121

/**

122

* Cross-platform relative path calculation

123

* @param from - Source path

124

* @param to - Target path

125

* @returns Relative path from source to target

126

*/

127

function relative(from: string, to: string): string;

128

129

/**

130

* Get directory name from path

131

* @param path - File or directory path

132

* @returns Directory name

133

*/

134

function dirname(path: string): string;

135

```

136

137

**Usage Examples:**

138

139

```typescript

140

import { join, resolve, relative, dirname } from "patch-package/dist/path";

141

142

// Cross-platform path joining

143

const patchPath = join("patches", "lodash+4.17.21.patch");

144

// Windows: "patches\\lodash+4.17.21.patch"

145

// Unix: "patches/lodash+4.17.21.patch"

146

147

// Resolve absolute path

148

const absolutePath = resolve("./patches", "../node_modules", "lodash");

149

150

// Calculate relative path

151

const relPath = relative("/app", "/app/node_modules/lodash");

152

// Returns: "node_modules/lodash"

153

154

// Get directory

155

const dir = dirname("/path/to/file.patch");

156

// Returns: "/path/to"

157

```

158

159

## File System Operations

160

161

### File Hashing

162

163

Content hashing for patch validation and integrity checking.

164

165

```typescript { .api }

166

/**

167

* Generate SHA-256 hash of file content

168

* @param filePath - Path to file to hash

169

* @returns SHA-256 hash string

170

*/

171

function hashFile(filePath: string): string;

172

173

/**

174

* Coerce version string to valid semver format

175

* @param version - Version string to coerce

176

* @returns Valid semver string or null if invalid

177

*/

178

function coerceSemVer(version: string): string | null;

179

```

180

181

**Usage Examples:**

182

183

```typescript

184

import { hashFile } from "patch-package/dist/hash";

185

import { coerceSemVer } from "patch-package/dist/coerceSemVer";

186

187

// Generate file hash for validation

188

const patchHash = hashFile("patches/lodash+4.17.21.patch");

189

console.log(`Patch hash: ${patchHash}`);

190

191

// Coerce version to valid semver

192

const validVersion = coerceSemVer("1.0.0-beta.1+build.123");

193

// Returns: "1.0.0-beta.1"

194

195

const invalidVersion = coerceSemVer("not-a-version");

196

// Returns: null

197

198

// Use in state management

199

import { savePatchApplicationState } from "patch-package/dist/stateFile";

200

savePatchApplicationState({

201

packageDetails,

202

patches: [{

203

patchFilename: "lodash+4.17.21.patch",

204

patchContentHash: hashFile("patches/lodash+4.17.21.patch"),

205

didApply: true

206

}],

207

isRebasing: false

208

});

209

```

210

211

### Safe Process Execution

212

213

Secure process spawning for executing shell commands.

214

215

```typescript { .api }

216

/**

217

* Safely execute shell commands

218

* @param command - Command to execute

219

* @param args - Command arguments array

220

* @param options - Spawn options

221

* @returns Spawn result with status and output

222

*/

223

function spawnSafeSync(

224

command: string,

225

args?: string[],

226

options?: SpawnSafeOptions

227

): SpawnResult;

228

229

interface SpawnSafeOptions {

230

/** Current working directory */

231

cwd?: string;

232

/** Environment variables */

233

env?: Record<string, string>;

234

/** Input to pass to command */

235

input?: string | Buffer;

236

/** Stdio configuration */

237

stdio?: "pipe" | "inherit" | "ignore";

238

/** Timeout in milliseconds */

239

timeout?: number;

240

/** Kill signal */

241

killSignal?: string;

242

}

243

244

interface SpawnResult {

245

/** Exit status code */

246

status: number | null;

247

/** Kill signal if terminated */

248

signal: string | null;

249

/** Standard output */

250

stdout: Buffer;

251

/** Standard error */

252

stderr: Buffer;

253

}

254

```

255

256

**Usage Examples:**

257

258

```typescript

259

import { spawnSafeSync } from "patch-package/dist/spawnSafe";

260

261

// Execute git command safely

262

const result = spawnSafeSync("git", ["diff", "--no-index", "original", "modified"], {

263

cwd: "/path/to/package",

264

timeout: 30000

265

});

266

267

if (result.status === 0) {

268

const diff = result.stdout.toString();

269

console.log("Git diff output:", diff);

270

} else {

271

console.error("Git command failed:", result.stderr.toString());

272

}

273

```

274

275

## Regular Expression Utilities

276

277

### RegExp Creation

278

279

Utility for creating regular expressions with error handling and validation.

280

281

```typescript { .api }

282

/**

283

* Create RegExp with error handling and validation

284

* @param reString - Regular expression string

285

* @param name - Name for error reporting

286

* @param defaultValue - Default regex if parsing fails

287

* @param caseSensitive - Case sensitivity flag

288

* @returns Compiled regular expression

289

*/

290

function makeRegExp(

291

reString: string,

292

name: string,

293

defaultValue: RegExp,

294

caseSensitive: boolean

295

): RegExp;

296

```

297

298

**Usage Examples:**

299

300

```typescript

301

import { makeRegExp } from "patch-package/dist/makeRegExp";

302

303

// Create include pattern with error handling

304

const includePaths = makeRegExp(

305

"src/.*\\.(js|ts)$",

306

"include paths",

307

/.*/,

308

false

309

);

310

311

// Create exclude pattern

312

const excludePaths = makeRegExp(

313

"(test|spec|__tests__)/.*",

314

"exclude paths",

315

/^package\.json$/,

316

true // case sensitive

317

);

318

319

// Use in patch creation

320

import { makePatch } from "patch-package/dist/makePatch";

321

makePatch({

322

packagePathSpecifier: "my-package",

323

appPath: process.cwd(),

324

packageManager: "npm",

325

includePaths,

326

excludePaths,

327

// ... other options

328

});

329

```

330

331

## Type Safety Utilities

332

333

### Exhaustiveness Checking

334

335

TypeScript utility for exhaustive type checking.

336

337

```typescript { .api }

338

/**

339

* TypeScript exhaustiveness checking utility

340

* @param x - Value that should never be reached

341

* @throws Error if called (indicates missing case)

342

*/

343

function assertNever(x: never): never;

344

```

345

346

**Usage Examples:**

347

348

```typescript

349

import { assertNever } from "patch-package/dist/assertNever";

350

351

type PackageManager = "npm" | "yarn" | "npm-shrinkwrap";

352

353

function handlePackageManager(pm: PackageManager) {

354

switch (pm) {

355

case "npm":

356

return "Using npm";

357

case "yarn":

358

return "Using yarn";

359

case "npm-shrinkwrap":

360

return "Using npm-shrinkwrap";

361

default:

362

// TypeScript will ensure this is never reached

363

return assertNever(pm);

364

}

365

}

366

```

367

368

## State File Management

369

370

### State Persistence

371

372

Utilities for managing patch application state persistence.

373

374

```typescript { .api }

375

/** State file name constant */

376

const STATE_FILE_NAME: ".patch-package.json";

377

378

/**

379

* Get current patch application state

380

* @param packageDetails - Package details

381

* @returns Current state or null if none exists

382

*/

383

function getPatchApplicationState(packageDetails: PackageDetails): PatchApplicationState | null;

384

385

/**

386

* Save patch application state

387

* @param options - State save options

388

*/

389

function savePatchApplicationState(options: SaveStateOptions): void;

390

391

/**

392

* Clear patch application state

393

* @param packageDetails - Package details

394

*/

395

function clearPatchApplicationState(packageDetails: PackageDetails): void;

396

397

interface SaveStateOptions {

398

packageDetails: PackageDetails;

399

patches: PatchState[];

400

isRebasing: boolean;

401

}

402

403

interface PatchState {

404

patchFilename: string;

405

patchContentHash: string;

406

didApply: boolean;

407

}

408

409

interface PatchApplicationState {

410

version: number;

411

patches: PatchState[];

412

isRebasing: boolean;

413

}

414

```

415

416

## Complete Utility Integration Example

417

418

```typescript

419

import {

420

getPatchDetailsFromCliString,

421

parseNameAndVersion,

422

join,

423

resolve,

424

hashFile,

425

makeRegExp,

426

spawnSafeSync,

427

getPatchApplicationState,

428

savePatchApplicationState

429

} from "patch-package/dist";

430

431

// Complete workflow using utilities

432

async function processPackagePatch(packageName: string) {

433

// Parse package details

434

const packageDetails = getPatchDetailsFromCliString(packageName);

435

if (!packageDetails) {

436

throw new Error(`Invalid package: ${packageName}`);

437

}

438

439

// Build paths using cross-platform utilities

440

const patchDir = resolve("patches");

441

const patchPath = join(patchDir, `${packageName}+1.0.0.patch`);

442

443

// Create regex patterns with error handling

444

const includePaths = makeRegExp("src/.*\\.(js|ts)$", "include", /.*/, false);

445

const excludePaths = makeRegExp("test/.*", "exclude", /^package\.json$/, false);

446

447

// Check current state

448

const currentState = getPatchApplicationState(packageDetails);

449

450

// Generate file hash for validation

451

const patchHash = hashFile(patchPath);

452

453

// Execute git command safely

454

const gitResult = spawnSafeSync("git", ["status", "--porcelain"], {

455

cwd: packageDetails.path,

456

timeout: 10000

457

});

458

459

// Update state

460

savePatchApplicationState({

461

packageDetails,

462

patches: [{

463

patchFilename: `${packageName}+1.0.0.patch`,

464

patchContentHash: patchHash,

465

didApply: true

466

}],

467

isRebasing: false

468

});

469

470

return {

471

packageDetails,

472

patchPath,

473

currentState,

474

gitStatus: gitResult.stdout.toString()

475

};

476

}

477

```

478

479

These utilities form the foundation that enables patch-package to work reliably across different platforms, package managers, and project structures while maintaining type safety and robust error handling.