Skip to content

Instantly share code, notes, and snippets.

View jmakeig's full-sized avatar

Justin Makeig jmakeig

View GitHub Profile
@jmakeig
jmakeig / README.md
Last active November 15, 2025 19:40

Validation

  • Strongly typed unknownEntity
  • Accumulation of all validation issues, not just the first (or the last)
  • Return the prepared entity, not just Boolean validation result. For example, parsing a string input as a number.
@jmakeig
jmakeig / entities.d.ts
Last active October 6, 2025 01:45
Pipeline entity model
declare const IDBrand: unique symbol;
type ID = string & { [IDBrand]: void };
/**
* Allows for each property’s original type or string.
* This is useful for accepting values from HTML forms,
* which only allow string inputs.
*/
type Stringish<T> = {
[p in keyof T]: T[p] | string;
@jmakeig
jmakeig / customer-revenue.sql
Last active November 22, 2025 20:04
Use case: Timeseries data that’s stored densely, but needs to be reported sparsely, i.e. with explicit zeros for missing periods. (RIGHT JOIN for the win!)
-- PostgreSQL syntax
DROP TABLE IF EXISTS revenue;
CREATE TABLE revenue (
month TEXT,
customer INT,
channel TEXT,
list NUMERIC
);
@jmakeig
jmakeig / example.js
Last active January 6, 2023 06:30
JSDoc can’t describe some generic functions declared in Typescript
/** @typedef {{name: string; title: string; description: string; sets: any[]; }} Workout */
/** @typedef {{name: string; instructions: string;}} Exercise */
/** @typedef {"en" | "fr" | "de" | "jp" | "zh" | "he"} Lang */
/** @typedef {string | {[L in Lang]?: string}} Message */
/** @typedef {{for: string, message?: Message}} ValidationResult */
/**
* @template Entity
* @typedef {{(condition: {(entity: Entity): boolean}, id: string, message: Message): {(entity: Entity): ValidationResult[]}}} RuleCreator<Entity>
@jmakeig
jmakeig / timer.css
Created December 29, 2021 20:56
Timer CSS animation
svg {
display: inline-block;
height: 90px;
width: 90px;
}
svg.timer {
transform: rotate(-90deg);
overflow: visible;
}
circle.gague {
@jmakeig
jmakeig / fy-date-converter.xlsx
Created July 2, 2020 22:54
Calendar date to MarkLogic fiscal year conversion
="FY"&IF(MONTH(G2)=1, YEAR(G2), YEAR(G2)+1) & "Q"&IF(MONTH(G2)=1, 4, FLOOR((MONTH(G2)+1)/3,1))
@jmakeig
jmakeig / split-json-array.sh
Last active March 23, 2023 15:43
Split a file containing a JSON Array into one file per item
#!/usr/bin/env bash
# Splits a file that contains a top-level JSON Array
# into individual files, one per item, named sequentially
# https://stedolan.github.io/jq/download/
jq -c .[] "$1" | awk '{print > (NR ".json")}'
@jmakeig
jmakeig / transform.js
Created March 15, 2020 18:15
Recursive descent transformation with visitor
#!/usr/bin/env node
/**
* Depth-first copy with selective transformation.
* For each of the `Iterable` selected by the selector function, it
* applies the `visitor` function and continues recursively.
*
*
* @param {object} node the tree structure
* @param {function} [visitor] the function to apply to selected children
@jmakeig
jmakeig / values.js
Last active February 27, 2020 07:37
MarkLogic’s cts.frequency function is magic. Could we do something more explicit? (Spoiler: probably not by much)
// https://github.com/jmakeig/iterant/issues/30
function head(itr) {
if (itr[Symbol.iterator]) return itr[Symbol.iterator]().next().value;
}
function* values(ref, options) {
const sequence = cts.values(ref, options);
for (const value of sequence) {
yield {
value: value.valueOf(),