{"_id":"@boring-stack-pkg/eslint-plugin-resource-architecture","_rev":"3-78d9494a5636679ad20269dae130c2be","name":"@boring-stack-pkg/eslint-plugin-resource-architecture","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.1":{"name":"@boring-stack-pkg/eslint-plugin-resource-architecture","version":"0.1.1","keywords":["eslint","eslintplugin","typescript","architecture","resource","conventions"],"author":"","license":"MIT","_id":"@boring-stack-pkg/eslint-plugin-resource-architecture@0.1.1","maintainers":[{"name":"agjs","email":"hi@aleksandar.xyz"}],"homepage":"https://github.com/agjs/eslint-plugin-resource-architecture#readme","bugs":{"url":"https://github.com/agjs/eslint-plugin-resource-architecture/issues"},"dist":{"shasum":"8abe24aa468b65ad3e474ef11d0a993c9f494c43","tarball":"https://registry.npmjs.org/@boring-stack-pkg/eslint-plugin-resource-architecture/-/eslint-plugin-resource-architecture-0.1.1.tgz","fileCount":16,"integrity":"sha512-qRtLk94fvU8pKHsv8+OM92m5f5EnXEP61So/pVnX6eaB3ZcrdLKJRq+EW2Mz0SQCK88tpLF7OtYmr5kOF4vHnw==","signatures":[{"sig":"MEUCIC/8kxb/0YaqhsmV53T3gv3/l5zalEViJLdAXQHTYDjFAiEAvBBQcLDyTpxj80NzkuLZjVMoG7RTZcLf63PQGUCUvMo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@boring-stack-pkg%2feslint-plugin-resource-architecture@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":72058},"main":"./dist/index.cjs","type":"module","_from":"file:boring-stack-pkg-eslint-plugin-resource-architecture-0.1.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"scripts":{"test":"vitest run","build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"agjs","email":"hi@aleksandar.xyz"},"_resolved":"/tmp/44a09f12df97e504047ed663801ef153/boring-stack-pkg-eslint-plugin-resource-architecture-0.1.1.tgz","_integrity":"sha512-qRtLk94fvU8pKHsv8+OM92m5f5EnXEP61So/pVnX6eaB3ZcrdLKJRq+EW2Mz0SQCK88tpLF7OtYmr5kOF4vHnw==","repository":{"url":"git+https://github.com/AI-Starter-Templates/eslint-plugins.git","type":"git","directory":"eslint-plugin-resource-architecture"},"_npmVersion":"10.9.7","description":"ESLint rules for resource-oriented, concern-suffixed project layouts.","directories":{},"sideEffects":false,"_nodeVersion":"22.22.2","dependencies":{"micromatch":"4.0.5","@typescript-eslint/utils":"8.0.0"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"tsup":"8.0.0","eslint":"9.0.0","vitest":"2.0.0","@eslint/js":"9.0.0","typescript":"6.0.3","@types/node":"22.0.0","@types/micromatch":"4.0.9","@typescript-eslint/parser":"8.0.0","@typescript-eslint/rule-tester":"8.0.0"},"peerDependencies":{"eslint":"8.57.0 || ^9.0.0","typescript":">=5.0.0","@typescript-eslint/parser":">=8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin-resource-architecture_0.1.1_1779219598933_0.8714872407772978","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@boring-stack-pkg/eslint-plugin-resource-architecture","version":"0.1.2","keywords":["eslint","eslintplugin","typescript","architecture","resource","conventions"],"author":"","license":"MIT","_id":"@boring-stack-pkg/eslint-plugin-resource-architecture@0.1.2","maintainers":[{"name":"agjs","email":"hi@aleksandar.xyz"}],"homepage":"https://github.com/agjs/eslint-plugin-resource-architecture#readme","bugs":{"url":"https://github.com/agjs/eslint-plugin-resource-architecture/issues"},"dist":{"shasum":"b56a82e55134617580a2c19f31ed422b4a01c88d","tarball":"https://registry.npmjs.org/@boring-stack-pkg/eslint-plugin-resource-architecture/-/eslint-plugin-resource-architecture-0.1.2.tgz","fileCount":16,"integrity":"sha512-BBPCN5acweexHevTwxaYkbvZt2S8UNc4gG4uDMQ03g8JSkbuL87ghZEMhg1R/D9Oid3OcE3cSm+5h4tk7horhQ==","signatures":[{"sig":"MEYCIQCKeWvEfnYVj3/Upvz7A/DzdQrVpvt9BU3pRrOdxMiRYgIhAIKBDAcAYE04ySelPylyA/Q2THSiNN7i7JCXS1lDLtoS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":72452},"main":"./dist/index.cjs","type":"module","_from":"file:boring-stack-pkg-eslint-plugin-resource-architecture-0.1.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"scripts":{"test":"vitest run","build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"agjs","email":"hi@aleksandar.xyz"},"_resolved":"/tmp/7a2a1a0295259044a002e91640827916/boring-stack-pkg-eslint-plugin-resource-architecture-0.1.2.tgz","_integrity":"sha512-BBPCN5acweexHevTwxaYkbvZt2S8UNc4gG4uDMQ03g8JSkbuL87ghZEMhg1R/D9Oid3OcE3cSm+5h4tk7horhQ==","repository":{"url":"git+https://github.com/boringstack-xyz/eslint-plugins.git","type":"git","directory":"eslint-plugin-resource-architecture"},"_npmVersion":"11.15.0","description":"ESLint rules for resource-oriented, concern-suffixed project layouts.","directories":{},"sideEffects":false,"_nodeVersion":"22.22.3","dependencies":{"micromatch":"4.0.5","@typescript-eslint/utils":"8.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"8.0.0","eslint":"9.0.0","vitest":"2.0.0","@eslint/js":"9.0.0","typescript":"6.0.3","@types/node":"22.0.0","@types/micromatch":"4.0.9","@typescript-eslint/parser":"8.0.0","@typescript-eslint/rule-tester":"8.0.0"},"peerDependencies":{"eslint":"8.57.0 || ^9.0.0","typescript":">=5.0.0","@typescript-eslint/parser":">=8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/eslint-plugin-resource-architecture_0.1.2_1779695645977_0.9152721819610672","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@boring-stack-pkg/eslint-plugin-resource-architecture","version":"0.2.0","description":"ESLint rules for resource-oriented, concern-suffixed project layouts.","type":"module","license":"MIT","author":"","repository":{"type":"git","url":"git+https://github.com/boringstack-xyz/eslint-plugins.git","directory":"eslint-plugin-resource-architecture"},"publishConfig":{"access":"public"},"sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"},"./package.json":"./package.json"},"keywords":["eslint","eslintplugin","typescript","architecture","resource","conventions"],"peerDependencies":{"@typescript-eslint/parser":">=8.0.0","eslint":"^8.57.0 || ^9.0.0 || ^10.0.0","typescript":">=5.0.0"},"dependencies":{"@typescript-eslint/utils":"8.0.0","micromatch":"4.0.5"},"devDependencies":{"@eslint/js":"9.0.0","@types/micromatch":"4.0.9","@types/node":"22.0.0","@typescript-eslint/parser":"8.0.0","@typescript-eslint/rule-tester":"8.0.0","eslint":"9.0.0","tsup":"8.0.0","typescript":"6.0.3","vitest":"2.0.0"},"bugs":{"url":"https://github.com/agjs/eslint-plugin-resource-architecture/issues"},"homepage":"https://github.com/agjs/eslint-plugin-resource-architecture#readme","scripts":{"build":"tsup src/index.ts --format esm,cjs --dts --clean","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest"},"_id":"@boring-stack-pkg/eslint-plugin-resource-architecture@0.2.0","_integrity":"sha512-v7EmVtIaiJwk06H+SwlbtlzLkUPHoFpCtw+LBEFVddFtGimkB0YGkQqgnCJaEKFuGviAI8WQ0TCgxx2z9seYEg==","_resolved":"/tmp/55401e1d2edc15aea49e33efa024e987/boring-stack-pkg-eslint-plugin-resource-architecture-0.2.0.tgz","_from":"file:boring-stack-pkg-eslint-plugin-resource-architecture-0.2.0.tgz","_nodeVersion":"22.22.3","_npmVersion":"11.15.0","dist":{"integrity":"sha512-v7EmVtIaiJwk06H+SwlbtlzLkUPHoFpCtw+LBEFVddFtGimkB0YGkQqgnCJaEKFuGviAI8WQ0TCgxx2z9seYEg==","shasum":"018fcae3f7ab90700a019af2e2198b9e2affa0af","tarball":"https://registry.npmjs.org/@boring-stack-pkg/eslint-plugin-resource-architecture/-/eslint-plugin-resource-architecture-0.2.0.tgz","fileCount":16,"unpackedSize":72414,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEtJU5unmUGiHd4nFqUg2cEUYMzZYm0HqXh1NeN66JOYAiEAx6URdsAU72BJ1F9nwPvN/+5l7VCUXeclZZD5nPT71fA="}]},"_npmUser":{"name":"agjs","email":"hi@aleksandar.xyz"},"directories":{},"maintainers":[{"name":"agjs","email":"hi@aleksandar.xyz"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/eslint-plugin-resource-architecture_0.2.0_1779826111851_0.8731654536135061"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-19T19:39:58.839Z","modified":"2026-05-26T20:08:32.140Z","0.1.1":"2026-05-19T19:39:59.087Z","0.1.2":"2026-05-25T07:54:06.115Z","0.2.0":"2026-05-26T20:08:31.997Z"},"bugs":{"url":"https://github.com/agjs/eslint-plugin-resource-architecture/issues"},"license":"MIT","homepage":"https://github.com/agjs/eslint-plugin-resource-architecture#readme","keywords":["eslint","eslintplugin","typescript","architecture","resource","conventions"],"repository":{"type":"git","url":"git+https://github.com/boringstack-xyz/eslint-plugins.git","directory":"eslint-plugin-resource-architecture"},"description":"ESLint rules for resource-oriented, concern-suffixed project layouts.","maintainers":[{"name":"agjs","email":"hi@aleksandar.xyz"}],"readme":"# eslint-plugin-resource-architecture\n\n[![npm](https://img.shields.io/npm/v/@boring-stack-pkg/eslint-plugin-resource-architecture?logo=npm)](https://www.npmjs.com/package/@boring-stack-pkg/eslint-plugin-resource-architecture) [![source](https://img.shields.io/badge/source-github-blue?logo=github)](https://github.com/boringstack-xyz/eslint-plugins/tree/main/eslint-plugin-resource-architecture)\n\nESLint rules for **resource-oriented** APIs: concern-suffixed files under `src/api/<resource>/`, import boundaries between concerns, and a few filesystem-backed conventions (noop providers).\n\n## Why\n\nThe same layout rules are usually copy-pasted into `no-restricted-imports`, filename conventions, and one-off scripts. This plugin encodes the **resource + concern** pattern once so new files either match the architecture or fail lint — without relying on humans to remember which suffix may import what.\n\n## Install\n\n```sh\npnpm add -D @boring-stack-pkg/eslint-plugin-resource-architecture @typescript-eslint/parser\n```\n\n## Flat config\n\n**Shortcut** (recommended preset only; add your own `files` / `languageOptions` as needed):\n\n```js\nimport tsParser from \"@typescript-eslint/parser\";\nimport resourceArchitecture from \"@boring-stack-pkg/eslint-plugin-resource-architecture\";\n\nexport default [\n  {\n    files: [\"**/*.{ts,tsx}\"],\n    languageOptions: {\n      parser: tsParser,\n      parserOptions: {\n        ecmaVersion: \"latest\",\n        sourceType: \"module\",\n        ecmaFeatures: { jsx: true },\n      },\n    },\n    ...resourceArchitecture.configs.recommended,\n  },\n];\n```\n\n**Explicit** (same as [eslint-plugin-elysia](https://github.com/agjs/eslint-plugin-elysia) / [eslint-plugin-drizzle-conventions](https://github.com/agjs/eslint-plugin-drizzle-conventions)):\n\n```js\nimport tsParser from \"@typescript-eslint/parser\";\nimport resourceArchitecture from \"@boring-stack-pkg/eslint-plugin-resource-architecture\";\n\nexport default [\n  {\n    files: [\"**/*.{ts,tsx}\"],\n    languageOptions: {\n      parser: tsParser,\n      parserOptions: {\n        ecmaVersion: \"latest\",\n        sourceType: \"module\",\n        ecmaFeatures: { jsx: true },\n      },\n    },\n    plugins: { \"resource-architecture\": resourceArchitecture },\n    rules: resourceArchitecture.configs.recommended.rules,\n  },\n];\n```\n\nThe recommended preset enables all five rules at `\"error\"`. Override individual rules as needed.\n\n## Rules\n\n| Rule                                                                                                                                  | Description                                                                         |\n| ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |\n| [files-must-be-resource-prefixed](https://github.com/boringstack-xyz/eslint-plugins/tree/main/eslint-plugin-resource-architecture)    | Under `src/api/<resource>/`, concern files must be named `<resource>.<concern>.ts`. |\n| [service-must-export-singleton](https://github.com/boringstack-xyz/eslint-plugins/tree/main/eslint-plugin-resource-architecture)      | `*.service.ts` must export a class and a singleton instance.                        |\n| [pluggable-providers-must-have-noop](https://github.com/boringstack-xyz/eslint-plugins/tree/main/eslint-plugin-resource-architecture) | `src/lib/.../providers/` must include a `noop.ts` sibling.                          |\n| [concern-import-boundaries](https://github.com/boringstack-xyz/eslint-plugins/tree/main/eslint-plugin-resource-architecture)          | Concern-specific import restrictions (`*.schemas.ts`, `*.types.ts`, etc.).          |\n| [no-cross-resource-internal-imports](https://github.com/boringstack-xyz/eslint-plugins/tree/main/eslint-plugin-resource-architecture) | Cross-resource imports must target public surface files only.                       |\n\n## Design notes\n\n- **Paths**: Rules use project-relative paths where possible so [RuleTester](https://typescript-eslint.io/packages/rule-tester/) filenames behave like real repo paths.\n- **Filesystem**: `pluggable-providers-must-have-noop` reads the directory on disk; tests inject an FS adapter. In CI, the real filesystem applies.\n- **Import resolution**: `no-cross-resource-internal-imports` resolves extensionless relative imports to `*.ts` deterministically (no dependency on OS module resolution in the linter).\n\n## Development\n\n```sh\npnpm install\npnpm test\npnpm run typecheck\npnpm run build\n```\n\n## Release\n\nTag a `v*` version and push the tag — [`.github/workflows/release.yml`](.github/workflows/release.yml) publishes with `NPM_TOKEN` (same pattern as [eslint-plugin-module-boundaries](https://github.com/agjs/eslint-plugin-module-boundaries)).\n\n## License\n\nMIT.\n","readmeFilename":"README.md"}