Skip to content

Instantly share code, notes, and snippets.

@qwtel
qwtel / whatwg-stream-to-async-iterable.ts
Created Oct 12, 2020
Convert WHATWG web streams to async iterables and back
View whatwg-stream-to-async-iterable.ts
export async function* streamToAsyncIterable<T>(stream: ReadableStream<T>): AsyncIterableIterator<T> {
const reader = stream.getReader();
try {
while (true) {
const { done, value } = await reader.read();
if (done) return;
yield value;
}
} finally { reader.releaseLock() }
}
@qwtel
qwtel / cf-storage-area.ts
Last active Dec 30, 2020
kv-storage implementation for Cloudflare Workers
View cf-storage-area.ts
import { Base64Encoder, Base64Decoder } from 'base64-encoding';
const PREFIX = 'data:application/octet-stream;base64,';
const b64e = new Base64Encoder();
const b64d = new Base64Decoder();
const encodeKey = (key: string | BufferSource) => typeof key !== 'string' ? PREFIX + b64e.encode(key) : key;
const decodeKey = (key: string) => key.startsWith(PREFIX) ? b64d.decode(key.substr(PREFIX.length)) : key;
@qwtel
qwtel / create-resolvable-promise.ts
Last active Jun 21, 2020
TS implementation of a promise that can be resolved after it has been created.
View create-resolvable-promise.ts
type Resolver<T> = (value: T | PromiseLike<T>) => void;
type Rejector = (reason?: any) => void;
type ResolvablePromise<T> = Promise<T> & { resolve: Resolver<T>, reject: Rejector }
export function createResolvablePromise<T>(): ResolvablePromise<T> {
let res: Resolver<T>
let rej: Rejector;
const promise = new Promise((r, s) => (res = r, rej = s)) as ResolvablePromise<T>;
promise.resolve = res;
promise.reject = rej;
return promise;
View 10.js
const nearestAsteroidsByAngle = pipe(
asteroids.filter(mkNe(laserPos)),
groupBy(mkCalcAngle(laserPos)),
mapValues(ps => ps.sort((p1, p2) => distToLaser(p1) - distToLaser(p2))),
intoMap(),
);
pipe(
cycle([...nearestAsteroidsByAngle.keys()].sort((a, b) => a - b)),
skipWhile(a => a < -Math.PI/2),
View ParamsURL.js
export class ParamsURL extends URL {
constructor(href, params, origin = globalThis.location) {
super(href, origin);
if (params) {
this.search = new URLSearchParams([...this.searchParams, ...Object.entries(params)]);
}
}
}
View urlWithParams.js
export const urlWithParams = (url, params) => {
const u = new URL(url, global.location.origin)
if (params) {
u.search = new URLSearchParams([...u.searchParams, ...Object.entries(params)])
}
return u.href
}
@qwtel
qwtel / README.md
Last active Aug 12, 2020
Subtypes of the browser's own Request and Response types adopted for JSON objects.
View README.md

Main difference to regular Response and Request types is that no manual JSON.stringify and headers.set('Content-Type', ...) is required.

In my opinion, JSONRequest is the most lightweight way of fixing the biggest issue of the Fetch API when dealing with JSON APIs, without resorting to full alternatives such as superagent or axios.

Example:

const response = await fetch(new JSONRequest('/comments', {
  method: 'POST',
  body: { text: 'Usage example: ...' },
@qwtel
qwtel / README.md
Last active Sep 8, 2019
Returns the first promise that resolves with a truthy value, or undefined if all promises resolve with a nullish value.
View README.md

Returns the first promise that resolves with a truthy value, or undefined if all promises resolve with a nullish value.

Note that this inherits the behavior of Promise.race, where the returned promise rejects as soon as one input promise rejects.

Example use case: Getting a cached response from a number of caches, without resorting to a lookup in all caches via caches.match:

View replacing-cryptojs-with-web-cryptography-for-aes.js
import md5 from "js-md5";
import { base64ToUint8Array, splitUint8Array, concatUint8Arrays } from "./utils";
const HEAD_SIZE_DWORD = 2;
const SALT_SIZE_DWORD = 2;
export async function decryptCryptoJSCipherBase64(
cryptoJSCipherBase64,
password,
View keybase.md

Keybase proof

I hereby claim:

  • I am qwtel on github.
  • I am qwtel (https://keybase.io/qwtel) on keybase.
  • I have a public key ASCbFur24236CAj1oGXKHjjTVGaT35JcTLQNXvXUFG7aOwo

To claim this, I am signing this object: