diff --git a/.changeset/lucky-moles-agree.md b/.changeset/lucky-moles-agree.md new file mode 100644 index 0000000..3e2dfeb --- /dev/null +++ b/.changeset/lucky-moles-agree.md @@ -0,0 +1,5 @@ +--- +"@naverpay/eslint-plugin": minor +--- + +✨ eslint-plugin > import-server-only 추가 diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 0451e3d..286d2c5 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -41,3 +41,4 @@ npm install @naverpay/eslint-plugin -D | [prevent-default-import](docs/prevent-default-import.md) | 패키지 목록을 받아, 해당 패키지 default import를 금지합니다. | 🔧 | | [sort-exports](docs/sort-exports.md) | 파일에 있는 모든 export 문을 정렬합니다. | 🔧 | | [svg-unique-id](docs/svg-unique-id.md) | 주어진 경로의 SVG 컴포넌트들에 고유한 id를 부여하는 HOC를 추가합니다. | 🔧 | +| [import-server-only](docs/import-server-only.md) | 주어진 경로의 파일에 server-only 패키지를 포함하도록 강제합니다. | 🔧 | diff --git a/packages/eslint-plugin/docs/import-server-only.md b/packages/eslint-plugin/docs/import-server-only.md new file mode 100644 index 0000000..3bde517 --- /dev/null +++ b/packages/eslint-plugin/docs/import-server-only.md @@ -0,0 +1,57 @@ +# `@naverpay/import-server-only` + +> 🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix). + +주어진 경로의 파일에 `server-only` 패키지를 포함하도록 강제합니다. + +## 설명 + +서버에서만 이용되는 파일에 대해서 `server-only` 패키지를 필수적으로 포함하도록 강제합니다. + +### This will be reported + +```tsx +// import 'server-only' +``` + +### This will not be reported + +```tsx +import 'server-only' +``` + +## 옵션 + +### `include: [array]` + +server-only 패키지를 포함해야하는 경로 + +```json +{ + "include": ["app/server/**/*.ts"] +} +``` + +### `exclude: [array]` + +server-only 패키지를 포함되지 않아도 되는 경로 + +```json +{ + "exclude": ["app/server/exclude/**/*.ts"] +} +``` + +## 예시 + +```json +{ + "@naverpay/import-server-only": [ + "error", + { + "include": ["app/server/**/*.ts"], + "exclude": ["app/server/exclude/**/*.ts"] + } + ] +} +``` diff --git a/packages/eslint-plugin/lib/index.js b/packages/eslint-plugin/lib/index.js index 7a25b54..ca892c7 100644 --- a/packages/eslint-plugin/lib/index.js +++ b/packages/eslint-plugin/lib/index.js @@ -9,4 +9,5 @@ module.exports.rules = { 'typescript/prevent-default-import': require('./rules/typescript/prevent-default-import'), 'sort-exports': require('./rules/sort-exports'), 'svg-unique-id': require('./rules/svg-unique-id'), + 'import-server-only': require('./rules/import-server-only'), } diff --git a/packages/eslint-plugin/lib/rules/import-server-only.js b/packages/eslint-plugin/lib/rules/import-server-only.js new file mode 100644 index 0000000..01da7c6 --- /dev/null +++ b/packages/eslint-plugin/lib/rules/import-server-only.js @@ -0,0 +1,63 @@ +const path = require('path') + +const micromatch = require('micromatch') + +module.exports = { + meta: { + type: 'problem', + docs: { + description: 'Require `server-only` import in specific folders.', + recommended: false, + }, + fixable: 'code', + schema: [ + { + type: 'object', + properties: { + include: { + type: 'array', + items: {type: 'string'}, + minItems: 1, + }, + exclude: { + type: 'array', + items: {type: 'string'}, + minItems: 0, + }, + }, + additionalProperties: false, + }, + ], + }, + create(context) { + const {include, exclude} = context.options[0] || {} + const filePath = path.relative(context.getCwd(), context.getFilename()) + + const isIncluded = micromatch.isMatch(filePath, include) + const isExcluded = micromatch.isMatch(filePath, exclude) + + if (!(isIncluded && !isExcluded)) { + return {} + } + + return { + Program(node) { + const hasServerOnlyImport = node.body.some( + (statement) => statement.type === 'ImportDeclaration' && statement.source.value === 'server-only', + ) + + const sourceCode = context.getSourceCode() + if (!hasServerOnlyImport) { + context.report({ + node, + message: 'This file must include `import server-only`.', + fix(fixer) { + const firstToken = sourceCode.getFirstToken(node) + return fixer.insertTextBefore(firstToken, "import 'server-only'\n") + }, + }) + } + }, + } + }, +}