{"id":24598450,"url":"https://github.com/technobre/powerutils.results","last_synced_at":"2025-04-30T15:48:19.857Z","repository":{"id":58740912,"uuid":"532474576","full_name":"TechNobre/PowerUtils.Results","owner":"TechNobre","description":"Wrapper to transfer results or errors between layers or resources","archived":false,"fork":false,"pushed_at":"2024-05-22T18:23:47.000Z","size":2071,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-05-22T19:39:51.516Z","etag":null,"topics":["aspnetcore","csharp","dotnet","dto","result"],"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/TechNobre.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-04T07:56:50.000Z","updated_at":"2024-05-28T01:46:28.744Z","dependencies_parsed_at":"2023-02-16T22:46:00.256Z","dependency_job_id":"987de829-f29e-4dae-8491-8bd86606f7ff","html_url":"https://github.com/TechNobre/PowerUtils.Results","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TechNobre%2FPowerUtils.Results","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TechNobre%2FPowerUtils.Results/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TechNobre%2FPowerUtils.Results/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TechNobre%2FPowerUtils.Results/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TechNobre","download_url":"https://codeload.github.com/TechNobre/PowerUtils.Results/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":235434491,"owners_count":18989606,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["aspnetcore","csharp","dotnet","dto","result"],"created_at":"2025-01-24T12:16:26.270Z","updated_at":"2025-01-24T12:16:26.996Z","avatar_url":"https://github.com/TechNobre.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PowerUtils.Results\n\n![Logo](https://raw.githubusercontent.com/TechNobre/PowerUtils.Results/main/assets/logo/logo_128x128.png)\n\n***Wrapper to transfer results or errors between layers or resources***\n\n![Tests](https://github.com/TechNobre/PowerUtils.Results/actions/workflows/tests.yml/badge.svg)\n[![Mutation tests](https://img.shields.io/endpoint?style=flat\u0026url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2FTechNobre%2FPowerUtils.Results%2Fmain)](https://dashboard.stryker-mutator.io/reports/github.com/TechNobre/PowerUtils.Results/main)\n\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=TechNobre_PowerUtils.Results\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=TechNobre_PowerUtils.Results)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=TechNobre_PowerUtils.Results\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=TechNobre_PowerUtils.Results)\n[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=TechNobre_PowerUtils.Results\u0026metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=TechNobre_PowerUtils.Results)\n[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=TechNobre_PowerUtils.Results\u0026metric=bugs)](https://sonarcloud.io/summary/new_code?id=TechNobre_PowerUtils.Results)\n\n[![NuGet](https://img.shields.io/nuget/v/PowerUtils.Results.svg)](https://www.nuget.org/packages/PowerUtils.Results)\n[![Nuget](https://img.shields.io/nuget/dt/PowerUtils.Results.svg)](https://www.nuget.org/packages/PowerUtils.Results)\n[![License: MIT](https://img.shields.io/github/license/TechNobre/PowerUtils.Results.svg)](https://github.com/TechNobre/PowerUtils.Results/blob/main/LICENSE)\n\n\n- [Support to](#support-to)\n- [How to use](#how-to-use)\n  - [Install NuGet package](#install-nuget-package)\n  - [Creating a Result](#creating-a-result)\n    - [Success](#success)\n    - [Errors](#errors)\n      - [Add more errors](#add-more-errors)\n      - [Built-in error types](#built-in-error-types)\n      - [Custom error](#custom-error)\n    - [Result factory](#result-factory)\n  - [Extensions](#extensions)\n    - [Handling errors](#handling-errors)\n    - [OfTypeFirstError](#oftypefirsterror)\n    - [Handling success](#handling-success)\n    - [Switch](#switch)\n    - [Match](#match)\n    - [Conversions](#conversions)\n    - [DistinctErrors](#distincterrors)\n  - [Deconstruct operators](#deconstruct-operators)\n  - [Implicit conversion](#implicit-conversion)\n  - [Check validity](#check-validity)\n  - [Serialization/Deserialization](#serializationdeserialization)\n    - [Results](#results)\n    - [Errors](#errors-1)\n- [Contribution](#contribution)\n\n\n\n## Support to\n- .NET 9.0\n- .NET 8.0\n- .NET 7.0\n- .NET 6.0\n- .NET 5.0\n\n\n## How to use\n\n### Install NuGet package\nThis package is available through Nuget Packages: https://www.nuget.org/packages/PowerUtils.Results\n\n**Nuget**\n```bash\nInstall-Package PowerUtils.Results\n```\n\n**.NET CLI**\n```\ndotnet add package PowerUtils.Results\n```\n\n\n\n### Creating a Result\n\n#### Success\n```csharp\n// Void result\nvar result = Result.Ok();\nvar result = Result.Success();\n\n// Result with typed value\nvar model = new Model();\nvar result = Result\u003cModel\u003e.Ok(model);\nvar result = Result.Ok\u003cModel\u003e(model);\nvar result = Result.Ok(model);\nvar result = Result.Success(model);\n\n// Implicit assignment\nResult\u003cModel\u003e result = model;\nResult result = new Success();\n```\n\n#### Errors\n\n\n```csharp\nResult result = Error.Failure(\"property\", \"code\", \"description\");\nResult result = Error.Unauthorized(\"property\", \"code\", \"description\");\nResult result = Error.Forbidden(\"property\", \"code\", \"description\");\nResult result = Error.NotFound(\"property\", \"code\", \"description\");\nResult result = Error.Conflict(\"property\", \"code\", \"description\");\nResult result = Error.Validation(\"property\", \"code\", \"description\");\nResult result = Error.Unexpected(\"property\", \"code\", \"description\");\n\n// Implicit assignment\nResult result = new Error(\"property\", \"code\", \"description\");\nResult result = new UnauthorizedError(\"property\", \"code\", \"description\");\nResult result = new ForbiddenError(\"property\", \"code\", \"description\");\nResult result = new NotFoundError(\"property\", \"code\", \"description\");\nResult result = new ConflictError(\"property\", \"code\", \"description\");\nResult result = new ValidationError(\"property\", \"code\", \"description\");\nResult result = new UnexpectedError(\"property\", \"code\", \"description\");\n\n// Error list\nvar errors = new List\u003cError\u003e\n{\n    new Error(\"property\", \"code\", \"description2\"),\n    new Error(\"property\", \"code\", \"description2\")\n};\n\nResult result = errors;\n```\n\n##### Add more errors\n\n```csharp\nResult result = new Error(\"property\", \"code\", \"description\");\n\nresult.AddError(new Error(\"property\", \"code\", \"description\"));\nresult.AddError(\"property\", \"code\", \"description\");\n\nresult.AddErrors(new List\u003cError\u003e\n{\n    new Error(\"property\", \"code\", \"description2\"),\n    new Error(\"property\", \"code\", \"description2\")\n});\n```\n\n##### Built-in error types\n\n- `Error.Error()`;\n- `Error.Unauthorized()`\n- `Error.Forbidden()`\n- `Error.NotFound()`\n- `Error.Conflict()`\n- `Error.Validation()`\n- `Error.Unexpected()`\n\n##### Custom error\n\n```csharp\npublic class CustomError : IError\n{\n    public string Property { get; init; }\n    public string Code { get; init; }\n    public string Description { get; init; }\n\n    public CustomError(string property, string code, string description)\n    {\n        Property = property;\n        Code = code;\n        Description = description;\n    }\n}\n\nvar error = new CustomError(property, code, description);\n\nvar result = Result.From(error);\nvar result = Result\u003cFakeModel\u003e.From(error);\nvar result = Result.From\u003cFakeModel\u003e(error);\n```\n\n\n#### Result factory\nCreates a `Result\u003cTValue\u003e` when the error list is null or empty otherwise creates a result with a list of errors.\n\nDelegate is used to instantiate the value only when there are no errors\n```csharp\n// Returns `Result` with value\nvar result = Result.Create(\n    Array.Empty\u003cError\u003e(),\n    () =\u003e new Model());\n\n// Returns `Result` with errors\nvar result = Result.Create(\n    new List\u003cError\u003e { Error.Failure(\"property\", \"code\", \"description\") },\n    () =\u003e new Model());\n```\n\n\n\n### Extensions\n\n#### Handling errors\n```csharp\nResult result = new Error[]\n{\n    new(\"Property\", \"Code\", \"Description\"),\n    new(\"Property\", \"Code\", \"Description\")\n};\n\nIError error = result.FirstError();\nIError error = result.FirstOrDefaultError();\nIError error = result.FirstOrDefaultError(Func\u003cIError, bool\u003e predicate);\n\nIError error = result.LastError();\nIError error = result.LastOrDefaultError();\nIError error = result.LastOrDefaultError(Func\u003cIError, bool\u003e predicate);\n\nIError error = result.SingleError();\nIError error = result.SingleOrDefaultError();\nIError error = result.SingleOrDefaultError(Func\u003cIError, bool\u003e predicate);\n\nbool IResult.ContainsError();\nbool IResult.ContainsError(Func\u003cIError, bool\u003e predicate);\n```\n\n#### OfTypeFirstError\n\n```csharp\nResult result = Error.Conflict(\"property\", \"code\", \"description\");\nvar type = result.OfTypeFirstError(); // Conflict\n\nResult result = Result.Ok();\nvar type = result.GetType(); // Success\n\nResult result = Error.Unauthorized(\"property\", \"code\", \"description\");\nvar type = result.GetType(); // UnauthorizedError\n\nResult\u003cModel\u003e result = Error.Forbidden(\"property\", \"code\", \"description\");\nvar type = result.GetType(); // ForbiddenError\n\nvar model = new Model();\nResult\u003cModel\u003e result = model;\nvar type = result.GetType(); // Model\n```\n\n#### Handling success\n\n```csharp\nbool IResult.IsSuccess();\nbool IResult.IsSuccess(Func\u003cTValue, bool\u003e predicate);\n```\n\n#### Switch\n\n```csharp\nresult.Switch(\n    value =\u003e onSuccess(value),\n    errors =\u003e onErrors(errors));\n\n// Only return the value or first erro\nresult.SwitchFirst(\n    value =\u003e onSuccess(value),\n    error =\u003e onError(error));\n\nawait result.SwitchAsync(\n    value =\u003e onSuccess(value),\n    errors =\u003e onErrors(errors));\n\n// Only return the value or first erro\nawait result.SwitchFirstAsync(\n    value =\u003e onSuccess(value),\n    error =\u003e onError(error));\n```\n\n#### Match\n\n```csharp\nTOutput response = result.Match\u003cTValue, TOutput\u003e(\n    value =\u003e onSuccess(value),\n    errors =\u003e onErrors(errors));\n\n// Only return the value or first erro\nTOutput response = result.MatchFirst\u003cTValue, TOutput\u003e(\n    value =\u003e onSuccess(value),\n    error =\u003e onError(error));\n\n\nTask\u003cTOutput\u003e response = result.MatchAsync\u003cTValue, TOutput\u003e(\n    value =\u003e onSuccess(value),\n    errors =\u003e onErrors(errors));\n\n// Only return the value or first erro\nTask\u003cTOutput\u003e response = result.MatchFirstAsync\u003cTValue, TOutput\u003e(\n    value =\u003e onSuccess(value),\n    error =\u003e onError(error));\n```\n\n#### Conversions\n\n```csharp\nvar errorList = result.Errors.AsList();\n```\n\n#### DistinctErrors\n\n```csharp\nResult result = new IError[]\n{\n    Error.Conflict(\"FakeProperty\", \"FakeCode\", \"FakeDescription\"),\n    Error.Conflict(\"FakeProperty\", \"FakeCode\", \"FakeDescription\")};\n\n// Only returns one error\nvar errors = result.DistinctErrors();\n```\n\n### Deconstruct operators\n\n```csharp\nvar (property, code, description) = Error.Unauthorized(\"property\", \"code\", \"description\");\n\nResult\u003cModel\u003e result = new Model { Id = id, Name = name };\n// Deconstruct -\u003e value is not null and errors is empty\n(var value, var errors) = result;\n```\n\n### Implicit conversion\n\n```csharp\nResult\u003cModel\u003e result = new Model { Id = id, Name = name };\nModel model = result;\n\n// Result with errors\nResult result = Error.Conflict(\"property\", \"code\", \"description\");\nList\u003cIError\u003e errors = result;\n```\n\n### Check validity\n\n**Valid example**\n```csharp\nResult\u003cModel\u003e result = new Model { Id = id, Name = name };\n\n// result = implicit conversion \"true\"\nif(result)\n{\n    // Do something\n}\n\n// Equivalent to\nif(result.IsError == false)\n{\n    // Do something\n}\n\nif(result.IsSuccess(out var value, out var errors))\n{\n    // Do something\n}\n\nif(result.IsError(out var value, out var errors))\n{\n    // Do something\n}\n```\n\n**Invalid example**\n```csharp\nResult result = Error.Conflict(\"property\", \"code\", \"description\");\n\n// result = implicit conversion \"false\"\nif(result)\n{\n    // Do something\n}\n\n// Equivalent to\nif(result.IsError == true)\n{\n    // Do something\n}\n```\n\n### Serialization/Deserialization\n\n#### Results\n\n**Serialization `Result` success example**\n```csharp\nvar result = Result.Success();\nvar json = JsonSerializer.Serialize(result);\n/*\njson = {\n    \"IsSuccess\": true\n}\n*/\n```\n\n```csharp\nvar result = Result.Success(45);\nvar json = JsonSerializer.Serialize(result);\n/*\njson = {\n    \"IsSuccess\": true,\n    \"Value\": 45\n}\n*/\n```\n\n**Serialization `Result` errors example**\n```csharp\nResult result = Error.NotFound(\"client\", \"NOT_FOUND\", \"Client not found\");\nResult\u003cint\u003e result = Error.NotFound(\"client\", \"NOT_FOUND\", \"Client not found\");\n\nvar json = JsonSerializer.Serialize(result);\n/*\njson = {\n    \"IsSuccess\": false,\n    \"Errors\": [\n        {\n            \"_type\": \"PowerUtils.Results.NotFoundError\",\n            \"Property\": \"client\",\n            \"Code\": \"NOT_FOUND\",\n            \"Description\":\"Client not found\"\n        }\n    ]\n}\n*/\n```\n\n**Deserialization `Result` success example**\n\n```csharp\nvar json = \"\"\"\n    \"IsSuccess\": true\n    \"\"\";\n\nvar result = JsonSerializer.Deserialize\u003cResult\u003e(json);\n```\n\n```csharp\nvar json = \"\"\"\n    \"IsSuccess\": true,\n    \"Value\": 541.7\n    \"\"\";\n\nvar result = JsonSerializer.Deserialize\u003cResult\u003cdouble\u003e\u003e(json);\n```\n\n**Deserialization `Result` errors example**\n\n```csharp\nvar json = \"\"\"\n    \"IsSuccess\": false,\n    \"Errors\": [\n        {\n            \"_type\": \"PowerUtils.Results.NotFoundError\",\n            \"Property\": \"client\",\n            \"Code\": \"NOT_FOUND\",\n            \"Description\":\"Client not found\"\n        }\n    ]\n    \"\"\";\n\nvar result = JsonSerializer.Deserialize\u003cResult\u003e(json);\nvar result = JsonSerializer.Deserialize\u003cResult\u003cClient\u003e\u003e(json);\n```\n\n\n#### Errors\n\n**Serialization example**\n```csharp\nvar error = Error.NotFound(\"client\", \"NOT_FOUND\", \"Client not found\");\n\nvar json = JsonSerializer.Serialize(error);\n/*\njson = {\n    \"_type\": \"PowerUtils.Results.NotFoundError\",\n    \"Property\": \"client\",\n    \"Code\": \"NOT_FOUND\",\n    \"Description\": \"Client not found\"\n}\n*/\n```\n\n**Deserialization example**\n```csharp\nvar json = \"\"\"\n    {\n        \"_type\": \"PowerUtils.Results.NotFoundError\",\n        \"Property\": \"client\",\n        \"Code\": \"NOT_FOUND\",\n        \"Description\": \"Client not found\"\n    }\n    \"\"\";\n\nvar error = JsonSerializer.Deserialize\u003cNotFoundError\u003e(json);\n```\n\nFor .NET 6.0 or greater, you can use the `IError` interface as the type to be deserialized.\nTo versions .NET 5.0 or lower, the deserialization using interface is not supported by `System.Text.Json`. You will get an exception `System.NotSupportedException`.\n\n```csharp\nvar error = JsonSerializer.Deserialize\u003cIError\u003e(json);\n```\n\n**Custom error Serialization/Deserialization example**\n\n```csharp\n[JsonConverter(typeof(ErrorJsonConverter\u003cCustomError\u003e))]\npublic class CustomError : IError { }\n```\n\n\n## Contribution\n\nIf you have any questions, comments, or suggestions, please open an [issue](https://github.com/TechNobre/PowerUtils.Results/issues/new/choose) or create a [pull request](https://github.com/TechNobre/PowerUtils.Results/compare)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechnobre%2Fpowerutils.results","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftechnobre%2Fpowerutils.results","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechnobre%2Fpowerutils.results/lists"}