@sqrzro/server 2.0.0-bz.9 → 2.0.0-r19.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/auth.js +1 -1
- package/cache.js +1 -1
- package/dist/auth/index.cjs +3 -0
- package/dist/auth/index.cjs.map +1 -0
- package/dist/auth/index.d.cts +110 -0
- package/dist/auth/index.d.ts +110 -6
- package/dist/auth/index.js +3 -6
- package/dist/auth/index.js.map +1 -0
- package/dist/cache/index.cjs +2 -0
- package/dist/cache/index.cjs.map +1 -0
- package/dist/cache/index.d.cts +4 -0
- package/dist/cache/index.d.ts +4 -1
- package/dist/cache/index.js +2 -1
- package/dist/cache/index.js.map +1 -0
- package/dist/database/schema.cjs +2 -0
- package/dist/database/schema.cjs.map +1 -0
- package/dist/database/schema.d.cts +405 -0
- package/dist/database/schema.d.ts +155 -34
- package/dist/database/schema.js +2 -42
- package/dist/database/schema.js.map +1 -0
- package/dist/forms/index.cjs +2 -0
- package/dist/forms/index.cjs.map +1 -0
- package/dist/forms/index.d.cts +50 -0
- package/dist/forms/index.d.ts +50 -3
- package/dist/forms/index.js +2 -3
- package/dist/forms/index.js.map +1 -0
- package/dist/lists/index.cjs +2 -0
- package/dist/lists/index.cjs.map +1 -0
- package/dist/lists/{ListService.d.ts → index.d.cts} +5 -3
- package/dist/lists/index.d.ts +18 -1
- package/dist/lists/index.js +2 -1
- package/dist/lists/index.js.map +1 -0
- package/dist/mail/index.cjs +3 -0
- package/dist/mail/index.cjs.map +1 -0
- package/dist/mail/index.d.cts +19 -0
- package/dist/mail/index.d.ts +19 -1
- package/dist/mail/index.js +3 -1
- package/dist/mail/index.js.map +1 -0
- package/dist/middleware.cjs +2 -0
- package/dist/middleware.cjs.map +1 -0
- package/dist/middleware.d.cts +5 -0
- package/dist/middleware.d.ts +5 -3
- package/dist/middleware.js +2 -30
- package/dist/middleware.js.map +1 -0
- package/dist/url/index.cjs +3 -0
- package/dist/url/index.cjs.map +1 -0
- package/dist/url/{URLService.d.ts → index.d.cts} +9 -2
- package/dist/url/index.d.ts +33 -1
- package/dist/url/index.js +3 -1
- package/dist/url/index.js.map +1 -0
- package/forms.js +1 -1
- package/jest.config.js +7 -0
- package/lists.js +1 -1
- package/mail.js +1 -1
- package/middleware.js +1 -1
- package/next-env.d.ts +5 -0
- package/package.json +77 -46
- package/schema.js +1 -1
- package/url.js +1 -1
- package/database.d.ts +0 -1
- package/database.js +0 -1
- package/dist/auth/AuthService.d.ts +0 -14
- package/dist/auth/AuthService.js +0 -135
- package/dist/auth/ClientService.d.ts +0 -11
- package/dist/auth/ClientService.js +0 -47
- package/dist/auth/LoginRequest.d.ts +0 -4
- package/dist/auth/LoginRequest.js +0 -8
- package/dist/auth/MFARequest.d.ts +0 -4
- package/dist/auth/MFARequest.js +0 -9
- package/dist/auth/MFAService.d.ts +0 -6
- package/dist/auth/MFAService.js +0 -105
- package/dist/auth/PasswordRequest.d.ts +0 -4
- package/dist/auth/PasswordRequest.js +0 -12
- package/dist/auth/PasswordResetRequest.d.ts +0 -4
- package/dist/auth/PasswordResetRequest.js +0 -13
- package/dist/auth/PasswordService.d.ts +0 -8
- package/dist/auth/PasswordService.js +0 -54
- package/dist/auth/SessionService.d.ts +0 -42
- package/dist/auth/SessionService.js +0 -127
- package/dist/auth/interfaces.d.ts +0 -20
- package/dist/auth/interfaces.js +0 -1
- package/dist/cache/CacheService.d.ts +0 -2
- package/dist/cache/CacheService.js +0 -14
- package/dist/database/DatabaseService.d.ts +0 -7
- package/dist/database/DatabaseService.js +0 -12
- package/dist/forms/FormService.d.ts +0 -16
- package/dist/forms/FormService.js +0 -78
- package/dist/forms/ImageService.d.ts +0 -7
- package/dist/forms/ImageService.js +0 -19
- package/dist/forms/ValidationError.d.ts +0 -4
- package/dist/forms/ValidationError.js +0 -7
- package/dist/forms/ValidationService.d.ts +0 -20
- package/dist/forms/ValidationService.js +0 -59
- package/dist/forms/lang.d.ts +0 -2
- package/dist/forms/lang.js +0 -115
- package/dist/lists/ListService.js +0 -28
- package/dist/mail/MailService.d.ts +0 -12
- package/dist/mail/MailService.js +0 -55
- package/dist/url/URLService.js +0 -48
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { DrizzlePostgreSQLAdapter } from '@lucia-auth/adapter-drizzle';
|
|
2
|
-
import { Lucia, generateId } from 'lucia';
|
|
3
|
-
import { cookies } from 'next/headers';
|
|
4
|
-
import { NextResponse } from 'next/server';
|
|
5
|
-
import { match } from 'path-to-regexp';
|
|
6
|
-
import { getAllowedRoles } from './AuthService';
|
|
7
|
-
import { db } from '../database/DatabaseService';
|
|
8
|
-
import { authSessionTable, authUserTable } from '../database/schema';
|
|
9
|
-
import { getFromCache, setToCache } from '../cache/CacheService';
|
|
10
|
-
import { getOrigin } from '../url/URLService';
|
|
11
|
-
import { getFromObject } from '@sqrzro/utility';
|
|
12
|
-
const DEFAULT_REDIRECT = '/auth/login';
|
|
13
|
-
const ID_LENGTH = 16;
|
|
14
|
-
const DEFAULT_SCOPES = {
|
|
15
|
-
ANON: {
|
|
16
|
-
allowedRoute: '/auth/(login|password)',
|
|
17
|
-
redirectOnUnauth: DEFAULT_REDIRECT,
|
|
18
|
-
},
|
|
19
|
-
MFA: {
|
|
20
|
-
allowedRoute: '/auth/mfa',
|
|
21
|
-
redirectOnUnauth: '/auth/mfa',
|
|
22
|
-
},
|
|
23
|
-
AUTHED: {
|
|
24
|
-
allowedRoute: '*',
|
|
25
|
-
redirectOnAuth: '/',
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
const adapter = new DrizzlePostgreSQLAdapter(db, authSessionTable, authUserTable);
|
|
29
|
-
export const lucia = new Lucia(adapter, {
|
|
30
|
-
sessionCookie: {
|
|
31
|
-
attributes: {
|
|
32
|
-
secure: process.env.NODE_ENV === 'production',
|
|
33
|
-
},
|
|
34
|
-
name: process.env.AUTH_COOKIE_NAME || 'auth_session',
|
|
35
|
-
},
|
|
36
|
-
getSessionAttributes: (attributes) => ({
|
|
37
|
-
scope: attributes.scope,
|
|
38
|
-
}),
|
|
39
|
-
getUserAttributes: (attributes) => ({
|
|
40
|
-
email: attributes.email,
|
|
41
|
-
role: attributes.role,
|
|
42
|
-
}),
|
|
43
|
-
});
|
|
44
|
-
export function generateID(length = ID_LENGTH) {
|
|
45
|
-
return generateId(length);
|
|
46
|
-
}
|
|
47
|
-
export async function invalidateSession(id) {
|
|
48
|
-
const cookie = lucia.createBlankSessionCookie();
|
|
49
|
-
cookies().set(cookie.name, cookie.value, cookie.attributes);
|
|
50
|
-
return lucia.invalidateSession(id);
|
|
51
|
-
}
|
|
52
|
-
export async function invalidateUserSessions(id) {
|
|
53
|
-
return lucia.invalidateUserSessions(id);
|
|
54
|
-
}
|
|
55
|
-
export async function createUserSession(id, scope = 'ANON') {
|
|
56
|
-
const session = await lucia.createSession(id, { scope });
|
|
57
|
-
const sessionCookie = lucia.createSessionCookie(session.id);
|
|
58
|
-
cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
export function getSessionID() {
|
|
62
|
-
return cookies().get(lucia.sessionCookieName)?.value ?? null;
|
|
63
|
-
}
|
|
64
|
-
export function checkSessionExists() {
|
|
65
|
-
return Boolean(getSessionID());
|
|
66
|
-
}
|
|
67
|
-
export async function getSessionUser() {
|
|
68
|
-
const sessionID = getSessionID();
|
|
69
|
-
if (!sessionID) {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
const { user } = await lucia.validateSession(sessionID);
|
|
73
|
-
if (!user?.role || !getAllowedRoles().includes(user.role)) {
|
|
74
|
-
return null;
|
|
75
|
-
}
|
|
76
|
-
return getFromObject(user, ['id', 'email', 'role']);
|
|
77
|
-
}
|
|
78
|
-
export function checkRouteAllowed(pathname, route) {
|
|
79
|
-
if (!route) {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
if (route === '*') {
|
|
83
|
-
return true;
|
|
84
|
-
}
|
|
85
|
-
return match(route)(pathname) !== false;
|
|
86
|
-
}
|
|
87
|
-
export async function getScopes() {
|
|
88
|
-
const scopes = await getFromCache(`${getOrigin()}:scopes`);
|
|
89
|
-
return scopes ? JSON.parse(scopes) : DEFAULT_SCOPES;
|
|
90
|
-
}
|
|
91
|
-
export async function getScopeByID(id) {
|
|
92
|
-
const scopes = await getScopes();
|
|
93
|
-
return scopes[id];
|
|
94
|
-
}
|
|
95
|
-
export async function setScopes(customScopes) {
|
|
96
|
-
const scopes = {
|
|
97
|
-
ANON: {
|
|
98
|
-
...DEFAULT_SCOPES.ANON,
|
|
99
|
-
...customScopes?.ANON,
|
|
100
|
-
},
|
|
101
|
-
MFA: {
|
|
102
|
-
...DEFAULT_SCOPES.MFA,
|
|
103
|
-
...customScopes?.MFA,
|
|
104
|
-
},
|
|
105
|
-
AUTHED: {
|
|
106
|
-
...DEFAULT_SCOPES.AUTHED,
|
|
107
|
-
...customScopes?.AUTHED,
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
return setToCache(`${getOrigin()}:scopes`, JSON.stringify(scopes));
|
|
111
|
-
}
|
|
112
|
-
async function validateSessionFromID(sessionID, pathname) {
|
|
113
|
-
const scopes = await getScopes();
|
|
114
|
-
const { session, user } = await lucia.validateSession(sessionID);
|
|
115
|
-
const scope = scopes[session && getAllowedRoles().includes(user?.role) ? session.scope : 'ANON'];
|
|
116
|
-
return checkRouteAllowed(pathname, scope.allowedRoute)
|
|
117
|
-
? null
|
|
118
|
-
: scope.redirectOnUnauth || DEFAULT_REDIRECT;
|
|
119
|
-
}
|
|
120
|
-
export async function handleSession(request, customScopes) {
|
|
121
|
-
const sessionID = request.nextUrl.searchParams.get('id') || '';
|
|
122
|
-
const pathname = request.nextUrl.searchParams.get('pathname') || '/';
|
|
123
|
-
await setScopes(customScopes);
|
|
124
|
-
return NextResponse.json({
|
|
125
|
-
redirect: await validateSessionFromID(sessionID, pathname),
|
|
126
|
-
});
|
|
127
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export interface LoginFormFields {
|
|
2
|
-
email: string;
|
|
3
|
-
password: string;
|
|
4
|
-
}
|
|
5
|
-
export interface MFAFormFields {
|
|
6
|
-
token: string;
|
|
7
|
-
}
|
|
8
|
-
export interface PasswordFormFields {
|
|
9
|
-
email: string;
|
|
10
|
-
}
|
|
11
|
-
export interface PasswordResetFormFields {
|
|
12
|
-
password: string;
|
|
13
|
-
token: string;
|
|
14
|
-
}
|
|
15
|
-
export interface UserObject {
|
|
16
|
-
id: string;
|
|
17
|
-
email: string;
|
|
18
|
-
password?: string | null;
|
|
19
|
-
role?: number;
|
|
20
|
-
}
|
package/dist/auth/interfaces.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { createClient } from 'redis';
|
|
2
|
-
async function getClient() {
|
|
3
|
-
const client = createClient();
|
|
4
|
-
await client.connect();
|
|
5
|
-
return client;
|
|
6
|
-
}
|
|
7
|
-
export async function getFromCache(key) {
|
|
8
|
-
const client = await getClient();
|
|
9
|
-
return client.get(key);
|
|
10
|
-
}
|
|
11
|
-
export async function setToCache(key, value) {
|
|
12
|
-
const client = await getClient();
|
|
13
|
-
await client.set(key, value);
|
|
14
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { drizzle } from 'drizzle-orm/postgres-js';
|
|
2
|
-
import postgres from 'postgres';
|
|
3
|
-
function createSingleton() {
|
|
4
|
-
if (!process.env.DATABASE_URL) {
|
|
5
|
-
throw new Error('DATABASE_URL is not defined');
|
|
6
|
-
}
|
|
7
|
-
return drizzle(postgres(process.env.DATABASE_URL, { prepare: false }));
|
|
8
|
-
}
|
|
9
|
-
export const db = globalThis.db ?? createSingleton();
|
|
10
|
-
if (!process.env.VERCEL_ENV) {
|
|
11
|
-
globalThis.db = db;
|
|
12
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Errorable } from '@sqrzro/interfaces';
|
|
2
|
-
import type Joi from 'joi';
|
|
3
|
-
import ValidationError from './ValidationError';
|
|
4
|
-
interface SubmitFormArgs<F extends object> {
|
|
5
|
-
formData: F;
|
|
6
|
-
onSuccess?: (model: F) => Promise<void> | void;
|
|
7
|
-
onValidationError?: (error: ValidationError) => void;
|
|
8
|
-
request?: Joi.ObjectSchema<F>;
|
|
9
|
-
}
|
|
10
|
-
interface SubmitFormArgsWithFn<F extends object, M> extends Omit<SubmitFormArgs<F>, 'onSuccess'> {
|
|
11
|
-
fn: (data: F) => Promise<M | null>;
|
|
12
|
-
onSuccess?: (model: M) => Promise<void> | void;
|
|
13
|
-
}
|
|
14
|
-
export declare function submitForm<F extends object>(args: SubmitFormArgs<F>): Promise<Errorable<F>>;
|
|
15
|
-
export declare function submitForm<F extends object, M>(args: SubmitFormArgsWithFn<F, M>): Promise<Errorable<M>>;
|
|
16
|
-
export {};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import ValidationError from './ValidationError';
|
|
3
|
-
import { validateSchema } from './ValidationService';
|
|
4
|
-
function serializeError(err) {
|
|
5
|
-
return {
|
|
6
|
-
cause: err.cause,
|
|
7
|
-
message: err.message,
|
|
8
|
-
name: err.name,
|
|
9
|
-
stack: err.stack,
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
function hasFn(args) {
|
|
13
|
-
return Boolean(Object.prototype.hasOwnProperty.call(args, 'fn'));
|
|
14
|
-
}
|
|
15
|
-
export async function submitForm(args) {
|
|
16
|
-
let data = { ...args.formData };
|
|
17
|
-
if (args.request) {
|
|
18
|
-
const [validated, validationError] = await validateSchema(args.formData, args.request);
|
|
19
|
-
if (validationError !== null) {
|
|
20
|
-
if (validationError instanceof ValidationError) {
|
|
21
|
-
args.onValidationError?.(validationError);
|
|
22
|
-
}
|
|
23
|
-
return [null, serializeError(validationError)];
|
|
24
|
-
}
|
|
25
|
-
data = validated;
|
|
26
|
-
}
|
|
27
|
-
if (!hasFn(args)) {
|
|
28
|
-
try {
|
|
29
|
-
await args.onSuccess?.(data);
|
|
30
|
-
}
|
|
31
|
-
catch (err) {
|
|
32
|
-
if (err instanceof Error) {
|
|
33
|
-
return [null, serializeError(err)];
|
|
34
|
-
}
|
|
35
|
-
return [
|
|
36
|
-
null,
|
|
37
|
-
serializeError(new Error('The submitForm onSuccess function encountered an unknown error')),
|
|
38
|
-
];
|
|
39
|
-
}
|
|
40
|
-
return [data, null];
|
|
41
|
-
}
|
|
42
|
-
let model = null;
|
|
43
|
-
try {
|
|
44
|
-
model = await args.fn(data);
|
|
45
|
-
}
|
|
46
|
-
catch (err) {
|
|
47
|
-
if (err instanceof ValidationError) {
|
|
48
|
-
args.onValidationError?.(err);
|
|
49
|
-
return [null, serializeError(err)];
|
|
50
|
-
}
|
|
51
|
-
if (err instanceof Error) {
|
|
52
|
-
return [null, serializeError(err)];
|
|
53
|
-
}
|
|
54
|
-
return [
|
|
55
|
-
null,
|
|
56
|
-
serializeError(new Error('The function supplied to submitForm encountered an unknown error')),
|
|
57
|
-
];
|
|
58
|
-
}
|
|
59
|
-
if (!model) {
|
|
60
|
-
return [
|
|
61
|
-
null,
|
|
62
|
-
serializeError(new Error('No model has been returned from the function supplied to submitForm')),
|
|
63
|
-
];
|
|
64
|
-
}
|
|
65
|
-
try {
|
|
66
|
-
await args.onSuccess?.(model);
|
|
67
|
-
}
|
|
68
|
-
catch (err) {
|
|
69
|
-
if (err instanceof Error) {
|
|
70
|
-
return [null, serializeError(err)];
|
|
71
|
-
}
|
|
72
|
-
return [
|
|
73
|
-
null,
|
|
74
|
-
serializeError(new Error('The submitForm onSuccess function encountered an unknown error')),
|
|
75
|
-
];
|
|
76
|
-
}
|
|
77
|
-
return [model, null];
|
|
78
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
'use server';
|
|
2
|
-
const DEFAULT_TYPES = ['image/png', 'image/jpeg', 'image/jpg'];
|
|
3
|
-
// 5MB
|
|
4
|
-
const DEFAULT_MAX_SIZE = 5242880;
|
|
5
|
-
export async function validateImage(image, config) {
|
|
6
|
-
if (!image) {
|
|
7
|
-
return Promise.resolve([null, new Error('IMAGE_UNDEFINED')]);
|
|
8
|
-
}
|
|
9
|
-
if (!(image instanceof File)) {
|
|
10
|
-
return Promise.resolve([null, new Error('IMAGE_NOT_VALID')]);
|
|
11
|
-
}
|
|
12
|
-
if (!(config?.types || DEFAULT_TYPES).includes(image.type)) {
|
|
13
|
-
return Promise.resolve([null, new Error('IMAGE_TYPE_NOT_VALID')]);
|
|
14
|
-
}
|
|
15
|
-
if (image.size > (config?.maxSize || DEFAULT_MAX_SIZE)) {
|
|
16
|
-
return Promise.resolve([null, new Error('IMAGE_TOO_HEAVY')]);
|
|
17
|
-
}
|
|
18
|
-
return Promise.resolve([image, null]);
|
|
19
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { Errorable } from '@sqrzro/interfaces';
|
|
2
|
-
import Joi from 'joi';
|
|
3
|
-
export declare function validate(): typeof Joi;
|
|
4
|
-
export type ValidationCustomHelpers<V = any> = Joi.CustomHelpers<V>;
|
|
5
|
-
export type ValidationExternalHelpers<V = any> = Joi.ExternalHelpers<V>;
|
|
6
|
-
export type ValidationErrorReport = Joi.ErrorReport;
|
|
7
|
-
/**
|
|
8
|
-
* This function takes FormData and a schema. It then attempts to transform the FormData into an
|
|
9
|
-
* object that matches `T`. This is because the FormData object is not typed and we want to be able
|
|
10
|
-
* to validate it properly typed.
|
|
11
|
-
*
|
|
12
|
-
* Once transformed, the object is validated against the schema. This will result in either a
|
|
13
|
-
* properly typed `T` object or an array of validation errors.
|
|
14
|
-
* @param formData
|
|
15
|
-
* @param validation
|
|
16
|
-
* @returns
|
|
17
|
-
*/
|
|
18
|
-
export declare function validateSchema<T>(formData: T, validation: Joi.ObjectSchema<T>): Promise<Errorable<T>>;
|
|
19
|
-
export declare function createSchema<T>(schema: Joi.SchemaMap<T, true>): Joi.ObjectSchema<T>;
|
|
20
|
-
export declare function extendSchema<T, U extends T>(schema: Joi.ObjectSchema<T>, appends: Joi.PartialSchemaMap<U>): Joi.ObjectSchema<U>;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import Joi from 'joi';
|
|
2
|
-
import lang from './lang';
|
|
3
|
-
import ValidationError from './ValidationError';
|
|
4
|
-
export function validate() {
|
|
5
|
-
return Joi;
|
|
6
|
-
}
|
|
7
|
-
function getErrorMessages() {
|
|
8
|
-
return Object.entries(lang).reduce((acc, [key, value]) => {
|
|
9
|
-
if (!value) {
|
|
10
|
-
return acc;
|
|
11
|
-
}
|
|
12
|
-
return {
|
|
13
|
-
...acc,
|
|
14
|
-
[key]: value,
|
|
15
|
-
};
|
|
16
|
-
}, {});
|
|
17
|
-
}
|
|
18
|
-
function transformErrors(error) {
|
|
19
|
-
const messages = error.details.reduce((acc, cur) => ({
|
|
20
|
-
...acc,
|
|
21
|
-
[cur.path.join('.')]: cur.message.replace(/"/gu, ''),
|
|
22
|
-
}), {});
|
|
23
|
-
return new ValidationError(messages);
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* This function takes FormData and a schema. It then attempts to transform the FormData into an
|
|
27
|
-
* object that matches `T`. This is because the FormData object is not typed and we want to be able
|
|
28
|
-
* to validate it properly typed.
|
|
29
|
-
*
|
|
30
|
-
* Once transformed, the object is validated against the schema. This will result in either a
|
|
31
|
-
* properly typed `T` object or an array of validation errors.
|
|
32
|
-
* @param formData
|
|
33
|
-
* @param validation
|
|
34
|
-
* @returns
|
|
35
|
-
*/
|
|
36
|
-
export async function validateSchema(formData, validation) {
|
|
37
|
-
try {
|
|
38
|
-
const validated = await validation.validateAsync(formData, {
|
|
39
|
-
abortEarly: false,
|
|
40
|
-
messages: getErrorMessages(),
|
|
41
|
-
});
|
|
42
|
-
return [validated, null];
|
|
43
|
-
}
|
|
44
|
-
catch (err) {
|
|
45
|
-
if (err instanceof Joi.ValidationError) {
|
|
46
|
-
return [null, transformErrors(err)];
|
|
47
|
-
}
|
|
48
|
-
if (err instanceof Error) {
|
|
49
|
-
return [null, err];
|
|
50
|
-
}
|
|
51
|
-
return [null, new Error('Unknown validation error occured')];
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
export function createSchema(schema) {
|
|
55
|
-
return Joi.object(schema);
|
|
56
|
-
}
|
|
57
|
-
export function extendSchema(schema, appends) {
|
|
58
|
-
return schema.append(appends);
|
|
59
|
-
}
|
package/dist/forms/lang.d.ts
DELETED
package/dist/forms/lang.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
const messages = {
|
|
2
|
-
'alternatives.all': '',
|
|
3
|
-
'alternatives.any': '',
|
|
4
|
-
'alternatives.match': '',
|
|
5
|
-
'alternatives.one': '',
|
|
6
|
-
'alternatives.types': '',
|
|
7
|
-
'any.custom': '',
|
|
8
|
-
'any.default': '',
|
|
9
|
-
'any.failover': '',
|
|
10
|
-
'any.invalid': '',
|
|
11
|
-
'any.only': '',
|
|
12
|
-
'any.ref': '',
|
|
13
|
-
'any.required': '{{#label}} is required',
|
|
14
|
-
'any.unknown': '',
|
|
15
|
-
'array.base': '',
|
|
16
|
-
'array.excludes': '',
|
|
17
|
-
'array.includesRequiredBoth': '',
|
|
18
|
-
'array.includesRequiredKnowns': '',
|
|
19
|
-
'array.includesRequiredUnknowns': '',
|
|
20
|
-
'array.includes': '',
|
|
21
|
-
'array.length': '',
|
|
22
|
-
'array.max': '',
|
|
23
|
-
'array.min': '',
|
|
24
|
-
'array.orderedLength': '',
|
|
25
|
-
'array.sort': '',
|
|
26
|
-
'array.sort.mismatching': '',
|
|
27
|
-
'array.sort.unsupported': '',
|
|
28
|
-
'array.sparse': '',
|
|
29
|
-
'array.unique': '',
|
|
30
|
-
'array.hasKnown': '',
|
|
31
|
-
'array.hasUnknown': '',
|
|
32
|
-
'binary.base': '',
|
|
33
|
-
'binary.length': '',
|
|
34
|
-
'binary.max': '',
|
|
35
|
-
'binary.min': '',
|
|
36
|
-
'boolean.base': '',
|
|
37
|
-
'date.base': '',
|
|
38
|
-
'date.format': '',
|
|
39
|
-
'date.greater': '',
|
|
40
|
-
'date.less': '',
|
|
41
|
-
'date.max': '',
|
|
42
|
-
'date.min': '',
|
|
43
|
-
'date.strict': '',
|
|
44
|
-
'function.arity': '',
|
|
45
|
-
'function.class': '',
|
|
46
|
-
'function.maxArity': '',
|
|
47
|
-
'function.minArity': '',
|
|
48
|
-
'number.base': '{{#label}} should be a number',
|
|
49
|
-
'number.greater': '',
|
|
50
|
-
'number.infinity': '',
|
|
51
|
-
'number.integer': '',
|
|
52
|
-
'number.less': '',
|
|
53
|
-
'number.max': '',
|
|
54
|
-
'number.min': '{{#label}} should be greater than or equal to {{#limit}}',
|
|
55
|
-
'number.multiple': '',
|
|
56
|
-
'number.negative': '',
|
|
57
|
-
'number.port': '',
|
|
58
|
-
'number.positive': '',
|
|
59
|
-
'number.precision': '',
|
|
60
|
-
'number.unsafe': '',
|
|
61
|
-
'object.unknown': '',
|
|
62
|
-
'object.and': '',
|
|
63
|
-
'object.assert': '',
|
|
64
|
-
'object.base': '',
|
|
65
|
-
'object.length': '',
|
|
66
|
-
'object.max': '',
|
|
67
|
-
'object.min': '',
|
|
68
|
-
'object.missing': '',
|
|
69
|
-
'object.nand': '',
|
|
70
|
-
'object.pattern.match': '',
|
|
71
|
-
'object.refType': '',
|
|
72
|
-
'object.regex': '',
|
|
73
|
-
'object.rename.multiple': '',
|
|
74
|
-
'object.rename.override': '',
|
|
75
|
-
'object.schema': '',
|
|
76
|
-
'object.instance': '',
|
|
77
|
-
'object.with': '',
|
|
78
|
-
'object.without': '',
|
|
79
|
-
'object.xor': '',
|
|
80
|
-
'object.oxor': '',
|
|
81
|
-
'string.alphanum': '',
|
|
82
|
-
'string.base64': '',
|
|
83
|
-
'string.base': '',
|
|
84
|
-
'string.creditCard': '',
|
|
85
|
-
'string.dataUri': '',
|
|
86
|
-
'string.domain': '',
|
|
87
|
-
'string.email': '',
|
|
88
|
-
'string.empty': '{{#label}} is required',
|
|
89
|
-
'string.guid': '',
|
|
90
|
-
'string.hexAlign': '',
|
|
91
|
-
'string.hex': '',
|
|
92
|
-
'string.hostname': '',
|
|
93
|
-
'string.ipVersion': '',
|
|
94
|
-
'string.ip': '',
|
|
95
|
-
'string.isoDate': '',
|
|
96
|
-
'string.isoDuration': '',
|
|
97
|
-
'string.length': '',
|
|
98
|
-
'string.lowercase': '',
|
|
99
|
-
'string.max': '',
|
|
100
|
-
'string.min': '',
|
|
101
|
-
'string.normalize': '',
|
|
102
|
-
'string.pattern.base': '',
|
|
103
|
-
'string.pattern.name': '',
|
|
104
|
-
'string.pattern.invert.base': '',
|
|
105
|
-
'string.pattern.invert.name': '',
|
|
106
|
-
'string.token': '',
|
|
107
|
-
'string.trim': '',
|
|
108
|
-
'string.uppercase': '',
|
|
109
|
-
'string.uri': '',
|
|
110
|
-
'string.uriCustomScheme': '',
|
|
111
|
-
'string.uriRelativeOnly': '',
|
|
112
|
-
'symbol.base': '',
|
|
113
|
-
'symbol.map': '',
|
|
114
|
-
};
|
|
115
|
-
export default messages;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { getFromObject } from '@sqrzro/utility';
|
|
2
|
-
const DEFAULT_SORT = 'id';
|
|
3
|
-
const DEFAULT_DIR = 'asc';
|
|
4
|
-
const DEFAULT_PAGE = 1;
|
|
5
|
-
const DEFAULT_LIMIT = 10;
|
|
6
|
-
function createPaginationArgs(page) {
|
|
7
|
-
return { skip: (page - 1) * DEFAULT_LIMIT, take: DEFAULT_LIMIT };
|
|
8
|
-
}
|
|
9
|
-
function createFindManyArgs(searchParams, allowedFilters = []) {
|
|
10
|
-
const { dir, page, sort, ...filters } = searchParams || {};
|
|
11
|
-
return {
|
|
12
|
-
...createPaginationArgs(page ? parseInt(page, 10) : DEFAULT_PAGE),
|
|
13
|
-
orderBy: { [sort || DEFAULT_SORT]: dir || DEFAULT_DIR },
|
|
14
|
-
where: getFromObject(filters, allowedFilters),
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
export async function getList({ allowedFilters, fn, searchParams, }) {
|
|
18
|
-
try {
|
|
19
|
-
const args = createFindManyArgs(searchParams, allowedFilters);
|
|
20
|
-
return [await fn(args), null];
|
|
21
|
-
}
|
|
22
|
-
catch (err) {
|
|
23
|
-
if (err instanceof Error) {
|
|
24
|
-
return [null, err];
|
|
25
|
-
}
|
|
26
|
-
return [null, new Error('[getList] An unknown error occurred')];
|
|
27
|
-
}
|
|
28
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
|
-
type MailFn<T extends object> = () => Promise<{
|
|
3
|
-
subject: string;
|
|
4
|
-
template: (data: T) => React.ReactElement;
|
|
5
|
-
}>;
|
|
6
|
-
export declare function createMail<T extends object>(subject: string, template: (data: T) => React.ReactElement): Promise<MailFn<T>>;
|
|
7
|
-
export declare function getMail<T extends object>(mail: MailFn<T>, data: T): Promise<{
|
|
8
|
-
subject: string;
|
|
9
|
-
html: string;
|
|
10
|
-
}>;
|
|
11
|
-
export declare function sendMail<T extends object>(mail: Promise<MailFn<T>>, data: T, to: string): Promise<boolean>;
|
|
12
|
-
export {};
|
package/dist/mail/MailService.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
export async function createMail(subject, template) {
|
|
2
|
-
return Promise.resolve(async () => Promise.resolve({ subject, template }));
|
|
3
|
-
}
|
|
4
|
-
export async function getMail(mail, data) {
|
|
5
|
-
const { subject, template } = await mail();
|
|
6
|
-
const ReactDOMServer = (await import('react-dom/server')).default;
|
|
7
|
-
return {
|
|
8
|
-
subject,
|
|
9
|
-
html: ReactDOMServer.renderToStaticMarkup(template(data)),
|
|
10
|
-
};
|
|
11
|
-
}
|
|
12
|
-
function getSenderDetails() {
|
|
13
|
-
if (!process.env.MAIL_FROM) {
|
|
14
|
-
throw new Error('Mail from address has not been set');
|
|
15
|
-
}
|
|
16
|
-
const matches = /^(?<name>[^<]+)<(?<email>[^>]+)>$/u.exec(process.env.MAIL_FROM);
|
|
17
|
-
if (!matches?.groups?.name || !matches?.groups?.email) {
|
|
18
|
-
throw new Error('Mail from address is not the correct format. It should be "Name <email>".');
|
|
19
|
-
}
|
|
20
|
-
return {
|
|
21
|
-
email: matches.groups.email.trim(),
|
|
22
|
-
name: matches.groups.name.trim(),
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
export async function sendMail(mail, data, to) {
|
|
26
|
-
if (!process.env.MAIL_API_URL) {
|
|
27
|
-
throw new Error('Mail URL has not been set');
|
|
28
|
-
}
|
|
29
|
-
if (!process.env.MAIL_API_KEY) {
|
|
30
|
-
throw new Error('Mail API key has not been set');
|
|
31
|
-
}
|
|
32
|
-
const from = getSenderDetails();
|
|
33
|
-
const { subject, html } = await getMail(await mail, data);
|
|
34
|
-
try {
|
|
35
|
-
const response = await fetch(process.env.MAIL_API_URL, {
|
|
36
|
-
method: 'POST',
|
|
37
|
-
headers: { 'Api-Token': process.env.MAIL_API_KEY, 'Content-Type': 'application/json' },
|
|
38
|
-
body: JSON.stringify({
|
|
39
|
-
from,
|
|
40
|
-
html,
|
|
41
|
-
subject,
|
|
42
|
-
to: [{ email: to }],
|
|
43
|
-
}),
|
|
44
|
-
});
|
|
45
|
-
const json = (await response.json());
|
|
46
|
-
return json.success;
|
|
47
|
-
}
|
|
48
|
-
catch (err) {
|
|
49
|
-
/* eslint-disable-next-line no-console */
|
|
50
|
-
console.log('err', err);
|
|
51
|
-
/* eslint-disable-next-line no-warning-comments */
|
|
52
|
-
// TODO: Log error to Sentry
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
}
|