Noundry Blueprints

Code examples showing how to use each Noundry library in real-world scenarios

🛡️ Noundry.Guardian

Attribute-based authorization with policies and claims

Security
Program.cs
using Noundry.Guardian;

// Add Guardian with policies
builder.Services.AddGuardian(options =>
{
    options.AddPolicy("AdminOnly", policy =>
        policy.RequireRole("Admin"));

    options.AddPolicy("CanEditPosts", policy =>
        policy.RequireClaim("Permission", "Posts.Edit"));

    options.AddPolicy("MinimumAge", policy =>
        policy.RequireAssertion(context =>
        {
            var ageClaim = context.User.FindFirst("age");
            return ageClaim != null && int.Parse(ageClaim.Value) >= 18;
        }));
});

// Use in controllers
[Authorize(Policy = "AdminOnly")]
public class AdminController : Controller
{
    [HttpPost]
    [Authorize(Policy = "CanEditPosts")]
    public async Task EditPost(int id, Post model)
    {
        // Only users with "Posts.Edit" claim can access
        return Ok();
    }
}
View Full Documentation →

✅ Noundry.Sod

Zod-inspired schema validation for .NET

Validation
UserValidator.cs
using Noundry.Sod;

// Define schema
var userSchema = Sod.Object()
    .Field(u => u.Email,
        Sod.String().Email().Required())
    .Field(u => u.Age,
        Sod.Number().Min(18).Max(120))
    .Field(u => u.Username,
        Sod.String().Min(3).Max(20).Regex("^[a-zA-Z0-9_]+$"))
    .Field(u => u.Password,
        Sod.String().Min(8).Regex(@"^(?=.*[A-Z])(?=.*\d).*$"))
    .Field(u => u.Website,
        Sod.String().Url().Optional());

// Validate in controller
[HttpPost]
public async Task Register(User user)
{
    var result = userSchema.Parse(user);

    if (!result.Success)
    {
        return BadRequest(result.Errors);
    }

    var validUser = result.Data;
    await _userService.CreateAsync(validUser);
    return Ok();
}
View Full Documentation →

🔐 Noundry.DotEnvX

Encrypted environment variables with validation

Config
Program.cs
using Noundry.DotEnvX.Core.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Load .env with encryption & validation
builder.Configuration.AddDotEnvX(options =>
{
    options.Path = ".env";
    options.EnvironmentSpecific = true;  // Also load .env.development
    options.Required = new[]
    {
        "DATABASE_URL",
        "JWT_SECRET",
        "STRIPE_API_KEY"
    };
    options.EncryptionKey =
        Environment.GetEnvironmentVariable("DOTENVX_KEY");
});

// Use configuration
var jwtSecret = builder.Configuration["JWT_SECRET"];
var dbUrl = builder.Configuration["DATABASE_URL"];

// .env file example:
// DATABASE_URL=postgresql://localhost/mydb
// JWT_SECRET=encrypted:AES256:base64encodedvalue
// STRIPE_API_KEY=sk_test_encrypted
View Full Documentation →

🔌 Noundry.Connector

Multi-database connection management

Data
Program.cs
using Noundry.Connector;

// Add multi-database support
builder.Services.AddConnector(options =>
{
    // Primary database
    options.AddDatabase("Default", config =>
    {
        config.Provider = DatabaseProvider.PostgreSQL;
        config.ConnectionString = builder.Configuration["DATABASE_URL"];
    });

    // Read replica
    options.AddDatabase("ReadReplica", config =>
    {
        config.Provider = DatabaseProvider.PostgreSQL;
        config.ConnectionString = builder.Configuration["READ_REPLICA_URL"];
        config.ReadOnly = true;
    });

    // Analytics database
    options.AddDatabase("Analytics", config =>
    {
        config.Provider = DatabaseProvider.ClickHouse;
        config.ConnectionString = builder.Configuration["ANALYTICS_URL"];
    });
});

// Use in services
public class UserService
{
    private readonly IConnectionFactory _factory;

    public async Task GetAsync(int id)
    {
        using var conn = await _factory.CreateAsync("ReadReplica");
        return await conn.QuerySingleAsync(
            "SELECT * FROM users WHERE id = @id",
            new { id });
    }

    public async Task CreateAsync(User user)
    {
        using var conn = await _factory.CreateAsync("Default");
        await conn.ExecuteAsync(
            "INSERT INTO users (name, email) VALUES (@name, @email)",
            user);
    }
}
View Full Documentation →

🎩 Noundry.Tuxedo

Lightweight ORM with fluent query builder

Data
ProductRepository.cs
using Noundry.Tuxedo;

public class ProductRepository
{
    private readonly IDbContext _db;

    // Fluent queries
    public async Task> GetActiveProducts()
    {
        return await _db.Query()
            .Where(p => p.IsActive == true)
            .Where(p => p.Stock > 0)
            .OrderBy(p => p.Name)
            .ToListAsync();
    }

    // Joins
    public async Task> GetProductsWithCategories()
    {
        return await _db.Query()
            .Join((p, c) => p.CategoryId == c.Id)
            .Select((p, c) => new ProductWithCategory
            {
                ProductName = p.Name,
                CategoryName = c.Name,
                Price = p.Price
            })
            .ToListAsync();
    }

