Skip to content

Instantly share code, notes, and snippets.

View richardscarrott's full-sized avatar

Richard Scarrott richardscarrott

View GitHub Profile
@richardscarrott
richardscarrott / box.css
Last active December 30, 2023 00:37
Fading an element in from display: none; with CSS transitions.
.box {
display: block;
background: red;
width: 200px;
height: 200px;
opacity: 1;
}
.box-hidden {
display: none;
@richardscarrott
richardscarrott / worker.ts
Last active August 25, 2023 19:17
Cloudflare Workers / Pages `stale-while-revalidate`
import { parse } from 'cache-control-parser';
export default {
async fetch(request: Request, env: {}, ctx: ExecutionContext): Promise<Response> {
try {
const cache = await caches.default;
const cachedResponse = await cache.match(request);
if (cachedResponse) {
console.log('Cache: HIT');
if (shouldRevalidate(cachedResponse)) {
@richardscarrott
richardscarrott / portal.tsx
Last active November 8, 2022 11:11
React portal implementation supporting enter / exit animations
import React, {
createContext,
useState,
useCallback,
useMemo,
useContext,
useId,
useLayoutEffect,
useEffect,
} from "react";
@richardscarrott
richardscarrott / request-next-animation-frame.ts
Last active October 18, 2022 10:19
Utility to enqueue + cancel callback for *next* animation frame (Double rAF)
const requestNextAnimationFrame = (callback: FrameRequestCallback) => {
const handles: number[] = [];
const requestThisAnimationFrame = (callback: FrameRequestCallback) => {
handles.push(window.requestAnimationFrame(callback));
};
requestThisAnimationFrame(() => requestThisAnimationFrame(callback));
return () => handles.forEach(handle => window.cancelAnimationFrame(handle));
};
@richardscarrott
richardscarrott / TError.ts
Last active September 5, 2022 13:51
Modern VError
interface TErrorOptions<Info, Cause> {
readonly msg?: string;
readonly info?: Info;
readonly cause?: Cause;
}
class TError<Info, Cause extends Error> extends Error {
public info?: Info;
public cause?: Cause;
constructor({ msg, cause, info }: TErrorOptions<Info, Cause>) {
@richardscarrott
richardscarrott / ___README.md
Last active July 31, 2022 12:08
Simple middleware stack for next.js getServerSideProps (and eventually Api Routes)

Next.js use

Simple middleware stack for next.js getServerSideProps (and eventually Api Routes)

import { use, wrap, Middleware } from './use';

interface WithUserVars {
   users?: User;
}
@richardscarrott
richardscarrott / with-transaction.ts
Created June 25, 2021 10:12
MongoDB withTransaction
// The docs for mongodb native driver sessions are pretty bare. The best example I can find is
// https://www.mongodb.com/blog/post/quick-start-nodejs--mongodb--how-to-implement-transactions
// but the code is generally not pretty; I think the following is likely the most suitable API:
// const doc = withTransaction(async session => {
// const doc = await users.updateOne({ _id: id }, { $set: { email } }, { returnOriginal: false, session });
// await orders.updateMany({ email }, { $set: { userId: id } }, { session });
// return doc;
// });
const withTransaction = async <T>(
fn: (session: ClientSession) => Promise<T>
@richardscarrott
richardscarrott / to-promise.js
Last active February 16, 2021 13:21
Highlandjs toPromise backpressure
const _ = require("highland");
const { Readable } = require("stream");
const wrapAsync = require("./wrap-async");
const sleep = (duration) =>
new Promise((resolve) => setTimeout(resolve, duration));
class Counter extends Readable {
constructor(opt) {
super(opt);
@richardscarrott
richardscarrott / !react-enzyme-render-methods.md
Last active September 9, 2020 01:39
react-enzyme - `shallow` vs `mount` vs `render` lifecycle methods

An exploration of the different render methods available in react-enzyme.

@richardscarrott
richardscarrott / server.js
Created January 9, 2020 10:39
HTTP retry
const express = require('express');
console.log(process.version);
const app = express();
app.get('/hello', (req, res) => {
console.log('HANDLING REQUEST');
res.setHeader('content-type', 'application/json');
res.flushHeaders(); // `flushHeaders` to prevent http client from retrying and therefore invoking this handler multiple times.