Skip to content
Open
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
4 changes: 4 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Normalize line endings to LF on checkout across platforms so the oxfmt
# snapshot tests produce identical output on Windows runners (default
# autocrlf=true would otherwise check out fixtures as CRLF).
* text=auto eol=lf
13 changes: 13 additions & 0 deletions .github/workflows/ci-module.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: ci

on:
push:
branches:
- master
- next
pull_request:
workflow_dispatch:

jobs:
test:
uses: hapijs/.github/.github/workflows/ci-module.yml@min-node-22-hapi-21
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
**/node_modules
**/package-lock.json
pnpm-lock.yaml

coverage

**/.DS_Store
**/._*

**/*.pem

**/.vs
**/.vscode
**/.idea
141 changes: 141 additions & 0 deletions API.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
## Configurations

### `@hapi/oxc-plugin/oxlint`

The oxlint configuration containing hapi style guide rules and config. To use in your project, add
[`@hapi/oxc-plugin`](https://github.com/hapijs/oxc-plugin) to your `package.json`, then in your `oxlint.config.ts` add:

```ts
import { defineConfig } from 'oxlint';
import DefaultOxlintConfig from '@hapi/oxc-plugin/oxlint';

export default defineConfig({
extends: [DefaultOxlintConfig],
env: {
...DefaultOxlintConfig.env,
},
});
```

### `@hapi/oxc-plugin/oxfmt`

The [oxfmt](https://oxc.rs/docs/guide/usage/formatter/oxfmt.html) configuration containing hapi style guide formatting rules. To use in your project, add
[`@hapi/oxc-plugin`](https://github.com/hapijs/oxc-plugin) to your `package.json`, then in your `oxfmt.config.ts` add:

```ts
import { defineConfig } from 'oxfmt';
import DefaultOxfmtConfig from '@hapi/oxc-plugin/oxfmt';

export default defineConfig({
...DefaultOxfmtConfig,
});
```

## Rules

This plugin includes the following Oxlint rules:

### capitalize-modules

Enforces capitalization of imported module variables.

#### `global-scope-only`

If the string `'global-scope-only'` is passed as the first option to this rule,
then it will only be enforced on assignments in the module's top level scope.

### for-loop

Enforces `for` loop iterator variable rules and restricts loop nesting depth.

This rule enforces the following:

- Restrict iterator variable names. `for` loop iterator variables should be named `i`. Nested loops should use the variables `j`, `k`, and so on.
- Restrict loop nesting. You can restrict the maximum nesting of `for` loops. By default, this limit is three.
- Prevent postfix increment and decrement operators. The hapi style guide does not allow postfix increment and decrement operators in `for` loop updates. The prefix version of these operators should be used instead.
- Single variable declaration in initialization section. A single `var i = 0;` is allowed in the initialization section. This only applies to variable declarations, not assignments to existing variables. This means that `for (i = 0, j = 0)` is allowed if `i` and `j` are existing variables. Variable declarations involving destructuring are not allowed.

#### Rule options

This rule can be configured by providing a single options object. The object supports the following keys.

##### `maxDepth`

A number representing the maximum allowed nesting of `for` loops. Defaults to three.

##### `startIterator`

The first variable iterator name to use. This defaults to `'i'`.

### no-var

Enforces the usage of var declarations only in try-catch scope.

### no-arrowception

Prevents arrow functions that implicitly create additional arrow functions.

This rule prevents the pattern () => () => () => ...;.

Functions can still be returned by arrow functions whose bodies use curly braces and an explicit return.

This rule does not accept any configuration options.

### consistent-this

Enforces consistent naming when capturing the current execution context in a variable.

The rule takes a list of permitted alias names. In the recommended configuration the only permitted alias is
`self`, so `const self = this;` is allowed while `const that = this;` is reported. It also reports a permitted
alias that is assigned a value other than `this` (for example `const self = 5;`).

Checks are performed at assignment sites. An alias that is declared but never assigned `this` (for example a
bare `let self;`) is not reported.

### one-var

Requires each variable to be declared in its own statement. Combined declarations such as `let a, b;` or
`const x = 1, y = 2;` are reported and should be split into separate statements.

This rule is configured with the string `'never'` in the recommended configuration.

## Vitest plugin

This plugin also exposes a [Vitest](https://vitest.dev) plugin at `@hapi/oxc-plugin/vitest`. It runs
the oxlint and oxfmt checks as a dedicated test project, so linting and formatting violations surface
as failing tests in your existing test run.

The Vitest plugin requires `vitest` >= 4 in your project. It is an optional part of this package — the
`oxlint` and `oxfmt` configurations work without `vitest` installed — so `vitest` is not declared as a
peer dependency.

To use it, add [`@hapi/oxc-plugin`](https://github.com/hapijs/oxc-plugin) to your `package.json`, then
in your `vitest.config.js` add:

```js
import { defineConfig } from 'vitest/config';
import oxc from '@hapi/oxc-plugin/vitest';

export default defineConfig({
plugins: [oxc()],
});
```

When run, the plugin checks for an existing oxlint or oxfmt configuration in the working directory. If
none is found, it falls back to the configurations shipped by this plugin.

### Options

The plugin accepts a single options object with the following keys.

#### `oxlint`

A boolean controlling whether the oxlint check runs. Defaults to `true`.

#### `oxfmt`

A boolean controlling whether the oxfmt check runs. Defaults to `true`.

#### `cwd`

The working directory the checks run against. Defaults to `process.cwd()`.
11 changes: 11 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Copyright (c) 2019-2020, Sideway Inc, and project contributors
Copyright (c) 2015-2019 Continuation Labs and Colin J. Ihrig
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
- The names of any contributors may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS OFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<a href="https://hapi.dev"><img src="https://raw.githubusercontent.com/hapijs/assets/master/images/family.png" width="180px" align="right" /></a>

# @hapi/oxc-plugin

#### Oxlint & Oxfmt plugin containing hapi style guide rules and config.

**oxc-plugin** is part of the **hapi** ecosystem and was designed to work seamlessly with the [hapi web framework](https://hapi.dev) and its other components (but works great on its own or with other frameworks). If you are using a different web framework and find this module useful, check out [hapi](https://hapi.dev) – they work even better together.

### Visit the [hapi.dev](https://hapi.dev) Developer Portal for tutorials, documentation, and support

## Useful resources

- [Documentation and API](https://hapi.dev/family/oxc-plugin/)
- [Version status](https://hapi.dev/resources/status/#oxc-plugin) (builds, dependencies, node versions, licenses, eol)
- [Changelog](https://hapi.dev/family/oxc-plugin/changelog/)
- [Project policies](https://hapi.dev/policies/)
- [Free and commercial support options](https://hapi.dev/support/)
8 changes: 8 additions & 0 deletions oxfmt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { defineConfig } from 'oxfmt';

import DefaultOxfmtConfig from './src/configs/oxfmt.config.js';

export default defineConfig({
...DefaultOxfmtConfig,
ignorePatterns: [...DefaultOxfmtConfig.ignorePatterns, 'test/configs/fixtures/**'],
});
15 changes: 15 additions & 0 deletions oxlint.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import HapiRecommended from '@hapi/oxc-plugin/oxlint';
import { defineConfig } from 'oxlint';

export default defineConfig({
extends: [HapiRecommended],
env: {
...HapiRecommended.env,
},
globals: {
__HAPI_OXC_OXLINT__: 'readonly',
__HAPI_OXC_OXFMT__: 'readonly',
__HAPI_OXC_CWD__: 'readonly',
},
ignorePatterns: ['test/configs/fixtures/**'],
});
60 changes: 60 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"name": "@hapi/oxc-plugin",
"version": "1.0.0",
"description": "Oxlint & Oxfmt plugin containing hapi style guide rules and config",
"keywords": [
"hapi",
"lint",
"oxfmt",
"oxlint"
],
"license": "BSD-3-Clause",
"repository": {
"type": "git",
"url": "git+https://github.com/hapijs/oxc-plugin.git"
},
"files": [
"src"
],
"type": "module",
"main": "src/index.js",
"types": "src/index.d.ts",
"exports": {
".": {
"types": "./src/index.d.ts",
"import": "./src/index.js"
},
"./oxlint": {
"types": "./src/configs/recommended.d.ts",
"import": "./src/configs/recommended.js"
},
"./oxfmt": {
"types": "./src/configs/oxfmt.config.d.ts",
"import": "./src/configs/oxfmt.config.js"
},
"./vitest": {
"types": "./src/vitest.d.ts",
"import": "./src/vitest.js"
}
},
"scripts": {
"test": "vitest run",
"lint": "oxlint && oxfmt --check",
"lint:fix": "oxlint --fix && oxfmt --write"
},
"devDependencies": {
"@hapi/oxc-plugin": "file:.",
"@oxlint/plugins": "1.68.0",
"@vitest/coverage-v8": "^4.1.8",
"oxfmt": "^0.53.0",
"oxlint": "^1.68.0",
"vitest": "^4.1.8"
},
"peerDependencies": {
"oxfmt": ">=0.53.0",
"oxlint": ">=1.68.0"
},
"engines": {
"node": ">=22"
}
}
5 changes: 5 additions & 0 deletions src/configs/oxfmt.config.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { OxfmtConfig } from 'oxfmt';

declare const config: OxfmtConfig;

export default config;
39 changes: 39 additions & 0 deletions src/configs/oxfmt.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { defineConfig } from 'oxfmt';

export default defineConfig({
// Non-source files that should not be reformatted in consumer repos. oxfmt
// otherwise rewrites LICENSE.md and CI workflow YAML on first adoption.
ignorePatterns: ['LICENSE.md', '.github/**'],
singleQuote: true,
tabWidth: 4,
printWidth: 120,
jsdoc: {},
sortImports: {
ignoreCase: true,
newlinesBetween: false,
sortSideEffects: true,
groups: [
'side_effect',
{ newlinesBetween: true },
'value-builtin',
{ newlinesBetween: true },
'external',
{ newlinesBetween: true },
'internal',
{ newlinesBetween: true },
'value-index',
'sibling',
'parent',
{ newlinesBetween: true },
'type-builtin',
'type-external',
'type-internal',
'type-index',
'type-sibling',
'type-parent',
'type-import',
'unknown',
],
},
sortPackageJson: true,
});
5 changes: 5 additions & 0 deletions src/configs/recommended.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { OxlintConfig } from 'oxlint';

declare const config: OxlintConfig;

export default config;
Loading
Loading