    // Insert/Update
    public async Task CreateAsync(Product product)
    {
        return await _db.InsertAsync(product);
    }

    public async Task UpdatePriceAsync(int id, decimal newPrice)
    {
        await _db.Update()
            .Set(p => p.Price, newPrice)
            .Set(p => p.UpdatedAt, DateTime.UtcNow)
            .Where(p => p.Id == id)
            .ExecuteAsync();
    }

    // Transactions
    public async Task TransferStock(int fromId, int toId, int quantity)
    {
        using var transaction = await _db.BeginTransactionAsync();
        try
        {
            await _db.Update()
                .Set(p => p.Stock, p => p.Stock - quantity)
                .Where(p => p.Id == fromId)
                .ExecuteAsync();

            await _db.Update()
                .Set(p => p.Stock, p => p.Stock + quantity)
                .Where(p => p.Id == toId)
                .ExecuteAsync();

            await transaction.CommitAsync();
        }
        catch
        {
            await transaction.RollbackAsync();
            throw;
        }
    }
}
View Full Documentation →

📥 Noundry.Slurp

High-performance CSV/JSON to database ingestion

Data
DataImporter.cs
using Noundry.Slurp;

public class DataImporter
{
    private readonly ISlurpService _slurp;

    // Import CSV to database
    public async Task ImportCustomers(Stream csvStream)
    {
        var result = await _slurp.IngestCsvAsync(csvStream, options =>
        {
            options.TableName = "customers";
            options.Provider = DatabaseProvider.PostgreSQL;
            options.ConnectionString = _config["DATABASE_URL"];
            options.BatchSize = 5000;
            options.CreateTableIfNotExists = true;
            options.TruncateBeforeInsert = false;

            // Column mapping
            options.ColumnMappings = new Dictionary
            {
                ["First Name"] = "first_name",
                ["Last Name"] = "last_name",
                ["E-mail"] = "email"
            };

            // Transformations
            options.Transform = (row) =>
            {
                row["email"] = row["email"].ToLower();
                row["created_at"] = DateTime.UtcNow;
                return row;
            };
        });

        Console.WriteLine($"Imported {result.RowsProcessed} rows in {result.Duration}");
    }

    // CLI Usage
    // slurp customers.csv --provider postgres --connection $DB_URL
    // ✓ Analyzing CSV structure...
    // ✓ Detected schema: 5 columns, 10,000 rows
    // ⚡ Ingesting at 125,000 rows/sec
    // ✅ Completed: 10,000 rows in 0.08 seconds
}
View Full Documentation →

⏰ Noundry.Jobs

Job scheduling and automation library

Automation
cleanup.csx
#!/usr/bin/env dotnet-script
#r "nuget: Noundry.Jobs, 1.0.0"

using Noundry.Jobs.Database;
using Noundry.Jobs.Email;

// Database cleanup job
var db = new JobsDb(connectionString, DatabaseType.PostgreSQL);

var deleted = await db.ExecuteAsync(
    "DELETE FROM logs WHERE created_at < @Date",
    new { Date = DateTime.UtcNow.AddDays(-30) }
);

Console.WriteLine($"Deleted {deleted} old log entries");

// Send email notification
using var email = new JobsEmail()
    .Configure("smtp.gmail.com", 587, username, password)
    .UseStartTls();

await email.SendAsync(
    from: "noreply@example.com",
    to: "admin@example.com",
    subject: $"Cleanup Complete: {deleted} records deleted",
    body: "Database cleanup job completed successfully"
);

// Schedule with njobs CLI:
// njobs create DailyCleanup cleanup.csx "0 2 * * *"
// njobs list
// njobs run DailyCleanup
View Full Documentation →

⚠️ Noundry.Assertive

Fluent assertions with custom error messages

Validation
OrderService.cs
using Noundry.Assertive;

public class OrderService
{
    public async Task ProcessOrder(Order order, User user)
    {
        // Guard clauses with custom messages
        Assert.That(order).IsNotNull("Order cannot be null");
        Assert.That(order.Items).IsNotEmpty("Order must contain at least one item");
        Assert.That(order.Total).IsGreaterThan(0, "Order total must be positive");
        Assert.That(user.Email).IsNotNullOrWhiteSpace("User email is required");
        Assert.That(user.Email).Matches(@"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$", "Invalid email format");

        // Complex assertions
        Assert.That(order.Items.Sum(i => i.Price * i.Quantity))
            .IsEqualTo(order.Total, "Order total doesn't match sum of items");

        // Conditional assertions
        if (order.RequiresShipping)
        {
            Assert.That(order.ShippingAddress).IsNotNull("Shipping address required");
            Assert.That(order.ShippingAddress.ZipCode).IsNotNullOrWhiteSpace();
        }

        // All assertions throw ArgumentException or custom exception if they fail
        await SaveOrderAsync(order);
    }
}
View Full Documentation →

Start Using Noundry Libraries

Install any Noundry library via NuGet and start building better .NET applications