@burdenoff/toolchain 0.0.0-stage → 2026.1107.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ // knip/base.ts
2
+ var KNIP_BASE = {
3
+ ignore: ["**/generated/**", "**/*.generated.ts", "dist/**", "coverage/**", "fixtures/**"],
4
+ ignoreDependencies: ["@burdenoff/toolchain", "bun-types", "@types/bun"],
5
+ ignoreBinaries: ["boff"],
6
+ ignoreExportsUsedInFile: true
7
+ };
8
+ function knipConfig(overrides = {}) {
9
+ return {
10
+ ...overrides,
11
+ ignore: [...KNIP_BASE.ignore, ...overrides.ignore ?? []],
12
+ ignoreDependencies: [...KNIP_BASE.ignoreDependencies, ...overrides.ignoreDependencies ?? []],
13
+ ignoreBinaries: [...KNIP_BASE.ignoreBinaries, ...overrides.ignoreBinaries ?? []],
14
+ ignoreExportsUsedInFile: overrides.ignoreExportsUsedInFile ?? KNIP_BASE.ignoreExportsUsedInFile
15
+ };
16
+ }
17
+ var base_default = knipConfig;
18
+ export {
19
+ KNIP_BASE,
20
+ base_default as default,
21
+ knipConfig
22
+ };
@@ -0,0 +1,4 @@
1
+ import type { BackendOptions, FlatConfigArray } from './index.js';
2
+
3
+ export type { BackendOptions };
4
+ export default function createBurdenoffConfig(dirname: string, options?: BackendOptions): FlatConfigArray;
@@ -0,0 +1,487 @@
1
+ import pluginJs from '@eslint/js';
2
+ import eslintComments from 'eslint-plugin-eslint-comments';
3
+ import importPlugin from 'eslint-plugin-import';
4
+ import security from 'eslint-plugin-security';
5
+ import sonarjs from 'eslint-plugin-sonarjs';
6
+ import globals from 'globals';
7
+ import tseslint from 'typescript-eslint';
8
+
9
+ /**
10
+ * Burdenoff backend ESLint profile (@burdenoff/toolchain/eslint/backend).
11
+ *
12
+ * A faithful port of @burdenoff/be-sdk/eslint (configs/eslint/index.js, v1.2.0):
13
+ * same plugins, same rules, same per-path overrides, same factory signature.
14
+ * The plugins are dependencies of @burdenoff/toolchain, so a consuming repo
15
+ * keeps only `eslint` itself as a devDependency.
16
+ *
17
+ * // eslint.config.js
18
+ * import backend from '@burdenoff/toolchain/eslint/backend';
19
+ * export default backend(import.meta.dirname, { project: './tsconfig.json' });
20
+ *
21
+ * @param {string} dirname - The directory of the consuming project (use import.meta.dirname)
22
+ * @param {object} [options] - Optional configuration
23
+ * @param {string} [options.project] - Path to the tsconfig used for type-aware rules (default: './tsconfig.eslint.json')
24
+ * @param {string[]} [options.ignores] - Extra ignore globs appended to the defaults
25
+ * @returns {import('eslint').Linter.Config[]}
26
+ */
27
+ export default function createBurdenoffConfig(dirname, options = {}) {
28
+ const { project = './tsconfig.eslint.json', ignores = [] } = options;
29
+
30
+ if (!dirname) {
31
+ throw new Error('@burdenoff/toolchain/eslint/backend: dirname is required. Use backend(import.meta.dirname)');
32
+ }
33
+ if (!Array.isArray(ignores) || ignores.some((g) => typeof g !== 'string')) {
34
+ throw new Error('@burdenoff/toolchain/eslint/backend: options.ignores must be an array of strings');
35
+ }
36
+
37
+ return [
38
+ {
39
+ files: ['**/*.{js,mjs,cjs,ts}'],
40
+ },
41
+ {
42
+ ignores: [
43
+ '**/generated/**',
44
+ '**/generated/*.ts',
45
+ '**/temp/**',
46
+ '**/dist/**',
47
+ '**/coverage/**',
48
+ '**/node_modules/**',
49
+ '*.d.ts',
50
+ '*.config.js',
51
+ '*.config.mjs',
52
+ ...ignores,
53
+ ],
54
+ },
55
+ {
56
+ languageOptions: {
57
+ globals: {
58
+ ...globals.node,
59
+ ...globals.es2022,
60
+ },
61
+ parserOptions: {
62
+ // Automatically configured from factory function parameters
63
+ project,
64
+ tsconfigRootDir: dirname,
65
+ ecmaVersion: 'latest',
66
+ sourceType: 'module',
67
+ },
68
+ },
69
+ },
70
+ // ============================================================================
71
+ // Base Recommended Configurations
72
+ // ============================================================================
73
+ pluginJs.configs.recommended,
74
+ ...tseslint.configs.recommended,
75
+ security.configs.recommended,
76
+ sonarjs.configs.recommended,
77
+ {
78
+ plugins: {
79
+ import: importPlugin,
80
+ 'eslint-comments': eslintComments,
81
+ },
82
+ rules: {
83
+ // ============================================================================
84
+ // ESLint Comments - Control inline ESLint directives
85
+ // ============================================================================
86
+ 'eslint-comments/no-use': 'error', // Require description for eslint-disable comments
87
+ 'eslint-comments/no-unlimited-disable': 'error', // Disallow unlimited eslint-disable
88
+ 'eslint-comments/no-restricted-disable': 'error', // Disallow disabling specific rules without justification
89
+ 'eslint-comments/no-duplicate-disable': 'error', // Disallow duplicate eslint-disable comments
90
+ 'eslint-comments/no-unused-disable': 'error', // Disallow unused eslint-disable comments
91
+ 'eslint-comments/no-unused-enable': 'error', // Disallow unused eslint-enable comments
92
+
93
+ // ============================================================================
94
+ // TypeScript Core Rules
95
+ // ============================================================================
96
+ '@typescript-eslint/ban-ts-ignore': 'off', // Allow @ts-ignore when needed
97
+ '@typescript-eslint/ban-ts-comment': 'off', // Allow @ts-expect-error with description
98
+
99
+ // Type Safety - Gradual adoption approach
100
+ '@typescript-eslint/no-explicit-any': 'warn', // Warn on 'any' usage (gradual improvement)
101
+ // Unused vars/imports - ERROR level since TypeScript's noUnusedLocals is disabled
102
+ // (TypeScript doesn't support per-file overrides, so ESLint handles this)
103
+ // Generated files are excluded via the ignores pattern and override section
104
+ '@typescript-eslint/no-unused-vars': [
105
+ 'error',
106
+ {
107
+ argsIgnorePattern: '^_',
108
+ varsIgnorePattern: '^_',
109
+ destructuredArrayIgnorePattern: '^_',
110
+ caughtErrorsIgnorePattern: '^_',
111
+ ignoreRestSiblings: true,
112
+ },
113
+ ],
114
+ '@typescript-eslint/explicit-function-return-type': [
115
+ 'warn',
116
+ {
117
+ allowExpressions: true,
118
+ allowTypedFunctionExpressions: true,
119
+ allowHigherOrderFunctions: true,
120
+ },
121
+ ],
122
+
123
+ // ============================================================================
124
+ // Async/Promise Handling - CRITICAL for backend reliability
125
+ // ============================================================================
126
+ '@typescript-eslint/no-floating-promises': 'error', // Prevent unhandled promises
127
+ '@typescript-eslint/no-misused-promises': 'error', // Prevent promises used in wrong contexts
128
+ '@typescript-eslint/await-thenable': 'error', // Ensure await is only used with promises
129
+ // Disable require-await - async functions without await are allowed for interface consistency,
130
+ // promise return types, and future async operations
131
+ '@typescript-eslint/require-await': 'off',
132
+ // Disable promise-function-async - produces numerous false positives on arrow functions
133
+ // in array methods that don't return promises (e.g., .map((x) => x.id), .filter((a) => a.tag))
134
+ // The rule incorrectly flags simple property access and synchronous operations as promise-returning
135
+ '@typescript-eslint/promise-function-async': 'off',
136
+ 'no-return-await': 'off', // Turned off in favor of @typescript-eslint version
137
+ '@typescript-eslint/return-await': 'error', // Enforce proper return await for try/catch
138
+
139
+ // ============================================================================
140
+ // Type Imports/Exports - Tree-shaking and performance
141
+ // ============================================================================
142
+ '@typescript-eslint/consistent-type-imports': [
143
+ 'error',
144
+ {
145
+ prefer: 'type-imports',
146
+ disallowTypeAnnotations: false, // Allow type imports in annotations
147
+ fixStyle: 'separate-type-imports',
148
+ },
149
+ ],
150
+ '@typescript-eslint/consistent-type-exports': 'error',
151
+ '@typescript-eslint/no-unnecessary-type-assertion': 'error',
152
+
153
+ // Type safety rules with too many false positives - disabled for now
154
+ '@typescript-eslint/no-unsafe-assignment': 'off',
155
+ '@typescript-eslint/no-unsafe-call': 'off',
156
+ '@typescript-eslint/no-unsafe-member-access': 'off',
157
+ '@typescript-eslint/no-unsafe-return': 'off',
158
+ '@typescript-eslint/no-namespace': 'warn', // Warn on namespaces (occasionally needed for type augmentation)
159
+
160
+ // ============================================================================
161
+ // Import Organization - Code organization and circular dependency prevention
162
+ // ============================================================================
163
+ 'import/order': 'off', // Disabled in favor of Prettier plugin (@trivago/prettier-plugin-sort-imports)
164
+ 'import/no-duplicates': 'error', // Prevent duplicate imports
165
+ 'import/no-cycle': ['error', { maxDepth: 3 }], // Prevent circular dependencies
166
+ 'import/no-self-import': 'error', // Prevent self imports
167
+ 'import/first': 'error', // Imports should be at top of file
168
+ 'import/newline-after-import': 'error', // Blank line after imports
169
+
170
+ // ============================================================================
171
+ // Code Quality - General best practices
172
+ // ============================================================================
173
+ 'no-console': ['warn', { allow: ['warn', 'error', 'info'] }], // Warn on console.log
174
+ 'no-debugger': 'error', // Disallow debugger statements
175
+ 'prefer-const': 'error', // Prefer const over let
176
+ 'no-var': 'error', // Disallow var
177
+ eqeqeq: ['error', 'always', { null: 'ignore' }], // Require === and !==
178
+ 'no-throw-literal': 'error', // Disallow throwing literals
179
+ 'prefer-promise-reject-errors': 'error', // Reject with Error objects
180
+
181
+ // ============================================================================
182
+ // Error Handling - Production reliability (NEW in v1.1.0)
183
+ // ============================================================================
184
+ 'no-ex-assign': 'error', // Disallow reassigning exceptions
185
+ 'no-unsafe-finally': 'error', // Disallow unsafe returns in finally blocks
186
+ 'no-unreachable': 'error', // Disallow unreachable code
187
+ 'no-loss-of-precision': 'error', // Disallow number precision loss
188
+
189
+ // ============================================================================
190
+ // Database Safety - Pagination guard (Phase 0.3)
191
+ // findMany without `take` risks full-table scans under production load.
192
+ // Use Platform.normalizeOffsetPagination / clampGraphqlLimit to enforce the
193
+ // MAX_GRAPHQL_PAGE_LIMIT (100) ceiling before passing limit to Prisma.
194
+ // Spread-based pagination ({ ...toPrismaPage(pg) }) is exempt — add a
195
+ // brief eslint-disable comment explaining the spread carries a clamped take.
196
+ // ============================================================================
197
+ 'no-restricted-syntax': [
198
+ 'warn',
199
+ {
200
+ selector:
201
+ "CallExpression[callee.property.name='findMany'] > ObjectExpression:not(:has(Property[key.name='take']))",
202
+ message:
203
+ 'findMany() must include a `take` arg to prevent full-table scans. ' +
204
+ 'Use Platform.normalizeOffsetPagination() → toPrismaPage() or clampGraphqlLimit().',
205
+ },
206
+ ],
207
+
208
+ // ============================================================================
209
+ // Performance - Backend optimization (NEW in v1.1.0)
210
+ // ============================================================================
211
+ // Disable no-await-in-loop globally - many sequential operations (transactions, batch processing)
212
+ // are intentionally using await in loops for data integrity and ordering
213
+ 'no-await-in-loop': 'off',
214
+ 'no-constant-condition': 'error', // Disallow constant conditions
215
+ 'no-dupe-else-if': 'error', // Disallow duplicate else-if conditions
216
+ 'no-duplicate-case': 'error', // Disallow duplicate case labels
217
+ 'no-empty': ['error', { allowEmptyCatch: false }], // Disallow empty blocks
218
+ 'no-extra-boolean-cast': 'error', // Disallow unnecessary boolean casts
219
+
220
+ // ============================================================================
221
+ // SonarJS Rules - Code complexity and quality
222
+ // ============================================================================
223
+ 'sonarjs/cognitive-complexity': ['warn', 25], // Warn on high complexity (25 is pragmatic)
224
+ 'sonarjs/no-dead-store': 'error', // Error on unused assignments (TypeScript noUnusedLocals disabled)
225
+ 'sonarjs/no-unused-vars': 'error', // Error on unused variables (TypeScript noUnusedLocals disabled)
226
+ 'sonarjs/unused-import': 'error', // Error on unused imports (TypeScript noUnusedLocals disabled)
227
+ 'sonarjs/no-duplicate-string': 'off', // Off for GraphQL/config strings
228
+ 'sonarjs/todo-tag': 'warn', // Warn on TODO comments
229
+ 'sonarjs/fixme-tag': 'off', // Allow FIXME for documented blockers
230
+ 'sonarjs/slow-regex': 'warn', // Warn on slow regex
231
+ 'sonarjs/pseudo-random': 'warn', // Warn on Math.random() for security
232
+ 'sonarjs/no-commented-code': 'warn', // Warn on commented code
233
+ 'sonarjs/redundant-type-aliases': 'off', // Too many false positives with generated types
234
+ 'sonarjs/no-invariant-returns': 'warn', // Warn on invariant returns
235
+ // Disable function-return-type - union return types and conditional returns are intentional
236
+ // design patterns (e.g., returning different types based on runtime conditions)
237
+ 'sonarjs/function-return-type': 'off',
238
+ 'sonarjs/different-types-comparison': 'warn', // Warn on comparing different types
239
+ 'sonarjs/deprecation': 'warn', // Warn on deprecated APIs
240
+ 'sonarjs/no-nested-conditional': 'warn', // Warn on nested conditionals
241
+ 'sonarjs/no-ignored-exceptions': 'warn', // Warn on ignored exceptions
242
+ 'sonarjs/no-small-switch': 'warn', // Warn on small switch statements
243
+ 'sonarjs/no-async-constructor': 'warn', // Warn on async constructors
244
+ 'sonarjs/no-control-regex': 'off', // Allow control characters in regex
245
+ 'no-control-regex': 'off', // Allow control characters in regex
246
+ 'sonarjs/class-name': 'off', // Allow underscores in generated types
247
+ // Disable sonarjs/encryption-secure-mode - false positive on cipher algorithm selection
248
+ 'sonarjs/encryption-secure-mode': 'off',
249
+ 'sonarjs/no-hardcoded-ip': 'off', // Allow hardcoded IPs for config
250
+ 'sonarjs/updated-loop-counter': 'warn', // Warn on loop counter updates
251
+ 'sonarjs/anchor-precedence': 'warn', // Warn on anchor precedence
252
+ 'sonarjs/void-use': 'off', // Allow void for ignoring promises
253
+
254
+ // ============================================================================
255
+ // Security Rules - Production security
256
+ // ============================================================================
257
+ 'security/detect-object-injection': 'off', // Too many false positives
258
+ // Other security rules are enabled via security.configs.recommended
259
+ },
260
+ },
261
+
262
+ // ============================================================================
263
+ // Override Rules for Test Files
264
+ // ============================================================================
265
+ {
266
+ files: ['**/__tests__/**/*.ts', '**/*.test.ts', '**/*.spec.ts', '**/*.integration.test.ts'],
267
+ rules: {
268
+ 'sonarjs/no-hardcoded-ip': 'off', // Test files can have hardcoded IPs
269
+ 'sonarjs/no-hardcoded-passwords': 'off', // Test files can have test passwords
270
+ 'no-control-regex': 'off', // Test files can have control chars in regex
271
+ 'sonarjs/no-control-regex': 'off', // Test files can have control chars
272
+ '@typescript-eslint/no-explicit-any': 'off', // Test files can use any
273
+ '@typescript-eslint/require-await': 'off', // Test setup functions often don't need await
274
+ '@typescript-eslint/no-misused-promises': 'off', // Test mocks properly handle async
275
+ 'sonarjs/no-nested-functions': 'off', // Test mocks often require nested functions
276
+ 'sonarjs/pseudo-random': 'off', // Test data generation can use Math.random()
277
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable in test files
278
+ 'no-await-in-loop': 'off', // Tests often need sequential async operations
279
+ },
280
+ },
281
+
282
+ // ============================================================================
283
+ // Override Rules for Cache/Storage Services
284
+ // ============================================================================
285
+ {
286
+ files: ['**/cache/**/*.ts', '**/storage/**/*.ts', '**/services/cache/**/*.ts', '**/services/storage/**/*.ts'],
287
+ rules: {
288
+ 'sonarjs/hashing': 'off', // MD5 for checksums/ETags is acceptable
289
+ 'sonarjs/publicly-writable-directories': 'off', // Temp directories are acceptable
290
+ 'security/detect-non-literal-fs-filename': 'off', // Storage services use dynamic paths
291
+ 'sonarjs/no-invariant-returns': 'off', // Interface implementations may require specific returns
292
+ 'sonarjs/cognitive-complexity': ['warn', 40], // Storage operations naturally complex
293
+ },
294
+ },
295
+
296
+ // ============================================================================
297
+ // Override Rules for Generated Type Files
298
+ // Generated files (codegen, prisma) have unused imports we cannot control
299
+ // ============================================================================
300
+ {
301
+ files: [
302
+ '**/types/**/*.ts',
303
+ '**/*.types.ts',
304
+ '**/generated/**/*.ts',
305
+ '**/*.generated.ts',
306
+ '**/mapper-models.ts', // Imports from generated Prisma types
307
+ '**/scalar-types.ts', // Scalar type definitions for codegen
308
+ ],
309
+ rules: {
310
+ 'sonarjs/class-name': 'off', // Generated types can have _ prefix
311
+ '@typescript-eslint/no-explicit-any': 'off', // Generated types can use any
312
+ '@typescript-eslint/explicit-function-return-type': 'off', // Generated types don't need explicit returns
313
+ // Disable unused vars/imports checks for generated files
314
+ '@typescript-eslint/no-unused-vars': 'off',
315
+ 'sonarjs/no-unused-vars': 'off',
316
+ 'sonarjs/unused-import': 'off',
317
+ 'sonarjs/no-dead-store': 'off',
318
+ },
319
+ },
320
+
321
+ // ============================================================================
322
+ // Override Rules for Adapter Files
323
+ // ============================================================================
324
+ {
325
+ files: ['**/adapters/**/*.ts', '**/*Adapter.ts'],
326
+ rules: {
327
+ 'sonarjs/function-return-type': 'off', // Adapters implement external API contracts
328
+ },
329
+ },
330
+
331
+ // ============================================================================
332
+ // Override Rules for Resolver Files (GraphQL)
333
+ // ============================================================================
334
+ {
335
+ files: ['**/resolvers/**/*.ts', '**/*.resolvers.ts'],
336
+ rules: {
337
+ 'sonarjs/function-return-type': 'off', // Resolvers implement GraphQL schema contracts
338
+ },
339
+ },
340
+
341
+ // ============================================================================
342
+ // Override Rules for Logger Transports (NEW in v1.1.0)
343
+ // Validated file paths from config, not user input
344
+ // ============================================================================
345
+ {
346
+ files: ['**/logger/**/transports.ts', '**/utils/logger/transports.ts'],
347
+ rules: {
348
+ 'security/detect-non-literal-fs-filename': 'off', // File paths validated in constructor
349
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented safe fs operations
350
+ },
351
+ },
352
+
353
+ // ============================================================================
354
+ // Override Rules for Export Services (NEW in v1.1.0)
355
+ // Validated export paths with security checks
356
+ // ============================================================================
357
+ {
358
+ files: ['**/export/**/ExportFormatService.ts', '**/modules/export/services/ExportFormatService.ts'],
359
+ rules: {
360
+ 'security/detect-non-literal-fs-filename': 'off', // Export paths validated before fs operations
361
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented safe export operations
362
+ },
363
+ },
364
+
365
+ // ============================================================================
366
+ // Override Rules for Services with Validated Dynamic RegExp (NEW in v1.1.0)
367
+ // RegExp patterns from validated application config, not user input
368
+ // ============================================================================
369
+ {
370
+ files: ['**/TemplateService.ts', '**/numberGenerator.ts', '**/tags/services/validation.ts'],
371
+ rules: {
372
+ 'security/detect-non-literal-regexp': 'off', // RegExp from validated config with error handling
373
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented safe regex usage
374
+ },
375
+ },
376
+
377
+ // ============================================================================
378
+ // Override Rules for Report Generators (NEW in v1.1.0)
379
+ // Naturally high complexity due to Excel/PDF formatting
380
+ // ============================================================================
381
+ {
382
+ files: ['**/ExcelReportGenerator.ts', '**/PDFReportGenerator.ts', '**/ReportService.ts'],
383
+ rules: {
384
+ 'sonarjs/cognitive-complexity': ['warn', 35], // Allow higher complexity for report generation
385
+ },
386
+ },
387
+
388
+ // ============================================================================
389
+ // Override Rules for GraphQL Modules Namespace Augmentation (NEW in v1.1.0)
390
+ // Required by @graphql-modules for context type augmentation
391
+ // ============================================================================
392
+ {
393
+ files: ['**/modules/*/index.ts', '**/modules/*/declarations.ts'],
394
+ rules: {
395
+ '@typescript-eslint/no-namespace': 'off', // Namespace augmentation required for GraphQL Modules
396
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented namespace usage
397
+ },
398
+ },
399
+
400
+ // ============================================================================
401
+ // Override Rules for Prisma JSON Type Handling (NEW in v1.1.0)
402
+ // Prisma.JsonValue is a union type by design
403
+ // ============================================================================
404
+ {
405
+ files: ['**/inputValidators.ts', '**/*Validator.ts'],
406
+ rules: {
407
+ 'sonarjs/function-return-type': 'off', // Prisma.JsonValue is a union type by design
408
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented Prisma type usage
409
+ },
410
+ },
411
+
412
+ // ============================================================================
413
+ // Override Rules for SDK Core Implementation Files
414
+ // Allow eslint-disable for documented design decisions
415
+ // ============================================================================
416
+ {
417
+ files: [
418
+ '**/database/index.ts',
419
+ '**/middleware/security.ts',
420
+ '**/event-queue/implementations/**/*.ts',
421
+ '**/instrumentation/metrics-collector.ts',
422
+ ],
423
+ rules: {
424
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented design patterns
425
+ },
426
+ },
427
+
428
+ // ============================================================================
429
+ // Override Rules for I18n Translation Loader
430
+ // Validated file paths from config, not user input
431
+ // ============================================================================
432
+ {
433
+ files: ['**/i18n/loader.ts', '**/i18n/**/loader.ts'],
434
+ rules: {
435
+ 'security/detect-non-literal-fs-filename': 'off', // File paths validated before fs operations
436
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented safe fs operations
437
+ },
438
+ },
439
+
440
+ // ============================================================================
441
+ // Override Rules for Prisma Generator
442
+ // Validated output paths with security checks
443
+ // ============================================================================
444
+ {
445
+ files: ['**/prisma/generator/**/*.ts', '**/generator/index.ts'],
446
+ rules: {
447
+ 'security/detect-non-literal-fs-filename': 'off', // Output paths validated before fs operations
448
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented safe fs operations
449
+ },
450
+ },
451
+
452
+ // ============================================================================
453
+ // Override Rules for Translation Service with Dynamic RegExp
454
+ // RegExp patterns from validated translation config, not user input
455
+ // ============================================================================
456
+ {
457
+ files: ['**/translation/index.ts', '**/translation/**/index.ts'],
458
+ rules: {
459
+ 'security/detect-non-literal-regexp': 'off', // RegExp from validated translation patterns
460
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented safe regex usage
461
+ },
462
+ },
463
+
464
+ // ============================================================================
465
+ // Override Rules for Validation Utilities with Dynamic RegExp
466
+ // RegExp patterns from validated validation rules, not user input
467
+ // ============================================================================
468
+ {
469
+ files: ['**/utils/validation.ts', '**/utils/**/validation.ts'],
470
+ rules: {
471
+ 'security/detect-non-literal-regexp': 'off', // RegExp from validated validation rules
472
+ 'eslint-comments/no-use': 'off', // Allow eslint-disable for documented safe regex usage
473
+ },
474
+ },
475
+
476
+ // ============================================================================
477
+ // Override Rules for Server Backwards Compatibility
478
+ // IUser is deprecated in favor of IActor, but SDK maintains backwards compat
479
+ // ============================================================================
480
+ {
481
+ files: ['**/server/context.ts', '**/server/types.ts'],
482
+ rules: {
483
+ 'sonarjs/deprecation': 'off', // Intentional use of deprecated IUser for backwards compatibility
484
+ },
485
+ },
486
+ ];
487
+ }
@@ -0,0 +1,5 @@
1
+ import type { BrowserOptions, FlatConfigArray } from './index.js';
2
+
3
+ export type { BrowserOptions };
4
+ export declare function createBrowserConfig(options?: BrowserOptions): FlatConfigArray;
5
+ export default createBrowserConfig;
@@ -0,0 +1,24 @@
1
+ import globals from 'globals';
2
+
3
+ import { createNodeConfig } from './node.js';
4
+
5
+ /**
6
+ * Burdenoff browser-extension ESLint profile (@burdenoff/toolchain/eslint/browser):
7
+ * the Node profile plus browser globals and the `chrome` extension API global.
8
+ *
9
+ * // eslint.config.js
10
+ * import browser from '@burdenoff/toolchain/eslint/browser';
11
+ * export default browser({ ignores: ['build/**'] });
12
+ *
13
+ * @param {object} [options] - Same options as the Node profile
14
+ * @returns {import('eslint').Linter.Config[]}
15
+ */
16
+ export function createBrowserConfig(options = {}) {
17
+ const { globals: extraGlobals = {}, ...rest } = options;
18
+ return createNodeConfig({
19
+ ...rest,
20
+ globals: { ...globals.browser, ...globals.webextensions, chrome: 'readonly', ...extraGlobals },
21
+ });
22
+ }
23
+
24
+ export default createBrowserConfig;
@@ -0,0 +1,4 @@
1
+ import type { FlatConfigArray, GatewayOptions } from './index.js';
2
+
3
+ export type { GatewayOptions };
4
+ export default function createGatewayConfig(dirname: string, options?: GatewayOptions): FlatConfigArray;
@@ -0,0 +1,53 @@
1
+ import eslint from '@eslint/js';
2
+ import tseslint from 'typescript-eslint';
3
+
4
+ /**
5
+ * Burdenoff gateway ESLint profile (@burdenoff/toolchain/eslint/gateway).
6
+ *
7
+ * Ported from gateways/global-int-gateway/eslint.config.js: typescript-eslint
8
+ * strictTypeChecked + stylisticTypeChecked with the project service.
9
+ *
10
+ * // eslint.config.js
11
+ * import gateway from '@burdenoff/toolchain/eslint/gateway';
12
+ * export default gateway(import.meta.dirname);
13
+ *
14
+ * @param {string} dirname - The directory of the consuming project (use import.meta.dirname)
15
+ * @param {object} [options]
16
+ * @param {string[]} [options.ignores] - Extra ignore globs appended to the defaults
17
+ * @returns {import('eslint').Linter.Config[]}
18
+ */
19
+ export default function createGatewayConfig(dirname, options = {}) {
20
+ const { ignores = [] } = options;
21
+ if (!dirname) {
22
+ throw new Error('@burdenoff/toolchain/eslint/gateway: dirname is required. Use gateway(import.meta.dirname)');
23
+ }
24
+ return tseslint.config(
25
+ eslint.configs.recommended,
26
+ ...tseslint.configs.strictTypeChecked,
27
+ ...tseslint.configs.stylisticTypeChecked,
28
+ {
29
+ languageOptions: {
30
+ parserOptions: {
31
+ projectService: true,
32
+ tsconfigRootDir: dirname,
33
+ },
34
+ },
35
+ },
36
+ {
37
+ rules: {
38
+ '@typescript-eslint/no-unused-vars': [
39
+ 'error',
40
+ {
41
+ argsIgnorePattern: '^_',
42
+ varsIgnorePattern: '^_',
43
+ },
44
+ ],
45
+ '@typescript-eslint/consistent-type-imports': 'error',
46
+ '@typescript-eslint/no-import-type-side-effects': 'error',
47
+ },
48
+ },
49
+ {
50
+ ignores: ['dist/', 'node_modules/', '*.js', ...ignores],
51
+ },
52
+ );
53
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Shared typings for the @burdenoff/toolchain ESLint profiles. Each profile
3
+ * module (`@burdenoff/toolchain/eslint/<profile>`) has its own .d.ts that
4
+ * re-uses these types.
5
+ */
6
+ import type { Linter } from 'eslint';
7
+
8
+ export type FlatConfig = Linter.Config;
9
+ export type FlatConfigArray = Linter.Config[];
10
+
11
+ export type RuleSeverity = 'error' | 'warn' | 'off';
12
+
13
+ export interface BackendOptions {
14
+ /** tsconfig used for type-aware rules, relative to `dirname`. Default './tsconfig.eslint.json'. */
15
+ project?: string;
16
+ /** Extra ignore globs appended to the defaults. */
17
+ ignores?: string[];
18
+ }
19
+
20
+ export interface GatewayOptions {
21
+ ignores?: string[];
22
+ }
23
+
24
+ export interface ReactOptions {
25
+ ignores?: string[];
26
+ additionalRules?: Linter.RulesRecord;
27
+ /** Severity of the raw-colour / palette-class guard. Default 'error'. */
28
+ rawColors?: RuleSeverity;
29
+ }
30
+
31
+ export interface NodeOptions {
32
+ ignores?: string[];
33
+ globals?: Linter.Globals;
34
+ rules?: Linter.RulesRecord;
35
+ }
36
+
37
+ export type BrowserOptions = NodeOptions;
@@ -0,0 +1,5 @@
1
+ import type { FlatConfigArray, NodeOptions } from './index.js';
2
+
3
+ export type { NodeOptions };
4
+ export declare function createNodeConfig(options?: NodeOptions): FlatConfigArray;
5
+ export default createNodeConfig;