Skip to content

Instantly share code, notes, and snippets.

View graffhyrum's full-sized avatar

Joshua Pendragon graffhyrum

View GitHub Profile
@graffhyrum
graffhyrum / range.ts
Created November 21, 2025 19:05
TS Range
// No idea why this isn't stdlib
function range(start: number, stop: number, step = 1) {
return Array(stop - start + 1).keys().map(k => k + start);
}
@graffhyrum
graffhyrum / 00_ComposablePageObject.md
Last active October 22, 2025 17:36
A Playwright Page (and Component) Object Model template.

Playwright Page and Component Object Model for Robust E2E Testing

This document outlines a highly effective and scalable pattern for organizing Playwright end-to-end tests using a combination of the Page Object Model (POM) and Component Object Model (COM). This approach dramatically enhances code reusability, improves test readability, and ensures maintainability as your application and test suite grow.

Introduction

In the realm of automated testing, particularly with frameworks like Playwright, managing selectors and test logic can become complex. Unstructured test suites often lead to brittle tests that are hard to understand and expensive to maintain. The POM and COM patterns address this by encapsulating the interactions and elements of your web application into dedicated objects.

  • Page Object Model (POM): Represents a distinct page within your web application. It abstracts the underlying HTML structure, providing high-level methods to interact with page elements and query their state. Thi
import {test, expect} from "bun:test";
import {getPagination, type PaginationArgs} from "./paginate.ts";
const baseArgs: PaginationArgs = {
currentPage: 7,
numberOfDisplayPages: 10,
resultsPerPage: 10,
totalResults: 175
}
@graffhyrum
graffhyrum / update_winget.ps1
Created October 13, 2025 13:52
From an admin powershell, silently update all packages installed with Winget. Also writes a log to the Desktop of the user.
# Check if winget is installed
try {
$winget = Get-Command winget -ErrorAction Stop
Write-Host "Winget is installed, proceeding with updates..." -ForegroundColor Green
} catch {
Write-Host "Winget is not installed. Please install winget first." -ForegroundColor Red
exit 1
}
# Create a log file with date stamp
@graffhyrum
graffhyrum / arktype-results.ts
Last active September 9, 2025 17:52
Wrap any arktype type in neverthrow to easily add validation to a callback chain.
import {ArkErrors, type TraversalError, type Type} from 'arktype';
import {err, ok, type Result} from 'neverthrow';
type ArkTypeOut<T> = T extends Type<infer Out, infer _Scope> ? Out : never;
type ArkTypeScope<T> = T extends Type<infer _Out, infer Scope> ? Scope : never;
export function toArkResult<
// biome-ignore lint/suspicious/noExplicitAny: generic function
ArkType extends Type<any,any>,
const Out extends ArkTypeOut<ArkType>,
@graffhyrum
graffhyrum / index.ts
Last active August 31, 2025 20:27
Validate and Parse process environment variables with Arktype.
import {validateAndParseEnv} from './schema';
const goodMockProcEnv = {
HOST: 'localhost',
PORT: '8080',
KEY: '1234567890',
SECRET: '1234567890',
EXTRAKEY: 'foo', // extra keys are ignored
};
@graffhyrum
graffhyrum / decompose-stepdown.md
Created August 29, 2025 23:34
LLM prompt to apply some of my most-used cleanups to a file.

This is a prompt I use often to improve readability of a module. With something like Claude custom slash commands you can map these to an alias for easy use.

Prompt:
Analyze this code in the context of the following rules and apply appropriate refactoring.

Summary:
The goal of these rules is to improve readability within a file. 
It is highly valuable to start at the top of the abstraction hierarchy 
@graffhyrum
graffhyrum / _idx.md
Last active October 22, 2025 18:59
AI summarize my day

This is a short LLM prompt to have the tool read your git history and summarize what you did in the project. It's nice to have. With something like Claude custom slash commands you can map these to an alias for easy use.

Read through my git commit history for today and summarize what I did in a file with the filename `${yyyy-mm-dd}_Summary.md`. 
Create a 'worklog' folder in the root of this project, and save the markdown there.
@graffhyrum
graffhyrum / _Summary.md
Last active July 17, 2025 16:07
Typescript Clean Architecture Filtering Layer

Clean Architecture Filtering Layer: Design Patterns and Implementation

Overview

This code sample demonstrates a complete filtering layer implementation that adheres to clean architecture principles. The system provides type-safe, configurable filtering for business entities while maintaining strict separation of concerns and dependency inversion.

Architecture Layers

Domain Layer (Innermost)

The domain layer contains pure business entities and value types with no external dependencies:

/**
* Creates a typed key-value pair object to work around TypeScript issue #13948.
* This function preserves the literal type of the key in the resulting object type.
*
* @see [source](https://github.com/microsoft/TypeScript/issues/13948#issuecomment-1333159066)
*
* @example
* const obj = createTypedKeyValue('userId', 123);
* // obj has type: { userId: number } with literal key preservation
*