Skip to content
Draft
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
7 changes: 7 additions & 0 deletions .changeset/code-style-cli-oxfmt-readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@naverpay/code-style-cli': patch
---

code-style-cli README의 잘못된 oxfmt 설명 삭제

oxfmt 가이드에서 "별도 config 패키지가 없습니다"라는 잘못된 문장을 제거했습니다. (`@naverpay/oxfmt-config` 패키지가 존재)
12 changes: 12 additions & 0 deletions .changeset/oxlint-config-jsplugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
'@naverpay/oxlint-config': minor
---

[#164] oxlint-config 프리셋에 jsPlugins 룰 추가 (unused-imports, @naverpay/prevent-default-import)

oxlint 네이티브에 없는 룰을 문자열 배열 형식의 `jsPlugins`로 추가했습니다 (`oxlint@>=1.0` 호환 유지). 필요한 플러그인은 패키지 `dependencies`로 함께 설치됩니다.

- node 프리셋: `eslint-plugin-unused-imports` → `unused-imports/no-unused-imports`
- react 프리셋: `@naverpay/eslint-plugin` → `@naverpay/prevent-default-import` (node의 unused-imports는 `extends`로 병합 상속)

주의: `jsPlugins`는 experimental 단계라 실행 시 경고가 출력되고 IDE(oxc LSP)에서는 표시되지 않습니다. `import/order`·react 옵션 오버라이드는 네임스페이스 예약(`import`/`react`) 때문에 문자열 형식으로 불가하여 객체 형식(oxlint 상향 필요)과 함께 후속 작업으로 분리합니다.
13 changes: 13 additions & 0 deletions .changeset/oxlint-config-react-preset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@naverpay/oxlint-config': minor
---

[#164] oxlint-config 에 `react` 프리셋 추가

`node` 프리셋을 확장하는 `react/.oxlintrc.json` 프리셋을 신설했습니다. `@naverpay/eslint-config` 의 react 프리셋을 기준으로, oxlint 가 **네이티브로 지원하는 룰만** 미러링했습니다 (jsPlugins 미사용 → 새 의존성 없음, IDE(oxc LSP) 정상 동작, experimental 경고 없음).

- `plugins: ["react", "jsx-a11y"]` 선언 (두 플러그인은 기본 비활성 → 선언 시 correctness 룰 활성화)
- 명시 룰: `curly`, `no-restricted-imports`(lodash), `react/rules-of-hooks`, `react/exhaustive-deps`, `react/jsx-handler-names`, `jsx-a11y/{alt-text,label-has-associated-control}`
- 소비: `extends: ["./node_modules/@naverpay/oxlint-config/react/.oxlintrc.json"]`

> `import/order`, `unused-imports`, `@naverpay/*` 커스텀 룰 등 네이티브 미지원분은 jsPlugins 가 필요해 이번 범위에서 제외했습니다 (#164 후속).
13 changes: 13 additions & 0 deletions .changeset/oxlint-config-readme-extends.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'@naverpay/oxlint-config': patch
---

oxlint-config README에 `extends` 상속 한계 및 소비자 필수 항목 안내 추가

`card-apply-web`에서 카나리(`0.1.0-canary.260701-d925f10`) react 프리셋을 검증한 결과, oxlint의 `extends`는 `rules`/`plugins`/`jsPlugins`만 병합하고 `env`/`globals`/`categories`는 **상속하지 않는다**는 것을 확인했습니다 (oxlint 1.71.0/1.72.0, [oxc#20087](https://github.com/oxc-project/oxc/issues/20087)).

- `categories`가 상속되지 않아 oxlint 기본 `correctness`가 켜져 `unicorn/*` 룰이 의도치 않게 발화
- `env`가 상속되지 않아 `no-undef`가 `require`/`module`/`process`/`__dirname` 등을 false positive로 잡음
- 프리셋에 `globals`를 직접 추가해도 extends로 상속되지 않아 해결 불가 (검증 완료)

따라서 소비자는 최상위 config에 `env`/`categories`(필요시 `globals`)를 직접 작성해야 합니다. README의 Node.js/React 예시에 해당 항목을 포함하고, 한계를 명시하는 Note를 추가했습니다.
2 changes: 1 addition & 1 deletion packages/code-style-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ CLI는 기본 설정 파일만 생성합니다. 추가 설정이 필요한 경
>
> **Note:** oxfmt는 현재 **alpha** 단계입니다. VSCode Extension 지원도 experimental 상태입니다.

oxfmt는 현재 `extends` 옵션을 지원하지 않아 별도 config 패키지가 없습니다. CLI에서 네이버페이 권장 설정이 포함된 `.oxfmtrc.json`을 생성합니다.
CLI에서 네이버페이 권장 설정이 포함된 `.oxfmtrc.json`을 생성합니다.

### 설정

Expand Down
42 changes: 39 additions & 3 deletions packages/oxlint-config/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# CLAUDE.md — @naverpay/oxlint-config

NaverPay's [oxlint](https://oxc.rs) config (Rust-based, ESLint-compatible linter). **Config-only** —
ships the `node/` directory (`node/.oxlintrc.json`). No build, no tests. Peer dep: `oxlint@>=1.0.0`.
ships the `node/` and `react/` preset directories (`<preset>/.oxlintrc.json`). No build, no tests.
Peer dep: `oxlint@>=1.0.0`.

## Consumption gotcha — path resolution

Expand All @@ -15,12 +16,47 @@ specifier. Consumers therefore reference the full path, not the package name:
}
```

This is why the package exposes a real directory (`files: ["node"]`) instead of `exports`/`main`.
This is why the package exposes real directories (`files: ["node", "react"]`) instead of
`exports`/`main`.

## Ruleset

`node/.oxlintrc.json` sets `env` (node/commonjs/es2023) and base rules (`eqeqeq: smart`,
`no-console`, `no-param-reassign`, `no-unused-vars` with `^_` ignore patterns) plus a set of
`@typescript-eslint/*` rules. An `overrides` block for `**/*.{ts,tsx}` disables the JS-only
`no-unused-vars`/`no-undef`/`no-unused-expressions` and switches to their `@typescript-eslint`
equivalents. Edit this file to change rules; add a changeset.
equivalents.

`react/.oxlintrc.json` `extends` the node preset (relative path `../node/.oxlintrc.json`), adds
`env.browser`, declares `plugins: ["react", "jsx-a11y"]` (both are **off by default** — declaring
them activates their `correctness` rules), and layers NaverPay's explicit React choices: `curly`,
`no-restricted-imports` (lodash), `react/rules-of-hooks`, `react/exhaustive-deps`,
`react/jsx-handler-names`, and `jsx-a11y/{alt-text,label-has-associated-control}`.

## jsPlugins (experimental)

For rules oxlint has no native (Rust) implementation, the presets load ESLint-compatible plugins
via `jsPlugins` (string-array form, so it works on `oxlint@>=1.0`). These plugins ship as package
`dependencies` so they resolve for consumers:

- node preset — `eslint-plugin-unused-imports` → `unused-imports/no-unused-imports`
- react preset — `@naverpay/eslint-plugin` → `@naverpay/prevent-default-import`

`jsPlugins` arrays **merge across `extends`**, so the react preset inherits the node preset's
`unused-imports`. Two caveats, inherent to oxlint's JS-plugin support (not the format):

- oxlint prints an **experimental warning** on every run.
- JS plugins are **not supported in the language server** (no IDE/oxc-LSP diagnostics for them).

**String-format limitation.** JS plugins can't be renamed, so plugins whose `meta.name` collides
with a reserved native namespace **fail to load** (`import`, `react` are reserved). That blocks
`import/order` (`eslint-plugin-import`) and `eslint-plugin-react` option overrides — those need the
object form `{name, specifier}`, which requires a newer oxlint and drops `1.x` back-compat. They are
deferred to a follow-up. Note the scoped `@naverpay/eslint-plugin` registers under namespace
`@naverpay` (first path segment), so its rules are keyed `@naverpay/<rule>`.

## Adding rules

oxlint **silently ignores** unknown rule names — verify native support with `oxlint --rules` before
adding a native rule, or add a jsPlugin (mind the reserved-namespace limitation above). Edit the
preset files to change rules; add a changeset.
34 changes: 33 additions & 1 deletion packages/oxlint-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,38 @@ npm install @naverpay/oxlint-config oxlint -D

프로젝트 루트에 `.oxlintrc.json` 파일을 생성하고 아래와 같이 설정합니다.

> **⚠️ 중요 — `extends`는 `rules`/`plugins`/`jsPlugins`만 상속합니다.**
>
> oxlint의 `extends`는 ESLint와 달리 `env`/`globals`/`categories`를 **상속하지 않습니다**. (oxlint 1.72.0 기준 확인, [oxc#20087](https://github.com/oxc-project/oxc/issues/20087) 참고)
>
> 따라서 아래 항목은 소비자의 **최상위** config에 직접 작성해야 합니다:
>
> - `env` — `no-undef`가 참조할 전역 변수 주입 (`node`, `browser`, `commonjs` 등). 프리셋에 선언된 `env`는 `extends`로 넘어오지 않습니다.
> - `categories` — oxlint 기본 `correctness` 카테고리를 끄지 않으면 프리셋에 없는 `unicorn/*` 룰이 의도치 않게 발화합니다. `categories: { "correctness": "off" }`를 명시하세요.
>
> 프리셋이 활성화하는 룰(`rules`)과 `jsPlugins`는 정상적으로 상속됩니다.

### Node.js 프로젝트

```json
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"extends": ["./node_modules/@naverpay/oxlint-config/node/.oxlintrc.json"]
"extends": ["./node_modules/@naverpay/oxlint-config/node/.oxlintrc.json"],
"env": { "node": true, "commonjs": true, "es2023": true },
"categories": { "correctness": "off" }
}
```

### React 프로젝트

`react` 프리셋은 `node` 프리셋을 확장하고 React / JSX 접근성(a11y) 룰을 추가로 활성화합니다.

```json
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"extends": ["./node_modules/@naverpay/oxlint-config/react/.oxlintrc.json"],
"env": { "node": true, "browser": true, "commonjs": true, "es2023": true },
"categories": { "correctness": "off" }
}
```

Expand All @@ -31,10 +57,16 @@ npm install @naverpay/oxlint-config oxlint -D
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"extends": ["./node_modules/@naverpay/oxlint-config/node/.oxlintrc.json"],
"env": { "node": true, "commonjs": true, "es2023": true },
"categories": { "correctness": "off" },
"ignorePatterns": ["dist", "node_modules"]
}
```

**Tip:** `no-undef`가 `.js`/`.cjs` 파일에서 전역(`require`, `process` 등)을 잡는다면 `env.node`/`env.commonjs`가 최상위에 선언되어 있는지 확인하세요. TypeScript(`.ts`/`.tsx`)에서는 프리셋의 `overrides`가 `no-undef`를 끄므로 영향이 없습니다.

> **Note:** oxlint 네이티브에 없는 일부 룰(`unused-imports/no-unused-imports`, `@naverpay/prevent-default-import`)은 `jsPlugins`로 제공되며, 필요한 플러그인은 이 패키지의 의존성으로 함께 설치됩니다. `jsPlugins`는 아직 **experimental** 단계라 lint 실행 시 경고가 출력되고, IDE(oxc language server)에서는 해당 룰이 표시되지 않습니다.

## CLI

package.json에 스크립트를 추가하여 lint 검사를 할 수 있습니다.
Expand Down
3 changes: 3 additions & 0 deletions packages/oxlint-config/node/.oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
"commonjs": true,
"es2023": true
},
"jsPlugins": ["eslint-plugin-unused-imports"],
"rules": {
"eqeqeq": ["error", "smart"],
"no-console": "error",
"no-param-reassign": "error",
"no-unused-vars": ["error", {"ignoreRestSiblings": true, "argsIgnorePattern": "^_", "varsIgnorePattern": "^_"}],
"no-undef": "error",

"unused-imports/no-unused-imports": "error",

"@typescript-eslint/consistent-type-imports": "error",
"@typescript-eslint/adjacent-overload-signatures": "error",
"@typescript-eslint/array-type": "error",
Expand Down
7 changes: 6 additions & 1 deletion packages/oxlint-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@
"author": "@NaverPayDev/frontend",
"type": "module",
"files": [
"node"
"node",
"react"
],
"dependencies": {
"@naverpay/eslint-plugin": "workspace:*",
"eslint-plugin-unused-imports": "^4.1.4"
},
"devDependencies": {
"oxlint": "^1.31.0"
},
Expand Down
40 changes: 40 additions & 0 deletions packages/oxlint-config/react/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"extends": ["../node/.oxlintrc.json"],
"env": {
"browser": true
},
"plugins": ["react", "jsx-a11y"],
"jsPlugins": ["@naverpay/eslint-plugin"],
"rules": {
"curly": ["error", "all"],
"no-restricted-imports": [
"error",
{
"paths": [
{
"name": "lodash",
"message": "lodash는 CommonJS로 작성되어 있어 트리쉐이킹이 되지 않아 번들 사이즈를 크게 합니다. lodash/* 형식으로 import 해주세요."
}
]
}
],

"@naverpay/prevent-default-import": ["error", {"packages": ["react"]}],

"react/rules-of-hooks": "error",
"react/exhaustive-deps": "error",
"react/jsx-handler-names": [
"warn",
{
"eventHandlerPrefix": "(on|handle)",
"eventHandlerPropPrefix": "(on|handle)",
"checkLocalVariables": true,
"checkInlineFunction": false
}
],

"jsx-a11y/alt-text": "error",
"jsx-a11y/label-has-associated-control": "error",
"jsx-a11y/click-events-have-key-events": "off"
}
}
11 changes: 9 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading