|
| 1 | +--- |
| 2 | +name: dotnet-sdk-builder |
| 3 | +description: This skill should be used when the user asks to "create a .NET SDK", "build a .NET library", "generate an SDK from classes", "create an API wrapper in C#", "build a .NET integration library", "create a .NET client library", "wrap a REST API in .NET", "generate a .NET HTTP client", or "create a typed HTTP client". Generates complete .NET SDK libraries with Dependency Injection support, interfaces, typed HTTP clients, Options pattern, typed exceptions, XML documentation (via csharp-docs skill), and tests (via tester skill). |
| 4 | +version: 0.1.0 |
| 5 | +--- |
| 6 | + |
| 7 | +# .NET SDK Library Builder |
| 8 | + |
| 9 | +Generate complete, production-ready .NET SDK libraries from existing C# classes or API documentation. The output follows Microsoft's library design guidelines with full DI support, testability via interfaces, and idiomatic C# patterns. |
| 10 | + |
| 11 | +## When to Use This Skill |
| 12 | + |
| 13 | +- Creating an HTTP client / REST API wrapper library |
| 14 | +- Building an integration library for an external service |
| 15 | +- Wrapping existing service classes into a redistributable library |
| 16 | +- Generating a typed SDK from OpenAPI/Swagger or Markdown documentation |
| 17 | + |
| 18 | +## Workflow Overview |
| 19 | + |
| 20 | +Follow these steps in order. See the reference files for detailed guidance on each phase. |
| 21 | + |
| 22 | +### Step 1: Analyze Input |
| 23 | + |
| 24 | +Determine what the input is: |
| 25 | + |
| 26 | +- **Existing C# classes**: Read and understand the public API surface, method signatures, and responsibilities. |
| 27 | +- **Documentation** (OpenAPI, Swagger JSON/YAML, Markdown): Parse endpoints, request/response models, authentication, and error responses. |
| 28 | + |
| 29 | +### Step 2: Determine .NET Version |
| 30 | + |
| 31 | +1. Find all `.csproj` files in the solution. |
| 32 | +2. Extract the `<TargetFramework>` (or `<TargetFrameworks>`) value. |
| 33 | +3. If all projects use the same version → use that version. |
| 34 | +4. If versions differ → ask the user which version to target. |
| 35 | +5. Enable nullable reference types based on version: |
| 36 | + - New project: add `<Nullable>enable</Nullable>` to `.csproj`. |
| 37 | + - Existing project with nullable disabled: add `#pragma warning disable CS8600` / `#nullable enable` per source file, not globally. |
| 38 | + |
| 39 | +### Step 3: Determine Target Project |
| 40 | + |
| 41 | +1. If the user specified a project → use it. |
| 42 | +2. If no project specified → scan the solution for existing library projects (`.csproj` with no `Sdk="Microsoft.NET.Sdk.Web"` and no executable output). |
| 43 | +3. If a candidate project is found → **ask the user** before adding files to it. |
| 44 | +4. If no suitable project exists → create a new class library project. See [project-setup.md](references/project-setup.md) for conventions. |
| 45 | + |
| 46 | +### Step 4: Derive Names |
| 47 | + |
| 48 | +Derive the service/client name from the input: |
| 49 | + |
| 50 | +| Input | Derived Name Example | |
| 51 | +|---|---| |
| 52 | +| `GitHubService` class | `GitHub` → `IGitHubClient`, `GitHubClient`, `AddGitHub(...)` | |
| 53 | +| `PaymentsApi` class | `Payments` → `IPaymentsClient`, `PaymentsClient`, `AddPayments(...)` | |
| 54 | +| OpenAPI `title: Stripe API` | `Stripe` → `IStripeClient`, `StripeClient`, `AddStripe(...)` | |
| 55 | + |
| 56 | +If the name cannot be derived with confidence → ask the user. |
| 57 | + |
| 58 | +### Step 5: Ask About Resilience |
| 59 | + |
| 60 | +Before generating HTTP client code, ask: |
| 61 | + |
| 62 | +> "Should resilience policies (retry, circuit breaker) be added to the HTTP client using `Microsoft.Extensions.Http.Resilience`?" |
| 63 | +
|
| 64 | +If yes → add the Polly-based resilience pipeline. See [http-client-patterns.md](references/http-client-patterns.md#resilience). |
| 65 | + |
| 66 | +### Step 6: Ask About Existing Types Used as Arguments or Return Values |
| 67 | + |
| 68 | +When wrapping existing C# classes, identify all types that appear directly as method parameters or return values in the wrapped API (e.g. classes, records, enums from the source assembly). |
| 69 | + |
| 70 | +For each such type, ask the user **once** (grouped into a single question): |
| 71 | + |
| 72 | +> "The following types from the source are used directly as parameters or return values: |
| 73 | +> - `OrderRequest` (argument of `PlaceOrder`) |
| 74 | +> - `ProductDto` (return value of `GetProduct`) |
| 75 | +> - ... |
| 76 | +> |
| 77 | +> Should these types be passed through as-is (reused from the source), or should new equivalents be generated in the SDK library?" |
| 78 | +
|
| 79 | +**Options and consequences:** |
| 80 | + |
| 81 | +| Choice | When to recommend | What to generate | |
| 82 | +|---|---|---| |
| 83 | +| **Pass through** | Source types are already in a shared/public assembly that consumers will reference | No new model code; use source types directly in the interface and implementation | |
| 84 | +| **Generate new types** | Source types are internal, in a non-distributable assembly, or consumers should not depend on the source project | New model classes/records in `Models/`; add mapping logic between source and SDK types in the implementation | |
| 85 | + |
| 86 | +If the user chooses to generate new types, apply the same conventions as for response DTOs (see [http-client-patterns.md](references/http-client-patterns.md)). Add a private mapping method or a `XxxMapper` internal class to the implementation to convert between the source type and the SDK type. |
| 87 | + |
| 88 | +### Step 7: Generate Library Code |
| 89 | + |
| 90 | +Generate all components. See [di-patterns.md](references/di-patterns.md) and [http-client-patterns.md](references/http-client-patterns.md) for full patterns. |
| 91 | + |
| 92 | +**Required components:** |
| 93 | + |
| 94 | +| Component | Description | |
| 95 | +|---|---| |
| 96 | +| `IXxxClient` interface | Public contract for DI and testing | |
| 97 | +| `XxxClient` implementation | Concrete HTTP client using `IHttpClientFactory` | |
| 98 | +| `XxxOptions` class | Configuration via Options pattern | |
| 99 | +| `XxxServiceCollectionExtensions` | `AddXxx(...)` extension method | |
| 100 | +| `XxxException` (+ subtypes) | Typed exceptions with diagnostic properties | |
| 101 | +| Model classes | Request/response DTOs | |
| 102 | + |
| 103 | +**NuGet packages to add:** |
| 104 | + |
| 105 | +```xml |
| 106 | +<PackageReference Include="Microsoft.Extensions.Http" Version="*" /> |
| 107 | +<PackageReference Include="Microsoft.Extensions.Options" Version="*" /> |
| 108 | +<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="*" /> |
| 109 | +<!-- If resilience requested: --> |
| 110 | +<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="*" /> |
| 111 | +``` |
| 112 | + |
| 113 | +Always use the latest stable, compatible with target framework version. |
| 114 | +Always use skill 'nuget-manager' for managing NuGet packages and package versions. |
| 115 | + |
| 116 | +### Step 8: Document the Code |
| 117 | + |
| 118 | +After generating all source files, invoke the `csharp-docs` skill to add XML documentation comments to all public types and members. |
| 119 | + |
| 120 | +### Step 9: Write Tests |
| 121 | + |
| 122 | +After documentation is complete, invoke the `tester` skill to generate unit and integration tests for the library. |
| 123 | + |
| 124 | +## Key Design Principles |
| 125 | + |
| 126 | +- **Interface-first**: Every public service class must have a corresponding interface. |
| 127 | +- **Options pattern**: Configuration always via `IOptions<XxxOptions>`, never constructor parameters for config values. |
| 128 | +- **IHttpClientFactory**: Never inject `HttpClient` directly; always use the named/typed factory pattern. |
| 129 | +- **Typed exceptions**: HTTP errors become typed exceptions with status code, reason, and response body properties. |
| 130 | +- **Nullable**: Follow the project's nullable settings (see Step 2). |
| 131 | +- **No static state**: All state via DI; no singleton anti-patterns. |
| 132 | + |
| 133 | +## Additional Resources |
| 134 | + |
| 135 | +- **[di-patterns.md](references/di-patterns.md)** — DI registration, Options pattern, extension method patterns |
| 136 | +- **[http-client-patterns.md](references/http-client-patterns.md)** — IHttpClientFactory, typed clients, resilience, typed exceptions |
| 137 | +- **[project-setup.md](references/project-setup.md)** — New project structure, folder layout, `.csproj` conventions |
0 commit comments