SAToolKit 1.0.0
dotnet add package SAToolKit --version 1.0.0
NuGet\Install-Package SAToolKit -Version 1.0.0
<PackageReference Include="SAToolKit" Version="1.0.0" />
<PackageVersion Include="SAToolKit" Version="1.0.0" />
<PackageReference Include="SAToolKit" />
paket add SAToolKit --version 1.0.0
#r "nuget: SAToolKit, 1.0.0"
#:package SAToolKit@1.0.0
#addin nuget:?package=SAToolKit&version=1.0.0
#tool nuget:?package=SAToolKit&version=1.0.0
SAToolKit
South African developer helpers for .NET 10. ID validation, Eskom load shedding utilities, security scanning, async helpers, and collection tools — all named after things that make life in the Republic uniquely interesting.
Installation
dotnet add package SAToolKit
Modules
IdController — SA ID Number Validation
Validates South African ID numbers using the Luhn algorithm and extracts encoded metadata.
using SAToolKit.Controllers;
var id = new IdController();
id.IsValid("9003155001089"); // true
id.GetAge("9003155001089"); // int (age in years)
id.GetGender("9003155001089"); // SaGender.Male
id.GetDateOfBirth("9003155001089"); // DateTime
id.IsCitizen("9003155001089"); // true
SaIdResult profile = id.Validate("9003155001089");
// profile.IsValid, profile.Age, profile.Gender, profile.DateOfBirth,
// profile.Citizenship, profile.ErrorMessage
String extensions — chain directly off any string:
using SAToolKit.Extensions;
"9003155001089".IsValidSouthAfricanId(); // true
"9003155001089".GetAgeFromId(); // int?
"9003155001089".GetGenderFromId(); // SaGender?
"9003155001089".GetDateOfBirthFromId(); // DateTime?
"9003155001089".IsSouthAfricanCitizen(); // bool
"9003155001089".GetFullIdProfile(); // SaIdResult
EskomController — Load Shedding Utilities
Because Eskom needs its own controller.
using SAToolKit.Controllers;
var eskom = new EskomController();
eskom.WhatsTheStage(); // LoadSheddingResult (current stage info)
eskom.EskomRemembered(); // true when power is on
eskom.CookingByFlashlight(); // true when load shedding is active
eskom.WhatEskomSays(); // a classic Eskom quote for the current stage
eskom.SimulateStage(LoadSheddingStage.Stage4); // test against a specific stage
Swap in your own ILoadSheddingService to connect live stage data from an API.
Braai — Value Comparison
Inspired by the eternal debate: KFC vs Hungry Lion.
using SAToolKit.Controllers;
// Pick the better deal
var winner = Braai.BestValue(dealA, dealB, x => x.ValuePerRand);
// Is this a Hungry Lion deal? (value/price >= threshold)
Braai.IsHungryLionDeal(price: 89, value: 150); // true
Braai.IsHungryLionDeal(price: 89, value: 150, threshold: 2.0); // false
// Rank all options, best first
var ranked = Braai.RankByValue(deals, x => x.ValuePerRand);
// Take the single best option from a collection
var best = Braai.TakeTheWhole(deals, x => x.ValuePerRand);
// Direct comparison
Braai.IsBetterThan(dealA, dealB, x => x.ValuePerRand); // bool
Taxi — Collection & Async Utilities
Taxi logic applied to your data.
using SAToolKit.Controllers;
// Null coalescing (reference and value types)
Taxi.UTurn(nullableString, "fallback");
Taxi.UTurnValue(nullableInt, 0);
// Shuffle a list (Fisher-Yates)
var shuffled = Taxi.Rank(passengers);
// Capacity helpers
var first15 = Taxi.FilledUp(source, capacity: 15);
var seatsLeft = Taxi.SeatsLeft(current, capacity: 15);
// Predicate inversion
Taxi.IsGoingTheWrongWay(value, x => x.IsValid); // true when predicate fails
// Sorting & grouping
Taxi.SpeedSort(items, x => x.Name);
Taxi.SpeedSortDescending(items, x => x.Price);
Taxi.FastGroup(items, x => x.Category);
// Bulk operations
Taxi.BulkInsertFast(data, items => db.BulkInsert(items));
await Taxi.BulkInsertFastAsync(data, items => db.BulkInsertAsync(items));
// Exception handling with optional logging hooks
var result = Taxi.JumpRedLight(
body: payload,
riskyOperation: p => Process(p),
onSuccessLog: p => logger.Info("done"),
onErrorLog: (ex, p) => logger.Error(ex, "failed")
);
// Fire-and-forget parallel insert + update per item
await Taxi.RunFromCops(data, fastInsert, fastUpdate, onComplete: item => Log(item));
// Bulk parallel version
await Taxi.RunFromCopsBulk(data, bulkInsert, bulkUpdate);
Kullid — Safe Console Output
The SA Console.WriteLine. Sanitizes control characters before printing.
using SAToolKit.Controllers;
Kullid.Hoya("Hello SA"); // prints sanitized value, returns KullidOutput<T>
Kullid.AreYouMal("quiet please"); // prints in UPPERCASE
Kullid.Whisper("dev only"); // writes to Debug output only
Kullid.Niks(null); // true — null, empty string, or empty collection
Kullid.Niks(""); // true
Kullid.Niks(new List<int>()); // true
Kullid.Niks("something"); // false
Kullid.Skoon("\t dirty\x00string"); // sanitized string without printing
Sars — Telemetry & Security Scanning
They see everything. Audit everything. And they always want more information.
using SAToolKit.Controllers;
using SAToolKit.Models;
// Wrap a call — records elapsed time and heap allocations
var result = Sars.Audit("GetUser", () => db.GetUser(id));
// Async version
var result = await Sars.AuditAsync("FetchOrders", () => api.GetOrdersAsync());
// Security scanning — detects XSS, SQL injection, path traversal
SecurityScanResult scan = Sars.Scan(userInput);
// scan.IsSafe, scan.ThreatType, scan.MatchedPattern
bool safe = Sars.IsSafe(userInput); // quick boolean check
// Colour-coded console logging
Sars.Log("Starting job", SarsLogLevel.Info);
Sars.Log("Something looks off", SarsLogLevel.Warning);
Sars.Tax("This went very wrong"); // shorthand for Error level
// Telemetry report
SarsTelemetryReport report = Sars.GetReport();
// report.Entries — list of TelemetryEntry (name, duration, bytes, success, timestamp)
Sars.ClearTelemetry(); // call periodically in long-running services
Swap in a custom ISarsService for structured logging integrations:
Sars.Configure(new MyStructuredLoggingSarsService());
Cupcake — Async & Lazy Utilities
Results will come. Eventually.
using SAToolKit.Controllers;
// Lazy evaluation
var value = Cupcake.Eventually(() => ExpensiveComputation());
// Async with timeout — returns null if it takes too long
var data = await Cupcake.Deliver(() => api.GetDataAsync(), timeoutMs: 3000);
// Value type version
int? count = await Cupcake.DeliverValue(() => db.CountAsync(), timeoutMs: 2000);
// Null checks
Cupcake.IsStillWaiting(data); // true when null
Cupcake.Promised(data, fallback); // returns fallback when null
// Run many async operations with concurrency control
var results = await Cupcake.DeliverAll(
actions: orderIds.Select(id => (Func<Task<Order>>)(() => GetOrderAsync(id))),
timeoutMs: 5000,
maxConcurrency: 10
);
// Returns only the operations that succeeded within the timeout
Springbok — Response Helpers
Success/failure utilities for HTTP and general result handling.
using SAToolKit.Controllers;
Springbok.IsSuccess(response, r => r.StatusCode == 200);
Springbok.IsFailure(response, r => r.StatusCode >= 400);
Springbok.IsSuccessStatusCode(200); // true
Springbok.IsErrorStatusCode(500); // true
Springbok.GetMessageForStatusCode(200); // random success message
Springbok.GetMessageForStatusCode(404); // random error message
Springbok.GetSuccessMessage(); // e.g. "Operation completed successfully."
Springbok.GetErrorMessage(); // e.g. "An error occurred while processing your request."
Requirements
- .NET 10.0+
License
MIT © ReeceMas
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 126 | 6/15/2026 |