← Public packages
@kentcdodds/raycast
Raycast launcher: stored execute commands via webhooks (canonical; do not use raycast-shortcuts).
src/launcher-auth.ts
38 lines · 1.4 KB · TypeScriptimport { packageStorage } from 'kody:runtime'
export const LAUNCHER_TOKEN_HASH_KEY = 'launcherTokenSha256'
export const LAUNCHER_TOKEN_HINT_KEY = 'launcherTokenHint'
export async function sha256Hex(value: string): Promise<string> {
const bytes = new TextEncoder().encode(value)
const digest = await crypto.subtle.digest('SHA-256', bytes)
return [...new Uint8Array(digest)]
.map((b) => b.toString(16).padStart(2, '0'))
.join('')
}
export async function storeLauncherToken(token: string) {
const trimmed = token.trim()
if (trimmed.length < 24) {
throw new Error('Launcher token must be at least 24 characters.')
}
const hash = await sha256Hex(trimmed)
const storage = packageStorage()
await storage.set(LAUNCHER_TOKEN_HASH_KEY, hash)
await storage.set(LAUNCHER_TOKEN_HINT_KEY, trimmed.slice(-4))
return { hash, hint: trimmed.slice(-4) }
}
export async function verifyLauncherToken(token: string | null): Promise<boolean> {
if (!token) return false
const expected = await packageStorage().get(LAUNCHER_TOKEN_HASH_KEY)
if (typeof expected !== 'string' || !expected) return false
const actual = await sha256Hex(token.trim())
return actual === expected
}
export function bearerFromRequest(request: Request): string | null {
const header = request.headers.get('authorization') || ''
const match = header.match(/^Bearer\s+(.+)$/i)
return match?.[1]?.trim() || null
}