Add all repos
This commit is contained in:
parent
faa12c60bc
commit
8a91c9b89b
369 changed files with 29047 additions and 28 deletions
44
metamigo-common/helpers/index.ts
Normal file
44
metamigo-common/helpers/index.ts
Normal 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;
|
||||
};
|
||||
59
metamigo-common/helpers/response.ts
Normal file
59
metamigo-common/helpers/response.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
62
metamigo-common/helpers/validation-error.ts
Normal file
62
metamigo-common/helpers/validation-error.ts
Normal 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);
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue