Move in progress apps temporarily

This commit is contained in:
Darren Clarke 2023-03-07 14:09:49 +00:00
parent ba04aa108c
commit 6eaaf8e9be
360 changed files with 6171 additions and 55 deletions

View file

@ -0,0 +1,44 @@
/**
* Used by Flavor to mark a type in a readable way.
*/
export interface Flavoring<FlavorT> {
_type?: FlavorT;
}
/**
*
* Create a "flavored" version of a type. TypeScript will disallow mixing
* flavors, but will allow unflavored values of that type to be passed in where
* a flavored version is expected. This is a less restrictive form of branding.
*
*/
export type Flavor<T, FlavorT> = T & Flavoring<FlavorT>;
export type UUID = Flavor<string, "A UUID">;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const deepFreeze = (o: unknown): any => {
Object.freeze(o);
const oIsFunction = typeof o === "function";
const hasOwnProp = Object.prototype.hasOwnProperty;
Object.getOwnPropertyNames(o).forEach((prop) => {
if (
hasOwnProp.call(o, prop) &&
(oIsFunction
? prop !== "caller" && prop !== "callee" && prop !== "arguments"
: true) &&
// @ts-expect-error
o[prop] !== null &&
// @ts-expect-error
(typeof o[prop] === "object" || typeof o[prop] === "function") &&
// @ts-expect-error
!Object.isFrozen(o[prop])
) {
// @ts-expect-error
deepFreeze(o[prop]);
}
});
return o;
};

View file

@ -0,0 +1,59 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import * as Boom from "@hapi/boom";
import * as Hapi from "@hapi/hapi";
interface IResponseMeta {
operation?: string;
method?: string;
paging?: string | null;
}
interface IResponseError {
code?: string | number;
message?: string;
error?: string;
}
interface IResponse<T> {
meta: IResponseMeta;
data: T[];
errors: IResponseError[];
}
interface IResponseOptions<T> {
value?: T | null | undefined;
boom?: Boom.Boom<any> | null | undefined;
}
export function createResponse<T>(
request: Hapi.Request,
{ value = undefined, boom = undefined }: IResponseOptions<T>
): IResponse<T> {
const errors: IResponseError[] = [];
const data: any = [];
if (boom) {
errors.push({
code: boom.output.payload.statusCode,
error: boom.output.payload.error,
message: boom.output.payload.message,
});
}
if (value && data) {
if (Array.isArray(value)) {
data.push(...value);
} else {
data.push(value);
}
}
return {
meta: {
method: request.method.toUpperCase(),
operation: request.url.pathname,
},
data,
errors,
};
}

View file

@ -0,0 +1,62 @@
import process from "process";
import * as Hapi from "@hapi/hapi";
import * as Joi from "joi";
import Hoek from "@hapi/hoek";
import * as Boom from "@hapi/boom";
export interface HapiValidationError extends Joi.ValidationError {
output: {
statusCode: number;
headers: Hapi.Utils.Dictionary<string | string[]>;
payload: {
statusCode: number;
error: string;
message?: string;
validation: {
source: string;
keys: string[];
};
};
};
}
export function defaultValidationErrorHandler(
request: Hapi.Request,
h: Hapi.ResponseToolkit,
err?: Error
): Hapi.Lifecycle.ReturnValue {
// Newer versions of Joi don't format the key for missing params the same way. This shim
// provides backwards compatibility. Unfortunately, Joi doesn't export it's own Error class
// in JS so we have to rely on the `name` key before we can cast it.
//
// The Hapi code we're 'overwriting' can be found here:
// https://github.com/hapijs/hapi/blob/master/lib/validation.js#L102
if (err && err.name === "ValidationError" && err.hasOwnProperty("output")) {
const validationError: HapiValidationError = err as HapiValidationError;
const validationKeys: string[] = [];
validationError.details.forEach((detail) => {
if (detail.path.length > 0) {
validationKeys.push(Hoek.escapeHtml(detail.path.join(".")));
} else {
// If no path, use the value sigil to signal the entire value had an issue.
validationKeys.push("value");
}
});
validationError.output.payload.validation.keys = validationKeys;
}
throw err;
}
export const validatingFailAction = async (
request: Hapi.Request,
h: Hapi.ResponseToolkit,
err: Error
): Promise<void> => {
if (process.env.NODE_ENV === "production") {
throw Boom.badRequest("Invalid request payload input");
} else {
defaultValidationErrorHandler(request, h, err);
}
};