Skip to content

Instantly share code, notes, and snippets.

View christophemarois's full-sized avatar

Christophe Marois christophemarois

  • Doximity
  • Montreal
View GitHub Profile
@christophemarois
christophemarois / async-hooks.ts
Created November 4, 2025 16:12
Context for node/bun
import { AsyncLocalStorage } from "node:async_hooks";
function createCtx<T>(name: string, defaultValue?: T) {
const ctx = new AsyncLocalStorage<T>({ name });
const set = (x: T) => ctx.enterWith(x);
const maybeGet = () => ctx.getStore();
const get = (): T => {
const val = maybeGet();
if (val === undefined) {

Keybase proof

I hereby claim:

  • I am christophemarois on github.
  • I am cmarois (https://keybase.io/cmarois) on keybase.
  • I have a public key ASC_FRYqHGxz6zFSsGZyeK8PGOKgiCsD90h8euiHjQgXeAo

To claim this, I am signing this object:

@christophemarois
christophemarois / attempt.ts
Last active April 15, 2025 13:55
attempt.ts
/** Make sure that an unknown object is an error. If it's not, wrap it in an
* error with a useful inspection message */
export function ensureError(err: unknown): Error {
if (err instanceof Error) {
return err
}
let data: string
try {

TS/JS go-to libs

Updated Apr 2025. For looking up trending newer alternatives, use npmtrends. For Nodejs, nodejstoolbox a precompiled list of trends by category.

Universal

Standard libs

Standard libs extend the runtime with convenience helpers, structures and patterns. Use these two in order

@christophemarois
christophemarois / createTypedContext.ts
Created December 3, 2024 16:10
createTypedContext
/** Typed context creation helper
* @example
* export const [useLevel, LevelProvider] = createTypedContext<{ level: number }>('LevelContext')
*/
export function createTypedContext<T>(name: string) {
const Context = createContext<T | null>(null)
function useEnsuredContext() {
const ctx = useContext(Context)
if (ctx === null) {
/* eslint-disable no-console */
/**
* Represents a deeply readonly version of a type, including nested objects,
* arrays, sets, and maps.
* @template T - The type to make deeply readonly.
*/
export type DeepReadonly<T> = T extends (infer R)[]
? ReadonlyArray<DeepReadonly<R>>
: T extends Set<infer R>
? ReadonlySet<DeepReadonly<R>>
/** Create a wrapped AbortController that is aborted when a SIGINT/SIGTERM is received.
* Supports auto-unregistering via explicit resource management.
*
* @example
* using shutdownSignal = new ShutdownSignal()
* shutdownSignal.throwIfAborted()
*
* // or
* const shutdownSignal = new ShutdownSignal()
* try { shutdownSignal.throwIfAborted() } finally { shutdownSignal.unregister() }
@christophemarois
christophemarois / use-map.tsx
Last active April 18, 2024 03:24
React hook for state using ES6 Map
import { useState } from 'react'
export default function useMap<K, V>(): [
Map<K, V>,
{
set: (key: K, value: V) => void
unset: (key: K) => void
clear: () => void
}
] {
@christophemarois
christophemarois / cloudflare-tunnels.md
Last active April 9, 2024 13:24
Cloudflare Tunnels

Cloudflare is a better and free ngrok. With a domain that uses it, set it up like this

  1. Setup a tunnel
cloudflared tunnel login
cloudflared tunnel create test
cloudflared tunnel route dns test test.christophemarois.com
@christophemarois
christophemarois / redactPasswordFromUrl.ts
Created March 7, 2024 15:08
redactPasswordFromUrl.ts
/** Transform the password part of a connection string URL into [redacted].
* Useful for logging. */
export function redactPasswordFromUrl(url: string) {
return url.replace(/^([^:]+):\/\/([^:]*):([^@]+)@/, '$1://$2:[redacted]@')
}