@morriconeluca/eslint-plugin-faf 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../package.json","../src/_rules/category-mutually-exclusive/category-mutually-exclusive.rule.ts","../src/_rules/_rules@shared/_utils/_aggregates/classify-folder/classify-folder.util.ts","../src/_rules/_rules@shared/_utils/_utils@shared/_stores/cache/cache.store.ts","../src/_rules/_rules@shared/_utils/_primitives/get-root-fragment-config/get-root-fragment-config.util.ts","../src/_rules/_rules@shared/_utils/_compounds/is-root-fragment/is-root-fragment.util.ts","../src/_rules/_rules@shared/_utils/_primitives/get-category-config/get-category-config.util.ts","../src/_rules/_rules@shared/_utils/_primitives/read-dir-cached/read-dir-cached.util.ts","../src/_rules/_rules@shared/_utils/_primitives/find-tree-config/find-tree-config.util.ts","../src/_rules/_rules@shared/_utils/_primitives/to-relative-path/to-relative-path.util.ts","../src/_rules/enforce-access-node/enforce-access-node.rule.ts","../src/_rules/naming-conventions/naming-conventions.rule.ts","../src/_rules/_rules@shared/_utils/_primitives/get-file-role/get-file-role.util.ts","../src/_rules/_rules@shared/_utils/_primitives/get-project-root/get-project-root.util.ts","../src/_rules/no-direct-fragment-import/no-direct-fragment-import.rule.ts","../src/_rules/_rules@shared/_utils/_aggregates/resolve-import-path/resolve-import-path.util.ts","../src/_rules/no-fractal-branch-leak/no-fractal-branch-leak.rule.ts","../src/_rules/_rules@shared/_utils/_systems/get-private-category-owner/get-private-category-owner.util.ts","../src/_rules/no-peer-dependency/no-peer-dependency.rule.ts","../src/_rules/_rules@shared/_utils/_primitives/find-tree-config-including-excluded/find-tree-config-including-excluded.util.ts","../src/_rules/_rules@shared/_utils/_primitives/get-lca-and-sub-branches/get-lca-and-sub-branches.util.ts","../src/_rules/_rules@shared/_utils/_primitives/get-role-hierarchy-index/get-role-hierarchy-index.util.ts","../src/_rules/_rules@shared/_utils/_primitives/resolve-horizontal-hierarchy/resolve-horizontal-hierarchy.util.ts","../src/_rules/no-private-category-leak/no-private-category-leak.rule.ts","../src/rules.ts","../src/configs.ts","../src/main.ts"],"sourcesContent":["{\n \"name\": \"@morriconeluca/eslint-plugin-faf\",\n \"version\": \"0.1.1\",\n \"description\": \"An ESLint plugin for FAF projects.\",\n \"main\": \"./dist/main.cjs\",\n \"module\": \"./dist/main.js\",\n \"types\": \"./dist/main.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/main.d.ts\",\n \"import\": \"./dist/main.js\",\n \"require\": \"./dist/main.cjs\"\n }\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"imports\": {\n \"#_rules@shared/*\": \"./src/_rules/_rules@shared/*\",\n \"#_utils@shared/*\": \"./src/_rules/_rules@shared/_utils/_utils@shared/*\"\n },\n \"type\": \"module\",\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"npm run lint && tsup\",\n \"test\": \"vitest run\",\n \"dev\": \"vitest\",\n \"lint\": \"npm run lint:types && npm run lint:eslint\",\n \"lint:eslint\": \"eslint .\",\n \"lint:types\": \"tsc --noEmit\",\n \"lint:fix\": \"eslint --fix .\",\n \"format\": \"prettier --write .\",\n \"check-format\": \"prettier --check .\",\n \"ci\": \"npm run build && npm run check-format && npm run test\",\n \"prepublishOnly\": \"npm run ci\",\n \"local-release\": \"changeset version && changeset publish\",\n \"prepare\": \"husky\"\n },\n \"keywords\": [\n \"eslint\",\n \"eslintplugin\",\n \"faf\"\n ],\n \"author\": \"Luca Morricone\",\n \"license\": \"MIT\",\n \"peerDependencies\": {\n \"eslint\": \"^8.57.0 || ^9.0.0 || ^10.0.0\"\n },\n \"devDependencies\": {\n \"@changesets/cli\": \"^2.31.0\",\n \"@commitlint/cli\": \"^21.0.2\",\n \"@commitlint/config-conventional\": \"^21.0.2\",\n \"@eslint/js\": \"^10.0.1\",\n \"@types/eslint\": \"^9.6.1\",\n \"@types/node\": \"^25.9.3\",\n \"@typescript-eslint/utils\": \"^8.24.1\",\n \"dependency-cruiser\": \"^17.4.3\",\n \"eslint\": \"^10.5.0\",\n \"eslint-import-resolver-typescript\": \"^4.4.5\",\n \"eslint-plugin-import-x\": \"^4.16.2\",\n \"eslint-plugin-perfectionist\": \"^5.9.0\",\n \"husky\": \"^9.1.7\",\n \"lint-staged\": \"^17.0.7\",\n \"prettier\": \"^3.8.4\",\n \"tsup\": \"^8.3.6\",\n \"typescript\": \"^6.0.3\",\n \"typescript-eslint\": \"^8.61.0\",\n \"vitest\": \"^4.1.9\"\n },\n \"lint-staged\": {\n \"*\": \"prettier --write --ignore-unknown\",\n \"src/**/*.ts\": \"eslint --fix\"\n }\n}\n","import type { Rule } from 'eslint';\n\nimport path from 'path';\n\nimport type { TFafSettings } from '#_rules@shared/_types/faf.type.js';\n\nimport { classifyFolder } from '#_rules@shared/_utils/_aggregates/classify-folder/index.js';\nimport { findTreeConfig } from '#_rules@shared/_utils/_primitives/find-tree-config/index.js';\nimport { getCategoryConfig } from '#_rules@shared/_utils/_primitives/get-category-config/index.js';\nimport { readDirCached } from '#_rules@shared/_utils/_primitives/read-dir-cached/index.js';\nimport { toRelativePath } from '#_rules@shared/_utils/_primitives/to-relative-path/index.js';\n\n/**\n * @fileoverview Rule: faf/category-mutually-exclusive\n * Enforces the FAF rule of Category Purity (Mutua Esclusività).\n *\n * FAF Law: Categories must contain either ONLY single files (Logical Nodes) or ONLY subfolders (Fragments).\n *\n * Valid:\n * - A category configured with `allowSingleFiles: true` containing only files (e.g. `_types/user.type.ts`).\n * - A category configured with `allowSingleFiles: false` containing only Fragment folders (e.g. `_utils/get-path/`).\n *\n * Invalid:\n * - Mixing single files and subfolders directly inside the same category directory.\n * - Placing files directly in a Category that is not configured to allow single files (`allowSingleFiles: false`).\n */\nconst rule: Rule.RuleModule = {\n create(context) {\n const absPath = context.filename;\n const relPath = toRelativePath(absPath);\n const settings = context.settings as { faf?: TFafSettings };\n\n if (!settings.faf) {\n return {};\n }\n\n const config = findTreeConfig(relPath, settings.faf);\n if (!config) {\n return {};\n }\n\n const relDir = path.dirname(relPath);\n const parentType = classifyFolder(relDir, config);\n\n // This check runs once per directory. To avoid reporting multiple times, we only run it on the Access Node or the first file processed in the directory.\n if (parentType !== 'category') {\n return {};\n }\n\n const fileName = path.basename(relPath);\n\n return {\n Program(node) {\n const contents = readDirCached(relDir);\n\n // Filter contents to ignore doc files, config files, and Fractal Branches\n const activeFiles = contents.files.filter(\n (f) => f !== 'README.md' && f !== 'package.json' && !f.startsWith('.')\n );\n const activeDirs = contents.dirs.filter((d) => !d.startsWith('_')); // Ignore sub-categories/layers/fractal branches\n\n const hasFiles = activeFiles.length > 0;\n const hasDirs = activeDirs.length > 0;\n\n if (hasFiles && hasDirs) {\n context.report({\n loc: { column: 0, line: 1 },\n message: `Mutua Esclusività violation in Category \"${path.basename(relDir)}\": cannot mix single files (${activeFiles.join(', ')}) and Fragment directories (${activeDirs.join(', ')}).`,\n node,\n });\n }\n\n // Also check if category config allows single files\n if (hasFiles) {\n const folderName = path.basename(relDir);\n const catConfig = getCategoryConfig(relDir, config);\n if (catConfig) {\n const ext = path.extname(fileName);\n const isAllowedAsset =\n catConfig.allowedExtensions?.includes(ext) ?? false;\n if (!catConfig.allowSingleFiles && !isAllowedAsset) {\n context.report({\n message: `Category \"${folderName}\" cannot contain file nodes directly. File \"${fileName}\" must be encapsulated inside a Fragment.`,\n node,\n });\n }\n }\n }\n },\n };\n },\n meta: {\n docs: {\n description:\n 'Enforce that Categories contain either only file nodes or only Fragment folders, and check whitelist roles',\n },\n schema: [],\n type: 'problem',\n },\n};\n\nexport default rule;\n","import path from 'path';\n\nimport { state } from '#_utils@shared/_stores/cache/index.js';\n\nimport type { TFolderType, TTreeConfig } from '../../../_types/faf.type.js';\n\nimport { isRootFragment } from '../../_compounds/is-root-fragment/index.js';\nimport { getCategoryConfig } from '../../_primitives/get-category-config/index.js';\nimport { readDirCached } from '../../_primitives/read-dir-cached/index.js';\n\n/**\n * Classifies a relative directory path into a FAF structural category (Layer, Category, Fragment, etc.).\n * Memoizes results in `state.classifyCache` to optimize recursive parent checks.\n *\n * @param relDirPath - Directory path relative to the project root.\n * @param config - Tree configuration.\n * @returns The classified folder type.\n */\nexport function classifyFolder(\n relDirPath: string,\n config: TTreeConfig\n): TFolderType {\n const cached = state.classifyCache.get(relDirPath);\n if (cached !== undefined) {\n return cached;\n }\n\n const result = _classifyFolder(relDirPath, config);\n state.classifyCache.set(relDirPath, result);\n return result;\n}\n\nfunction _classifyFolder(relDirPath: string, config: TTreeConfig): TFolderType {\n const isExcluded = config.excludes?.some(\n (exc) => relDirPath === exc || relDirPath.startsWith(exc + '/')\n );\n if (isExcluded) {\n return 'foreign';\n }\n\n if (isRootFragment(relDirPath, config)) {\n return 'root-fragment';\n }\n\n const folderName = path.basename(relDirPath);\n\n if (folderName.startsWith('_') && folderName.includes('@shared')) {\n return 'fractal-branch';\n }\n\n const contents = readDirCached(relDirPath);\n const hasAccessNode = contents.files.some(\n (f) => f === 'index.ts' || f === 'index.js'\n );\n\n const isRoute =\n config.routeHierarchies &&\n config.routeHierarchies.some((rh) =>\n rh.paths.some((rp) => {\n if (relDirPath.startsWith(rp + '/')) {\n const remainder = relDirPath.substring(rp.length + 1);\n const segments = remainder.split('/');\n return !segments.some(\n (seg) => seg.endsWith('@shared') || seg.includes('@shared')\n );\n }\n return false;\n })\n );\n\n if (isRoute && !hasAccessNode) {\n return 'layer';\n }\n\n if (folderName.startsWith('_')) {\n const catConfig = getCategoryConfig(relDirPath, config);\n if (catConfig) {\n return 'category';\n }\n\n return 'layer';\n }\n\n const isCategory =\n config.categories &&\n config.categories.some((c) => c.name === '_' + folderName);\n if (isCategory && !hasAccessNode) {\n return 'category';\n }\n\n if (hasAccessNode) {\n return 'fragment';\n }\n\n return 'invalid-fragment';\n}\n","import type { TCacheState } from './cache.type.js';\n\n/**\n * Persistent global caching state mapping to optimized native collections.\n * Persists for the lifetime of a single ESLint run.\n * Cleaned up between testing suites dynamically using clearDirCache.\n */\nexport const state: TCacheState = {\n categoryConfigCache: new Map(),\n classifyCache: new Map(),\n dirCache: {},\n packageImports: null,\n projectRoot: process.cwd(),\n resolvedImportPathCache: new Map(),\n rolesCache: new WeakMap(),\n treeConfigCache: new Map(),\n treeConfigIncludingExcludedCache: new Map(),\n};\n","import type {\n TRootFragmentConfig,\n TTreeConfig,\n} from '../../../_types/faf.type.js';\n\n/**\n * Searches the tree configuration for the Root Fragment configuration matching the given path.\n * Traverses recursively down through sub-root configurations.\n *\n * @param relDirPath - Directory path relative to the project root.\n * @param config - Tree configuration.\n * @returns The matching Root Fragment configuration or null if not found.\n */\nexport function getRootFragmentConfig(\n relDirPath: string,\n config: TTreeConfig\n): null | TRootFragmentConfig {\n const checkConfig = (\n rfConfig: TRootFragmentConfig\n ): null | TRootFragmentConfig => {\n if (rfConfig.paths.includes(relDirPath)) {\n return rfConfig;\n }\n if (rfConfig.subRootFragments) {\n for (const sub of rfConfig.subRootFragments) {\n const res = checkConfig(sub);\n if (res) return res;\n }\n }\n return null;\n };\n\n if (config.rootFragments) {\n for (const rf of config.rootFragments) {\n const res = checkConfig(rf);\n if (res) return res;\n }\n }\n return null;\n}\n","import type { TTreeConfig } from '../../../_types/faf.type.js';\n\nimport { getRootFragmentConfig } from '../../_primitives/get-root-fragment-config/index.js';\n\n/**\n * Checks if a relative directory path corresponds to a configured Root Fragment.\n *\n * @param relDirPath - Directory path relative to the project root.\n * @param config - Tree configuration.\n * @returns True if the path is a Root Fragment.\n */\nexport function isRootFragment(\n relDirPath: string,\n config: TTreeConfig\n): boolean {\n return getRootFragmentConfig(relDirPath, config) !== null;\n}\n","import path from 'path';\n\nimport { state } from '#_utils@shared/_stores/cache/index.js';\n\nimport type { TCategoryConfig, TTreeConfig } from '../../../_types/faf.type.js';\n\n/**\n * Returns the TCategoryConfig for a given path by traversing upwards to the closest Category folder.\n * Result is cached in `state.categoryConfigCache`.\n *\n * @param relDirPath - Directory path relative to the project root.\n * @param config - Tree configuration.\n * @returns The Category configuration or null if not in a Category.\n */\nexport function getCategoryConfig(\n relDirPath: string,\n config: TTreeConfig\n): null | TCategoryConfig {\n const cached = state.categoryConfigCache.get(relDirPath);\n if (cached !== undefined) {\n return cached;\n }\n\n let result: null | TCategoryConfig = null;\n let current = relDirPath;\n while (current && current !== '.' && current !== '/') {\n const folderName = path.basename(current);\n if (folderName.startsWith('_') && !folderName.includes('@shared')) {\n const catConfig = config.categories?.find((c) => c.name === folderName);\n if (catConfig) {\n result = catConfig;\n break;\n }\n } else {\n break;\n }\n const parent = path.dirname(current).replace(/\\\\/g, '/');\n if (parent === current) break;\n current = parent;\n }\n\n state.categoryConfigCache.set(relDirPath, result);\n return result;\n}\n","import fs from 'fs';\nimport path from 'path';\n\nimport { state } from '#_utils@shared/_stores/cache/index.js';\n\n/**\n * Returns a cached record of files and directories within a target directory path.\n * Limits disk access by caching results in `state.dirCache` on the first miss.\n * Performs a single fs.readdirSync operation to optimize synchronous I/O.\n *\n * @param relDirPath - Directory path relative to the project root.\n * @returns Object with arrays of directory names and file names.\n */\nexport function readDirCached(relDirPath: string): {\n dirs: string[];\n files: string[];\n} {\n const absPath = path\n .resolve(state.projectRoot, relDirPath)\n .replace(/\\\\/g, '/');\n if (state.dirCache[absPath]) {\n return state.dirCache[absPath];\n }\n\n try {\n const entries = fs.readdirSync(absPath, { withFileTypes: true });\n const files: string[] = [];\n const dirs: string[] = [];\n\n for (const entry of entries) {\n if (entry.isFile()) {\n files.push(entry.name);\n } else if (entry.isDirectory()) {\n dirs.push(entry.name);\n }\n }\n\n state.dirCache[absPath] = { dirs, files };\n return state.dirCache[absPath];\n } catch {\n return { dirs: [], files: [] };\n }\n}\n","import { state } from '#_utils@shared/_stores/cache/index.js';\n\nimport type { TFafSettings, TTreeConfig } from '../../../_types/faf.type.js';\n\n/**\n * Finds the tree configuration that includes the given relative file path,\n * excluding paths designated as Foreign Domains. Uses `state.treeConfigCache`\n * to speed up subsequent queries.\n *\n * @param relPath - Path relative to the project root.\n * @param settings - The global FAF settings containing trees configuration.\n * @returns The matching tree configuration or null if not found or excluded.\n */\nexport function findTreeConfig(\n relPath: string,\n settings: TFafSettings\n): null | TTreeConfig {\n if (!settings || !settings.trees) {\n return null;\n }\n\n const cached = state.treeConfigCache.get(relPath);\n if (cached !== undefined) {\n return cached;\n }\n\n let result: null | TTreeConfig = null;\n for (const tree of settings.trees) {\n const isIncluded = tree.includes.some(\n (inc) => relPath === inc || relPath.startsWith(inc + '/')\n );\n const isExcluded = tree.excludes?.some(\n (exc) => relPath === exc || relPath.startsWith(exc + '/')\n );\n\n if (isIncluded && !isExcluded) {\n result = tree;\n break;\n }\n }\n\n state.treeConfigCache.set(relPath, result);\n return result;\n}\n","import path from 'path';\n\nimport { state } from '#_utils@shared/_stores/cache/index.js';\n\n/**\n * Normalizes any path to be relative to the project root and formats it with forward slashes.\n *\n * @param absoluteOrRelative - Input path string.\n * @returns Normalized relative path.\n */\nexport function toRelativePath(absoluteOrRelative: string): string {\n let abs = absoluteOrRelative;\n if (!path.isAbsolute(abs)) {\n abs = path.resolve(state.projectRoot, abs);\n }\n const rel = path.relative(state.projectRoot, abs);\n return rel.replace(/\\\\/g, '/');\n}\n","import type { Rule } from 'eslint';\n\nimport path from 'path';\n\nimport type { TFafSettings } from '#_rules@shared/_types/faf.type.js';\n\nimport { classifyFolder } from '#_rules@shared/_utils/_aggregates/classify-folder/index.js';\nimport { findTreeConfig } from '#_rules@shared/_utils/_primitives/find-tree-config/index.js';\nimport { toRelativePath } from '#_rules@shared/_utils/_primitives/to-relative-path/index.js';\n\n/**\n * @fileoverview Rule: faf/enforce-access-node\n * Enforces the FAF Law of Access Node Integrity.\n *\n * FAF Law: An Access Node (barrel file like `index.ts`) must only define and export the Fragment's public interface.\n * It is restricted to import/export only its own sibling Fragment Nodes using simple relative paths.\n *\n * Valid:\n * - `export * from './button.component';` inside `button/index.ts`.\n * - `export type * from './button.type';` inside `button/index.ts`.\n *\n * Invalid:\n * - Importing/exporting files from subfolders (e.g. `export * from './_components/child';`).\n * - Importing/exporting files from parent folders or external paths (e.g. `export * from '../utils';`).\n * - Exporting files that do not share the parent Fragment's name prefix.\n */\nconst rule: Rule.RuleModule = {\n create(context) {\n const absPath = context.filename;\n const relPath = toRelativePath(absPath);\n const fileName = path.basename(relPath);\n\n // This rule only applies to Access Nodes (index.ts / index.js)\n if (fileName !== 'index.ts' && fileName !== 'index.js') {\n return {};\n }\n\n const settings = context.settings as { faf?: TFafSettings };\n if (!settings.faf) {\n return {};\n }\n\n const config = findTreeConfig(relPath, settings.faf);\n if (!config) {\n return {};\n }\n\n const relDir = path.dirname(relPath);\n const parentType = classifyFolder(relDir, config);\n\n // If it's not a Fragment, naming-conventions handles it, but let's ignore it here\n if (parentType !== 'fragment') {\n return {};\n }\n\n function checkSource(node: Rule.Node, sourceVal: string) {\n // Must be a relative import pointing to a file in the same directory (no subfolders, no parent folders)\n // Allowed format: \"./filename\" or \"./filename.js\" etc.\n // Must start with \"./\" and not contain any further \"/\"\n const isValidSibling = /^\\.\\/[^/]+$/.test(sourceVal);\n if (!isValidSibling) {\n context.report({\n message: `Access Node (index file) can only import or export its own sibling Fragment Nodes using simple relative paths (e.g. \"./example.component\"). Got \"${sourceVal}\".`,\n node,\n });\n return;\n }\n\n // FAF Guideline G1: The Access Node (barrel file) must only re-export\n // its sibling Fragment Nodes that reside within the same Fragment directory.\n const importedFilename = path.basename(sourceVal);\n if (\n importedFilename === 'index' ||\n importedFilename === 'index.ts' ||\n importedFilename === 'index.js' ||\n importedFilename === 'README.md' ||\n importedFilename === 'package.json'\n ) {\n return;\n }\n\n const fragmentName = path.basename(relDir);\n if (!importedFilename.startsWith(fragmentName + '.')) {\n context.report({\n message: `Access Node (index file) can only re-export its own Fragment Nodes (names starting with \"${fragmentName}.\"). Got \"${importedFilename}\".`,\n node,\n });\n }\n }\n\n return {\n ExportAllDeclaration(node) {\n checkSource(node, node.source.value as string);\n },\n ExportNamedDeclaration(node) {\n if (node.source) {\n checkSource(node, node.source.value as string);\n }\n },\n ImportDeclaration(node) {\n checkSource(node, node.source.value as string);\n },\n };\n },\n meta: {\n docs: {\n description: 'Enforce Access Node rules for Fragments',\n },\n schema: [],\n type: 'problem',\n },\n};\n\nexport default rule;\n","import type { Rule } from 'eslint';\n\nimport path from 'path';\n\nimport type { TFafSettings } from '#_rules@shared/_types/faf.type.js';\n\nimport { classifyFolder } from '#_rules@shared/_utils/_aggregates/classify-folder/index.js';\nimport { findTreeConfig } from '#_rules@shared/_utils/_primitives/find-tree-config/index.js';\nimport { getCategoryConfig } from '#_rules@shared/_utils/_primitives/get-category-config/index.js';\nimport { getFileRole } from '#_rules@shared/_utils/_primitives/get-file-role/index.js';\nimport { getProjectRoot } from '#_rules@shared/_utils/_primitives/get-project-root/index.js';\nimport { getRootFragmentConfig } from '#_rules@shared/_utils/_primitives/get-root-fragment-config/index.js';\nimport { readDirCached } from '#_rules@shared/_utils/_primitives/read-dir-cached/index.js';\nimport { toRelativePath } from '#_rules@shared/_utils/_primitives/to-relative-path/index.js';\n\nconst KEBAB_CASE_REGEX = /^[a-z0-9]+(-[a-z0-9]+)*$/;\n\n/**\n * @fileoverview Rule: faf/naming-conventions\n * Enforces FAF folder taxonomy, naming conventions, and file role suffixes.\n *\n * FAF Law:\n * - Folders and files in the logical domain must use kebab-case.\n * - Categories/Layers must start with an underscore (e.g. `_components`).\n * - Fragments must NOT start with an underscore.\n * - Sibling Fragment Nodes must share the parent Fragment folder's name.\n * - All logical nodes must end with a valid role suffix (e.g. `[name].[role].ts`).\n * - Fragments placed under a Category (or Route) must contain a Master Node with the corresponding role.\n */\nconst rule: Rule.RuleModule = {\n create(context) {\n return {\n Program(node) {\n const absPath = context.filename;\n const relPath = toRelativePath(absPath);\n const settings = context.settings as { faf?: TFafSettings };\n\n if (!settings.faf) {\n return;\n }\n\n const config = findTreeConfig(relPath, settings.faf);\n if (!config) {\n return;\n }\n\n const relDir = path.dirname(relPath);\n const folderName = path.basename(relDir);\n const parentType = classifyFolder(relDir, config);\n\n // 1. Check if file is in a Foreign Domain\n if (parentType === 'foreign') {\n return;\n }\n\n const fileName = path.basename(relPath);\n\n // 2. Validate folder name casing and conventions (including all ancestors)\n let currentDir = relDir;\n while (currentDir && currentDir !== '.' && currentDir !== '/') {\n const isInTree = config.includes.some(\n (inc) => currentDir === inc || currentDir.startsWith(inc + '/')\n );\n const isExcluded =\n config.excludes?.some(\n (exc) => currentDir === exc || currentDir.startsWith(exc + '/')\n ) ?? false;\n\n if (!isInTree || isExcluded) {\n break;\n }\n\n const currentFolderName = path.basename(currentDir);\n const currentType = classifyFolder(currentDir, config);\n\n // FAF Guideline G3: Layer/Category Underscore Prefix. All organizational folders (Layers and Categories)\n // must start with an underscore (e.g. \"_my-layer\") to separate them from Fragments.\n if (\n (currentType === 'layer' || currentType === 'category') &&\n !currentFolderName.startsWith('_')\n ) {\n context.report({\n message: `Layer/Category directory \"${currentFolderName}\" must be prefixed with an underscore (e.g. \"_${currentFolderName}\").`,\n node,\n });\n }\n\n // FAF Guideline G4: Fragment Underscore Absence. Logical Fragment directories must NOT be prefixed\n // with an underscore since they represent clean domain-driven entrypoints.\n if (\n currentFolderName.startsWith('_') &&\n !currentFolderName.includes('@shared')\n ) {\n const contents = readDirCached(currentDir);\n const hasIndex =\n contents.files.includes('index.ts') ||\n contents.files.includes('index.js');\n if (hasIndex) {\n context.report({\n message: `Directory \"${currentFolderName}\" has an Access Node (index.ts) but its name starts with \"_\". Fragments must not be prefixed with underscore.`,\n node,\n });\n }\n }\n\n // Validate casing\n if (currentFolderName !== 'src') {\n let baseFolderName = currentFolderName.replace(/@shared$/, '');\n if (baseFolderName.startsWith('_')) {\n baseFolderName = baseFolderName.substring(1);\n }\n if (\n baseFolderName.startsWith('[') &&\n baseFolderName.endsWith(']')\n ) {\n baseFolderName = baseFolderName.substring(\n 1,\n baseFolderName.length - 1\n );\n }\n const isKebab = KEBAB_CASE_REGEX.test(baseFolderName);\n if (!isKebab) {\n context.report({\n message: `Folder name \"${currentFolderName}\" must be in kebab-case (e.g. \"_my-folder\" or \"_[my-param]\").`,\n node,\n });\n }\n }\n\n // Validate Fractal Branch naming\n if (currentType === 'fractal-branch') {\n const expectedScope = path.basename(path.dirname(currentDir));\n const normalizedExpectedScope = expectedScope.startsWith('_')\n ? expectedScope.substring(1)\n : expectedScope;\n const expectedName = `_${normalizedExpectedScope}@shared`;\n if (currentFolderName !== expectedName) {\n context.report({\n message: `Fractal Branch name \"${currentFolderName}\" must match its parent scope name: \"${expectedName}\".`,\n node,\n });\n }\n }\n\n // Validate invalid fragments (missing index file)\n if (currentType === 'invalid-fragment') {\n context.report({\n message: `Fragment directory \"${currentFolderName}\" is missing an Access Node (index.ts/index.js).`,\n node,\n });\n }\n\n // Validate Fragment inside Layer restriction\n const relParentDir = path.dirname(currentDir).replace(/\\\\/g, '/');\n const parentFolderName = path.basename(relParentDir);\n const relParentType =\n relParentDir === '.' || relParentDir === '/'\n ? 'unknown'\n : classifyFolder(relParentDir, config);\n\n // Validate Root Fragment parent\n // Root Fragments are execution entry points and must only reside directly inside the Root Container\n // (classified as 'unknown' relative to config paths) or nested within another Root Fragment.\n if (currentType === 'root-fragment') {\n if (\n relParentType !== 'root-fragment' &&\n relParentType !== 'unknown'\n ) {\n context.report({\n message: `Root Fragment directory \"${currentFolderName}\" must be placed directly inside a Root Container or another Root Fragment, not inside \"${parentFolderName}\" (classified as ${relParentType}).`,\n node,\n });\n }\n }\n\n // Validate Layer parent\n // Layers establish boundaries of abstraction and are strictly prohibited from residing inside Fragments.\n if (currentType === 'layer') {\n if (\n relParentType === 'fragment' ||\n relParentType === 'invalid-fragment'\n ) {\n context.report({\n message: `Layer directory \"${currentFolderName}\" cannot be placed inside \"${parentFolderName}\" (classified as ${relParentType}). Layers cannot reside within Fragments.`,\n node,\n });\n }\n }\n\n // Validate Fragment/Sub-Fragment parent\n // Fragments (or invalid fragments) are encapsulated logical units. They cannot be placed:\n // 1. Directly under Layers (unless configured as terminal Route Hierarchies).\n // 2. Directly inside another Fragment (must be nested within a Private Category).\n // 3. Directly inside a Fractal Branch.\n // 4. Directly inside a nested Root Fragment (must be contained within a Category).\n if (\n currentType === 'fragment' ||\n currentType === 'invalid-fragment'\n ) {\n const isParentRootContainer =\n config.includes.includes(relParentDir);\n if (relParentType === 'layer') {\n const isParentRoute =\n config.routeHierarchies &&\n config.routeHierarchies.some((rh) =>\n rh.paths.some(\n (rp) =>\n relParentDir === rp || relParentDir.startsWith(rp + '/')\n )\n );\n if (!isParentRoute) {\n context.report({\n message: `Fragment directory \"${currentFolderName}\" cannot be placed directly inside Layer \"${parentFolderName}\". Fragments must be contained within a Category.`,\n node,\n });\n }\n } else if (\n relParentType === 'fragment' ||\n relParentType === 'invalid-fragment'\n ) {\n context.report({\n message: `Fragment directory \"${currentFolderName}\" cannot be placed directly inside Fragment \"${parentFolderName}\". Sub-Fragments must be contained within a Private Category.`,\n node,\n });\n } else if (relParentType === 'fractal-branch') {\n context.report({\n message: `Fragment directory \"${currentFolderName}\" cannot be placed directly inside Fractal Branch \"${parentFolderName}\". Fragments must be contained within a Category.`,\n node,\n });\n } else if (\n relParentType === 'root-fragment' &&\n !isParentRootContainer\n ) {\n context.report({\n message: `Fragment directory \"${currentFolderName}\" cannot be placed directly inside Root Fragment \"${parentFolderName}\". Fragments must be contained within a Category.`,\n node,\n });\n }\n }\n\n // Validate Fractal Branch parent\n // Fractal Branches hold shared resources and cannot contain another Fractal Branch directly.\n if (currentType === 'fractal-branch') {\n if (relParentType === 'fractal-branch') {\n context.report({\n message: `Fractal Branch \"${currentFolderName}\" cannot be placed inside another Fractal Branch \"${parentFolderName}\".`,\n node,\n });\n }\n }\n\n currentDir = path.dirname(currentDir).replace(/\\\\/g, '/');\n }\n\n // 3. Validate direct parent type restrictions on files\n if (parentType === 'layer') {\n context.report({\n message: `Layers cannot contain files directly. File \"${fileName}\" is placed directly inside Layer \"${folderName}\".`,\n node,\n });\n return;\n }\n\n if (parentType === 'fractal-branch') {\n context.report({\n message: `Fractal Branches cannot contain files directly. File \"${fileName}\" is placed directly inside Fractal Branch \"${folderName}\".`,\n node,\n });\n return;\n }\n\n if (parentType === 'invalid-fragment') {\n return; // Already reported by ancestor loop\n }\n\n // 5. File level validation\n if (fileName === 'index.ts' || fileName === 'index.js') {\n // Access Node\n if (parentType !== 'fragment') {\n context.report({\n message: `Access Nodes (\"index.ts/index.js\") are exclusive to Fragments. Found index file directly inside \"${folderName}\" (classified as ${parentType}).`,\n node,\n });\n }\n return;\n }\n\n // Check if file is a Root Node\n const rfConfig = getRootFragmentConfig(relDir, config);\n if (rfConfig) {\n const flatRootNodes = rfConfig.rootNodes.flat();\n // Check if file matches any relative rootNode path (or simple filename)\n const isMatchedRootNode = flatRootNodes.some((rn) => {\n if (rn.includes('/')) {\n const rfPath = rfConfig.paths[0] ?? '';\n const absRn = path.resolve(getProjectRoot(), rfPath, rn);\n return toRelativePath(absRn) === relPath;\n }\n return rn === fileName;\n });\n\n if (isMatchedRootNode) {\n return; // Valid Root Node\n }\n }\n\n // Check if file is README or config file that is not a Logical Node\n if (\n fileName === 'README.md' ||\n fileName === 'package.json' ||\n fileName === 'tsconfig.json'\n ) {\n return;\n }\n\n const role = getFileRole(fileName, config);\n const ext = path.extname(fileName);\n\n if (parentType === 'fragment') {\n // Check route hierarchy role constraint\n const matchedRoute = config.routeHierarchies?.find((rh) =>\n rh.paths.some((rp) => relDir === rp || relDir.startsWith(rp + '/'))\n );\n if (matchedRoute) {\n const contents = readDirCached(relDir);\n const fileRoles = contents.files.map((f) => getFileRole(f, config));\n if (!fileRoles.includes(matchedRoute.role)) {\n context.report({\n message: `Route terminal Fragment \"${folderName}\" must contain a Master Node with role \"${matchedRoute.role}\" (e.g. \"${folderName}.${matchedRoute.role}.ts\").`,\n node,\n });\n }\n }\n\n // Check category role constraint\n let currentParent = path.dirname(relDir).replace(/\\\\/g, '/');\n let categoryConfig = null;\n let categoryFolderName = '';\n while (\n currentParent &&\n currentParent !== '.' &&\n currentParent !== '/'\n ) {\n const parentType = classifyFolder(currentParent, config);\n if (parentType === 'category') {\n categoryConfig = getCategoryConfig(currentParent, config);\n categoryFolderName = path.basename(currentParent);\n break;\n } else if (\n parentType === 'fragment' ||\n parentType === 'root-fragment' ||\n parentType === 'layer'\n ) {\n break;\n }\n const nextParent = path.dirname(currentParent).replace(/\\\\/g, '/');\n if (nextParent === currentParent) break;\n currentParent = nextParent;\n }\n\n if (categoryConfig && categoryConfig.role) {\n const contents = readDirCached(relDir);\n const fileRoles = contents.files.map((f) => getFileRole(f, config));\n if (!fileRoles.includes(categoryConfig.role)) {\n context.report({\n message: `Fragment \"${folderName}\" inside Category \"${categoryFolderName}\" must contain a Master Node with role \"${categoryConfig.role}\" (e.g. \"${folderName}.${categoryConfig.role}.ts\").`,\n node,\n });\n }\n }\n\n // Check that it shares the Fragment's name\n if (!fileName.startsWith(folderName + '.')) {\n context.report({\n message: `Fragment Node \"${fileName}\" must share the parent Fragment name: \"${folderName}.<role>${ext}\".`,\n node,\n });\n }\n\n // In a Fragment, ALL files must have a role, even if they have whitelisted extensions\n if (!role) {\n context.report({\n message: `File \"${fileName}\" inside Fragment \"${folderName}\" must have an explicit role suffix (e.g. \"${folderName}.style${ext}\").`,\n node,\n });\n }\n }\n\n if (parentType === 'category') {\n const catConfig = getCategoryConfig(relDir, config);\n if (catConfig) {\n const allowedExts = catConfig.allowedExtensions ?? [\n '.js',\n '.jsx',\n '.ts',\n '.tsx',\n ];\n if (!allowedExts.includes(ext)) {\n context.report({\n message: `File extension \"${ext}\" is not allowed in Category \"${folderName}\". Allowed extensions: ${allowedExts.join(', ')}.`,\n node,\n });\n return;\n }\n\n const isCodeExt = ['.js', '.jsx', '.ts', '.tsx'].includes(ext);\n if (isCodeExt) {\n if (!role) {\n context.report({\n message: `Logical Node \"${fileName}\" inside Category \"${folderName}\" must have a role suffix.`,\n node,\n });\n } else if (role !== catConfig.role) {\n context.report({\n message: `Role \"${role}\" for file \"${fileName}\" does not match the expected Category role \"${catConfig.role}\".`,\n node,\n });\n }\n } else {\n // Asset files\n if (role && role !== catConfig.role) {\n context.report({\n message: `Role \"${role}\" for asset \"${fileName}\" does not match the expected Category role \"${catConfig.role}\".`,\n node,\n });\n }\n }\n }\n }\n },\n };\n },\n meta: {\n docs: {\n description:\n 'Enforce naming conventions and folder taxonomy in FAF architecture',\n },\n schema: [],\n type: 'problem',\n },\n};\n\nexport default rule;\n","import { state } from '#_utils@shared/_stores/cache/index.js';\n\nimport type { TTreeConfig } from '../../../_types/faf.type.js';\n\n/**\n * Extracts the architectural role of a file based on its name extensions.\n * Returns special role 'index' for Access Nodes.\n * Uses `state.rolesCache` to store configurations flattened as Set for O(1) lookups.\n *\n * @param fileName - Base name of the file.\n * @param config - Tree configuration.\n * @returns The matching role suffix or null if none.\n */\nexport function getFileRole(\n fileName: string,\n config: TTreeConfig\n): null | string {\n // Exclusions: Access nodes\n if (fileName === 'index.ts' || fileName === 'index.js') {\n return 'index';\n }\n\n const parts = fileName.split('.');\n\n // Cache flat roles as a Set inside WeakMap\n let allRoles = state.rolesCache.get(config);\n if (!allRoles) {\n allRoles = new Set(config.roles.flat());\n state.rolesCache.set(config, allRoles);\n }\n\n // Search from right to left\n for (let i = parts.length - 2; i >= 1; i--) {\n const part = parts[i];\n if (part && allRoles.has(part)) {\n return part;\n }\n }\n\n return null;\n}\n","import { state } from '#_utils@shared/_stores/cache/index.js';\n\n/**\n * Returns the currently configured project root directory path.\n */\nexport function getProjectRoot(): string {\n return state.projectRoot;\n}\n","import type { Rule } from 'eslint';\n\nimport path from 'path';\n\nimport type { TFafSettings } from '#_rules@shared/_types/faf.type.js';\n\nimport { classifyFolder } from '#_rules@shared/_utils/_aggregates/classify-folder/index.js';\nimport { resolveImportPath } from '#_rules@shared/_utils/_aggregates/resolve-import-path/index.js';\nimport { findTreeConfig } from '#_rules@shared/_utils/_primitives/find-tree-config/index.js';\nimport { toRelativePath } from '#_rules@shared/_utils/_primitives/to-relative-path/index.js';\n\n/**\n * @fileoverview Rule: faf/no-direct-fragment-import\n * Enforces the FAF Law of Fragment Encapsulation.\n *\n * FAF Law: External files must never import directly a Fragment's internal files.\n * All imports from outside the Fragment's boundaries must pass exclusively through its Access Node (`index.ts`).\n *\n * Valid:\n * - `import { Button } from '#_ui/_components/button/index.js';`\n *\n * Invalid:\n * - `import { Button } from '#_ui/_components/button/button.component.js';`\n */\nconst rule: Rule.RuleModule = {\n create(context) {\n const absPath = context.filename;\n const relPath = toRelativePath(absPath);\n const settings = context.settings as { faf?: TFafSettings };\n\n if (!settings.faf) {\n return {};\n }\n\n const config = findTreeConfig(relPath, settings.faf);\n if (!config) {\n return {};\n }\n\n function checkImport(node: Rule.Node, importValue: string) {\n const resolvedRelPath = resolveImportPath(\n importValue,\n relPath,\n settings.faf!\n );\n if (!resolvedRelPath) {\n return; // External import or unresolved alias\n }\n\n const importedDir = path.dirname(resolvedRelPath);\n const importedFile = path.basename(resolvedRelPath);\n\n // If the imported file is inside a Fragment\n const importedFolderType = classifyFolder(importedDir, config!);\n if (importedFolderType === 'fragment') {\n const isAccessNode =\n importedFile === 'index.ts' || importedFile === 'index.js';\n if (!isAccessNode) {\n // Check if the importing file is outside B's Fragment\n const isInside =\n relPath === importedDir || relPath.startsWith(importedDir + '/');\n if (!isInside) {\n context.report({\n message: `Direct import of Fragment internal file \"${importedFile}\" is forbidden. You must import through its Access Node (index file) in \"${importedDir}\".`,\n node,\n });\n }\n }\n }\n }\n\n return {\n ExportAllDeclaration(node) {\n checkImport(node, node.source.value as string);\n },\n ExportNamedDeclaration(node) {\n if (node.source) {\n checkImport(node, node.source.value as string);\n }\n },\n ImportDeclaration(node) {\n checkImport(node, node.source.value as string);\n },\n };\n },\n meta: {\n docs: {\n description:\n 'Prevent direct import of Fragment internal files from outside the Fragment',\n },\n schema: [],\n type: 'problem',\n },\n};\n\nexport default rule;\n","import fs from 'fs';\nimport path from 'path';\n\nimport { state } from '#_utils@shared/_stores/cache/index.js';\n\nimport type { TFafSettings } from '../../../_types/faf.type.js';\n\nimport { readDirCached } from '../../_primitives/read-dir-cached/index.js';\nimport { toRelativePath } from '../../_primitives/to-relative-path/index.js';\n\n/**\n * Resolves an import path into a project-root-relative path.\n * Checks against aliases (both package.json subpath imports and faf.config.ts settings).\n * Caches mapping in `state.resolvedImportPathCache` to optimize duplicate node checks.\n *\n * @param importPath - Import value (e.g. \"./helper.js\" or \"#_rules@shared/foo\").\n * @param currentFileRelative - Path of the file performing the import, relative to root.\n * @param settings - Global FAF settings.\n * @returns The resolved project-relative path, or empty string if it's an external library.\n */\nexport function resolveImportPath(\n importPath: string,\n currentFileRelative: string,\n settings: TFafSettings\n): string {\n const cacheKey = `${currentFileRelative}::${importPath}`;\n const cached = state.resolvedImportPathCache.get(cacheKey);\n if (cached !== undefined) {\n return cached;\n }\n\n const result = _resolveImportPath(importPath, currentFileRelative, settings);\n state.resolvedImportPathCache.set(cacheKey, result);\n return result;\n}\n\nfunction _resolveImportPath(\n importPath: string,\n currentFileRelative: string,\n settings: TFafSettings\n): string {\n const pkgImports = loadPackageImports(state.projectRoot);\n const aliases =\n Object.keys(pkgImports).length > 0 ? pkgImports : settings?.aliases || {};\n\n // Check if it matches any registered alias prefix\n let matchedAlias: null | string = null;\n let longestMatch = 0;\n\n for (const alias of Object.keys(aliases)) {\n if (importPath === alias || importPath.startsWith(alias + '/')) {\n if (alias.length > longestMatch) {\n longestMatch = alias.length;\n matchedAlias = alias;\n }\n }\n }\n\n let relResolved: string;\n\n if (matchedAlias) {\n // 1. Alias resolution\n const target = aliases[matchedAlias];\n if (target) {\n const remainder = importPath.substring(matchedAlias.length);\n const absTarget = path.resolve(state.projectRoot, target + remainder);\n relResolved = toRelativePath(absTarget);\n } else {\n return ''; // Unresolved alias target\n }\n } else {\n // 2. Relative/absolute path resolution\n if (importPath.startsWith('.') || importPath.startsWith('/')) {\n const absCurrentDir = path.dirname(\n path.resolve(state.projectRoot, currentFileRelative)\n );\n const absResolved = path.resolve(absCurrentDir, importPath);\n relResolved = toRelativePath(absResolved);\n } else {\n return ''; // External import (e.g. library from node_modules)\n }\n }\n\n return finalizeResolvedPath(relResolved);\n}\n\n/**\n * Helper to check if a resolved relative path points to a directory with an index file,\n * or a file missing its extension, and resolves it accordingly.\n */\nfunction finalizeResolvedPath(relResolved: string): string {\n const resolvedDir = path.dirname(relResolved).replace(/\\\\/g, '/');\n const resolvedBase = path.basename(relResolved);\n\n // 1. Check if the path itself is a directory containing index.ts/js\n const dirContents = readDirCached(relResolved);\n if (dirContents.files.includes('index.ts')) {\n return (relResolved === '.' ? '' : relResolved + '/') + 'index.ts';\n }\n if (dirContents.files.includes('index.js')) {\n return (relResolved === '.' ? '' : relResolved + '/') + 'index.js';\n }\n\n // 2. Check if the path is a file missing its extension\n const parentContents = readDirCached(resolvedDir);\n const exactMatch = parentContents.files.find((f) => f === resolvedBase);\n if (!exactMatch) {\n const matchWithExt = parentContents.files.find((f) =>\n f.startsWith(resolvedBase + '.')\n );\n if (matchWithExt) {\n return (resolvedDir === '.' ? '' : resolvedDir + '/') + matchWithExt;\n }\n }\n\n return relResolved;\n}\n\nfunction loadPackageImports(projectRootPath: string): Record<string, string> {\n if (state.packageImports !== null) {\n return state.packageImports;\n }\n\n state.packageImports = {};\n\n // Isolate the test environment from physical package.json of the host plugin codebase\n const isTest =\n typeof process !== 'undefined' &&\n (process.env.NODE_ENV === 'test' || process.env.VITEST === 'true');\n if (isTest) {\n return state.packageImports;\n }\n\n const pkgPath = path.resolve(projectRootPath, 'package.json');\n if (fs.existsSync(pkgPath)) {\n try {\n const pkgContent = fs.readFileSync(pkgPath, 'utf8');\n const pkg = JSON.parse(pkgContent) as {\n imports?: Record<string, unknown>;\n };\n if (pkg.imports) {\n for (const [key, val] of Object.entries(pkg.imports)) {\n if (typeof val === 'string') {\n // Strip wildcards\n const cleanKey = key.endsWith('/*')\n ? key.slice(0, -2)\n : key.endsWith('*')\n ? key.slice(0, -1)\n : key;\n let cleanVal = val.endsWith('/*')\n ? val.slice(0, -2)\n : val.endsWith('*')\n ? val.slice(0, -1)\n : val;\n\n // Normalize target path (remove leading './' or '/')\n if (cleanVal.startsWith('./')) {\n cleanVal = cleanVal.substring(2);\n } else if (cleanVal.startsWith('/')) {\n cleanVal = cleanVal.substring(1);\n }\n\n state.packageImports[cleanKey] = cleanVal;\n }\n }\n }\n } catch {\n // Ignore parsing errors and keep packageImports empty\n }\n }\n\n return state.packageImports;\n}\n","import type { Rule } from 'eslint';\n\nimport path from 'path';\n\nimport type { TFafSettings } from '#_rules@shared/_types/faf.type.js';\n\nimport { resolveImportPath } from '#_rules@shared/_utils/_aggregates/resolve-import-path/index.js';\nimport { findTreeConfig } from '#_rules@shared/_utils/_primitives/find-tree-config/index.js';\nimport { toRelativePath } from '#_rules@shared/_utils/_primitives/to-relative-path/index.js';\nimport { getPrivateCategoryOwner } from '#_rules@shared/_utils/_systems/get-private-category-owner/index.js';\n\n/**\n * Returns the owner of the closest Fractal Branch ancestor, or null.\n */\nfunction getFractalBranchOwner(relPath: string): null | string {\n let current = relPath;\n while (current && current !== '.' && current !== '/') {\n const folderName = path.basename(current);\n if (folderName.startsWith('_') && folderName.includes('@shared')) {\n return path.dirname(current).replace(/\\\\/g, '/');\n }\n const parent = path.dirname(current).replace(/\\\\/g, '/');\n if (parent === current) {\n break;\n }\n current = parent;\n }\n return null;\n}\n\n/**\n * @fileoverview Rule: faf/no-fractal-branch-leak\n * Enforces the FAF Law of Fractal Branch Encapsulation.\n *\n * FAF Law: Fractal Branches (directories following the `_<Scope>@shared` naming convention)\n * hold internal shared implementations. They are private to their parent Scope's subtree\n * and cannot leak or be imported by files outside of that scope.\n *\n * Valid:\n * - A utility inside `src/_rules/_rules@shared/_utils/` importing from `src/_rules/_rules@shared/`.\n *\n * Invalid:\n * - A rule inside `src/_rules/naming-conventions/` importing from `src/_rules/_rules@shared/_utils/_utils@shared/` (out-of-scope).\n */\nconst rule: Rule.RuleModule = {\n create(context) {\n const absPath = context.filename;\n const relPath = toRelativePath(absPath);\n const settings = context.settings as { faf?: TFafSettings };\n\n if (!settings.faf) {\n return {};\n }\n\n const config = findTreeConfig(relPath, settings.faf);\n if (!config) {\n return {};\n }\n\n function checkImport(node: Rule.Node, importValue: string) {\n const resolvedRelPath = resolveImportPath(\n importValue,\n relPath,\n settings.faf!\n );\n if (!resolvedRelPath) {\n return; // External import or unresolved alias\n }\n\n const importedDir = path.dirname(resolvedRelPath);\n const owner = getFractalBranchOwner(importedDir);\n\n if (owner) {\n // The importing file must be inside the owner's sub-tree\n const isDescendant =\n relPath === owner || relPath.startsWith(owner + '/');\n if (!isDescendant) {\n context.report({\n message: `Importing from Fractal Branch is forbidden. The imported resource is private to \"${owner}\" and its descendants.`,\n node,\n });\n } else {\n // FAF Guideline G2: Private Category Leak check. Even within an authorized Fractal Branch scope,\n // importing from a Private Category is forbidden unless the importer is inside the owner Fragment's subtree.\n const privateOwner = getPrivateCategoryOwner(importedDir, config!);\n if (privateOwner) {\n const isPrivateDescendant =\n relPath === privateOwner ||\n relPath.startsWith(privateOwner + '/');\n if (!isPrivateDescendant) {\n context.report({\n message: `Importing from Private Category is forbidden. The imported resource is private to \"${privateOwner}\".`,\n node,\n });\n }\n }\n }\n }\n }\n\n return {\n ExportAllDeclaration(node) {\n checkImport(node, node.source.value as string);\n },\n ExportNamedDeclaration(node) {\n if (node.source) {\n checkImport(node, node.source.value as string);\n }\n },\n ImportDeclaration(node) {\n checkImport(node, node.source.value as string);\n },\n };\n },\n meta: {\n docs: {\n description:\n 'Prevent leakage of Fractal Branch internals outside their owner scope',\n },\n schema: [],\n type: 'problem',\n },\n};\n\nexport default rule;\n","import path from 'path';\n\nimport type { TTreeConfig } from '../../../_types/faf.type.js';\n\nimport { classifyFolder } from '../../_aggregates/classify-folder/index.js';\n\n/**\n * Identifies the owner Fragment/Root Fragment path if the given path is situated inside a Private Category.\n * Traverses up the directory structure.\n *\n * @param relPath - Path to inspect, relative to project root.\n * @param config - Tree configuration.\n * @returns The path of the owning Fragment or null if not inside a Private Category.\n */\nexport function getPrivateCategoryOwner(\n relPath: string,\n config: TTreeConfig\n): null | string {\n let current = relPath;\n while (current && current !== '.' && current !== '/') {\n const parent = path.dirname(current).replace(/\\\\/g, '/');\n if (parent === current) {\n break;\n }\n\n const currentType = classifyFolder(current, config);\n const parentType = classifyFolder(parent, config);\n\n if (\n currentType === 'category' &&\n (parentType === 'fragment' || parentType === 'root-fragment')\n ) {\n return parent;\n }\n\n current = parent;\n }\n return null;\n}\n","import type { Rule } from 'eslint';\n\nimport path from 'path';\n\nimport type {\n TFafSettings,\n TRootFragmentConfig,\n TTreeConfig,\n} from '#_rules@shared/_types/faf.type.js';\n\nimport { classifyFolder } from '#_rules@shared/_utils/_aggregates/classify-folder/index.js';\nimport { resolveImportPath } from '#_rules@shared/_utils/_aggregates/resolve-import-path/index.js';\nimport { findTreeConfigIncludingExcluded } from '#_rules@shared/_utils/_primitives/find-tree-config-including-excluded/index.js';\nimport { getFileRole } from '#_rules@shared/_utils/_primitives/get-file-role/index.js';\nimport { getLcaAndSubBranches } from '#_rules@shared/_utils/_primitives/get-lca-and-sub-branches/index.js';\nimport { getRoleHierarchyIndex } from '#_rules@shared/_utils/_primitives/get-role-hierarchy-index/index.js';\nimport { getRootFragmentConfig } from '#_rules@shared/_utils/_primitives/get-root-fragment-config/index.js';\nimport { readDirCached } from '#_rules@shared/_utils/_primitives/read-dir-cached/index.js';\nimport { resolveHorizontalHierarchy } from '#_rules@shared/_utils/_primitives/resolve-horizontal-hierarchy/index.js';\nimport { toRelativePath } from '#_rules@shared/_utils/_primitives/to-relative-path/index.js';\n\nfunction getDirectoryRole(dirPath: string, config: TTreeConfig): null | string {\n const folderName = path.basename(dirPath);\n if (folderName.startsWith('_')) {\n return getRoleFromFolderName(folderName, config);\n }\n const contents = readDirCached(dirPath);\n for (const file of contents.files) {\n if (file.startsWith(folderName + '.')) {\n const role = getFileRole(file, config);\n if (role) return role;\n }\n }\n return null;\n}\n\nfunction getRoleFromFolderName(\n name: string,\n config: TTreeConfig\n): null | string {\n const catConfig = config.categories?.find((c) => c.name === name);\n return catConfig ? (catConfig.role ?? null) : null;\n}\n\nfunction getRootNodeIndex(\n relPath: string,\n rfConfig: TRootFragmentConfig,\n lcaPath: string\n): number {\n const relToLca = path.relative(lcaPath, relPath).replace(/\\\\/g, '/');\n for (let i = 0; i < rfConfig.rootNodes.length; i++) {\n const group = rfConfig.rootNodes[i];\n if (group && group.includes(relToLca)) {\n return i;\n }\n }\n return -1;\n}\n\n/**\n * Checks if B is inside a Private Category of the LCA directory.\n */\nfunction isInsidePrivateCategoryOfLca(\n relPathB: string,\n lcaPath: string,\n config: TTreeConfig\n): boolean {\n let current = relPathB;\n while (current && current !== '.' && current !== '/' && current !== lcaPath) {\n const parent = path.dirname(current).replace(/\\\\/g, '/');\n if (parent === current) {\n break;\n }\n\n const currentType = classifyFolder(current, config);\n const parentType = classifyFolder(parent, config);\n\n if (\n currentType === 'category' &&\n (parentType === 'fragment' || parentType === 'root-fragment') &&\n parent === lcaPath\n ) {\n return true;\n }\n\n current = parent;\n }\n return false;\n}\n\n/**\n * @fileoverview Rule: faf/no-peer-dependency\n * Enforces the FAF Law of Separation between Peers.\n *\n * FAF Law: Sibling directories and files (at the same filesystem level) must not import each other\n * unless a horizontal hierarchy flow is explicitly configured (via local/global horizontal hierarchies).\n * For files inside a Fragment, peer imports flow according to the index order defined in the `roles` configuration.\n *\n * Valid:\n * - A compound utility importing from a primitive utility (if compounds ➔ primitives is configured).\n * - Sibling Fragment Nodes importing from each other according to the roles scale order (e.g. `util` imports `type`).\n *\n * Invalid:\n * - A primitive utility importing from a compound utility (violating horizontal hierarchy).\n * - Circular imports between sibling folders with no configured hierarchy.\n */\nconst rule: Rule.RuleModule = {\n create(context) {\n const absPath = context.filename;\n const relPath = toRelativePath(absPath);\n const settings = context.settings as { faf?: TFafSettings };\n\n if (!settings.faf) {\n return {};\n }\n\n const config = findTreeConfigIncludingExcluded(relPath, settings.faf);\n if (!config) {\n return {};\n }\n\n const currentDir = path.dirname(relPath);\n const isCurrentFileExcluded =\n config.excludes?.some(\n (exc) => relPath === exc || relPath.startsWith(exc + '/')\n ) ?? false;\n\n function checkImport(node: Rule.Node, importValue: string) {\n const resolvedRelPath = resolveImportPath(\n importValue,\n relPath,\n settings.faf!\n );\n if (!resolvedRelPath) {\n return; // External import\n }\n\n const isImportedFileExcluded =\n config?.excludes?.some(\n (exc) =>\n resolvedRelPath === exc || resolvedRelPath.startsWith(exc + '/')\n ) ?? false;\n\n // Case A (Logical Node ➔ Foreign Domain)\n if (!isCurrentFileExcluded && isImportedFileExcluded) {\n context.report({\n message: `Importing from Foreign Domain \"${resolvedRelPath}\" is forbidden for Logical Nodes.`,\n node,\n });\n return;\n }\n\n // Case B (Foreign Domain ➔ Logical Node)\n if (isCurrentFileExcluded && !isImportedFileExcluded) {\n context.report({\n message: `Foreign Domain files cannot import Logical Nodes from FAF tree (\"${resolvedRelPath}\").`,\n node,\n });\n return;\n }\n\n // If either is excluded, do not run further peer dependency checks\n if (isCurrentFileExcluded || isImportedFileExcluded) {\n return;\n }\n\n const importedDir = path.dirname(resolvedRelPath);\n\n // Scenario 1: Same directory (Fragment Nodes or direct siblings)\n if (currentDir === importedDir) {\n const fileA = path.basename(relPath);\n const fileB = path.basename(resolvedRelPath);\n\n const roleA = getFileRole(fileA, config!);\n const roleB = getFileRole(fileB, config!);\n\n if (roleA && roleB) {\n const idxA = getRoleHierarchyIndex(roleA, config!);\n const idxB = getRoleHierarchyIndex(roleB, config!);\n\n if (idxA !== -1 && idxB !== -1) {\n if (idxB >= idxA) {\n context.report({\n message: `Sibling import violation: \"${fileA}\" (role \"${roleA}\", level ${idxA}) cannot import from \"${fileB}\" (role \"${roleB}\", level ${idxB}). Imports must flow from lower to higher levels.`,\n node,\n });\n }\n }\n }\n return;\n }\n\n // Scenario 2: Different directories\n const lcaInfo = getLcaAndSubBranches(currentDir, importedDir);\n if (!lcaInfo) {\n return;\n }\n\n const { lca, subA, subB } = lcaInfo;\n\n // Exception: Fractal Branch\n if (subB.startsWith('_') && subB.includes('@shared')) {\n // Allowed to import from own Fractal Branch\n return;\n }\n\n // Exception: Private Category of the LCA\n if (isInsidePrivateCategoryOfLca(importedDir, lca, config!)) {\n return;\n }\n\n // Exception: Descendants of a Fragment importing from the Fragment's root\n if (subB === '' && classifyFolder(lca, config!) === 'fragment') {\n return;\n }\n\n // Check if LCA is a Root Fragment and we are importing between Root Nodes\n const rfConfig = getRootFragmentConfig(lca, config!);\n if (rfConfig) {\n const idxRootA = getRootNodeIndex(relPath, rfConfig, lca);\n const idxRootB = getRootNodeIndex(resolvedRelPath, rfConfig, lca);\n\n if (idxRootA !== -1 && idxRootB !== -1) {\n if (idxRootB >= idxRootA) {\n context.report({\n message: `Root Node import violation: \"${path.basename(relPath)}\" cannot import from \"${path.basename(resolvedRelPath)}\" under Root Fragment \"${lca}\".`,\n node,\n });\n }\n return;\n }\n }\n\n // Determine if there is a defined horizontal hierarchy at LCA and whether the import is allowed\n const { allowed, defined: hasDefinedHierarchy } =\n resolveHorizontalHierarchy(lca, subA, subB, config!);\n\n if (hasDefinedHierarchy) {\n if (!allowed) {\n context.report({\n message: `Horizontal hierarchy violation: \"${subA}\" cannot import from \"${subB}\" under parent \"${lca}\".`,\n node,\n });\n }\n } else {\n // Fallback to role-based hierarchy comparison\n const roleA = getDirectoryRole(path.posix.join(lca, subA), config!);\n const roleB = getDirectoryRole(path.posix.join(lca, subB), config!);\n\n const idxA = roleA ? getRoleHierarchyIndex(roleA, config!) : -1;\n const idxB = roleB ? getRoleHierarchyIndex(roleB, config!) : -1;\n\n if (idxA !== -1 && idxB !== -1) {\n if (idxB >= idxA) {\n context.report({\n message: `Horizontal hierarchy violation (fallback to roles): sibling directory \"${subA}\" (mapped to role \"${roleA}\", level ${idxA}) cannot import from \"${subB}\" (mapped to role \"${roleB}\", level ${idxB}) under parent \"${lca}\".`,\n node,\n });\n }\n } else {\n // If no hierarchy is defined and cannot resolve roles, it is forbidden by default\n context.report({\n message: `Peer separation violation: sibling directories \"${subA}\" and \"${subB}\" cannot import each other because no horizontal hierarchy is defined under parent \"${lca}\".`,\n node,\n });\n }\n }\n }\n\n return {\n ExportAllDeclaration(node) {\n checkImport(node, node.source.value as string);\n },\n ExportNamedDeclaration(node) {\n if (node.source) {\n checkImport(node, node.source.value as string);\n }\n },\n ImportDeclaration(node) {\n checkImport(node, node.source.value as string);\n },\n };\n },\n meta: {\n docs: {\n description:\n 'Enforce the Law of Separation between Peers (no-peer-dependency)',\n },\n schema: [],\n type: 'problem',\n },\n};\n\nexport default rule;\n","import { state } from '#_utils@shared/_stores/cache/index.js';\n\nimport type { TFafSettings, TTreeConfig } from '../../../_types/faf.type.js';\n\n/**\n * Finds the tree configuration that includes the given relative file path,\n * even if it is otherwise excluded (Foreign Domain). Uses `state.treeConfigIncludingExcludedCache`\n * for performance.\n *\n * @param relPath - Path relative to the project root.\n * @param settings - The global FAF settings containing trees configuration.\n * @returns The matching tree configuration or null if not found.\n */\nexport function findTreeConfigIncludingExcluded(\n relPath: string,\n settings: TFafSettings\n): null | TTreeConfig {\n if (!settings || !settings.trees) {\n return null;\n }\n\n const cached = state.treeConfigIncludingExcludedCache.get(relPath);\n if (cached !== undefined) {\n return cached;\n }\n\n let result: null | TTreeConfig = null;\n for (const tree of settings.trees) {\n const isIncluded = tree.includes.some(\n (inc) => relPath === inc || relPath.startsWith(inc + '/')\n );\n\n if (isIncluded) {\n result = tree;\n break;\n }\n }\n\n state.treeConfigIncludingExcludedCache.set(relPath, result);\n return result;\n}\n","/**\n * Finds the Lowest Common Ancestor (LCA) path of two given path strings,\n * as well as the immediate child segment of the LCA for each path.\n * Used to identify parent-child relationships and siblings.\n *\n * @param pathA - First path string.\n * @param pathB - Second path string.\n * @returns Object containing the LCA and immediate sub-branches, or null if no common ancestor.\n */\nexport function getLcaAndSubBranches(\n pathA: string,\n pathB: string\n): null | { lca: string; subA: string; subB: string } {\n const partsA = pathA.split('/');\n const partsB = pathB.split('/');\n\n let commonLength = 0;\n while (\n commonLength < partsA.length &&\n commonLength < partsB.length &&\n partsA[commonLength] === partsB[commonLength]\n ) {\n commonLength++;\n }\n\n if (commonLength === 0) {\n return null;\n }\n\n const lca = partsA.slice(0, commonLength).join('/');\n const subA = partsA[commonLength] || '';\n const subB = partsB[commonLength] || '';\n\n return { lca, subA, subB };\n}\n","import type { TTreeConfig } from '../../../_types/faf.type.js';\n\n/**\n * Returns the hierarchy level index of a given role.\n * Roles at lower indexes (earlier in the roles array) represent lower-level/primitive constructs,\n * while higher indexes represent higher-level/composed ones.\n *\n * @param role - Role string to look up.\n * @param config - Tree configuration containing the roles scale.\n * @returns The index of the role group or -1 if the role is not defined.\n */\nexport function getRoleHierarchyIndex(\n role: string,\n config: TTreeConfig\n): number {\n for (let i = 0; i < config.roles.length; i++) {\n const roleGroup = config.roles[i];\n if (roleGroup && roleGroup.includes(role)) {\n return i;\n }\n }\n return -1;\n}\n","import type { TTreeConfig } from '../../../_types/faf.type.js';\n\n/**\n * Resolves the horizontal hierarchy relationship between sub-directories subA and subB at a common ancestor lcaPath.\n * Checks local path-specific hierarchies before falling back to global hierarchies.\n * Returns both whether a hierarchy constraint is defined, and if defined, whether the import is allowed.\n *\n * @param lcaPath - Path of the common parent directory.\n * @param subA - Sibling directory segment of the importer.\n * @param subB - Sibling directory segment of the imported module.\n * @param config - Tree configuration.\n * @returns Object indicating if the hierarchy is defined and if the import is allowed.\n */\nexport function resolveHorizontalHierarchy(\n lcaPath: string,\n subA: string,\n subB: string,\n config: TTreeConfig\n): { allowed: boolean; defined: boolean } {\n // 1. Check local hierarchies first\n const local = config.localHorizontalHierarchies?.find((lh) =>\n lh.paths.includes(lcaPath)\n );\n if (local) {\n const idxA = local.hierarchies.findIndex((group) => group.includes(subA));\n const idxB = local.hierarchies.findIndex((group) => group.includes(subB));\n if (idxA !== -1 && idxB !== -1) {\n return { allowed: idxB < idxA, defined: true };\n }\n }\n\n // 2. Check global hierarchies\n const globalHierarchies = config.globalHorizontalHierarchies || [];\n for (const gh of globalHierarchies) {\n const idxA = gh.findIndex((group) => group.includes(subA));\n const idxB = gh.findIndex((group) => group.includes(subB));\n if (idxA !== -1 && idxB !== -1) {\n return { allowed: idxB < idxA, defined: true };\n }\n }\n\n // No hierarchy defined for this pair — sibling imports forbidden by default\n return { allowed: false, defined: false };\n}\n","import type { Rule } from 'eslint';\n\nimport path from 'path';\n\nimport type { TFafSettings } from '#_rules@shared/_types/faf.type.js';\n\nimport { resolveImportPath } from '#_rules@shared/_utils/_aggregates/resolve-import-path/index.js';\nimport { findTreeConfig } from '#_rules@shared/_utils/_primitives/find-tree-config/index.js';\nimport { toRelativePath } from '#_rules@shared/_utils/_primitives/to-relative-path/index.js';\nimport { getPrivateCategoryOwner } from '#_rules@shared/_utils/_systems/get-private-category-owner/index.js';\n\n/**\n * @fileoverview Rule: faf/no-private-category-leak\n * Enforces the FAF Law of Private Category Encapsulation.\n *\n * FAF Law: Category folders prefixed with `_` nested directly inside a Fragment/Root Fragment\n * are Private Categories containing internal implementation details.\n * Their contents are private to the owning Fragment/Root Fragment subtree and cannot leak or be imported externally.\n *\n * Valid:\n * - Sibling nodes within the owner Fragment importing from the Private Category (e.g. `example/example.component.tsx`\n * importing from `example/_components/child/index.js`).\n *\n * Invalid:\n * - A rule inside `src/_rules/naming-conventions/` importing from `src/_rules/_rules@shared/_utils/_utils@shared/_stores/cache/` (leak).\n */\nconst rule: Rule.RuleModule = {\n create(context) {\n const absPath = context.filename;\n const relPath = toRelativePath(absPath);\n const settings = context.settings as { faf?: TFafSettings };\n\n if (!settings.faf) {\n return {};\n }\n\n const config = findTreeConfig(relPath, settings.faf);\n if (!config) {\n return {};\n }\n\n function checkImport(node: Rule.Node, importValue: string) {\n const resolvedRelPath = resolveImportPath(\n importValue,\n relPath,\n settings.faf!\n );\n if (!resolvedRelPath) {\n return; // External import or unresolved alias\n }\n\n const importedDir = path.dirname(resolvedRelPath);\n const owner = getPrivateCategoryOwner(importedDir, config!);\n\n if (owner) {\n // The importing file must be inside the owner's sub-tree\n const isDescendant =\n relPath === owner || relPath.startsWith(owner + '/');\n if (!isDescendant) {\n context.report({\n message: `Importing from Private Category is forbidden. The imported resource is private to \"${owner}\".`,\n node,\n });\n }\n }\n }\n\n return {\n ExportAllDeclaration(node) {\n checkImport(node, node.source.value as string);\n },\n ExportNamedDeclaration(node) {\n if (node.source) {\n checkImport(node, node.source.value as string);\n }\n },\n ImportDeclaration(node) {\n checkImport(node, node.source.value as string);\n },\n };\n },\n meta: {\n docs: {\n description:\n 'Prevent leakage and unauthorized imports of Private Category internals',\n },\n schema: [],\n type: 'problem',\n },\n};\n\nexport default rule;\n","import categoryMutuallyExclusive from './_rules/category-mutually-exclusive/index.js';\nimport enforceAccessNode from './_rules/enforce-access-node/index.js';\nimport namingConventions from './_rules/naming-conventions/index.js';\nimport noDirectFragmentImport from './_rules/no-direct-fragment-import/index.js';\nimport noFractalBranchLeak from './_rules/no-fractal-branch-leak/index.js';\nimport noPeerDependency from './_rules/no-peer-dependency/index.js';\nimport noPrivateCategoryLeak from './_rules/no-private-category-leak/index.js';\n\n/**\n * Mapping of FAF rule identifiers to their respective ESLint rule modules.\n * All rules are namespaced under 'faf/*' when consumed in configurations.\n */\nexport const rules = {\n 'category-mutually-exclusive': categoryMutuallyExclusive,\n 'enforce-access-node': enforceAccessNode,\n 'naming-conventions': namingConventions,\n 'no-direct-fragment-import': noDirectFragmentImport,\n 'no-fractal-branch-leak': noFractalBranchLeak,\n 'no-peer-dependency': noPeerDependency,\n 'no-private-category-leak': noPrivateCategoryLeak,\n} as const;\n","import type { TFafPlugin } from './types.js';\n\nimport { rules } from './rules.js';\n\n/**\n * Predefined configuration presets exposed by the FAF ESLint plugin.\n * Includes the recommended flat configuration preset that registers the plugin\n * and activates all taxonomy and dependency rules as blocking \"error\" diagnostics.\n */\nexport const configs: TFafPlugin['configs'] = {\n recommended: {\n plugins: {\n faf: {\n rules,\n },\n },\n rules: {\n 'faf/category-mutually-exclusive': 'error',\n 'faf/enforce-access-node': 'error',\n 'faf/naming-conventions': 'error',\n 'faf/no-direct-fragment-import': 'error',\n 'faf/no-fractal-branch-leak': 'error',\n 'faf/no-peer-dependency': 'error',\n 'faf/no-private-category-leak': 'error',\n },\n },\n};\n","import type { TFafPlugin } from './types.js';\n\nimport pkg from '../package.json' with { type: 'json' };\nimport { configs } from './configs.js';\nimport { rules } from './rules.js';\n\nexport { configs } from './configs.js';\nexport { rules } from './rules.js';\n\n/**\n * Default export representing the ESLint plugin for the Fractal Architecture Framework (FAF).\n * Assembles configs, rules, and package metadata.\n *\n * Exposes rules and configs both as named exports (for backward compatibility/direct consumption)\n * and within the default plugin export container.\n */\nconst plugin: TFafPlugin = {\n configs,\n meta: {\n name: '@morriconeluca/eslint-plugin-faf',\n version: pkg.version,\n },\n rules,\n};\n\nexport default plugin;\n"],"mappings":"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","names":["path","path","path","path","path","path","path","path","path","rule","path","path","rule","path","parentType","path","fs","path","path","fs","rule","path","path","path","path","path","rule","path","path","rule","path","rule","path"]}
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@morriconeluca/eslint-plugin-faf",
3
+ "version": "0.1.1",
4
+ "description": "An ESLint plugin for FAF projects.",
5
+ "main": "./dist/main.cjs",
6
+ "module": "./dist/main.js",
7
+ "types": "./dist/main.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/main.d.ts",
11
+ "import": "./dist/main.js",
12
+ "require": "./dist/main.cjs"
13
+ }
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "imports": {
19
+ "#_rules@shared/*": "./src/_rules/_rules@shared/*",
20
+ "#_utils@shared/*": "./src/_rules/_rules@shared/_utils/_utils@shared/*"
21
+ },
22
+ "type": "module",
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "scripts": {
27
+ "build": "npm run lint && tsup",
28
+ "test": "vitest run",
29
+ "dev": "vitest",
30
+ "lint": "npm run lint:types && npm run lint:eslint",
31
+ "lint:eslint": "eslint .",
32
+ "lint:types": "tsc --noEmit",
33
+ "lint:fix": "eslint --fix .",
34
+ "format": "prettier --write .",
35
+ "check-format": "prettier --check .",
36
+ "ci": "npm run build && npm run check-format && npm run test",
37
+ "prepublishOnly": "npm run ci",
38
+ "local-release": "changeset version && changeset publish",
39
+ "prepare": "husky"
40
+ },
41
+ "keywords": [
42
+ "eslint",
43
+ "eslintplugin",
44
+ "faf"
45
+ ],
46
+ "author": "Luca Morricone",
47
+ "license": "MIT",
48
+ "peerDependencies": {
49
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0"
50
+ },
51
+ "devDependencies": {
52
+ "@changesets/cli": "^2.31.0",
53
+ "@commitlint/cli": "^21.0.2",
54
+ "@commitlint/config-conventional": "^21.0.2",
55
+ "@eslint/js": "^10.0.1",
56
+ "@types/eslint": "^9.6.1",
57
+ "@types/node": "^25.9.3",
58
+ "@typescript-eslint/utils": "^8.24.1",
59
+ "dependency-cruiser": "^17.4.3",
60
+ "eslint": "^10.5.0",
61
+ "eslint-import-resolver-typescript": "^4.4.5",
62
+ "eslint-plugin-import-x": "^4.16.2",
63
+ "eslint-plugin-perfectionist": "^5.9.0",
64
+ "husky": "^9.1.7",
65
+ "lint-staged": "^17.0.7",
66
+ "prettier": "^3.8.4",
67
+ "tsup": "^8.3.6",
68
+ "typescript": "^6.0.3",
69
+ "typescript-eslint": "^8.61.0",
70
+ "vitest": "^4.1.9"
71
+ },
72
+ "lint-staged": {
73
+ "*": "prettier --write --ignore-unknown",
74
+ "src/**/*.ts": "eslint --fix"
75
+ }
76
+ }