Skip to content

Instantly share code, notes, and snippets.

View xzec's full-sized avatar

Juraj Žec xzec

View GitHub Profile
@xzec
xzec / AuthError.ts
Created October 1, 2025 15:25
Simple AuthError
import type { AuthErrorType } from '~/auth/types'
export class AuthError extends Error {
readonly type: AuthErrorType
constructor(
type: AuthErrorType,
{ message, cause }: { message?: string } & ErrorOptions = {},
) {
super(message ?? AuthError.defaultMessage[type], { cause })
@xzec
xzec / deno-watchfs-debounce.ts
Last active September 23, 2024 17:49
Deno watch file system with debounce
import { debounce } from 'https://deno.land/std@0.224.0/async/debounce.ts'
await Array.fromAsync(
Deno.watchFs('file.txt'),
debounce((event) => console.debug(`[${event.kind}] ${event.paths[0]}`), 50),
)
// Credits: https://github.com/denoland/deno/issues/12874#issuecomment-1935198354
@xzec
xzec / zodPrivateKeySchema.ts
Last active September 13, 2024 08:32
Zod schema to validate a private key in PEM format. Useful when validating private keys from environment variables, for instance. https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail#Format
import { z } from 'zod'
const privateKeySchema = z.object({
MY_PRIVATE_KEY: z
.string()
.regex(
/-----BEGIN PRIVATE KEY-----\s*\S[\s\S]*?\s*-----END PRIVATE KEY-----/,
'MY_PRIVATE_KEY must be a valid private key.',
)
.describe('Full contents of the private key used to sign/encrypt the thing.'),
@xzec
xzec / fibonacci.ts
Created September 8, 2024 19:57
Simple and readable Fibonacci sequence AsyncGenerator in Node.js
import { setTimeout } from 'node:timers/promises'
export async function* fibonacci(frequencyMs = 200) {
let a = 0n
let b = 1n
while (true) {
yield String(b)
b = a + b
a = b - a
@xzec
xzec / parametrize.ts
Created May 24, 2024 08:17
Appends search params to a URL
const parametrize = (url: string, params: ConstructorParameters<typeof URLSearchParams>[0]) => {
return `${url}?${new URLSearchParams(params)}`
}
@xzec
xzec / isRegExpMatchArrayWithGroups.ts
Created January 3, 2024 13:04
Type guard for RegExp match with named capturing groups
type RegExpMatchArrayWithGroups<G extends string> = RegExpMatchArray & {
groups: Record<G, string> & Record<string, never>
}
const isRegExpMatchArrayWithGroups = <G extends string>(
match: RegExpMatchArray | null,
...groups: G[]
): match is RegExpMatchArrayWithGroups<G> => groups.every((g) => match?.groups !== undefined && g in match.groups)
// usage
@xzec
xzec / resolveFetch.ts
Last active December 13, 2023 16:30
const [err, res] = await resolveFetch(fetch(url))
import resolve from './resolve' // https://gist.github.com/xzec/fac8ca82ce0e5cee41cf3d9769f9c9d0
const resolveFetch = (promise: Promise<Response>) =>
resolve(
promise.then((response) => {
if (response.ok) return response
throw new Error(`${response.status} ${response.statusText}`)
})
)
@xzec
xzec / filterAndTypePredicate.ts
Last active December 13, 2023 16:28
Array.prototype.filter() + type predicate
type Sensor = {
lastMeasuredValue?: number | null
}
const sensors: Sensor[] = []
// type of `values` is narrowed down to `number[]`
const values = sensors
.map((sensor) => sensor.lastMeasuredValue)
.filter((value): value is number => typeof value === 'number')
@xzec
xzec / resolve.ts
Last active December 13, 2023 16:23
const [error, result] = await resolve(promise)
type Resolved<Data> = [undefined, Data] | [Error, undefined]
export const resolve = <Data>(promise: Promise<Data>): Promise<Resolved<Data>> =>
promise
.then((data): [undefined, Data] => [undefined, data])
.catch((error): [Error, undefined] => [error, undefined])
@xzec
xzec / resolveAllSettled.ts
Last active September 28, 2025 07:03
const [errors, results] = resolveAllSettled(await Promise.allSettled(promises))
const resolveAllSettled = <T>(results: PromiseSettledResult<T>[]): [errors: string[], data: T[]] => {
const errors = results
.filter((result): result is PromiseRejectedResult => result.status === 'rejected')
.map(({ reason }) => {
if (reason instanceof Error) return reason.message
if (typeof reason === 'string') return reason
return 'undetected reason'
})
const data = results