or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configurations.mddependency-checks.mdindex.mdmodule-boundaries.mdplugin-validation.mdworkspace-rules.md

workspace-rules.mddocs/

0

# Workspace Rule Integration

1

2

The @nx/eslint-plugin provides dynamic loading and integration of custom ESLint rules from the workspace's `tools/eslint-rules` directory, enabling project-specific linting extensions while maintaining proper namespacing and TypeScript support.

3

4

## Capabilities

5

6

### Workspace Rules Loading

7

8

Automatically discovers and loads custom ESLint rules from the workspace tools directory.

9

10

```typescript { .api }

11

/**

12

* Dynamically loaded workspace rules with automatic namespacing

13

*/

14

interface WorkspaceRules {

15

/** Current namespacing format */

16

[key: `workspace-${string}`]: TSESLint.RuleModule<string, unknown[]>;

17

18

/** Legacy namespacing format for backwards compatibility */

19

[key: `workspace/${string}`]: TSESLint.RuleModule<string, unknown[]>;

20

}

21

22

/**

23

* Function that loads workspace rules on plugin initialization

24

*/

25

function loadWorkspaceRules(): WorkspaceRules;

26

```

27

28

### Workspace Plugin Structure

29

30

Expected structure for custom workspace rules.

31

32

```typescript { .api }

33

// tools/eslint-rules/index.ts

34

interface WorkspacePlugin {

35

rules: {

36

[ruleName: string]: TSESLint.RuleModule<string, unknown[]>;

37

};

38

}

39

40

// Example workspace plugin

41

export const rules = {

42

"no-barrel-imports": noBarrelImportsRule,

43

"enforce-naming-convention": enforceNamingConventionRule,

44

"restrict-third-party-libs": restrictThirdPartyLibsRule

45

};

46

```

47

48

### Rule Namespacing

49

50

All workspace rules are automatically namespaced to prevent conflicts with official rules.

51

52

```typescript { .api }

53

interface RuleNamespacing {

54

/** Original rule name in workspace */

55

originalName: string;

56

57

/** Current namespaced format */

58

namespacedName: `workspace-${string}`;

59

60

/** Legacy namespaced format (backwards compatibility) */

61

legacyNamespacedName: `workspace/${string}`;

62

}

63

64

// Example transformations:

65

// "no-barrel-imports" → "workspace-no-barrel-imports"

66

// "no-barrel-imports" → "workspace/no-barrel-imports" (legacy)

67

```

68

69

### Constants and Configuration

70

71

Key constants used for workspace rule integration.

72

73

```typescript { .api }

74

/** Path to workspace rules directory relative to workspace root */

75

const WORKSPACE_RULES_PATH: "tools/eslint-rules";

76

77

/** Full path to workspace plugin directory */

78

const WORKSPACE_PLUGIN_DIR: string; // join(workspaceRoot, WORKSPACE_RULES_PATH)

79

80

/** Namespace prefix for workspace rules */

81

const WORKSPACE_RULE_PREFIX: "workspace";

82

```

83

84

**Usage Examples:**

85

86

```typescript

87

// Creating custom workspace rule

88

// tools/eslint-rules/rules/no-barrel-imports.ts

89

import { ESLintUtils } from '@typescript-eslint/utils';

90

91

export default ESLintUtils.RuleCreator(() => '')({

92

name: 'no-barrel-imports',

93

meta: {

94

type: 'problem',

95

docs: {

96

description: 'Disallow barrel exports that re-export everything'

97

},

98

messages: {

99

noBarrelImports: 'Avoid barrel imports that re-export everything'

100

},

101

schema: []

102

},

103

defaultOptions: [],

104

create(context) {

105

return {

106

ExportAllDeclaration(node) {

107

context.report({

108

node,

109

messageId: 'noBarrelImports'

110

});

111

}

112

};

113

}

114

});

115

116

// tools/eslint-rules/index.ts

117

import noBarrelImports from './rules/no-barrel-imports';

118

119

export const rules = {

120

'no-barrel-imports': noBarrelImports

121

};

122

123

// Using workspace rule in ESLint config

124

module.exports = {

125

rules: {

126

'@nx/workspace-no-barrel-imports': 'error'

127

}

128

};

129

130

// Flat config usage

131

import nxPlugin from '@nx/eslint-plugin';

132

133

export default [

134

{

135

plugins: {

136

'@nx': nxPlugin

137

},

138

rules: {

139

'@nx/workspace-no-barrel-imports': 'error'

140

}

141

}

142

];

143

```

144

145

### TypeScript Integration

