Skip to content

Commit

Permalink
3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Igorkowalski94 committed Oct 2, 2024
1 parent 97ee1fb commit dcf1848
Show file tree
Hide file tree
Showing 32 changed files with 975 additions and 315 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
</p>
<h1 align="center"><picture><img src="https://raw.githubusercontent.com/Igorkowalski94/eslint-plugin-project-structure/main/images/File%20Folder.png" alt="Folder" width="60" height="60" /></picture><picture><img src="https://raw.githubusercontent.com/Igorkowalski94/eslint-plugin-project-structure/main/images/Owl.png" alt="Owl" width="60" height="60" /></picture><br>eslint&#8209;plugin-project&#8209;structure</h1>

<p align="center">ESLint plugin with rules to help you achieve a scalable, consistent, and well-structured project.</p>
<p align="center">Create your own framework! Define your folder structure, advanced naming conventions, file composition, and create independent modules.</p>
<p align="center">Powerful ESLint plugin with rules to help you achieve a scalable, consistent, and well-structured project.</p>
<p align="center">Create your own framework! Define your folder structure, file composition, advanced naming conventions, and create independent modules.</p>
<p align="center">Take your project to the next level and save time by automating the review of key principles of a healthy project!</p>

<div align="center">
Expand Down Expand Up @@ -43,7 +43,6 @@ Leave a ⭐ and share the link with your friends.<br>

## 📚 Documentation

