Skip to content

Instantly share code, notes, and snippets.

View nikoheikkila's full-sized avatar
:electron:
Nice to meet you!

Niko Heikkilä nikoheikkila

:electron:
Nice to meet you!
View GitHub Profile
@nikoheikkila
nikoheikkila / changelog.sh
Created June 30, 2025 19:03
A quick and dirty changelog generator for Bash
#!/usr/bin/env bash
set -euo pipefail
SINCE="${1:-HEAD~1}"
query_log() {
local type="$1"
local pattern="^${type}\(.*\):\s"
local GH_HOST="github.com"
local owner="nikoheikkila"
@nikoheikkila
nikoheikkila / RULES.md
Created June 9, 2025 16:10
Mandatory rules to use with coding agents. Use at your own risk!

Rules for Agents

This document describes a working agreement that agents must obey when implementing features on behalf of humans.

Mandatory Workflow

After every single code change, you MUST run both test and quality tasks. This is non-negotiable.

Required Commands After Every Change

@nikoheikkila
nikoheikkila / type-validation.ts
Created May 13, 2025 16:50
TypeScript type-system validation
type IPv4Tuple = [number, number, number, number];
type IPv4String = `${number}.${number}.${number}.${number}`;
/**
* TypeScript validates up to a point.
* But we still need runtime validation and a type guard.
**/
const createIpAddress = (values: number[]): IPv4String => {
if (!isValidIpAddress(values)) {
throw new Error(`Invalid IP address: ${values.join('.')}`);
@nikoheikkila
nikoheikkila / assert.ts
Created May 13, 2025 15:53
node:assert example
/* Requires '@types/node' to be installed */
import { deepEqual as equal } from 'node:assert';
const test = () => {
equal(pixels(), '');
equal(pixels(0), '0');
equal(pixels(1), '1px');
equal(pixels(-1), '-1px');
equal(pixels(0.5), '1px');
equal(pixels(0.4), '0');
@nikoheikkila
nikoheikkila / polymorphism.ts
Created April 8, 2025 15:39
A polymorphism example with classes in Typescript
export abstract class Vehicle {
public abstract wheels: number;
public get name() {
return this.constructor.name;
}
}
export class Bicycle extends Vehicle {
public get wheels() {
@nikoheikkila
nikoheikkila / handlebars.ts
Created January 21, 2025 18:02
TypeScript: Compiling Handlebars templates with custom data
import Handlebars from "handlebars";
import fs from "node:fs";
type Data = Record<string, unknown>;
type Template = (data: Data) => string;
export default class Templater {
private readonly template: Template;
public static using(templatePath: string): Templater {
@nikoheikkila
nikoheikkila / interplanetary.py
Last active January 14, 2025 17:23
Python: Calculate person's weight on different planets
import sys
Weights = dict[str, float]
def calculate_planetary_weight(weight_kg: float) -> Weights:
"""
Calculate a person's weight on different planets in the Solar System.
Input weight should be in kilograms.
Returns a dictionary with weights on each planet in kilograms.
@nikoheikkila
nikoheikkila / harvest.fish
Last active March 22, 2024 06:03
A quick way to record a new time entry using the official Harvest CLI package.
# A quick way to record a new time entry using the official Harvest CLI package.
# Usage: `hours duration [alias]`
# Create a new alias for a project/task mapping with `hrvst alias create` if needed.
function hours -d "Record new entry to Harvest" -a hours -a alias
__hrvst_auth
if test (count $argv) -eq 0
__total_hours
return 0
end
@nikoheikkila
nikoheikkila / Taskile.yml
Last active May 29, 2023 08:15
Global Task definitions for handling routine tasks across my computers.
# USAGE
#
# 1. Install Taskfile from <https://taskfile.dev>
# 2. Save this file to $HOME/Taskfile.yml
# 3. Run `task -g <name of the task>`
version: '3'
vars:
EDITOR: nvim # Set this to your preferred text editor
@nikoheikkila
nikoheikkila / CardGame.ts
Last active March 10, 2023 09:57
TypeScript version of the card game presented in the talk Domain Modelling Made Functional by Scott Wlaschin.
export enum Suit {
Club,
Diamond,
Spade,
Heart,
}
export enum Rank {
Two = 2,
Three,