146

147

Workspace rules support full TypeScript compilation and type checking.

148

149

```typescript { .api }

150

interface TypeScriptIntegration {

151

/** TypeScript configuration for workspace rules */

152

tsConfigPath: string; // tools/eslint-rules/tsconfig.json

153

154

/** Automatic TypeScript project registration */

155

projectRegistration: () => (() => void) | undefined;

156

157

/** Compilation and loading process */

158

compilationSupport: boolean;

159

}

160

161

// Example tsconfig.json for workspace rules

162

{

163

"extends": "../../tsconfig.base.json",

164

"compilerOptions": {

165

"module": "commonjs",

166

"target": "es2020",

167

"lib": ["es2020"],

168

"declaration": false,

169

"strict": true,

170

"noImplicitReturns": true,

171

"noFallthroughCasesInSwitch": true

172

},

173

"include": ["**/*.ts"],

174

"exclude": ["**/*.spec.ts"]

175

}

176

```

177

178

### Error Handling and Fallbacks

179

180

Robust error handling ensures the plugin continues to work even when workspace rules fail to load.

181

182

```typescript { .api }

183

interface ErrorHandling {

184

/** Fallback when tools/eslint-rules doesn't exist */

185

missingDirectory: () => WorkspaceRules; // Returns {}

186

187

/** Fallback when loading fails */

188

loadingError: (error: Error) => WorkspaceRules; // Logs error, returns {}

189

190

/** Cleanup function for TypeScript registration */

191

cleanup: () => void;

192

}

193

```

194

195

**Usage Examples:**

196

197

```typescript

198

// Complex workspace rule with options

199

// tools/eslint-rules/rules/enforce-project-structure.ts

200

import { ESLintUtils } from '@typescript-eslint/utils';

201

202

interface Options {

203

allowedDirectories: string[];

204

bannedPatterns: string[];

205

}

206

207

export default ESLintUtils.RuleCreator(() => '')({

208

name: 'enforce-project-structure',

209

meta: {

210

type: 'problem',

211

docs: {

212

description: 'Enforce project structure conventions'

213

},

214

schema: [{

215

type: 'object',

216

properties: {

217

allowedDirectories: {

218

type: 'array',

219

items: { type: 'string' }

220

},

221

bannedPatterns: {

222

type: 'array',

223

items: { type: 'string' }

224

}

225

},

226

additionalProperties: false

227

}],

228

messages: {

229

invalidDirectory: 'Files in {{directory}} are not allowed',

230

bannedPattern: 'File matches banned pattern: {{pattern}}'

231

}

232

},

233

defaultOptions: [{

234

allowedDirectories: ['src', 'lib'],

235

bannedPatterns: []

236

}],

237

create(context, [options]) {

238

return {

239

Program(node) {

240

const filename = context.getFilename();

241

// Implementation logic

242

}

243

};

244

}

245

});

246

247

// Using in ESLint config with options

248

module.exports = {

249

rules: {

250

'@nx/workspace-enforce-project-structure': [

251

'error',

252

{

253

allowedDirectories: ['src', 'lib', 'test'],

254

bannedPatterns: ['**/legacy/**', '**/*.old.*']

255

}

256

]

257

}

258

};

259

```

260

261

### Integration with Nx Plugin System

262

263

Workspace rules integrate seamlessly with Nx's broader plugin ecosystem:

264

265

- **Project Graph Access**: Rules can access the Nx project graph for workspace-aware linting

266

- **Configuration Integration**: Rules can read Nx project configurations

267

- **Build System Integration**: Rules can integrate with Nx build targets and caching

268

- **Migration Support**: Rules can participate in Nx migration workflows

269

270

### Best Practices for Workspace Rules

271

272

Guidelines for creating effective workspace-specific rules:

273

274

1. **Namespace Carefully**: Use descriptive names that won't conflict with future official rules

275

2. **TypeScript First**: Write rules in TypeScript for better maintainability

276

3. **Error Handling**: Provide clear error messages and handle edge cases

277

4. **Performance**: Consider performance impact on large workspaces

278

5. **Testing**: Include comprehensive tests for workspace rules

279

6. **Documentation**: Document rule purpose and configuration options

280

281

### Backwards Compatibility

282

283

The plugin maintains backwards compatibility for existing workspace rule configurations:

284

285

```typescript

286

// Both formats work:

287

module.exports = {

288

rules: {

289

'@nx/workspace-my-rule': 'error', // Current format

290

'@nx/workspace/my-rule': 'error' // Legacy format (still supported)

291

}

292

};

293

```