Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: next version #1079

Merged
merged 6 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions .eslintignore

This file was deleted.

5 changes: 2 additions & 3 deletions .github/workflows/ci-module.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ on:
push:
branches:
- master
- next
pull_request:
workflow_dispatch:

jobs:
test:
uses: hapijs/.github/.github/workflows/ci-module.yml@master
with:
min-node-version: 14
uses: hapijs/.github/.github/workflows/ci-module.yml@min-node-18-hapi-21
15 changes: 11 additions & 4 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -632,10 +632,17 @@ Your project's eslint configuration will now extend the default **lab** configur

### Ignoring files in linting

Since [eslint](http://eslint.org/) is used to lint, you can create an `.eslintignore` containing paths to be ignored:
```
node_modules/*
**/vendor/*.js
Since [eslint](http://eslint.org/) is used to lint, if you don't already have an `eslint.config.{js|cjs|mjs|ts|mts|cts}` you can create one,
and add an `ignores` rule containing paths to be ignored. Here is an example preserving default hapi rules:
```javascript
import HapiPlugin from '@hapi/eslint-plugin';

export default [
{
ignores: ['node_modules/*', '**/vendor/*.js'],
},
...HapiPlugin.configs.module,
];
```

### Only run linting
Expand Down
20 changes: 20 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';

const HapiPlugin = require('@hapi/eslint-plugin');

module.exports = [
{
ignores: [
'node_modules/',
'test_runner/',
'test/coverage/',
'test/cli/',
'test/cli_*/',
'test/lint/',
'test/override/',
'test/plan/',
'test/transform/'
]
},
...HapiPlugin.configs.module
];
6 changes: 3 additions & 3 deletions lib/linter/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict';

module.exports = {
extends: 'plugin:@hapi/module'
};
const HapiPlugin = require('@hapi/eslint-plugin');

module.exports = [...HapiPlugin.configs.module];
55 changes: 40 additions & 15 deletions lib/linter/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

const Fs = require('fs');
const Path = require('path');

const Eslint = require('eslint');
const Hoek = require('@hapi/hoek');
Expand All @@ -18,31 +17,50 @@ exports.lint = async function () {

const options = process.argv[2] ? JSON.parse(process.argv[2]) : undefined;

if (!Fs.existsSync('.eslintrc.js') &&
!Fs.existsSync('.eslintrc.cjs') && // Needed for projects with "type": "module"
!Fs.existsSync('.eslintrc.yaml') &&
!Fs.existsSync('.eslintrc.yml') &&
!Fs.existsSync('.eslintrc.json') &&
!Fs.existsSync('.eslintrc')) {
configuration.overrideConfigFile = Path.join(__dirname, '.eslintrc.js');
let usingDefault = false;

if (!Fs.existsSync('eslint.config.js') &&
!Fs.existsSync('eslint.config.cjs') &&
!Fs.existsSync('eslint.config.mjs') &&
!Fs.existsSync('eslint.config.ts') &&
!Fs.existsSync('eslint.config.mts') &&
!Fs.existsSync('eslint.config.cts')) {
// No configuration file found, using the default one
usingDefault = true;
configuration.baseConfig = require('./.eslintrc.js');
configuration.overrideConfigFile = true;
}

if (options) {
Hoek.merge(configuration, options, true, false);
}

if (!configuration.extensions) {
configuration.extensions = ['.js', '.cjs', '.mjs'];
// Only the default configuration should be altered, otherwise the user's configuration should be used as is
if (usingDefault) {
if (!configuration.extensions) {
const extensions = ['js', 'cjs', 'mjs'];

if (configuration.typescript) {
configuration.extensions.push('.ts');
if (configuration.typescript) {
extensions.push('ts');
}

configuration.baseConfig.unshift({
files: extensions.map((ext) => `**/*.${ext}`)
});
}
}

if (configuration.typescript) {
delete configuration.typescript;
if (configuration.ignores) {
configuration.baseConfig.unshift({
ignores: configuration.ignores
});
}
}

delete configuration.extensions;
delete configuration.typescript;
delete configuration.ignores;


let results;
try {
const eslint = new Eslint.ESLint(configuration);
Expand All @@ -66,6 +84,13 @@ exports.lint = async function () {

transformed.errors = result.messages.map((err) => {

if (err.messageTemplate === 'all-matched-files-ignored') {
return {
severity: 'ERROR',
message: err.message
};
}

return {
line: err.line,
severity: err.severity === 1 ? 'WARNING' : 'ERROR',
Expand Down
40 changes: 34 additions & 6 deletions lib/modules/coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ const SourceMap = require('../source-map');
const Transform = require('./transform');

const internals = {
_state: Symbol.for('@hapi/lab/coverage/_state'),
eslint: new ESLint.ESLint({ baseConfig: Eslintrc })
_state: Symbol.for('@hapi/lab/coverage/_state')
};


Expand Down Expand Up @@ -111,7 +110,7 @@ internals.prime = function (extension, ctx) {
require.extensions[extension] = function (localModule, filename) {

// We never want to instrument eslint configs in order to avoid infinite recursion
if (Path.basename(filename, extension) !== '.eslintrc') {
if (!['.eslintrc', 'eslint.config'].includes(Path.basename(filename, extension))) {
for (let i = 0; i < internals.state.patterns.length; ++i) {
if (internals.state.patterns[i].test(filename.replace(/\\/g, '/'))) {
return localModule._compile(internals.instrument(filename, ctx), filename);
Expand Down Expand Up @@ -761,11 +760,40 @@ internals.file = async function (filename, data, options) {

internals.context = async (options) => {

const filePath = Path.join(options.coveragePath || '', 'x.js');
let calculated;

// The parserOptions are shared by all files for coverage purposes, based on
// the effective eslint config for a hypothetical file {coveragePath}/x.js
const { parserOptions } = await internals.eslint.calculateConfigForFile(
Path.join(options.coveragePath || '', 'x.js')
);
try {
// Let's try first with eslint's native configuration detection
const eslint = new ESLint.ESLint({
ignore: false
});

calculated = await eslint.calculateConfigForFile(filePath);
}
catch (err) {
/* $lab:coverage:off$ */
if (err.messageTemplate !== 'config-file-missing') {
throw err;
}

// If the eslint config file is missing, we'll use the one provided by lab
const eslint = new ESLint.ESLint({
overrideConfig: Eslintrc,
overrideConfigFile: true,
ignore: false
});

calculated = await eslint.calculateConfigForFile(filePath);
/* $lab:coverage:on$ */
}

