The Coline App SDK: apps, tools, file types and surfaces that run inside Coline workspaces, and public websites with Coline Sites. TypeScript, with an in-memory test workspace. MIT.
| 4 | let binary = ""; |
| 5 | for (const byte of bytes) { |
| 6 | binary += String.fromCharCode(byte); |
| 7 | } |
| 8 |
| 9 | return btoa(binary) |
| 10 | .replace(/\+/g, "-") |
| 11 | .replace(/\//g, "_") |
| 12 | .replace(/=+$/g, ""); |
| 13 | } |
| 14 |
| 15 | export function generatePkceCodeVerifier(byteLength = 48): string { |
| 16 | if (!Number.isInteger(byteLength) || byteLength < 32 || byteLength > 96) { |
| 17 | throw new Error("byteLength must be an integer between 32 and 96."); |
| 18 | } |
| 19 |
| 20 | const bytes = crypto.getRandomValues(new Uint8Array(byteLength)); |
| 21 | return toBase64Url(bytes); |
| 22 | } |
| 23 |
| 24 | export async function createPkceCodeChallenge( |
| 25 | verifier: string, |
| 26 | ): Promise<string> { |
| 27 | const digest = await crypto.subtle.digest("SHA-256", encoder.encode(verifier)); |
| 28 | return toBase64Url(new Uint8Array(digest)); |
| 29 | } |
| 30 |
| 31 | export async function createPkcePair(byteLength = 48): Promise<{ |
| 32 | verifier: string; |
| 33 | challenge: string; |
| 34 | method: "S256"; |
| 35 | }> { |
| 36 | const verifier = generatePkceCodeVerifier(byteLength); |
| 37 | const challenge = await createPkceCodeChallenge(verifier); |
| 38 |
| 39 | return { |
| 40 | verifier, |
| 41 | challenge, |
| 42 | method: "S256", |
| 43 | }; |
| 44 | } |
| 45 |
| 46 | export function createOauthState(byteLength = 24): string { |
| 47 | if (!Number.isInteger(byteLength) || byteLength < 16 || byteLength > 96) { |
| 48 | throw new Error("byteLength must be an integer between 16 and 96."); |
| 49 | } |
| 50 |
| 51 | return toBase64Url(crypto.getRandomValues(new Uint8Array(byteLength))); |
| 52 | } |
| 53 |