{"id":47623517,"url":"https://github.com/aim4code/nanoserviceflow","last_synced_at":"2026-04-01T22:30:20.835Z","repository":{"id":343359957,"uuid":"1177323125","full_name":"aim4code/nanoserviceflow","owner":"aim4code","description":"A lightweight, Zustand-inspired, true zero-dependency state management and event-driven architecture for modern Unity.","archived":false,"fork":false,"pushed_at":"2026-03-30T22:03:58.000Z","size":853,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-31T00:14:11.675Z","etag":null,"topics":["csharp","event-driven","reactive-programming","redux","state-management","unity","unity-package","unity3d","zero-dependency","zustand"],"latest_commit_sha":null,"homepage":"","language":"C#","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/aim4code.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","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":"2026-03-09T23:16:59.000Z","updated_at":"2026-03-27T18:40:18.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/aim4code/nanoserviceflow","commit_stats":null,"previous_names":["aim4code/nanor3dux","aim4code/nanoserviceflow"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/aim4code/nanoserviceflow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aim4code%2Fnanoserviceflow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aim4code%2Fnanoserviceflow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aim4code%2Fnanoserviceflow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aim4code%2Fnanoserviceflow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aim4code","download_url":"https://codeload.github.com/aim4code/nanoserviceflow/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aim4code%2Fnanoserviceflow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"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":["csharp","event-driven","reactive-programming","redux","state-management","unity","unity-package","unity3d","zero-dependency","zustand"],"created_at":"2026-04-01T22:30:18.822Z","updated_at":"2026-04-01T22:30:20.819Z","avatar_url":"https://github.com/aim4code.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\"Documentation~\\images\\Logo.png\" width=\"600\"\u003e\n\n# NanoServiceFlow\n\n[![Test](https://github.com/aim4code/nanoserviceflow/actions/workflows/test.yml/badge.svg)](https://github.com/aim4code/nanoserviceflow/actions)\n[![openupm](https://img.shields.io/npm/v/com.aim4code.nanoserviceflow?label=openupm\u0026registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.aim4code.nanoserviceflow/)\n![](https://img.shields.io/badge/Unity-2022.3+-57b9d3.svg?style=flat\u0026logo=unity)\n![last-commit](https://img.shields.io/github/last-commit/aim4code/nanoserviceflow)\n![open-issues](https://img.shields.io/github/issues/aim4code/nanoserviceflow)\n\n\u003e **A lightweight, Zustand-inspired, true zero-dependency state management and event-driven architecture for modern Unity.**\n\nNanoServiceFlow is a micro-framework designed to bring the predictability of Redux and the pragmatic, modular state slices of Zustand into Unity without the massive boilerplate. Built entirely on modern C# (C# 9.0 compliant), it provides a blazing-fast, GC-friendly state management solution with absolutely zero external dependencies, ready for enterprise Unity LTS versions.\n\n\u003e [!NOTE]\n\u003e **A Note on C# Compatibility:** While NanoServiceFlow is designed for modern Unity, the codebase is currently strictly **C# 9.0 compliant**. This is a deliberate choice for developer experience (DX). Currently, Unity's `.csproj` generation pipeline (particularly for isolated test assemblies) still defaults to C# 9.0, which causes IDE errors for users trying to use modern syntax out-of-the-box. Once Unity's project generation fully and natively supports the C# 12 pipeline across all contexts without requiring custom compiler overrides, this framework will be updated to leverage cleaner modern features like C# 10 `record struct` and C# 12 primary constructors.\n\n## Key Features\n\n* **Zustand / Redux Inspired:** State is read-only and mutated exclusively by dispatching `Actions`. No massive global store—state is sliced into domain-specific modules.\n* **Zero-Allocation Reactivity:** Includes a custom, GC-free `ReactiveProperty\u003cT\u003e` built specifically for high-performance Unity games. No need for heavy Rx libraries.\n* **Service-Oriented CQRS:** Cleanly separate your data (State) from your logic (Services).\n* **Agnostic Asynchronous Side-Effects:** Safely handle asynchronous logic using your preferred method. The framework routes actions perfectly whether you use standard .NET `Task`, Unity Coroutines, or highly-optimized third-party libraries like `UniTask`.\n* **Zero Boilerplate DI:** Features a lightweight, interface-driven Dependency Injection container that resolves services and wires up Reducers automatically via reflection caching.\n\n## Installation\n\n### Option 1: Install via OpenUPM (Recommended)\n\nThe package is available on the [OpenUPM](https://openupm.com/) registry. The easiest way to install it is via the `openupm-cli`:\n\n```bash\nopenupm add com.aim4code.nanoserviceflow\n```\n\nAlternatively, you can manually add the scoped registry to your `Packages/manifest.json`:\n\n```json\n\"scopedRegistries\": [\n  {\n    \"name\": \"package.openupm.com\",\n    \"url\": \"https://package.openupm.com\",\n    \"scopes\": [\n      \"com.aim4code\"\n    ]\n  }\n],\n\"dependencies\": {\n  \"com.aim4code.nanoserviceflow\": \"0.2.1\"\n}\n```\n\n### Option 2: Install via Git URL\n\nYou can also install the package directly from GitHub. Add the following dependency to your `Packages/manifest.json`:\n\n```json\n\"dependencies\": {\n  \"com.aim4code.nanoserviceflow\": \"https://github.com/aim4code/nanoserviceflow.git#v0.2.1\"\n}\n```\n\n\u003e [!IMPORTANT]\n\u003e **Version Determinism:** Notice the `#v0.2.1` at the end of the URL. If you omit the version tag, Unity will resolve the dependency using the latest commit on the default branch at the time of checkout. As the branch updates, this can lead to team members having different versions of the package installed, breaking version determinism. Always lock your Git dependencies to a specific release tag.\n\u003e\n\u003e *See Unity's official documentation on [Targeting a specific revision](https://docs.unity3d.com/Manual/upm-git.html#revision) for more details.*\n\n## Quick Start\n\n### 1. Define Pure Data (State) \u0026 Actions\n\nUse the built-in `ReactiveProperty` for state, and standard C# structs for immutable, zero-allocation actions.\n\n```csharp\nusing Aim4code.NanoServiceFlow;\n\npublic class PlayerState {\n    public ReactiveProperty\u003cint\u003e Health { get; } = new(100);\n}\n\npublic readonly struct DamageAction : IAction {\n    public readonly int Amount;\n    public DamageAction(int amount) =\u003e Amount = amount;\n}\n\npublic readonly struct HealSequenceAction : IAction {}\n```\n\n### 2. Create a Service (Logic)\n\nServices handle both synchronous state mutations (`[Reducer]`) and asynchronous side-effects (`[SideEffect]`).\n\n```csharp\nusing System.Threading.Tasks;\nusing Aim4code.NanoServiceFlow;\n\npublic class PlayerService : IInitializable {\n    \n    private readonly PlayerState _state;\n\n    public PlayerService(PlayerState state) {\n        _state = state;\n    }\n\n    public void Initialize() {\n        // Optional: Run setup logic during Phase 2 Boot\n    }\n\n    [Reducer]\n    public void OnDamage(DamageAction action) {\n        _state.Health.Value -= action.Amount;\n    }\n\n    // Note: The framework is async-agnostic. Standard Tasks are used here, \n    // but libraries like Cysharp's UniTask are highly recommended for production!\n    [SideEffect]\n    public async Task PlayHealSequenceAsync(HealSequenceAction action) {\n        await Task.Delay(1000); // Non-blocking async flow\n        \n        // Re-use Reducer logic via the Locator\n        ServiceLocator.Dispatch(new DamageAction(-50)); \n    }\n}\n```\n\n### 3. Bootstrap the Architecture\n\nRegister your states, resolve your services, and start the engine.\n\n```csharp\nusing UnityEngine;\nusing Aim4code.NanoServiceFlow;\n\npublic class GameBootstrapper : MonoBehaviour {\n    void Awake() {\n        // 1. Build the Data Graph (State Slices)\n        ServiceLocator.RegisterState(new PlayerState());\n        \n        // 2. Resolve Services (State is injected automatically)\n        ServiceLocator.RegisterService\u003cPlayerService\u003e();\n        \n        // 3. Start the Engine\n        ServiceLocator.InitializeAll();\n    }\n}\n```\n\n### 4. Bind to the View (Unity UI)\n\nViews only query the State and dispatch Actions. They never know about the Services.\n\n```csharp\nusing System;\nusing UnityEngine;\nusing UnityEngine.UI;\nusing Aim4code.NanoServiceFlow;\n\npublic class PlayerView : MonoBehaviour {\n    [SerializeField] private Text _healthText;\n    private IDisposable _healthSub;\n\n    void Start() {\n        var state = ServiceLocator.Get\u003cPlayerState\u003e();\n\n        // Bind UI to state\n        _healthSub = state.Health.Subscribe(hp =\u003e _healthText.text = $\"HP: {hp}\");\n    }\n\n    public void OnDamageButtonClicked() {\n        ServiceLocator.Dispatch(new DamageAction(10));\n    }\n\n    void OnDestroy() {\n        _healthSub?.Dispose(); // Clean up subscription\n    }\n}\n```\n\n### 5. Middleware Pipeline (Optional)\n\nNanoServiceFlow supports a robust middleware pipeline, allowing you to intercept actions globally before they reach your Reducers or Side Effects. This is perfect for logging, analytics, or action filtering.\n\nFirst, implement the `IMiddleware` interface:\n\n```csharp\nusing System;\nusing UnityEngine;\nusing Aim4code.NanoServiceFlow;\n\npublic class LoggingMiddleware : IMiddleware \n{\n    public void Invoke(IAction action, Action\u003cIAction\u003e next) \n    {\n        Debug.Log($\"[Dispatcher] Action Started: {action.GetType().Name}\");\n        \n        // Pass the action to the next middleware, or to the handlers if this is the last one\n        next(action); \n        \n        Debug.Log($\"[Dispatcher] Action Finished: {action.GetType().Name}\");\n    }\n}\n```\n\nThen, register it to the `ServiceLocator` during your boot phase. Middlewares are executed in the exact order they are added.\n\n```csharp\nServiceLocator.AddMiddleware(new LoggingMiddleware());\n```\n\n## Architectural Philosophy\n\nNanoServiceFlow diverges from traditional Redux by embracing **Composition over Inheritance**. Instead of a single global store, state is segregated into modular classes. The `ServiceLocator` acts as a **Mediator**, intercepting dispatched actions and routing them to the correct `[Reducer]` or `[SideEffect]`. This ensures high testability, true decoupling, and an architecture that scales cleanly as your codebase grows.\n\n## License\n\nMIT License. See `LICENSE.md` for more information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faim4code%2Fnanoserviceflow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faim4code%2Fnanoserviceflow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faim4code%2Fnanoserviceflow/lists"}