Skip to content

Commit 3955f48

Browse files
committed
AG-49079 Initial release
Squashed commit of the following: commit d25bfad Author: scripthunter7 <[email protected]> Date: Mon Dec 8 15:09:11 2025 +0100 Update Node.js version from 22.14.0 to 22.17.0 in release workflow commit 470c72b Author: scripthunter7 <[email protected]> Date: Mon Dec 8 15:08:48 2025 +0100 Update Node.js Docker image version from 22.14 to 22.17 in Bamboo specs commit 5bfe2f1 Author: scripthunter7 <[email protected]> Date: Mon Dec 8 09:23:13 2025 +0100 Rename lint:ts script to lint:code and add JS file linting support commit 9e7e37c Author: scripthunter7 <[email protected]> Date: Fri Dec 5 19:09:41 2025 +0100 bump release date commit 32407ac Author: scripthunter7 <[email protected]> Date: Fri Dec 5 14:11:06 2025 +0100 fix release date commit 25123e5 Author: scripthunter7 <[email protected]> Date: Fri Dec 5 14:03:20 2025 +0100 add cleanup script to specs commit 7cfb510 Author: scripthunter7 <[email protected]> Date: Thu Dec 4 09:12:17 2025 +0100 Update build comments to clarify build.txt file creation purpose commit 6584afb Author: scripthunter7 <[email protected]> Date: Thu Dec 4 09:11:32 2025 +0100 Add comments explaining packageManager field removal in pre-commit hook commit 4cc4246 Author: scripthunter7 <[email protected]> Date: Wed Dec 3 17:30:20 2025 +0100 Initial release
1 parent 273e771 commit 3955f48

36 files changed

+7832
-0
lines changed

.eslintrc.cjs

Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
const path = require('node:path');
2+
3+
const MAX_LINE_LENGTH = 120;
4+
5+
/**
6+
* ESLint rules.
7+
*
8+
* @see {@link https://eslint.org/docs/v8.x/rules/}
9+
*/
10+
const ESLINT_RULES = {
11+
indent: 'off',
12+
'no-bitwise': 'off',
13+
'no-new': 'off',
14+
'no-continue': 'off',
15+
'arrow-body-style': 'off',
16+
17+
'no-restricted-syntax': ['error', 'LabeledStatement', 'WithStatement'],
18+
'no-constant-condition': ['error', { checkLoops: false }],
19+
'max-len': [
20+
'error',
21+
{
22+
code: MAX_LINE_LENGTH,
23+
comments: MAX_LINE_LENGTH,
24+
tabWidth: 4,
25+
ignoreUrls: true,
26+
ignoreTrailingComments: false,
27+
ignoreComments: false,
28+
},
29+
],
30+
// Sort members of import statements, e.g. `import { B, A } from 'module';` -> `import { A, B } from 'module';`
31+
// Note: imports themself are sorted by import/order rule
32+
'sort-imports': ['error', {
33+
ignoreCase: true,
34+
// Avoid conflict with import/order rule
35+
ignoreDeclarationSort: true,
36+
ignoreMemberSort: false,
37+
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
38+
}],
39+
};
40+
41+
/**
42+
* TypeScript ESLint rules.
43+
*
44+
* @see {@link https://typescript-eslint.io/rules/}
45+
*/
46+
const TYPESCRIPT_ESLINT_RULES = {
47+
'@typescript-eslint/no-non-null-assertion': 'off',
48+
'@typescript-eslint/interface-name-prefix': 'off',
49+
50+
'@typescript-eslint/member-delimiter-style': 'error',
51+
52+
'@typescript-eslint/indent': ['error', 4],
53+
'@typescript-eslint/explicit-member-accessibility': [
54+
'error',
55+
{
56+
accessibility: 'explicit',
57+
overrides: {
58+
accessors: 'explicit',
59+
constructors: 'no-public',
60+
methods: 'explicit',
61+
properties: 'off',
62+
parameterProperties: 'explicit',
63+
},
64+
},
65+
],
66+
// Force proper import and export of types
67+
'@typescript-eslint/consistent-type-imports': [
68+
'error',
69+
{
70+
prefer: 'type-imports',
71+
fixStyle: 'inline-type-imports',
72+
},
73+
],
74+
'@typescript-eslint/consistent-type-exports': [
75+
'error',
76+
{
77+
fixMixedExportsWithInlineTypeSpecifier: true,
78+
},
79+
],
80+
};
81+
82+
/**
83+
* Import plugin rules.
84+
*
85+
* @see {@link https://github.com/import-js/eslint-plugin-import/tree/main/docs/rules}
86+
*/
87+
const IMPORT_PLUGIN_RULES = {
88+
'import/prefer-default-export': 'off',
89+
90+
'import-newlines/enforce': ['error', 3, MAX_LINE_LENGTH],
91+
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
92+
// Split external and internal imports with an empty line
93+
'import/order': [
94+
'error',
95+
{
96+
groups: [
97+
// Built-in Node.js modules
98+
'builtin',
99+
// External packages
100+
'external',
101+
// Parent modules, e.g. `import { foo } from '../bar';`
102+
'parent',
103+
// Sibling modules, e.g. `import { foo } from './bar';`
104+
'sibling',
105+
// All other imports
106+
],
107+
alphabetize: { order: 'asc', caseInsensitive: true },
108+
'newlines-between': 'always',
109+
},
110+
],
111+
};
112+
113+
/**
114+
* JSDoc plugin rules.
115+
*
116+
* @see {@link https://github.com/gajus/eslint-plugin-jsdoc?tab=readme-ov-file#user-content-eslint-plugin-jsdoc-rules}
117+
*/
118+
const JSDOC_PLUGIN_RULES = {
119+
// Types are described in TypeScript
120+
'jsdoc/require-param-type': 'off',
121+
'jsdoc/no-undefined-types': 'off',
122+
'jsdoc/require-returns-type': 'off',
123+
124+
'jsdoc/require-param-description': 'error',
125+
'jsdoc/require-property-description': 'error',
126+
'jsdoc/require-returns-description': 'error',
127+
'jsdoc/require-returns': 'error',
128+
'jsdoc/require-param': 'error',
129+
'jsdoc/require-returns-check': 'error',
130+
131+
'jsdoc/check-tag-names': [
132+
'warn',
133+
{
134+
// Define additional tags
135+
// https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-tag-names.md#definedtags
136+
definedTags: ['note'],
137+
},
138+
],
139+
140+
'jsdoc/require-hyphen-before-param-description': ['error', 'never'],
141+
'jsdoc/require-jsdoc': [
142+
'error',
143+
{
144+
contexts: [
145+
'ClassDeclaration',
146+
'ClassProperty',
147+
'PropertyDefinition',
148+
'FunctionDeclaration',
149+
'MethodDefinition',
150+
],
151+
},
152+
],
153+
'jsdoc/require-description': [
154+
'error',
155+
{
156+
contexts: [
157+
'ClassDeclaration',
158+
'ClassProperty',
159+
'PropertyDefinition',
160+
'FunctionDeclaration',
161+
'MethodDefinition',
162+
],
163+
},
164+
],
165+
'jsdoc/require-description-complete-sentence': [
166+
'error',
167+
{
168+
abbreviations: [
169+
'e.g.',
170+
'i.e.',
171+
],
172+
},
173+
],
174+
'jsdoc/multiline-blocks': [
175+
'error',
176+
{
177+
noSingleLineBlocks: true,
178+
singleLineTags: [
179+
'inheritdoc',
180+
],
181+
},
182+
],
183+
'jsdoc/tag-lines': [
184+
'error',
185+
'any',
186+
{
187+
startLines: 1,
188+
},
189+
],
190+
'jsdoc/sort-tags': [
191+
'error',
192+
{
193+
linesBetween: 1,
194+
tagSequence: [
195+
{ tags: ['file'] },
196+
{ tags: ['template'] },
197+
{ tags: ['see'] },
198+
{ tags: ['param'] },
199+
{ tags: ['returns'] },
200+
{ tags: ['throws'] },
201+
{ tags: ['example'] },
202+
],
203+
},
204+
],
205+
};
206+
207+
/**
208+
* N plugin rules.
209+
*
210+
* @see {@link https://github.com/eslint-community/eslint-plugin-n?tab=readme-ov-file#-rules}
211+
*/
212+
const N_PLUGIN_RULES = {
213+
// Import plugin is enough, also, this rule requires extensions in ESM, but we use bundler resolution
214+
'n/no-missing-import': 'off',
215+
// Require using node protocol for node modules, e.g. `node:fs` instead of `fs`.
216+
'n/prefer-node-protocol': 'error',
217+
// Prefer `/promises` API for `fs` and `dns` modules, if the corresponding imports are used.
218+
'n/prefer-promises/fs': 'error',
219+
'n/prefer-promises/dns': 'error',
220+
221+
'n/hashbang': [
222+
'error',
223+
{
224+
// This rule reads the bin property from package.json, and only allows shebangs for that file.
225+
// But since we transform the source files to the dist folder, we need to convert the paths.
226+
convertPath: [
227+
{
228+
include: ['src/**/*.ts'],
229+
replace: ['^src/(.+)\\.ts$', 'dist/$1.js'],
230+
},
231+
],
232+
},
233+
],
234+
};
235+
236+
/**
237+
* Boundaries plugin rules.
238+
*
239+
* @see {@link https://github.com/javierbrea/eslint-plugin-boundaries#readme}
240+
*/
241+
const BOUNDARIES_PLUGIN_RULES = {
242+
'boundaries/element-types': ['error', {
243+
default: 'disallow',
244+
rules: [
245+
{
246+
from: 'cli-folder',
247+
allow: ['utils-folder', 'lib-folder'],
248+
},
249+
{
250+
from: 'lib-folder',
251+
allow: ['utils-folder'],
252+
},
253+
{
254+
from: 'test-folder',
255+
allow: ['cli-folder', 'utils-folder', 'lib-folder'],
256+
},
257+
],
258+
}],
259+
};
260+
261+
/**
262+
* Merges multiple rule sets into a single object.
263+
*
264+
* @param ruleSets The rule sets to merge.
265+
*
266+
* @returns The merged rule set.
267+
*/
268+
function mergeRules(...ruleSets) {
269+
const merged = {};
270+
for (const rules of ruleSets) {
271+
for (const [key, value] of Object.entries(rules)) {
272+
if (merged[key]) {
273+
throw new Error(`Duplicate ESLint rule: ${key}`);
274+
}
275+
merged[key] = value;
276+
}
277+
}
278+
return merged;
279+
}
280+
281+
module.exports = {
282+
root: true,
283+
parser: '@typescript-eslint/parser',
284+
parserOptions: {
285+
tsconfigRootDir: path.join(__dirname),
286+
project: 'tsconfig.json',
287+
},
288+
plugins: [
289+
'import',
290+
'import-newlines',
291+
'@typescript-eslint',
292+
'n',
293+
'boundaries',
294+
],
295+
extends: [
296+
'airbnb-base',
297+
'airbnb-typescript/base',
298+
'plugin:@typescript-eslint/eslint-recommended',
299+
'plugin:jsdoc/recommended',
300+
'plugin:jsdoc/recommended-typescript',
301+
'plugin:n/recommended',
302+
],
303+
ignorePatterns: [
304+
'dist',
305+
'coverage',
306+
],
307+
settings: {
308+
'boundaries/elements': [
309+
{
310+
type: 'test-folder',
311+
pattern: 'test',
312+
mode: 'folder',
313+
},
314+
{
315+
type: 'lib-folder',
316+
pattern: 'src/lib',
317+
mode: 'folder',
318+
},
319+
{
320+
type: 'cli-folder',
321+
pattern: 'src/cli',
322+
mode: 'folder',
323+
},
324+
{
325+
type: 'utils-folder',
326+
pattern: 'src/utils',
327+
mode: 'folder',
328+
},
329+
],
330+
},
331+
rules: mergeRules(
332+
ESLINT_RULES,
333+
TYPESCRIPT_ESLINT_RULES,
334+
IMPORT_PLUGIN_RULES,
335+
JSDOC_PLUGIN_RULES,
336+
N_PLUGIN_RULES,
337+
BOUNDARIES_PLUGIN_RULES,
338+
),
339+
};

0 commit comments

Comments
 (0)