128 lines
3.7 KiB
TypeScript
128 lines
3.7 KiB
TypeScript
import { ExecutionContext } from '@nestjs/common';
|
|
import { GqlExecutionContext } from '@nestjs/graphql';
|
|
import { pipe } from 'fp-ts/lib/function';
|
|
import * as O from 'fp-ts/Option';
|
|
import * as TE from 'fp-ts/TaskEither';
|
|
import * as T from 'fp-ts/Task';
|
|
import * as E from 'fp-ts/Either';
|
|
import { User } from './user/user.model';
|
|
import * as A from 'fp-ts/Array';
|
|
import { JSON_INVALID } from './errors';
|
|
|
|
/**
|
|
* A workaround to throw an exception in an expression.
|
|
* JS throw keyword creates a statement not an expression.
|
|
* This function allows throw to be used as an expression
|
|
* @param errMessage Message present in the error message
|
|
*/
|
|
export function throwErr(errMessage: string): never {
|
|
throw new Error(errMessage);
|
|
}
|
|
|
|
/**
|
|
* Prints the given value to log and returns the same value.
|
|
* Used for debugging functional pipelines.
|
|
* @param val The value to print
|
|
* @returns `val` itself
|
|
*/
|
|
export const trace = <T>(val: T) => {
|
|
console.log(val);
|
|
return val;
|
|
};
|
|
|
|
/**
|
|
* Similar to `trace` but allows for labels and also an
|
|
* optional transform function.
|
|
* @param name The label to given to the trace log (log outputs like this "<name>: <value>")
|
|
* @param transform An optional function to transform the log output value (useful for checking specific aspects or transforms (duh))
|
|
* @returns A function which takes a value, and is traced.
|
|
*/
|
|
export const namedTrace =
|
|
<T>(name: string, transform?: (val: T) => unknown) =>
|
|
(val: T) => {
|
|
console.log(`${name}:`, transform ? transform(val) : val);
|
|
|
|
return val;
|
|
};
|
|
|
|
/**
|
|
* Returns the list of required roles annotated on a GQL Operation
|
|
* @param reflector NestJS Reflector instance
|
|
* @param context NestJS Execution Context
|
|
* @returns An Option which contains the defined roles
|
|
*/
|
|
// export const getAnnotatedRequiredRoles = (
|
|
// reflector: Reflector,
|
|
// context: ExecutionContext,
|
|
// ) =>
|
|
// pipe(
|
|
// reflector.get<TeamMemberRole[]>('requiresTeamRole', context.getHandler()),
|
|
// O.fromNullable,
|
|
// );
|
|
|
|
/**
|
|
* Gets the user from the NestJS GQL Execution Context.
|
|
* Usually used within guards.
|
|
* @param ctx The Execution Context to use to get it
|
|
* @returns An Option of the user
|
|
*/
|
|
export const getUserFromGQLContext = (ctx: ExecutionContext) =>
|
|
pipe(
|
|
ctx,
|
|
GqlExecutionContext.create,
|
|
(ctx) => ctx.getContext<{ user?: User }>(),
|
|
({ user }) => user,
|
|
O.fromNullable,
|
|
);
|
|
|
|
/**
|
|
* Gets a GQL Argument in the defined operation.
|
|
* Usually used in guards.
|
|
* @param argName The name of the argument to get
|
|
* @param ctx The NestJS Execution Context to use to get it.
|
|
* @returns The argument value typed as `unknown`
|
|
*/
|
|
export const getGqlArg = <ArgName extends string>(
|
|
argName: ArgName,
|
|
ctx: ExecutionContext,
|
|
) =>
|
|
pipe(
|
|
ctx,
|
|
GqlExecutionContext.create,
|
|
(ctx) => ctx.getArgs<object>(),
|
|
// We are not sure if this thing will even exist
|
|
// We pass that worry to the caller
|
|
(args) => args[argName as any] as unknown,
|
|
);
|
|
|
|
/**
|
|
* Sequences an array of TaskEither values while maintaining an array of all the error values
|
|
* @param arr Array of TaskEithers
|
|
* @returns A TaskEither saying all the errors possible on the left or all the success values on the right
|
|
*/
|
|
export const taskEitherValidateArraySeq = <A, B>(
|
|
arr: TE.TaskEither<A, B>[],
|
|
): TE.TaskEither<A[], B[]> =>
|
|
pipe(
|
|
arr,
|
|
A.map(TE.mapLeft(A.of)),
|
|
A.sequence(
|
|
TE.getApplicativeTaskValidation(T.ApplicativeSeq, A.getMonoid<A>()),
|
|
),
|
|
);
|
|
|
|
/**
|
|
* String to JSON parser
|
|
* @param {str} str The string to parse
|
|
* @returns {E.Right<T> | E.Left<"json_invalid">} An Either of the parsed JSON
|
|
*/
|
|
export function stringToJson<T>(
|
|
str: string,
|
|
): E.Right<T | any> | E.Left<string> {
|
|
try {
|
|
return E.right(JSON.parse(str));
|
|
} catch (err) {
|
|
return E.left(JSON_INVALID);
|
|
}
|
|
}
|