{"id":32286089,"url":"https://github.com/evandersondev/arch_dart","last_synced_at":"2026-02-23T10:35:37.000Z","repository":{"id":303704281,"uuid":"1016393240","full_name":"evandersondev/arch_dart","owner":"evandersondev","description":"🎯 Dart/Flutter Architectural Testing Framework inspired by ArchUnit for Java. ","archived":false,"fork":false,"pushed_at":"2025-10-16T14:52:59.000Z","size":205,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-23T01:56:07.046Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/arch_dart","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/evandersondev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-09T00:32:38.000Z","updated_at":"2025-10-16T15:05:33.000Z","dependencies_parsed_at":"2025-07-09T01:58:20.910Z","dependency_job_id":"4dd8883d-d38a-407d-8668-bcd2c8f7c631","html_url":"https://github.com/evandersondev/arch_dart","commit_stats":null,"previous_names":["evandersondev/arch_dart"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/evandersondev/arch_dart","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evandersondev%2Farch_dart","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evandersondev%2Farch_dart/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evandersondev%2Farch_dart/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evandersondev%2Farch_dart/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/evandersondev","download_url":"https://codeload.github.com/evandersondev/arch_dart/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/evandersondev%2Farch_dart/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29741155,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T07:44:07.782Z","status":"ssl_error","status_checked_at":"2026-02-23T07:44:07.432Z","response_time":90,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-10-23T01:56:05.876Z","updated_at":"2026-02-23T10:35:36.980Z","avatar_url":"https://github.com/evandersondev.png","language":"Dart","funding_links":["https://buymeacoffee.com/evandersondev"],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/logo.png\" width=\"200px\" align=\"center\" alt=\"Darto logo\" /\u003e\n  \u003ch1 align=\"center\"\u003eArchDart\u003c/h1\u003e\n  \u003cbr\u003e\n  \u003cp align=\"center\"\u003e\n  \u003c!-- \u003ca href=\"https://darto-docs.vercel.app/\"\u003e🐶 Oficial Darto Documentation\u003c/a\u003e --\u003e\n  \u003cbr/\u003e\n    Dart/Flutter Architectural Testing Framework inspired by ArchUnit for Java. \n  \u003c/p\u003e\n\u003c/p\u003e\n\n\u003cbr/\u003e\n\n### Support 💖\n\nIf you find ArchDart useful, please consider supporting its development 🌟[Buy Me a Coffee](https://buymeacoffee.com/evandersondev).🌟 Your support helps us improve the framework and make it even better!\n\n\u003cbr\u003e\n\u003cbr\u003e\n\n**Note**: Some rules in ArchDart have not been thoroughly tested and may contain potential errors. Please report any issues or unexpected behavior to the project repository for further investigation and improvement.\n\nArchDart is a Dart and Flutter package inspired by Java's ArchUnit, designed to enforce architectural rules in your projects. It provides a fluent, expressive API to validate the structure, naming conventions, dependencies, and other architectural aspects of your Dart/Flutter codebase. ArchDart helps ensure that your project adheres to clean architecture principles, domain-driven design, or custom architectural patterns.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n- [Selectors](#selectors)\n- [Scopes](#scopes)\n- [Filters](#filters)\n- [Assertions](#assertions)\n  - [Modifiers and Types](#modifiers-and-types)\n  - [Inheritance and Implementation](#inheritance-and-implementation)\n  - [Structure, Naming, and Constructors](#structure-naming-and-constructors)\n  - [Dependencies and Layers](#dependencies-and-layers)\n  - [File Content](#file-content)\n- [Negations](#negations)\n- [Utilities](#utilities)\n- [Examples](#examples)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Installation\n\nAdd ArchDart to your project by including it in your `pubspec.yaml`:\n\n```yaml\ndev_dependencies:\n  arch_dart: ^[latest-version]\n```\n\nRun `flutter pub get` to install the package.\n\n## Usage\n\nArchDart provides a fluent API to define architectural rules and validate them against your Dart/Flutter codebase. Rules are defined using selectors, scopes, filters, and assertions, and are executed using the `check` method. The package integrates with `flutter_test` for writing test cases.\n\nHere’s a basic example:\n\n```dart\nimport 'package:arch_dart/arch_dart.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\nvoid main() {\n  test('Repositories should end with Repository', () async {\n    await classes()\n        .inFolder('infra/repositories')\n        .shouldHaveNameEndingWith('Repository')\n        .check();\n  });\n}\n```\n\n## Selectors\n\nSelectors define the type of elements to validate:\n\n| Selector      | Description                     |\n| ------------- | ------------------------------- |\n| `classes()`   | Selects all classes             |\n| `enums()`     | Selects all enums               |\n| `methods()`   | Selects all methods             |\n| `functions()` | Selects all top-level functions |\n| `features()`  | Selects feature directories     |\n\n## Scopes\n\nScopes narrow down the elements to a specific location in the project:\n\n| Method                | Description                                      |\n| --------------------- | ------------------------------------------------ |\n| `inPackage('name')`   | Logical package (e.g., `controller`, `service`)  |\n| `inFolder('path')`    | Directory path in the project (e.g., `lib/core`) |\n| `inDirectory('path')` | Alias for `inFolder`                             |\n| `inFile('file.dart')` | Specific Dart file                               |\n\n## Filters\n\nFilters select a subset of elements based on specific criteria:\n\n| Method                         | Description                              |\n| ------------------------------ | ---------------------------------------- |\n| `withNameEndingWith('suffix')` | Names ending with the specified suffix   |\n| `withNameContaining('text')`   | Names containing the specified text      |\n| `withAnnotation('name')`       | Elements with the specified annotation   |\n| `withLineCountGreaterThan(n)`  | Classes with more than `n` lines of code |\n| `withValueCountGreaterThan(n)` | Enums with more than `n` values          |\n\n## Assertions\n\nAssertions define the rules that elements must satisfy. They are prefixed with `should...`.\n\n### Modifiers and Types\n\n| Method                       | Description                   |\n| ---------------------------- | ----------------------------- |\n| `shouldBePublic()`           | Must be public                |\n| `shouldBePrivate()`          | Must be private               |\n| `shouldBeFinal()`            | Must be `final`               |\n| `shouldBeAbstract()`         | Must be `abstract`            |\n| `shouldBeSealed()`           | Must be `sealed`              |\n| `shouldBeBase()`             | Must be `base`                |\n| `shouldBeMixin()`            | Must be a `mixin`             |\n| `shouldBeEnum()`             | Must be an `enum`             |\n| `shouldBeRecord()`           | Must be a `record`            |\n| `shouldBeAnnotatedWith('X')` | Must have the `@X` annotation |\n\n### Inheritance and Implementation\n\n| Method                         | Description                                  |\n| ------------------------------ | -------------------------------------------- |\n| `shouldExtend('SuperClass')`   | Must extend the specified class              |\n| `shouldExtendAnyOf([...])`     | Must extend one of the specified classes     |\n| `shouldImplement('Interface')` | Must implement the specified interface       |\n| `shouldImplementOnly([...])`   | Must implement only the specified interfaces |\n\n### Structure, Naming, and Constructors\n\n| Method                                | Description                                                      |\n| ------------------------------------- | ---------------------------------------------------------------- |\n| `shouldHaveNameEndingWith('X')`       | Name must end with `X`                                           |\n| `shouldHaveOnlyPrivateConstructors()` | All constructors must be private                                 |\n| `shouldRequireAllParams()`            | Constructors must have all required parameters                   |\n| `shouldHaveOnlyNamedRequiredParams()` | Constructors must have only named required parameters            |\n| `shouldHaveMethodThat()`              | Methods must satisfy specific criteria (e.g., name, return type) |\n\n### Dependencies and Layers\n\n| Method                          | Description                                    |\n| ------------------------------- | ---------------------------------------------- |\n| `shouldOnlyDependOn([...])`     | Can only depend on the specified packages      |\n| `shouldOnlyBeAccessedBy([...])` | Can only be accessed by the specified packages |\n| `shouldBeInPackage('X')`        | Must reside in the specified package           |\n| `shouldBeInAnyPackage([...])`   | Must reside in one of the specified packages   |\n| `shouldBeInFolder('path')`      | Must reside in the specified folder            |\n| `shouldNotHaveImports([...])`   | Must not import the specified packages         |\n| `shouldNotBeImportedIn('file')` | Must not be imported in the specified file     |\n| `shouldBeIndependent()`         | Features must not reference each other         |\n\n### File Content\n\n| Method                          | Description                                     |\n| ------------------------------- | ----------------------------------------------- |\n| `shouldContain('text')`         | File must contain the specified text            |\n| `shouldNotBeExportedIn('file')` | File must not be exported in the specified file |\n\n## Negations\n\nNegations are assertions prefixed with `shouldNot...` to ensure elements do not meet certain criteria:\n\n| Method                              | Description                                |\n| ----------------------------------- | ------------------------------------------ |\n| `shouldNotBe(type)`                 | Must not be of the specified type/modifier |\n| `shouldNotDependOn('package')`      | Must not depend on the specified package   |\n| `shouldNotAccessPackage('package')` | Must not access the specified package      |\n| `shouldNotHaveImports([...])`       | Must not import the specified packages     |\n| `shouldNotContain('text')`          | File must not contain the specified text   |\n| `shouldNotBeExportedIn('file')`     | Must not be exported in the specified file |\n\n## Utilities\n\nUtilities help control rule execution and chaining:\n\n| Method         | Description                                               |\n| -------------- | --------------------------------------------------------- |\n| `check()`      | Executes the rule validation                              |\n| `andAlso()`    | Chains multiple rules with AND logic                      |\n| `orElse()`     | Chains multiple rules with OR logic                       |\n| `shouldFail()` | Marks the rule as expected to fail (for negative testing) |\n\n## Examples\n\nBelow are example test cases demonstrating common use cases for ArchDart:\n\n### Enforcing Naming Conventions\n\nEnsure all enums in `lib/core/enums` have a `stringToEnum` method and end with `Enum`:\n\n```dart\ntest('All enums should have stringToEnum method', () async {\n  await enums()\n      .inFolder('lib/core/enums')\n      .shouldHaveMethodThat()\n      .hasMethodNamed('stringToEnum')\n      .andAlso()\n      .shouldHaveNameEndingWith('Enum')\n      .check();\n});\n```\n\n### Enforcing Layer Dependencies\n\nEnsure classes in the `presentation` package do not depend on `infra`:\n\n```dart\ntest('Presentation should not access Infra', () async {\n  await classes()\n      .inPackage('presentation')\n      .shouldNotDependOn('infra')\n      .check();\n});\n```\n\n### Enforcing Clean Architecture\n\nEnsure use cases in `domain/usecases` have an `execute` method:\n\n```dart\ntest('UseCases should have an execute method', () async {\n  await classes()\n      .inFolder('domain/usecases')\n      .shouldHaveMethodThat()\n      .hasMethodNamed('execute')\n      .check();\n});\n```\n\n### Enforcing Feature Isolation\n\nEnsure features are independent of each other:\n\n```dart\ntest('Features should not reference each other', () async {\n  await features()\n      .shouldBeIndependent()\n      .check();\n});\n```\n\n### Enforcing Constructor Rules\n\nEnsure entities in `domain/entities` use only named required parameters:\n\n```dart\ntest('Entities should have all required named parameters', () async {\n  await classes()\n      .inFolder('domain/entities')\n      .shouldHaveOnlyNamedRequiredParams()\n      .check();\n});\n```\n\n### Enforcing Layer Structure\n\nEnsure the project follows the expected layer structure:\n\n```dart\ntest('Layers should follow the expected structure', () async {\n  await layers(['presentation', 'domain', 'infra', 'core'])\n      .onlyStructure()\n      .allowMissingLayers()\n      .check();\n});\n```\n\n### Use `ArchRule` Type\n\nUse the `ArchRule` type to define custom rules:\n\n```dart\ntest('Custom rule example', () async {\n  ArchRule rule = classes()\n    .inPackage('presentation')\n    .shouldNotDependOn('infra');\n\n  await rule.check();\n});\n```\n\n## Contributing\n\nContributions to ArchDart are welcome! Please submit issues or pull requests to the project repository. When contributing, ensure that:\n\n- New rules are thoroughly tested.\n- Documentation is updated to reflect new features.\n- Code follows Dart best practices and includes appropriate comments.\n\n## License\n\nArchDart is licensed under the [MIT License](LICENSE). See the LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevandersondev%2Farch_dart","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fevandersondev%2Farch_dart","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fevandersondev%2Farch_dart/lists"}