- [Migration guide to 2.7.0](https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/Migration-guide-to-2.7.0)
- [project-structure/folder-structure](https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bfolder%E2%80%91structure#root)
- [project-structure/independent-modules](https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bindependent%E2%80%91modules#root)
- [project-structure/file-composition](https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bfile%E2%80%91composition#root)
Expand Down Expand Up @@ -84,18 +83,19 @@ where removing or editing one feature triggers a chain reaction that impacts the
- An option to create a separate configuration file with TypeScript support.

<h2 align="center"><a href="https://github.com/Igorkowalski94/eslint-plugin-project-structure/wiki/project%E2%80%91structure-%E2%80%8Bfile%E2%80%91composition#root">project&#8209;structure/&#8203;file&#8209;composition</a></h2>
<p align="center">Enforce advanced naming rules and prohibit the use of given selectors in a given file.</p>
<p align="center">Have full control over what your file can contain and the naming conventions it must follow.</p>
<p align="center">Compose your ideal files!</p>
<p align="center">Have full control over the order and quantity of selectors. Define advanced naming conventions and prohibit the use of specific selectors in given files.</p>

<h4><picture><img src="https://raw.githubusercontent.com/Igorkowalski94/eslint-plugin-project-structure/main/images/Rocket.png" alt="Rocket" width="35" height="35" /></picture> Features:</h4>

- File composition validation.
- Supported selectors: `class`, `function`, `arrowFunction`, `type`, `interface`, `enum`, `variable`, `variableExpression`.
- Inheriting the filename as the selector name. Option to add your own prefixes/suffixes, change the case, or remove parts of the filename.
- Prohibit the use of given selectors in a given file. For example, `**/*.consts.ts` files can only contain variables, `**/*.types.ts` files can only contain interfaces and types.
- Define the order in which your selectors should appear in a given file. Support for `--fix` to automatically correct the order.
- Rules for exported selectors, selectors in the root of the file and nested/all selectors in the file. They can be used together in combination.
- Prohibit the use of given selectors in a given file. For example, `**/*.consts.ts` files can only contain variables, `**/*.types.ts` files can only contain enums, interfaces and types.
- Enforcing a maximum of one main function/class per file.
- The ability to set a specific limit on the occurrence of certain selectors in the root of a given file.
- Inheriting the filename as the selector name. Option to add your own prefixes/suffixes, change the case, or remove parts of the filename.
- Selector name regex validation.
- Build in case validation.
- Different rules for different files.
Expand Down
103 changes: 53 additions & 50 deletions fileComposition.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@
}
]
},
"scope": {
"type": "string",
"default": "file",
"enum": ["file", "fileExport", "fileRoot"]
},
"positionIndex": { "type": "number", "default": 0 },
"filenamePartsToRemove": {
"oneOf": [
{ "type": "string", "default": "" },
Expand All @@ -109,34 +115,20 @@
},
"required": ["selector"]
},
"FileRuleObject": {
"CustomErrors": {
"type": "object",
"default": {},
"additionalProperties": false,
"properties": {
"allowOnlySpecifiedSelectors": { "type": "boolean", "default": true },
"errors": {
"type": "object",
"default": {},
"additionalProperties": false,
"properties": {
"class": { "type": "string", "default": "" },
"variable": { "type": "string", "default": "" },
"variableExpression": { "type": "string", "default": "" },
"function": { "type": "string", "default": "" },
"arrowFunction": { "type": "string", "default": "" },
"type": { "type": "string", "default": "" },
"interface": { "type": "string", "default": "" },
"enum": { "type": "string", "default": "" }
}
},
"rules": {
"type": "array",
"default": [],
"items": { "$ref": "#/definitions/FileRule" }
}
},
"required": ["rules"]
"class": { "type": "string", "default": "" },
"variable": { "type": "string", "default": "" },
"variableExpression": { "type": "string", "default": "" },
"function": { "type": "string", "default": "" },
"arrowFunction": { "type": "string", "default": "" },
"type": { "type": "string", "default": "" },
"interface": { "type": "string", "default": "" },
"enum": { "type": "string", "default": "" }
}
},
"FileRules": {
"type": "object",
Expand All @@ -162,36 +154,47 @@
}
]
},
"rootSelectorsLimits": { "$ref": "#/definitions/RootSelectorsLimits" },
"fileRootRules": {
"allowOnlySpecifiedSelectors": {
"oneOf": [
{ "type": "boolean", "default": true },
{
"type": "array",
"default": [],
"items": { "$ref": "#/definitions/FileRule" }
},
{ "$ref": "#/definitions/FileRuleObject" }
]
},
"fileExportRules": {
"oneOf": [
{
"type": "array",
"default": [],
"items": { "$ref": "#/definitions/FileRule" }
},
{ "$ref": "#/definitions/FileRuleObject" }
"type": "object",
"additionalProperties": false,
"default": {
"errors": {},
"fileRoot": true,
"fileExport": true,
"file": true
},
"properties": {
"error": { "$ref": "#/definitions/CustomErrors" },
"fileRoot": {
"oneOf": [
{ "type": "boolean", "default": true },
{ "$ref": "#/definitions/CustomErrors" }
]
},
"fileExport": {
"oneOf": [
{ "type": "boolean", "default": true },
{ "$ref": "#/definitions/CustomErrors" }
]
},
"file": {
"oneOf": [
{ "type": "boolean", "default": true },
{ "$ref": "#/definitions/CustomErrors" }
]
}
}
}
]
},
"fileRules": {
"oneOf": [
{
"type": "array",
"default": [],
"items": { "$ref": "#/definitions/FileRule" }
},
{ "$ref": "#/definitions/FileRuleObject" }
]
"rootSelectorsLimits": { "$ref": "#/definitions/RootSelectorsLimits" },
"rules": {
"type": "array",
"default": [],
"items": { "$ref": "#/definitions/FileRule" }
}
},
"required": ["filePattern"]
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"author": "Igor Kowalski (Igorkowalski94)",
"name": "eslint-plugin-project-structure",
"version": "2.7.4",
"version": "3.0.0",
"license": "MIT",
"description": "ESLint plugin with rules to help you achieve a scalable, consistent, and well-structured project. Define your folder structure, advanced naming conventions, file composition, and create independent modules. react folder structure react file structure react project structure react conventions architecture react next.js angular node solid vue svelte",
"description": "Powerful ESLint plugin with rules to help you achieve a scalable, consistent, and well-structured project. Create your own framework! Define your folder structure, file composition, advanced naming conventions, and create independent modules. Take your project to the next level and save time by automating the review of key principles of a healthy project! react folder structure react file structure react project structure react conventions architecture react next.js angular node solid vue svelte",
"keywords": [
"react",
"native",
Expand Down
1 change: 1 addition & 0 deletions src/rules/fileComposition/fileComposition.consts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export const ESLINT_ERRORS = {
invalidName: `🔥 Invalid {{selectorType}} name, allowed formats = {{formatWithoutReferences}} 🔥`,
invalidPosition: `🔥 Invalid {{selectorType}} position. The current 'positionIndex' is {{currentPosition}}, but {{positionIndex}} is required. 🔥`,
prohibitedSelector: `🔥 The use of '{{selectorType}}' is prohibited in this file. 🔥{{error}}`,
prohibitedSelectorRoot: `🔥 The use of '{{selectorType}}' is prohibited in the root of the file. 🔥{{error}}`,
prohibitedSelectorExport: `🔥 Exporting '{{selectorType}}' is prohibited in this file. 🔥{{error}}`,
Expand Down
1 change: 1 addition & 0 deletions src/rules/fileComposition/fileComposition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const fileComposition = ESLintUtils.RuleCreator(
type: "problem",
schema: [{ type: "object", additionalProperties: true }],
messages: ESLINT_ERRORS,
fixable: "code",
},
defaultOptions: [],
create(context) {
Expand Down
26 changes: 15 additions & 11 deletions src/rules/fileComposition/fileComposition.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,31 +44,35 @@ interface VariableExpression {

export type Selector = SelectorType | VariableExpression;

export interface FileRule {
export type Scope = "fileExport" | "fileRoot" | "file";

export interface Rule {
selector: Selector | Selector[];
scope?: Scope;
positionIndex?: number;
filenamePartsToRemove?: string | string[];
format?: string[] | string;
}

export type CustomErrors = Partial<Record<SelectorType, string>>;

export interface FileRuleObject {
allowOnlySpecifiedSelectors?: boolean;
errors?: CustomErrors;
rules: FileRule[];
}
type CustomErrors = Partial<Record<SelectorType, string>>;

export interface RootSelectorLimit {
selector: SelectorType | SelectorType[];
limit: number;
}

export interface AllowOnlySpecifiedSelectors {
error?: CustomErrors;
fileRoot?: boolean | CustomErrors;
fileExport?: boolean | CustomErrors;
file?: boolean | CustomErrors;
}

export interface FileRules {
filePattern: Pattern;
allowOnlySpecifiedSelectors?: AllowOnlySpecifiedSelectors | boolean;
rootSelectorsLimits?: RootSelectorLimit[];
fileRootRules?: FileRule[] | FileRuleObject;
fileExportRules?: FileRule[] | FileRuleObject;
fileRules?: FileRule[] | FileRuleObject;
rules?: Rule[];
}

export interface FileCompositionConfig {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ export const FILE_COMPOSITION_SCHEMA: JSONSchema4 = {
},
],
},
scope: {
type: "string",
default: "file",
enum: ["file", "fileExport", "fileRoot"],
},
positionIndex: { type: "number", default: 0 },
filenamePartsToRemove: {
oneOf: [
{ type: "string", default: "" },
Expand All @@ -111,34 +117,20 @@ export const FILE_COMPOSITION_SCHEMA: JSONSchema4 = {
},
required: ["selector"],
},
FileRuleObject: {
CustomErrors: {
type: "object",
default: {},
additionalProperties: false,
properties: {
allowOnlySpecifiedSelectors: { type: "boolean", default: true },
errors: {
type: "object",
default: {},
additionalProperties: false,
properties: {
class: { type: "string", default: "" },
variable: { type: "string", default: "" },
variableExpression: { type: "string", default: "" },
function: { type: "string", default: "" },
arrowFunction: { type: "string", default: "" },
type: { type: "string", default: "" },
interface: { type: "string", default: "" },
enum: { type: "string", default: "" },
},
},
rules: {
type: "array",
default: [],
items: { $ref: "#/definitions/FileRule" },
},
class: { type: "string", default: "" },
variable: { type: "string", default: "" },
variableExpression: { type: "string", default: "" },
function: { type: "string", default: "" },
arrowFunction: { type: "string", default: "" },
type: { type: "string", default: "" },
interface: { type: "string", default: "" },
enum: { type: "string", default: "" },
},
required: ["rules"],
},
FileRules: {
type: "object",
Expand All @@ -164,36 +156,47 @@ export const FILE_COMPOSITION_SCHEMA: JSONSchema4 = {
},
],
},
rootSelectorsLimits: { $ref: "#/definitions/RootSelectorsLimits" },
fileRootRules: {
oneOf: [
{
type: "array",
default: [],
items: { $ref: "#/definitions/FileRule" },
},
{ $ref: "#/definitions/FileRuleObject" },
],
},
fileExportRules: {
allowOnlySpecifiedSelectors: {
oneOf: [
{ type: "boolean", default: true },
{
type: "array",
default: [],
items: { $ref: "#/definitions/FileRule" },
type: "object",
additionalProperties: false,
default: {
errors: {},
fileRoot: true,
fileExport: true,
file: true,
},
properties: {
error: { $ref: "#/definitions/CustomErrors" },
fileRoot: {
oneOf: [
{ type: "boolean", default: true },
{ $ref: "#/definitions/CustomErrors" },
],
},
fileExport: {
oneOf: [
{ type: "boolean", default: true },
{ $ref: "#/definitions/CustomErrors" },
],
},
file: {
oneOf: [
{ type: "boolean", default: true },
{ $ref: "#/definitions/CustomErrors" },
],
},
},
},
{ $ref: "#/definitions/FileRuleObject" },
],
},
fileRules: {
oneOf: [
{
type: "array",
default: [],
items: { $ref: "#/definitions/FileRule" },
},
{ $ref: "#/definitions/FileRuleObject" },
],
rootSelectorsLimits: { $ref: "#/definitions/RootSelectorsLimits" },
rules: {
type: "array",
default: [],
items: { $ref: "#/definitions/FileRule" },
},
},
required: ["filePattern"],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TSESTree } from "@typescript-eslint/utils";

import { getProgramFromNode } from "rules/fileComposition/helpers/validateFile/helpers/isExportedName/helpers/getProgramFromNode";
import { getProgramFromNode } from "rules/fileComposition/helpers/validateFile/helpers/getProgramFromNode";
import { ValidateFileProps } from "rules/fileComposition/helpers/validateFile/validateFile";

describe("IsExportName", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TSESTree } from "@typescript-eslint/utils";

import { getProgramFromNode } from "rules/fileComposition/helpers/validateFile/helpers/isExportedName/helpers/getProgramFromNode";
import { getProgramFromNode } from "rules/fileComposition/helpers/validateFile/helpers/getProgramFromNode";
import { ValidateFileProps } from "rules/fileComposition/helpers/validateFile/validateFile";

export interface IsExportDefaultProps {
Expand Down
Loading

0 comments on commit dcf1848

Please sign in to comment.