Getting Started
Choose your language to get started:
Installation
Section titled “Installation”-
Install the
holeypackage:Terminal window npm install holey -
Import
holewherever you need it:import { hole } from 'holey'; -
Replace placeholders with
hole():export async function createUser(data: UserInput): Promise<User> {hole("validate input before saving")return hole("save user to database", { id: "1", ...data })}
-
Install the
HoleyNuGet package:Terminal window dotnet add package Holey -
Add a global using (C# 10+) or import per file:
// In GlobalUsings.csglobal using Holey; -
Replace placeholders with
Hole.Todo():public async Task<User> CreateUser(UserInput data){Hole.Todo("validate input before saving");return Hole.Todo("save user to database", new User { Id = 1, Name = data.Name });}
Your first hole
Section titled “Your first hole”The simplest use of a hole is as a named placeholder — a // TODO comment that actually does something:
function sendWelcomeEmail(user: User): void { hole("send welcome email via SendGrid")}public void SendWelcomeEmail(User user){ Hole.Todo("send welcome email via SendGrid");}Unlike a comment, this hole:
- Shows up as a diagnostic in your editor
- Gets reported at runtime when the function is called
- Can be given a temporary implementation to keep your app running
Providing a temporary implementation
Section titled “Providing a temporary implementation”Pass a second argument to give the hole a stand-in value or behavior while the real implementation is pending:
// Return a hardcoded value for nowconst apiKey = hole("read API_KEY from secrets manager", "dev-key-123")
// Use an environment variable as a stopgapconst port = hole("read port from config service", () => parseInt(process.env.PORT ?? "3000"))
// Simulate an async operationawait hole("persist session to Redis", Promise.resolve())// Return a hardcoded value for nowvar apiKey = Hole.Todo("read API_KEY from secrets manager", "dev-key-123");
// Use an environment variable as a stopgapvar port = Hole.Todo("read port from config service", () => int.Parse(Environment.GetEnvironmentVariable("PORT") ?? "3000"));
// Simulate an async operationawait Hole.Todo("persist session to Redis", Task.Delay(0));The temporary implementation is clearly separated from its description, so it’s obvious what’s real and what’s a stand-in.
Next steps
Section titled “Next steps”- Learn about replacing existing placeholders like
throw new Error()and// TODOcomments - Understand Hole-Driven Development and why it helps
- See the full API reference