mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-02-19 13:00:32 -05:00
124 lines
3.1 KiB
TypeScript
124 lines
3.1 KiB
TypeScript
import { randomBytes, createHash } from 'crypto';
|
|
import { type TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
|
|
import {
|
|
ContextConfigDefault,
|
|
FastifyReply,
|
|
RawReplyDefaultExpression,
|
|
type FastifyRequest,
|
|
type FastifySchema,
|
|
type RawRequestDefaultExpression,
|
|
type RawServerDefault,
|
|
type RouteGenericInterface
|
|
} from 'fastify';
|
|
|
|
/**
|
|
* Utility to encode a buffer to a base64 URI.
|
|
*
|
|
* @param buf The buffer to encode.
|
|
* @returns The encoded string.
|
|
*/
|
|
export function base64URLEncode(buf: Buffer): string {
|
|
return buf
|
|
.toString('base64')
|
|
.replace(/\+/g, '-')
|
|
.replace(/\//g, '_')
|
|
.replace(/=/g, '');
|
|
}
|
|
export const verifier = base64URLEncode(randomBytes(32));
|
|
|
|
function sha256(buf: Buffer) {
|
|
return createHash('sha256').update(buf).digest();
|
|
}
|
|
export const challenge = base64URLEncode(sha256(Buffer.from(verifier)));
|
|
|
|
export type UpdateReqType<Schema extends FastifySchema> = FastifyRequest<
|
|
RouteGenericInterface,
|
|
RawServerDefault,
|
|
RawRequestDefaultExpression<RawServerDefault>,
|
|
Schema,
|
|
TypeBoxTypeProvider
|
|
>;
|
|
|
|
export type UpdateReplyType<Schema extends FastifySchema> = FastifyReply<
|
|
RouteGenericInterface,
|
|
RawServerDefault,
|
|
RawRequestDefaultExpression<RawServerDefault>,
|
|
RawReplyDefaultExpression<RawServerDefault>,
|
|
ContextConfigDefault,
|
|
Schema,
|
|
TypeBoxTypeProvider
|
|
>;
|
|
|
|
/* eslint-disable jsdoc/require-description-complete-sentence */
|
|
/**
|
|
* Wrapper around a promise to catch errors and return them as part of the promise.
|
|
*
|
|
* This is most useful to prevent callback / try...catch hell.
|
|
*
|
|
* ## Example:
|
|
*
|
|
* ```ts
|
|
* const maybeWhatIWant = await mapErr(
|
|
* this.prisma.whatIWantCollection.create({
|
|
* data: {}
|
|
* })
|
|
* );
|
|
*
|
|
* if (maybeWhatIWant.hasError) {
|
|
* void reply.code(500);
|
|
* return reply.send('Unable to generate exam, due to: ' +
|
|
* JSON.stringify(maybeWhatIWant.error)
|
|
* );
|
|
* }
|
|
*
|
|
* const whatIWant = maybeWhatIWant.data;
|
|
* ```
|
|
*
|
|
* @param promise - any promise to be tried.
|
|
* @returns a promise with either the data or the caught error
|
|
*/
|
|
export async function mapErr<T>(promise: Promise<T>): Promise<Result<T>> {
|
|
try {
|
|
return { hasError: false, data: await promise };
|
|
} catch (error) {
|
|
return { hasError: true, error };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wrapper around a synchronise function to catch throws and return them as part of the value.
|
|
*
|
|
* This is most useful to prevent try...catch hell.
|
|
*
|
|
* ## Example:
|
|
*
|
|
* ```ts
|
|
* const maybeWhatIWant = await syncMapErr(
|
|
* () => chai.assert.deepEqual({}, {})
|
|
* );
|
|
*
|
|
* if (maybeWhatIWant.hasError) {
|
|
* void reply.code(500);
|
|
* return reply.send('Unable to generate exam, due to: ' +
|
|
* JSON.stringify(maybeWhatIWant.error)
|
|
* );
|
|
* }
|
|
*
|
|
* const whatIWant = maybeWhatIWant.data;
|
|
* ```
|
|
*
|
|
* @param fn - any function to be tried.
|
|
* @returns the data or the caught error
|
|
*/
|
|
export function syncMapErr<T>(fn: () => T): Result<T> {
|
|
try {
|
|
return { hasError: false, data: fn() };
|
|
} catch (error) {
|
|
return { hasError: true, error };
|
|
}
|
|
}
|
|
|
|
export type Result<T> =
|
|
| { hasError: false; data: T }
|
|
| { hasError: true; error: unknown };
|