Add PostgreSQL and Redis integration for users and sessions Implement password and WebAuthn passkey login flows Add Docker stack, super-admin seeding, and protected routes
42 lines
957 B
TypeScript
42 lines
957 B
TypeScript
import { randomBytes } from 'node:crypto'
|
|
|
|
export function encodeBase64Url(value: Buffer | Uint8Array | string): string {
|
|
const buffer = typeof value === 'string'
|
|
? Buffer.from(value, 'utf8')
|
|
: Buffer.from(value)
|
|
|
|
return buffer
|
|
.toString('base64')
|
|
.replace(/\+/g, '-')
|
|
.replace(/\//g, '_')
|
|
.replace(/=+$/g, '')
|
|
}
|
|
|
|
export function decodeBase64Url(value: string): Buffer {
|
|
const normalized = value
|
|
.replace(/-/g, '+')
|
|
.replace(/_/g, '/')
|
|
|
|
const padding = normalized.length % 4 === 0
|
|
? ''
|
|
: '='.repeat(4 - (normalized.length % 4))
|
|
|
|
return Buffer.from(`${normalized}${padding}`, 'base64')
|
|
}
|
|
|
|
export function randomToken(length = 32): string {
|
|
return encodeBase64Url(randomBytes(length))
|
|
}
|
|
|
|
export function toIsoString(value: Date | string | null): string | null {
|
|
if (!value) {
|
|
return null
|
|
}
|
|
|
|
if (value instanceof Date) {
|
|
return value.toISOString()
|
|
}
|
|
|
|
return new Date(value).toISOString()
|
|
}
|