@centreon/js-config 24.9.1 → 24.10.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.
Files changed (33) hide show
  1. package/biome/base.json +224 -0
  2. package/cypress/component/commands.tsx +82 -22
  3. package/cypress/component/configuration.js +39 -16
  4. package/cypress/component/disableCssTransitions.ts +19 -0
  5. package/cypress/component/enableVisualTesting.ts +1 -1
  6. package/cypress/component/excludeNodeModulesFromCoverage.js +36 -0
  7. package/cypress/e2e/commands/configuration.ts +330 -1
  8. package/cypress/e2e/commands/monitoring.ts +225 -0
  9. package/cypress/e2e/commands.ts +629 -149
  10. package/cypress/e2e/configuration.ts +46 -40
  11. package/cypress/e2e/esbuild-preprocessor.ts +26 -0
  12. package/cypress/e2e/plugins.ts +52 -114
  13. package/cypress/e2e/reporter-config.js +13 -0
  14. package/cypress/e2e/tasks.ts +259 -0
  15. package/eslint/base.typescript.eslintrc.js +15 -3
  16. package/eslint/lambda/typescript.eslintrc.js +48 -0
  17. package/jest/index.js +5 -2
  18. package/jest/lambda/typescript.js +49 -0
  19. package/package.json +57 -45
  20. package/rspack/base/globalConfig.js +71 -0
  21. package/rspack/base/index.js +89 -0
  22. package/rspack/patch/dev.js +12 -0
  23. package/{webpack → rspack}/patch/devServer.js +4 -8
  24. package/rspack/patch/module.js +13 -0
  25. package/rspack/plugins/TransformPreloadScript.js +37 -0
  26. package/rspack/plugins/WriteRemoteEntryNameToModuleFederation.js +30 -0
  27. package/tsconfig/index.json +5 -4
  28. package/tsconfig/lambda/node20.tsconfig.json +12 -0
  29. package/tsconfig/lambda/tsconfig.json +14 -0
  30. package/tsconfig.json +21 -0
  31. package/webpack/base/index.js +0 -130
  32. package/webpack/patch/dev.js +0 -24
  33. package/webpack/patch/module.js +0 -46
@@ -1,16 +1,21 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
1
2
  /* eslint-disable import/extensions */
2
3
  /* eslint-disable import/no-unresolved */
3
4
 
4
5
  import { execSync } from 'child_process';
5
6
 
6
7
  import { defineConfig } from 'cypress';
8
+ import installLogsPrinter from 'cypress-terminal-report/src/installLogsPrinter';
9
+ import { config as configDotenv } from 'dotenv';
7
10
 
8
- import setupNodeEvents from './plugins';
11
+ import esbuildPreprocessor from './esbuild-preprocessor';
12
+ import plugins from './plugins';
13
+ import tasks from './tasks';
9
14
 
10
15
  interface ConfigurationOptions {
11
16
  cypressFolder?: string;
12
- dockerName?: string;
13
17
  env?: Record<string, unknown>;
18
+ envFile?: string;
14
19
  isDevelopment?: boolean;
15
20
  specPattern: string;
16
21
  }
