npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@3o3/eslint-config

v1.0.0

Published

3o3 공유 ESLint 설정 — 사용처에 따라 레이어(base/react/docs/all)를 골라 쓴다.

Readme

@3o3/eslint-config

3o3 공유 ESLint 설정(ESLint 9 flat config). 사용처에 따라 레이어를 골라 쓴다.

설치

pnpm add -D @3o3/eslint-config eslint typescript

eslinttypescript 는 peerDependency, 나머지 플러그인(typescript-eslint, eslint-plugin-react, react-hooks, import, @emotion, jsdoc, tsdoc, prettier)은 이 패키지의 dependency 라 따로 설치할 필요가 없다.

레이어

| 레이어 | 내용 | 언제 | |---|---|---| | base | js + ts 공통(@eslint/js + typescript-eslint + import) + 3o3 하우스 규칙 | 모든 TS 코드(토대) | | react | base 위 React 델타(eslint-plugin-react + react-hooks + @emotion) | React 패키지/앱 | | docs | 공개 API 문서 완전성(jsdoc + tsdoc) — src/** 글롭, 내부는 파일 지시어로 opt-out | 공개 API 문서 강제 | | all | base + react + prettier 번들 | "전부 켜기" | | prettier | eslint-config-prettier(포매팅 충돌 규칙 off) | 항상 마지막에 스프레드 |

reactbase 위에 얹는 누적 델타다. 각 영역의 3o3 규칙을 이미 포함한다. 전역 무시(dist/esm/비 ts·tsx)와 프로젝트 고유 규칙은 소비하는 쪽 config 에서 직접 둔다.

사용법

루트에 eslint.config.mjs 하나를 두는 단일 설정을 권장한다(이 모노레포도 동일). defineConfig + 문자열 extends 스타일(ESLint 가 미는 방식)을 기본으로 쓴다. default export 는 configs 맵을 가진 플러그인 형태(typescript-eslint / eslint-plugin-react 와 동일)라 extends: ['@3o3/<layer>'] 로 참조된다.

// eslint.config.mjs  (React 포함 레포)
import { defineConfig } from 'eslint/config'
import threeo3 from '@3o3/eslint-config'

export default defineConfig([
  // 전역 무시는 소비하는 쪽에서 직접 둔다(빌드 산출물 + 비 ts·tsx)
  { ignores: ['**/dist/**', '**/esm/**', '**/*.{js,cjs,mjs,jsx,json}'] },
  { plugins: { '@3o3': threeo3 }, extends: ['@3o3/base', '@3o3/react'] },
  ...threeo3.docs(), // 공개 API 문서 검사(선택)
  threeo3.prettier, // 항상 마지막
])
// 플레인 TS 레포(React 없음) — react 레이어만 빼면 된다
export default defineConfig([
  { ignores: ['**/dist/**', '**/esm/**', '**/*.{js,cjs,mjs,jsx,json}'] },
  { plugins: { '@3o3': threeo3 }, extends: ['@3o3/base'] },
  threeo3.prettier,
])

프로젝트 고유 규칙은 마지막(프리티어 앞)에 flat-config 객체로 직접 얹는다:

  { files: ['**/*.{ts,tsx}'], rules: { 'no-console': 'error' } },
  { files: ['scripts/**'], rules: { '@typescript-eslint/no-explicit-any': 'off' } },

배열 스프레드 스타일 (named export)

extends 대신 배열을 직접 펼쳐도 된다.

import { base, react, docs, prettier } from '@3o3/eslint-config'

export default [
  { ignores: ['**/dist/**', '**/esm/**', '**/*.{js,cjs,mjs,jsx,json}'] },
  ...base,
  ...react,
  ...docs(),
  prettier,
]

docs 레이어 — 공개 API 문서 강제 (글롭 + 지시어 opt-out)

docs()src/** 의 ts/tsx 에서 export 된 함수·상수·인터페이스에 문서 블록을 요구한다(jsdoc/require-jsdoc). 즉 "문서 필수가 기본값".

내부 전용 모듈(배럴로 공개 안 하는 헬퍼)은 파일 맨 위 한 줄로 제외한다:

/* eslint-disable jsdoc/require-jsdoc -- 비공개(내부) 모듈: 공개 API 아님 */
  • jsdoc/require-jsdoc 하나만 끄면 docs 강제가 통째로 꺼진다(base/react 등은 그대로).
  • tsdoc/syntax 는 같이 적지 말 것 — 그 파일에 TSDoc 주석이 없으면 "unused directive" 경고가 난다.

files 글롭은 옵션으로 바꿀 수 있다: docs({ files: ['packages/**/src/**/*.{ts,tsx}'] }). 기본은 ['**/src/**/*.{ts,tsx}'](test/spec·stories·d.ts·_internal 자동 제외).

왜 이 방식인가 (과거 re-export fs 스캔 대비)

  • 에디터 즉시 반영 — 정적 글롭이라 배럴을 바꿔도 ESLint 서버 재시작이 필요 없다. (스캔 방식은 공개 목록을 config 로드 때 한 번 계산·캐시해서, 배럴 변경이 에디터에 반영되려면 재시작이 필요했다.)
  • 모르게 빠지지 않음 — 기본이 "문서 필수"라, 새 공개 파일은 자동으로 강제 대상. 내부 제외는 코드에 지시어로 명시되어 코드리뷰에서 보인다.
  • 런타임 fs 작업 없음 — docs 설정이 순수 정적.

설계 메모

  • 타입 인지 규칙 미사용: recommended(not type-checked)만 켠다 → parserOptions.project 가 필요 없어 어떤 레포에서도 그대로 동작한다.
  • 무시·프로젝트 규칙은 소비처 config 에서: base/react 는 순수 룰 레이어라 무시 규칙을 갖지 않는다. 전역 무시(dist/esm 등)와 프로젝트 고유 규칙은 소비하는 쪽 eslint.config 에서 직접 둔다.
  • 공개/내부 구분은 위치·지시어로 : 재export 그래프(동적)가 아니라 src/** 글롭 + 파일 지시어(정적)로 판정 → 예측 가능하고 에디터에 실시간.