const parserOptions = {
...calculated.languageOptions,
...calculated.languageOptions?.parserOptions
};

return { parserOptions };
};
2 changes: 1 addition & 1 deletion lib/modules/lint.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ exports.lint = function (settings) {
try {
linterOptions = JSON.parse(settings['lint-options'] || '{}');
}
catch (err) {
catch {
return reject(new Error('lint-options could not be parsed'));
}

Expand Down
2 changes: 1 addition & 1 deletion lib/modules/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ exports.retrieveFile = function (path) {
try {
contents = Fs.readFileSync(path, 'utf8');
}
catch (e) {
catch {
contents = null;
}

Expand Down
2 changes: 2 additions & 0 deletions lib/modules/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ const Utils = require('../utils');
const internals = {
compiler: {
strict: true,
noUncheckedIndexedAccess: true,
exactOptionalPropertyTypes: true,
jsx: Ts.JsxEmit.React,
lib: ['lib.es2020.d.ts'],
module: Ts.ModuleKind.CommonJS,
Expand Down
2 changes: 1 addition & 1 deletion lib/modules/typescript.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internals.transform = function (content, fileName) {
try {
var { config, error } = Typescript.readConfigFile(configFile, Typescript.sys.readFile);
}
catch (err) {
catch {
throw new Error(`Cannot find a tsconfig file for ${fileName}`);
}

Expand Down
2 changes: 2 additions & 0 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ const internals = {};

// Prevent libraries like Sinon from clobbering global time functions

/* eslint-disable no-redeclare */
const Date = global.Date;
const setTimeout = global.setTimeout;
const clearTimeout = global.clearTimeout;
const setImmediate = global.setImmediate;
/* eslint-enable no-redeclare */


Error.stackTraceLimit = Infinity; // Set Error stack size
Expand Down
23 changes: 11 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"repository": "git://github.com/hapijs/lab",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"engines": {
"node": ">=18"
},
"keywords": [
"test",
"runner"
Expand All @@ -13,19 +16,14 @@
"bin/lab",
"lib"
],
"eslintConfig": {
"extends": [
"plugin:@hapi/module"
]
},
"dependencies": {
"@babel/core": "^7.16.0",
"@babel/eslint-parser": "^7.16.0",
"@babel/eslint-parser": "^7.25.1",
"@hapi/bossy": "^6.0.0",
"@hapi/eslint-plugin": "^6.0.0",
"@hapi/eslint-plugin": "^7.0.0",
"@hapi/hoek": "^11.0.2",
"diff": "^5.0.0",
"eslint": "8.x.x",
"eslint": "9.x.x",
"find-rc": "4.x.x",
"globby": "^11.1.0",
"handlebars": "4.x.x",
Expand All @@ -37,8 +35,8 @@
"will-call": "1.x.x"
},
"peerDependencies": {
"@hapi/eslint-plugin": "^6.0.0",
"typescript": ">=3.6.5"
"@hapi/eslint-plugin": "^7.0.0",
"typescript": ">=4.4.0"
},
"peerDependenciesMeta": {
"typescript": {
Expand All @@ -48,13 +46,14 @@
"devDependencies": {
"@hapi/code": "^9.0.0",
"@hapi/somever": "^4.0.0",
"@types/eslint": "^9.6.0",
"@types/node": "^18.11.17",
"@typescript-eslint/parser": "^5.62.0",
"cpr": "3.x.x",
"lab-event-reporter": "1.x.x",
"semver": "7.x.x",
"tsconfig-paths": "^4.0.0",
"typescript": "^4.5.4"
"typescript": "^4.5.4",
"typescript-eslint": "^8.1.0"
},
"bin": {
"lab": "./bin/lab"
Expand Down
3 changes: 2 additions & 1 deletion test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Load modules

const ChildProcess = require('child_process');
// eslint-disable-next-line no-redeclare
const Crypto = require('crypto');
const Fs = require('fs');
const Http = require('http');
Expand Down Expand Up @@ -702,7 +703,7 @@ describe('CLI', () => {
try {
await unlink(outputPath);
}
catch (err) {
catch {

// Error is ok here
}
Expand Down
6 changes: 3 additions & 3 deletions test/coverage.js
Original file line number Diff line number Diff line change
Expand Up @@ -566,19 +566,19 @@ describe('Coverage', () => {
it('sorts file paths in report', async () => {

const files = global.__$$labCov.files;
const paths = ['/a/b', '/a/b/c', '/a/c/b', '/a/c', '/a/b/c', '/a/b/a'];
const paths = ['./a/b', './a/b/c', './a/c/b', './a/c', './a/b/c', './a/b/a'];
paths.forEach((path) => {

files[path] = { source: [] };
});

const cov = await Lab.coverage.analyze({ coveragePath: '/a' });
const cov = await Lab.coverage.analyze({ coveragePath: './a' });
const sorted = cov.files.map((file) => {

return file.filename;
});

expect(sorted).to.equal(['/a/b', '/a/c', '/a/b/a', '/a/b/c', '/a/c/b']);
expect(sorted).to.equal(['./a/b', './a/c', './a/b/a', './a/b/c', './a/c/b']);
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use strict';

const HapiPlugin = require('@hapi/eslint-plugin');

// this is a deliberately unused function that will reduce coverage percentage
// if it ends up getting instrumented, giving us something to assert against
const unusedMethod = () => {
console.log('hello world')
}

module.exports = {
extends: 'plugin:@hapi/module'
}
module.exports = [...HapiPlugin.configs.module]
Loading