@@ -19,12 +24,14 @@ export default ({
19
24
  specPattern,
20
25
  cypressFolder,
21
26
  isDevelopment,
22
- dockerName,
23
- env
27
+ env,
28
+ envFile
24
29
  }: ConfigurationOptions): Cypress.ConfigOptions => {
25
- const resultsFolder = `${cypressFolder || 'cypress'}/results${
26
- isDevelopment ? '/dev' : ''
27
- }`;
30
+ if (envFile) {
31
+ configDotenv({ path: envFile });
32
+ }
33
+
34
+ const resultsFolder = `${cypressFolder || '.'}/results`;
28
35
 
29
36
  const webImageVersion = execSync('git rev-parse --abbrev-ref HEAD')
30
37
  .toString('utf8')
@@ -32,47 +39,46 @@ export default ({
32
39
 
33
40
  return defineConfig({
34
41
  chromeWebSecurity: false,
35
- defaultCommandTimeout: 6000,
42
+ defaultCommandTimeout: 20000,
43
+ downloadsFolder: `${resultsFolder}/downloads`,
36
44
  e2e: {
37
45
  excludeSpecPattern: ['*.js', '*.ts', '*.md'],
38
- setupNodeEvents,
39
- specPattern
46
+ fixturesFolder: 'fixtures',
47
+ reporter: require.resolve('cypress-multi-reporters'),
48
+ reporterOptions: {
49
+ configFile: `${__dirname}/reporter-config.js`
50
+ },
51
+ setupNodeEvents: async (cypressOn, config) => {
52
+ const on = require('cypress-on-fix')(cypressOn)
53
+ installLogsPrinter(on);
54
+ await esbuildPreprocessor(on, config);
55
+ tasks(on);
56
+
57
+ return plugins(on, config);
58
+ },
59
+ specPattern,
60
+ supportFile: 'support/e2e.{js,jsx,ts,tsx}'
40
61
  },
41
62
  env: {
42
63
  ...env,
43
- OPENID_IMAGE_VERSION: '23.04',
64
+ DATABASE_IMAGE: 'bitnami/mariadb:10.11',
65
+ OPENID_IMAGE_VERSION: process.env.MAJOR || '24.04',
66
+ SAML_IMAGE_VERSION: process.env.MAJOR || '24.04',
67
+ STABILITY: 'unstable',
44
68
  WEB_IMAGE_OS: 'alma9',
45
- WEB_IMAGE_VERSION: webImageVersion,
46
- dockerName: dockerName || 'centreon-dev'
69
+ WEB_IMAGE_VERSION: webImageVersion
47
70
  },
48
- execTimeout: 120000,
49
- reporter: 'mochawesome',
50
- reporterOptions: {
51
- html: false,
52
- json: true,
53
- overwrite: true,
54
- reportDir: `${resultsFolder}/reports`,
55
- reportFilename: '[name]-report.json'
71
+ execTimeout: 60000,
72
+ requestTimeout: 20000,
73
+ retries: {
74
+ openMode: 0,
75
+ runMode: 2
56
76
  },
57
- requestTimeout: 10000,
58
- retries: 0,
59
77
  screenshotsFolder: `${resultsFolder}/screenshots`,
60
- setupNodeEvents: (on, config) => {
61
- on('before:browser:launch', (browser, launchOptions) => {
62
- if (browser.name === 'chrome' && browser.isHeadless) {
63
- launchOptions.args = launchOptions.args.map((arg) => {
64
- if (arg === '--headless') {
65
- return '--headless=new';
66
- }
67
-
68
- return arg;
69
- });
70
- }
71
-
72
- return launchOptions;
73
- });
74
- },
75
- video: true,
76
- videosFolder: `${resultsFolder}/videos`
78
+ video: isDevelopment,
79
+ videoCompression: 0,
80
+ videosFolder: `${resultsFolder}/videos`,
81
+ viewportHeight: 1080,
82
+ viewportWidth: 1920
77
83
  });
78
84
  };
@@ -0,0 +1,26 @@
1
+ import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill';
2
+ import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill';
3
+ import { addCucumberPreprocessorPlugin } from '@badeball/cypress-cucumber-preprocessor';
4
+ import createBundler from '@bahmutov/cypress-esbuild-preprocessor';
5
+ import createEsbuildPlugin from '@badeball/cypress-cucumber-preprocessor/esbuild';
6
+
7
+ export default async (
8
+ on: Cypress.PluginEvents,
9
+ config: Cypress.PluginConfigOptions
10
+ ): Promise<void> => {
11
+ await addCucumberPreprocessorPlugin(on, config);
12
+
13
+ on(
14
+ 'file:preprocessor',
15
+ createBundler({
16
+ plugins: [
17
+ createEsbuildPlugin(config),
18
+ NodeModulesPolyfillPlugin(),
19
+ NodeGlobalsPolyfillPlugin({
20
+ buffer: true,
21
+ process: true
22
+ })
23
+ ]
24
+ })
25
+ );
26
+ };
@@ -3,130 +3,68 @@
3
3
  /* eslint-disable @typescript-eslint/no-var-requires */
4
4
  /* eslint-disable no-param-reassign */
5
5
 
6
- import Docker from 'dockerode';
7
- import { addCucumberPreprocessorPlugin } from '@badeball/cypress-cucumber-preprocessor';
8
- import webpackPreprocessor from '@cypress/webpack-preprocessor';
9
-
10
- const docker = new Docker();
11
-
12
- const getWebpackOptions = (config): object => {
13
- return {
14
- module: {
15
- rules: [
16
- {
17
- exclude: [/node_modules/],
18
- test: /\.ts?$/,
19
- use: [
20
- {
21
- loader: 'swc-loader'
22
- }
23
- ]
24
- },
25
- {
26
- test: /\.feature$/,
27
- use: [
28
- {
29
- loader: '@badeball/cypress-cucumber-preprocessor/webpack',
30
- options: config
31
- }
32
- ]
33
- }
34
- ]
35
- },
36
- resolve: {
37
- extensions: ['.ts', '.js']
38
- }
39
- };
40
- };
41
-
42
- export default async (on, config): Promise<void> => {
43
- await addCucumberPreprocessorPlugin(on, config);
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+
9
+ export default (
10
+ on: Cypress.PluginEvents,
11
+ config: Cypress.PluginConfigOptions
12
+ ): Cypress.PluginConfigOptions => {
13
+ on('before:browser:launch', (browser, launchOptions) => {
14
+ const width = 1920;
15
+ const height = 1080;
16
+
17
+ if (browser.family === 'chromium' && browser.name !== 'electron') {
18
+ if (browser.isHeadless) {
19
+ launchOptions.args.push('--headless=new');
20
+ }
44
21
 
45
- const webpackOptions = await getWebpackOptions(config);
46
- const options = {
47
- webpackOptions
48
- };
22
+ // flags description : https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md
23
+ launchOptions.args.push('--disable-gpu');
24
+ launchOptions.args.push('--auto-open-devtools-for-tabs');
25
+ launchOptions.args.push('--disable-extensions');
26
+ launchOptions.args.push('--hide-scrollbars');
27
+ launchOptions.args.push('--mute-audio');
49
28
 
50
- on('file:preprocessor', webpackPreprocessor(options));
29
+ // force screen to be non-retina and just use our given resolution
30
+ launchOptions.args.push('--force-device-scale-factor=1');
51
31
 
52
- on('before:browser:launch', (browser = {}, launchOptions) => {
53
- if ((browser as { name }).name === 'chrome') {
54
- launchOptions.args.push('--disable-gpu');
55
- launchOptions.args = launchOptions.args.filter(
56
- (element) => element !== '--disable-dev-shm-usage'
57
- );
32
+ launchOptions.args.push(`--window-size=${width},${height}`);
58
33
  }
59
34
 
60
35
  return launchOptions;
61
36
  });
62
37
 
63
- interface PortBinding {
64
- destination: number;
65
- source: number;
66
- }
67
-
68
- interface StartContainerProps {
69
- image: string;
70
- name: string;
71
- portBindings: Array<PortBinding>;
72
- }
73
-
74
- interface StopContainerProps {
75
- name: string;
76
- }
77
-
78
- on('task', {
79
- startContainer: async ({
80
- image,
81
- name,
82
- portBindings = []
83
- }: StartContainerProps) => {
84
- const webContainers = await docker.listContainers({
85
- all: true,
86
- filters: { name: [name] }
38
+ on('after:run', (results) => {
39
+ const testRetries: { [key: string]: boolean } = {};
40
+ if ('runs' in results) {
41
+ results.runs.forEach((run) => {
42
+ run.tests.forEach((test) => {
43
+ if (test.attempts && test.attempts.length > 1) {
44
+ const testTitle = test.title.join(' > '); // Convert the array to a string
45
+ testRetries[testTitle] = true;
46
+ }
47
+ });
87
48
  });
88
- if (webContainers.length) {
89
- return webContainers[0];
90
- }
91
-
92
- const container = await docker.createContainer({
93
- AttachStderr: true,
94
- AttachStdin: false,
95
- AttachStdout: true,
96
- ExposedPorts: portBindings.reduce((accumulator, currentValue) => {
97
- accumulator[`${currentValue.source}/tcp`] = {};
98
-
99
- return accumulator;
100
- }, {}),
101
- HostConfig: {
102
- PortBindings: portBindings.reduce((accumulator, currentValue) => {
103
- accumulator[`${currentValue.source}/tcp`] = [
104
- {
105
- HostIP: '0.0.0.0',
106
- HostPort: `${currentValue.destination}`
107
- }
108
- ];
109
-
110
- return accumulator;
111
- }, {})
112
- },
113
- Image: image,
114
- OpenStdin: false,
115
- StdinOnce: false,
116
- Tty: true,
117
- name
118
- });
119
-
120
- await container.start();
121
-
122
- return container;
123
- },
124
- stopContainer: async ({ name }: StopContainerProps) => {
125
- const container = await docker.getContainer(name);
126
- await container.kill();
127
- await container.remove();
49
+ }
128
50
 
129
- return null;
51
+ console.log('After run results:', results);
52
+ console.log('Test retries:', testRetries);
53
+
54
+ // Save the testRetries object to a file in the e2e/results directory
55
+ const resultFilePath = path.join(
56
+ __dirname,
57
+ '../../../../tests/e2e/results',
58
+ 'hasRetries.json'
59
+ );
60
+ if (results.totalFailed > 0) {
61
+ fs.writeFileSync(resultFilePath, '{}');
62
+ } else if (Object.keys(testRetries).length > 0) {
63
+ // If tests succeeded but there were retries, write the retries to the file
64
+ fs.writeFileSync(resultFilePath, JSON.stringify(testRetries, null, 2));
65
+ } else {
66
+ // If no retries, empty the file
67
+ fs.writeFileSync(resultFilePath, '{}');
130
68
  }
131
69
  });
132
70
 
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ mochawesomeReporterOptions: {
3
+ consoleReporter: 'none',
4
+ html: false,
5
+ json: true,
6
+ overwrite: true,
7
+ reportDir: 'results/reports',
8
+ reportFilename: '[name]-report.json'
9
+ },
10
+ reporterEnabled: `mochawesome,${require.resolve(
11
+ '@badeball/cypress-cucumber-preprocessor/pretty-reporter'
12
+ )}`
13
+ };
@@ -0,0 +1,259 @@
1
+ /* eslint-disable no-console */
2
+ import { execSync } from 'child_process';
3
+ import { existsSync, mkdirSync } from 'fs';
4
+ import path from 'path';
5
+
6
+ import tar from 'tar-fs';
7
+ import {
8
+ DockerComposeEnvironment,
9
+ GenericContainer,
10
+ StartedDockerComposeEnvironment,
11
+ StartedTestContainer,
12
+ Wait,
13
+ getContainerRuntimeClient
14
+ } from 'testcontainers';
15
+ import { createConnection } from 'mysql2/promise';
16
+
17
+ interface Containers {
18
+ [key: string]: StartedTestContainer;
19
+ }
20
+
21
+ export default (on: Cypress.PluginEvents): void => {
22
+ let dockerEnvironment: StartedDockerComposeEnvironment | null = null;
23
+ const containers: Containers = {};
24
+
25
+ const getContainer = (containerName): StartedTestContainer => {
26
+ let container;
27
+
28
+ if (dockerEnvironment !== null) {
29
+ container = dockerEnvironment.getContainer(`${containerName}-1`);
30
+ } else if (containers[containerName]) {
31
+ container = containers[containerName];
32
+ } else {
33
+ throw new Error(`Cannot get container ${containerName}`);
34
+ }
35
+
36
+ return container;
37
+ };
38
+
39
+ interface PortBinding {
40
+ destination: number;
41
+ source: number;
42
+ }
43
+
44
+ interface StartContainerProps {
45
+ command?: string;
46
+ image: string;
47
+ name: string;
48
+ portBindings: Array<PortBinding>;
49
+ }
50
+
51
+ interface StopContainerProps {
52
+ name: string;
53
+ }
54
+
55
+ on('task', {
56
+ copyFromContainer: async ({ destination, serviceName, source }) => {
57
+ try {
58
+ if (dockerEnvironment !== null) {
59
+ const container = dockerEnvironment.getContainer(`${serviceName}-1`);
60
+
61
+ await container
62
+ .copyArchiveFromContainer(source)
63
+ .then((archiveStream) => {
64
+ return new Promise<void>((resolve) => {
65
+ const dest = tar.extract(destination);
66
+ archiveStream.pipe(dest);
67
+ dest.on('finish', resolve);
68
+ });
69
+ });
70
+ }
71
+ } catch (error) {
72
+ console.error(error);
73
+ }
74
+
75
+ return null;
76
+ },
77
+ copyToContainer: async ({ destination, serviceName, source, type }) => {
78
+ const container = getContainer(serviceName);
79
+
80
+ if (type === 'directory') {
81
+ await container.copyDirectoriesToContainer([
82
+ {
83
+ source,
84
+ target: destination
85
+ }
86
+ ]);
87
+ } else if (type === 'file') {
88
+ await container.copyFilesToContainer([
89
+ {
90
+ source,
91
+ target: destination
92
+ }
93
+ ]);
94
+ }
95
+
96
+ return null;
97
+ },
98
+ createDirectory: async (directoryPath: string) => {
99
+ if (!existsSync(directoryPath)) {
100
+ mkdirSync(directoryPath, { recursive: true });
101
+ }
102
+
103
+ return null;
104
+ },
105
+ execInContainer: async ({ command, name }) => {
106
+ const { exitCode, output } = await getContainer(name).exec([
107
+ 'bash',
108
+ '-c',
109
+ `${command}${command.match(/[\n\r]/) ? '' : ' 2>&1'}`
110
+ ]);
111
+
112
+ return { exitCode, output };
113
+ },
114
+ getContainerId: (containerName: string) =>
115
+ getContainer(containerName).getId(),
116
+ getContainerIpAddress: (containerName: string) => {
117
+ const container = getContainer(containerName);
118
+
119
+ const networkNames = container.getNetworkNames();
120
+
121
+ return container.getIpAddress(networkNames[0]);
122
+ },
123
+ getContainersLogs: async () => {
124
+ try {
125
+ const { dockerode } = (await getContainerRuntimeClient()).container;
126
+ const loggedContainers = await dockerode.listContainers();
127
+
128
+ return loggedContainers.reduce((acc, container) => {
129
+ const containerName = container.Names[0].replace('/', '');
130
+ acc[containerName] = execSync(`docker logs -t ${container.Id}`, {
131
+ stdio: 'pipe'
132
+ }).toString('utf8');
133
+
134
+ return acc;
135
+ }, {});
136
+ } catch (error) {
137
+ console.warn('Cannot get containers logs');
138
+ console.warn(error);
139
+
140
+ return null;
141
+ }
142
+ },
143
+ requestOnDatabase: async ({ database, query }) => {
144
+ let container: StartedTestContainer | null = null;
145
+
146
+ if (dockerEnvironment !== null) {
147
+ container = dockerEnvironment.getContainer('db-1');
148
+ } else {
149
+ container = getContainer('web');
150
+ }
151
+
152
+ const client = await createConnection({
153
+ database,
154
+ host: container.getHost(),
155
+ password: 'centreon',
156
+ port: container.getMappedPort(3306),
157
+ user: 'centreon'
158
+ });
159
+
160
+ const [rows, fields] = await client.query(query);
161
+
162
+ await client.end();
163
+
164
+ return [rows, fields];
165
+ },
166
+ startContainer: async ({
167
+ command,
168
+ image,
169
+ name,
170
+ portBindings = []
171
+ }: StartContainerProps) => {
172
+ let container = await new GenericContainer(image).withName(name);
173
+
174
+ portBindings.forEach(({ source, destination }) => {
175
+ container = container.withExposedPorts({
176
+ container: source,
177
+ host: destination
178
+ });
179
+ });
180
+
181
+ if (command) {
182
+ container
183
+ .withCommand(['bash', '-c', command])
184
+ .withWaitStrategy(Wait.forSuccessfulCommand('ls'));
185
+ }
186
+
187
+ containers[name] = await container.start();
188
+
189
+ return container;
190
+ },
191
+ startContainers: async ({
192
+ composeFile,
193
+ databaseImage,
194
+ openidImage,
195
+ profiles,
196
+ samlImage,
197
+ webImage
198
+ }) => {
199
+ try {
200
+ const composeFileDir = path.dirname(composeFile);
201
+ const composeFileName = path.basename(composeFile);
202
+
203
+ dockerEnvironment = await new DockerComposeEnvironment(
204
+ composeFileDir,
205
+ composeFileName
206
+ )
207
+ .withEnvironment({
208
+ MYSQL_IMAGE: databaseImage,
209
+ OPENID_IMAGE: openidImage,
210
+ SAML_IMAGE: samlImage,
211
+ WEB_IMAGE: webImage
212
+ })
213
+ .withProfiles(...profiles)
214
+ .withStartupTimeout(120000)
215
+ .withWaitStrategy(
216
+ 'web-1',
217
+ Wait.forAll([
218
+ Wait.forHealthCheck(),
219
+ Wait.forLogMessage('Centreon is ready')
220
+ ])
221
+ )
222
+ .up();
223
+
224
+ return null;
225
+ } catch (error) {
226
+ if (error instanceof Error) {
227
+ console.error(error.message);
228
+ }
229
+
230
+ throw error;
231
+ }
232
+ },
233
+ stopContainer: async ({ name }: StopContainerProps) => {
234
+ if (containers[name]) {
235
+ const container = containers[name];
236
+
237
+ await container.stop();
238
+
239
+ delete containers[name];
240
+ }
241
+
242
+ return null;
243
+ },
244
+ stopContainers: async () => {
245
+ if (dockerEnvironment !== null) {
246
+ await dockerEnvironment.down();
247
+
248
+ dockerEnvironment = null;
249
+ }
250
+
251
+ return null;
252
+ },
253
+ waitOn: async (url: string) => {
254
+ execSync(`npx wait-on ${url}`);
255
+
256
+ return null;
257
+ }
258
+ });
259
+ };
@@ -21,11 +21,15 @@ module.exports = {
21
21
  }
22
22
  ],
23
23
  '@typescript-eslint/camelcase': 'off',
24
- '@typescript-eslint/consistent-type-definitions': [
24
+ '@typescript-eslint/consistent-type-definitions': ['off', 'interface'],
25
+ '@typescript-eslint/explicit-function-return-type': [
25
26
  'error',
26
- 'interface'
27
+ {
28
+ allowExpressions: true,
29
+ allowHigherOrderFunctions: true,
30
+ allowTypedFunctionExpressions: true
31
+ }
27
32
  ],
28
- '@typescript-eslint/explicit-function-return-type': ['error'],
29
33
  '@typescript-eslint/explicit-member-accessibility': [
30
34
  'error',
31
35
  {
@@ -76,13 +80,21 @@ module.exports = {
76
80
  }
77
81
  ],
78
82
  camelcase: 'off',
83
+ 'import/no-cycle': 'off',
84
+ 'import/no-named-as-default': 'warn',
79
85
  'no-shadow': 'off',
80
86
  'no-unused-expressions': 'off'
81
87
  },
82
88
  settings: {
89
+ 'import/parsers': {
90
+ '@typescript-eslint/parser': ['.ts', '.tsx']
91
+ },
83
92
  'import/resolver': {
84
93
  alias: {
85
94
  extensions: ['.ts', '.tsx', '.js', '.jsx']
95
+ },
96
+ typescript: {
97
+ alwaysTryTypes: true
86
98
  }
87
99
  }
88
100
  }
@@ -0,0 +1,48 @@
1
+ module.exports = {
2
+ extends: [ '../node/typescript.eslintrc.js'],
3
+ overrides: [
4
+ {
5
+ files: ["*.spec.js", "*.test.ts", "*.tests.ts"],
6
+ rules: {
7
+ "import/first": 0,
8
+ "import/order": 0,
9
+ "@typescript-eslint/ban-ts-comment": 0,
10
+ "@typescript-eslint/no-explicit-any": 0
11
+ }
12
+ }
13
+ ],
14
+ rules: {
15
+ "import/extensions": ["off"],
16
+ "no-console": "off",
17
+ "no-underscore-dangle": "off",
18
+ "class-methods-use-this": "off",
19
+ "@typescript-eslint/naming-convention": [
20
+ "error",
21
+ {
22
+ format: ["camelCase", "PascalCase", "UPPER_CASE"],
23
+ selector: "variable"
24
+ },
25
+ {
26
+ filter: {
27
+ match: false,
28
+ regex: "(__esModule|.+-.+)"
29
+ },
30
+ format: ["snake_case", "camelCase", "PascalCase", "UPPER_CASE"],
31
+ selector: "property",
32
+ leadingUnderscore: "allow"
33
+ },
34
+ {
35
+ filter: {
36
+ match: false,
37
+ regex: "^_$"
38
+ },
39
+ format: ["snake_case", "camelCase", "PascalCase"],
40
+ selector: "parameter"
41
+ }
42
+ ],
43
+ "@typescript-eslint/require-array-sort-compare": "error"
44
+ },
45
+ parserOptions: {
46
+ project: ["./tsconfig.json"]
47
+ }
48
+ }