or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/npm-pirates

Properly hijack require, i.e., properly define require hooks and customizations

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/pirates@4.0.x

To install, run

npx @tessl/cli install tessl/npm-pirates@4.0.0

0

# Pirates

1

2

Pirates is a Node.js library that provides functionality to properly hijack the CommonJS `require()` process, allowing multiple require hooks to coexist without interfering with each other. It solves compatibility issues between tools like Babel and Istanbul by providing a clean API for implementing custom require transformations.

3

4

## Package Information

5

6

- **Package Name**: pirates

7

- **Package Type**: npm

8

- **Language**: JavaScript with TypeScript definitions

9

- **Installation**: `npm install pirates`

10

11

## Core Imports

12

13

```javascript

14

const { addHook } = require('pirates');

15

```

16

17

For ES modules:

18

19

```javascript

20

import { addHook } from 'pirates';

21

```

22

23

## Basic Usage

24

25

```javascript

26

const { addHook } = require('pirates');

27

28

// Create a simple transformation hook

29

const revert = addHook((code, filename) => {

30

// Transform the code before it's executed

31

return code.replace('@@placeholder', 'console.log("transformed!");');

32

}, {

33

exts: ['.js'], // Only process .js files

34

ignoreNodeModules: true // Skip node_modules (default: true)

35

});

36

37

// Later, if you want to remove the hook:

38

revert();

39

```

40

41

## Architecture

42

43

Pirates works by intercepting Node.js's internal `Module._extensions` mechanism. Key design principles:

44

45

- **Non-interfering**: Multiple hooks can coexist without breaking each other

46

- **Reversible**: All hooks can be cleanly removed using returned revert functions

47

- **Flexible**: Supports custom file extensions, matcher functions, and selective processing

48

- **Safe**: Built-in validation and error handling prevent broken transformations

49

50

## Capabilities

51

52

### Require Hook Registration

53

54

The main functionality for adding transformation hooks to the Node.js require process.

55

56

```typescript { .api }

57

/**

58

* Add a require hook that transforms code before execution

59

* @param hook - Function that receives code and filename, returns transformed code

60

* @param opts - Configuration options for the hook

61

* @returns Function to revert/remove the hook when called

62

*/

63

function addHook(hook: Hook, opts?: Options): RevertFunction;

64

65

/**

66

* Hook function signature for transforming module code

67

* @param code - Source code of the module being required

68

* @param filename - Absolute path of the file being processed

69

* @returns Transformed code as a string

70

*/

71

type Hook = (code: string, filename: string) => string;

72

73

/**

74

* Function returned by addHook to remove the hook

75

*/

76

type RevertFunction = () => void;

77

```

78

79

**Usage Example:**

80

81

```javascript

82

const { addHook } = require('pirates');

83

84

const revert = addHook((code, filename) => {

85

// Only transform files containing a specific marker

86

if (code.includes('// @custom-transform')) {

87

return code

88

.replace(/var /g, 'let ')

89

.replace(/function /g, 'const ');

90

}

91

return code;

92

});

93

94

// Use your transformed modules...

95

require('./my-module'); // Will be transformed

96

97

// Clean up when done

98

revert();

99

```

100

101

### Hook Configuration

102

103

Comprehensive options for controlling when and how hooks are applied.

104

105

```typescript { .api }

106

interface Options {

107

/**

108

* File extensions to process (takes precedence over other extension options)

109

* @default ['.js']

110

*/

111

extensions?: ReadonlyArray<string> | string;

112

113

/**

114

* File extensions to process (alias for extensions)

115

* @default ['.js']

116

*/

117

exts?: ReadonlyArray<string> | string;

118

119

/**

120

* File extensions to process (alias for extensions)

121

* @default ['.js']

122

*/

123

extension?: ReadonlyArray<string> | string;

124

125

/**

126

* File extensions to process (alias for extensions)

127

* @default ['.js']

128

*/

129

ext?: ReadonlyArray<string> | string;

130

131

/**

132

* Custom function to determine which files should be processed

133

* @param path - Absolute path of the file being evaluated

134

* @returns true to process the file, false to skip it

135

*/

136

matcher?: Matcher | null;

137

138

/**

139

* Whether to automatically ignore node_modules directories

140

* @default true

141

*/

142

ignoreNodeModules?: boolean;

143

}

144

145

/**

146

* Custom matcher function for selective file processing

147

*/

148

type Matcher = (path: string) => boolean;

149

```

150

151

**Configuration Examples:**

152

153

```javascript

154

const { addHook } = require('pirates');

155

156

// Process only TypeScript files

157

addHook(transformTypeScript, {

158

exts: ['.ts', '.tsx']

159

});

160

161

// Use custom file matching logic

162

addHook(transformSpecialFiles, {

163

matcher: (filename) => {

164

return filename.includes('.special.') &&

165

!filename.includes('.test.');

166

}

167

});

168

169

// Process files in node_modules (usually not recommended)

170

addHook(transformEverything, {

171

ignoreNodeModules: false

172

});

173

174

// Multiple extensions with array syntax

175

addHook(transformJavaScript, {

176

extensions: ['.js', '.jsx', '.mjs']

177

});

178

```

179

180

## Error Handling

181

182

Pirates includes built-in validation and clear error messages:

183

184

- **Invalid Extensions**: Throws `TypeError` if extension is not a string

185

- **Invalid Hook Return**: Throws `Error` if hook doesn't return a string

186

- **Hook Chain Safety**: Automatically prevents hook interference and memory leaks

187

188

```javascript

189

const { addHook } = require('pirates');

190

191

// This will throw an error

192

addHook((code, filename) => {

193

// Returning undefined/null breaks the require process

194

return null; // Error: Hook returned nothing!

195

});

196

197

// This will throw a TypeError

198

addHook(myHook, {

199

ext: 123 // Error: Invalid Extension: 123

200

});

201

```

202

203

## Multiple Hook Management

204

205

```javascript

206

const { addHook } = require('pirates');

207

208

// Add multiple hooks that work together

209

const revertBabel = addHook(babelTransform, { exts: ['.jsx'] });

210

const revertTypeScript = addHook(tsTransform, { exts: ['.ts'] });

211

const revertCustom = addHook(customTransform, {

212

matcher: (path) => path.endsWith('.custom.js')

213

});

214

215

// All hooks work independently and can be reverted separately

216

setTimeout(() => {

217

revertBabel(); // Only removes Babel hook

218

}, 5000);

219

220

// Or revert all at once

221

function cleanup() {

222

revertBabel();

223

revertTypeScript();

224

revertCustom();

225

}

226

```