move stuff around until it feels right
This commit is contained in:
5
helpers/get-environment-value.ts
Normal file
5
helpers/get-environment-value.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { raise } from "./raise.js"
|
||||
|
||||
export function getEnvironmentValue(name: string) {
|
||||
return process.env[name] ?? raise(`Missing environment variable: ${name}`)
|
||||
}
|
||||
3
helpers/last.ts
Normal file
3
helpers/last.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function last<T>(array: T[]): T | undefined {
|
||||
return array[array.length - 1]
|
||||
}
|
||||
12
helpers/log-pretty.ts
Normal file
12
helpers/log-pretty.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { inspect } from "node:util"
|
||||
|
||||
// eslint-disable-next-line import/no-unused-modules
|
||||
export function logPretty(value: unknown) {
|
||||
console.info(
|
||||
inspect(value, {
|
||||
// depth: Number.POSITIVE_INFINITY,
|
||||
depth: 10,
|
||||
colors: true,
|
||||
}),
|
||||
)
|
||||
}
|
||||
15
helpers/omit.ts
Normal file
15
helpers/omit.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { Except } from "type-fest"
|
||||
|
||||
// eslint-disable-next-line import/no-unused-modules
|
||||
export function omit<Subject extends object, Key extends keyof Subject>(
|
||||
subject: Subject,
|
||||
keys: Key[],
|
||||
): Except<Subject, Key> {
|
||||
const result: any = {}
|
||||
for (const key in subject) {
|
||||
if (!keys.includes(key as unknown as Key)) {
|
||||
result[key] = subject[key]
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
14
helpers/pick.ts
Normal file
14
helpers/pick.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
// eslint-disable-next-line import/no-unused-modules
|
||||
export function pick<T, K extends keyof T>(
|
||||
object: T,
|
||||
...keys: K[]
|
||||
): Pick<T, K> {
|
||||
const result: any = {}
|
||||
for (const key of keys) {
|
||||
const value = object[key]
|
||||
if (value !== undefined) {
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
5
helpers/raise.ts
Normal file
5
helpers/raise.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { toError } from "./to-error.js"
|
||||
|
||||
export function raise(error: unknown): never {
|
||||
throw toError(error)
|
||||
}
|
||||
10
helpers/reject-after.ts
Normal file
10
helpers/reject-after.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { setTimeout } from "node:timers/promises"
|
||||
import { toError } from "./to-error.js"
|
||||
|
||||
export async function rejectAfter(
|
||||
timeMs: number,
|
||||
error: unknown = `rejected after ${timeMs}ms`,
|
||||
): Promise<never> {
|
||||
await setTimeout(timeMs)
|
||||
return Promise.reject(toError(error))
|
||||
}
|
||||
21
helpers/retry-with-timeout.ts
Normal file
21
helpers/retry-with-timeout.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { setTimeout } from "node:timers/promises"
|
||||
|
||||
const maxTime = 500
|
||||
const waitPeriod = 50
|
||||
|
||||
export async function retryWithTimeout<T>(
|
||||
callback: () => Promise<T> | T,
|
||||
): Promise<T> {
|
||||
const startTime = Date.now()
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
try {
|
||||
return await callback()
|
||||
} catch (error) {
|
||||
if (Date.now() - startTime > maxTime) {
|
||||
throw error
|
||||
}
|
||||
await setTimeout(waitPeriod)
|
||||
}
|
||||
}
|
||||
}
|
||||
3
helpers/to-error.ts
Normal file
3
helpers/to-error.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export function toError(value: unknown) {
|
||||
return value instanceof Error ? value : new Error(String(value))
|
||||
}
|
||||
4
helpers/to-upper.ts
Normal file
4
helpers/to-upper.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
/** A typesafe version of toUpperCase */
|
||||
export function toUpper<S extends string>(string: S) {
|
||||
return string.toUpperCase() as Uppercase<S>
|
||||
}
|
||||
6
helpers/types.ts
Normal file
6
helpers/types.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
/* eslint-disable import/no-unused-modules */
|
||||
export type MaybePromise<T> = T | Promise<T>
|
||||
|
||||
export type ValueOf<Type> = Type extends ReadonlyArray<infer Value>
|
||||
? Value
|
||||
: Type[keyof Type]
|
||||
25
helpers/with-logged-method-calls.ts
Normal file
25
helpers/with-logged-method-calls.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { inspect } from "node:util"
|
||||
|
||||
// eslint-disable-next-line import/no-unused-modules
|
||||
export function withLoggedMethodCalls<T extends object>(value: T) {
|
||||
return new Proxy(value as Record<string | symbol, unknown>, {
|
||||
get(target, property) {
|
||||
const value = target[property]
|
||||
if (typeof value !== "function") {
|
||||
return value
|
||||
}
|
||||
return (...values: any[]) => {
|
||||
console.info(
|
||||
`${String(property)}(${values
|
||||
.map((value) =>
|
||||
typeof value === "object" && value !== null
|
||||
? value.constructor.name
|
||||
: inspect(value, { colors: true }),
|
||||
)
|
||||
.join(", ")})`,
|
||||
)
|
||||
return value.apply(target, values)
|
||||
}
|
||||
},
|
||||
}) as T
|
||||
}
|
||||
Reference in New Issue
Block a user