@sqrzro/server 2.0.0-bz.12 → 2.0.0-bz.14
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.d.ts +1 -1
- package/auth.js +1 -1
- package/cache.d.ts +1 -1
- package/cache.js +1 -1
- package/dist/auth/AuthService.d.ts +14 -0
- package/dist/auth/AuthService.js +135 -0
- package/dist/auth/ClientService.d.ts +11 -0
- package/dist/auth/ClientService.js +47 -0
- package/dist/auth/LoginRequest.d.ts +4 -0
- package/dist/auth/LoginRequest.js +8 -0
- package/dist/auth/MFARequest.d.ts +4 -0
- package/dist/auth/MFARequest.js +9 -0
- package/dist/auth/MFAService.d.ts +6 -0
- package/dist/auth/MFAService.js +105 -0
- package/dist/auth/PasswordRequest.d.ts +4 -0
- package/dist/auth/PasswordRequest.js +12 -0
- package/dist/auth/PasswordResetRequest.d.ts +4 -0
- package/dist/auth/PasswordResetRequest.js +13 -0
- package/dist/auth/PasswordService.d.ts +8 -0
- package/dist/auth/PasswordService.js +54 -0
- package/dist/auth/SessionService.d.ts +42 -0
- package/dist/auth/SessionService.js +127 -0
- package/dist/auth/index.d.ts +6 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/interfaces.d.ts +20 -0
- package/dist/auth/interfaces.js +1 -0
- package/dist/cache/CacheService.d.ts +2 -0
- package/dist/cache/CacheService.js +14 -0
- package/dist/cache/index.d.ts +1 -0
- package/dist/cache/index.js +1 -0
- package/dist/database/DatabaseService.d.ts +7 -0
- package/dist/database/DatabaseService.js +12 -0
- package/dist/{schema.d.ts → database/schema.d.ts} +34 -38
- package/dist/database/schema.js +42 -0
- package/dist/forms/FormService.d.ts +16 -0
- package/dist/forms/FormService.js +78 -0
- package/dist/forms/ImageService.d.ts +7 -0
- package/dist/forms/ImageService.js +19 -0
- package/dist/forms/ValidationError.d.ts +4 -0
- package/dist/forms/ValidationError.js +7 -0
- package/dist/forms/ValidationService.d.ts +20 -0
- package/dist/forms/ValidationService.js +59 -0
- package/dist/forms/index.d.ts +3 -0
- package/dist/forms/index.js +3 -0
- package/dist/forms/lang.d.ts +2 -0
- package/dist/forms/lang.js +115 -0
- package/dist/{lists.d.ts → lists/ListService.d.ts} +3 -5
- package/dist/lists/ListService.js +28 -0
- package/dist/lists/index.d.ts +1 -0
- package/dist/lists/index.js +1 -0
- package/dist/mail/MailService.d.ts +12 -0
- package/dist/mail/MailService.js +55 -0
- package/dist/mail/index.d.ts +1 -0
- package/dist/mail/index.js +1 -0
- package/dist/middleware.d.ts +3 -5
- package/dist/middleware.js +22 -58
- package/dist/{url.d.ts → url/URLService.d.ts} +2 -4
- package/dist/url/URLService.js +48 -0
- package/dist/url/index.d.ts +1 -0
- package/dist/url/index.js +1 -0
- package/forms.d.ts +1 -1
- package/forms.js +1 -1
- package/lists.d.ts +1 -1
- package/lists.js +1 -1
- package/mail.d.ts +1 -1
- package/mail.js +1 -1
- package/middleware.d.ts +1 -1
- package/middleware.js +1 -1
- package/package.json +2 -2
- package/schema.d.ts +1 -1
- package/schema.js +1 -1
- package/url.d.ts +1 -1
- package/url.js +1 -1
- package/dist/auth.d.ts +0 -100
- package/dist/auth.js +0 -891
- package/dist/cache.d.ts +0 -4
- package/dist/cache.js +0 -46
- package/dist/forms.d.ts +0 -46
- package/dist/forms.js +0 -327
- package/dist/lists.js +0 -61
- package/dist/mail.d.ts +0 -12
- package/dist/mail.js +0 -97
- package/dist/schema.js +0 -77
- package/dist/url.js +0 -56
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './CacheService';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './CacheService';
|
|
@@ -0,0 +1,12 @@
|
|
|
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,14 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
declare const
|
|
5
|
-
|
|
6
|
-
declare const authSchema: drizzle_orm_pg_core.PgSchema<"auth">;
|
|
7
|
-
declare const authUserTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
1
|
+
export declare const mfaType: import("drizzle-orm/pg-core").PgEnum<["TOTP", "HARDWARE"]>;
|
|
2
|
+
export declare const scope: import("drizzle-orm/pg-core").PgEnum<["ANON", "MFA", "AUTHED"]>;
|
|
3
|
+
export type Scope = (typeof scope.enumValues)[number];
|
|
4
|
+
export declare const authSchema: import("drizzle-orm/pg-core").PgSchema<"auth">;
|
|
5
|
+
export declare const authUserTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
8
6
|
name: "user_credentials";
|
|
9
7
|
schema: "auth";
|
|
10
8
|
columns: {
|
|
11
|
-
id:
|
|
9
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
12
10
|
name: "id";
|
|
13
11
|
tableName: "user_credentials";
|
|
14
12
|
dataType: "string";
|
|
@@ -20,7 +18,7 @@ declare const authUserTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
20
18
|
enumValues: [string, ...string[]];
|
|
21
19
|
baseColumn: never;
|
|
22
20
|
}, {}, {}>;
|
|
23
|
-
email:
|
|
21
|
+
email: import("drizzle-orm/pg-core").PgColumn<{
|
|
24
22
|
name: "email";
|
|
25
23
|
tableName: "user_credentials";
|
|
26
24
|
dataType: "string";
|
|
@@ -32,7 +30,7 @@ declare const authUserTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
32
30
|
enumValues: [string, ...string[]];
|
|
33
31
|
baseColumn: never;
|
|
34
32
|
}, {}, {}>;
|
|
35
|
-
password:
|
|
33
|
+
password: import("drizzle-orm/pg-core").PgColumn<{
|
|
36
34
|
name: "password";
|
|
37
35
|
tableName: "user_credentials";
|
|
38
36
|
dataType: "string";
|
|
@@ -44,7 +42,7 @@ declare const authUserTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
44
42
|
enumValues: [string, ...string[]];
|
|
45
43
|
baseColumn: never;
|
|
46
44
|
}, {}, {}>;
|
|
47
|
-
role:
|
|
45
|
+
role: import("drizzle-orm/pg-core").PgColumn<{
|
|
48
46
|
name: "role";
|
|
49
47
|
tableName: "user_credentials";
|
|
50
48
|
dataType: "number";
|
|
@@ -59,12 +57,12 @@ declare const authUserTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
59
57
|
};
|
|
60
58
|
dialect: "pg";
|
|
61
59
|
}>;
|
|
62
|
-
type AuthUser = typeof authUserTable.$inferSelect;
|
|
63
|
-
declare const authSessionTable:
|
|
60
|
+
export type AuthUser = typeof authUserTable.$inferSelect;
|
|
61
|
+
export declare const authSessionTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
64
62
|
name: "sessions";
|
|
65
63
|
schema: "auth";
|
|
66
64
|
columns: {
|
|
67
|
-
id:
|
|
65
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
68
66
|
name: "id";
|
|
69
67
|
tableName: "sessions";
|
|
70
68
|
dataType: "string";
|
|
@@ -76,7 +74,7 @@ declare const authSessionTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
76
74
|
enumValues: [string, ...string[]];
|
|
77
75
|
baseColumn: never;
|
|
78
76
|
}, {}, {}>;
|
|
79
|
-
userId:
|
|
77
|
+
userId: import("drizzle-orm/pg-core").PgColumn<{
|
|
80
78
|
name: "userId";
|
|
81
79
|
tableName: "sessions";
|
|
82
80
|
dataType: "string";
|
|
@@ -88,7 +86,7 @@ declare const authSessionTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
88
86
|
enumValues: [string, ...string[]];
|
|
89
87
|
baseColumn: never;
|
|
90
88
|
}, {}, {}>;
|
|
91
|
-
scope:
|
|
89
|
+
scope: import("drizzle-orm/pg-core").PgColumn<{
|
|
92
90
|
name: "scope";
|
|
93
91
|
tableName: "sessions";
|
|
94
92
|
dataType: "string";
|
|
@@ -100,7 +98,7 @@ declare const authSessionTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
100
98
|
enumValues: ["ANON", "MFA", "AUTHED"];
|
|
101
99
|
baseColumn: never;
|
|
102
100
|
}, {}, {}>;
|
|
103
|
-
expiresAt:
|
|
101
|
+
expiresAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
104
102
|
name: "expiresAt";
|
|
105
103
|
tableName: "sessions";
|
|
106
104
|
dataType: "date";
|
|
@@ -115,12 +113,12 @@ declare const authSessionTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
115
113
|
};
|
|
116
114
|
dialect: "pg";
|
|
117
115
|
}>;
|
|
118
|
-
type AuthSession = typeof authSessionTable.$inferSelect;
|
|
119
|
-
declare const authResetTable:
|
|
116
|
+
export type AuthSession = typeof authSessionTable.$inferSelect;
|
|
117
|
+
export declare const authResetTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
120
118
|
name: "resets";
|
|
121
119
|
schema: "auth";
|
|
122
120
|
columns: {
|
|
123
|
-
id:
|
|
121
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
124
122
|
name: "id";
|
|
125
123
|
tableName: "resets";
|
|
126
124
|
dataType: "string";
|
|
@@ -132,7 +130,7 @@ declare const authResetTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
132
130
|
enumValues: [string, ...string[]];
|
|
133
131
|
baseColumn: never;
|
|
134
132
|
}, {}, {}>;
|
|
135
|
-
userId:
|
|
133
|
+
userId: import("drizzle-orm/pg-core").PgColumn<{
|
|
136
134
|
name: "userId";
|
|
137
135
|
tableName: "resets";
|
|
138
136
|
dataType: "string";
|
|
@@ -144,7 +142,7 @@ declare const authResetTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
144
142
|
enumValues: [string, ...string[]];
|
|
145
143
|
baseColumn: never;
|
|
146
144
|
}, {}, {}>;
|
|
147
|
-
expiresAt:
|
|
145
|
+
expiresAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
148
146
|
name: "expiresAt";
|
|
149
147
|
tableName: "resets";
|
|
150
148
|
dataType: "date";
|
|
@@ -159,12 +157,12 @@ declare const authResetTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
159
157
|
};
|
|
160
158
|
dialect: "pg";
|
|
161
159
|
}>;
|
|
162
|
-
type AuthReset = typeof authResetTable.$inferSelect;
|
|
163
|
-
declare const authMFATable:
|
|
160
|
+
export type AuthReset = typeof authResetTable.$inferSelect;
|
|
161
|
+
export declare const authMFATable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
164
162
|
name: "mfas";
|
|
165
163
|
schema: "auth";
|
|
166
164
|
columns: {
|
|
167
|
-
id:
|
|
165
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
168
166
|
name: "id";
|
|
169
167
|
tableName: "mfas";
|
|
170
168
|
dataType: "string";
|
|
@@ -176,7 +174,7 @@ declare const authMFATable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
176
174
|
enumValues: [string, ...string[]];
|
|
177
175
|
baseColumn: never;
|
|
178
176
|
}, {}, {}>;
|
|
179
|
-
name:
|
|
177
|
+
name: import("drizzle-orm/pg-core").PgColumn<{
|
|
180
178
|
name: "name";
|
|
181
179
|
tableName: "mfas";
|
|
182
180
|
dataType: "string";
|
|
@@ -188,7 +186,7 @@ declare const authMFATable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
188
186
|
enumValues: [string, ...string[]];
|
|
189
187
|
baseColumn: never;
|
|
190
188
|
}, {}, {}>;
|
|
191
|
-
userId:
|
|
189
|
+
userId: import("drizzle-orm/pg-core").PgColumn<{
|
|
192
190
|
name: "userId";
|
|
193
191
|
tableName: "mfas";
|
|
194
192
|
dataType: "string";
|
|
@@ -200,7 +198,7 @@ declare const authMFATable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
200
198
|
enumValues: [string, ...string[]];
|
|
201
199
|
baseColumn: never;
|
|
202
200
|
}, {}, {}>;
|
|
203
|
-
type:
|
|
201
|
+
type: import("drizzle-orm/pg-core").PgColumn<{
|
|
204
202
|
name: "type";
|
|
205
203
|
tableName: "mfas";
|
|
206
204
|
dataType: "string";
|
|
@@ -212,7 +210,7 @@ declare const authMFATable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
212
210
|
enumValues: ["TOTP", "HARDWARE"];
|
|
213
211
|
baseColumn: never;
|
|
214
212
|
}, {}, {}>;
|
|
215
|
-
secret:
|
|
213
|
+
secret: import("drizzle-orm/pg-core").PgColumn<{
|
|
216
214
|
name: "secret";
|
|
217
215
|
tableName: "mfas";
|
|
218
216
|
dataType: "string";
|
|
@@ -224,7 +222,7 @@ declare const authMFATable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
224
222
|
enumValues: [string, ...string[]];
|
|
225
223
|
baseColumn: never;
|
|
226
224
|
}, {}, {}>;
|
|
227
|
-
verifiedAt:
|
|
225
|
+
verifiedAt: import("drizzle-orm/pg-core").PgColumn<{
|
|
228
226
|
name: "verifiedAt";
|
|
229
227
|
tableName: "mfas";
|
|
230
228
|
dataType: "date";
|
|
@@ -239,12 +237,12 @@ declare const authMFATable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
239
237
|
};
|
|
240
238
|
dialect: "pg";
|
|
241
239
|
}>;
|
|
242
|
-
type AuthMFA = typeof authMFATable.$inferSelect;
|
|
243
|
-
declare const authClientTable:
|
|
240
|
+
export type AuthMFA = typeof authMFATable.$inferSelect;
|
|
241
|
+
export declare const authClientTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
244
242
|
name: "client_credentials";
|
|
245
243
|
schema: "auth";
|
|
246
244
|
columns: {
|
|
247
|
-
id:
|
|
245
|
+
id: import("drizzle-orm/pg-core").PgColumn<{
|
|
248
246
|
name: "id";
|
|
249
247
|
tableName: "client_credentials";
|
|
250
248
|
dataType: "string";
|
|
@@ -256,7 +254,7 @@ declare const authClientTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
256
254
|
enumValues: [string, ...string[]];
|
|
257
255
|
baseColumn: never;
|
|
258
256
|
}, {}, {}>;
|
|
259
|
-
alias:
|
|
257
|
+
alias: import("drizzle-orm/pg-core").PgColumn<{
|
|
260
258
|
name: "alias";
|
|
261
259
|
tableName: "client_credentials";
|
|
262
260
|
dataType: "string";
|
|
@@ -268,7 +266,7 @@ declare const authClientTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
268
266
|
enumValues: [string, ...string[]];
|
|
269
267
|
baseColumn: never;
|
|
270
268
|
}, {}, {}>;
|
|
271
|
-
secret:
|
|
269
|
+
secret: import("drizzle-orm/pg-core").PgColumn<{
|
|
272
270
|
name: "secret";
|
|
273
271
|
tableName: "client_credentials";
|
|
274
272
|
dataType: "string";
|
|
@@ -283,6 +281,4 @@ declare const authClientTable: drizzle_orm_pg_core.PgTableWithColumns<{
|
|
|
283
281
|
};
|
|
284
282
|
dialect: "pg";
|
|
285
283
|
}>;
|
|
286
|
-
type AuthClient = typeof authClientTable.$inferSelect;
|
|
287
|
-
|
|
288
|
-
export { type AuthClient, type AuthMFA, type AuthReset, type AuthSession, type AuthUser, type Scope, authClientTable, authMFATable, authResetTable, authSchema, authSessionTable, authUserTable, mfaType, scope };
|
|
284
|
+
export type AuthClient = typeof authClientTable.$inferSelect;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* istanbul ignore file */
|
|
2
|
+
import { integer, pgEnum, pgSchema, text, timestamp } from 'drizzle-orm/pg-core';
|
|
3
|
+
const DEFAULT_ROLE = 10;
|
|
4
|
+
export const mfaType = pgEnum('mfaType', ['TOTP', 'HARDWARE']);
|
|
5
|
+
export const scope = pgEnum('scope', ['ANON', 'MFA', 'AUTHED']);
|
|
6
|
+
export const authSchema = pgSchema('auth');
|
|
7
|
+
export const authUserTable = authSchema.table('user_credentials', {
|
|
8
|
+
id: text('id').primaryKey(),
|
|
9
|
+
email: text('email').notNull().unique(),
|
|
10
|
+
password: text('password'),
|
|
11
|
+
role: integer('role').notNull().default(DEFAULT_ROLE),
|
|
12
|
+
});
|
|
13
|
+
export const authSessionTable = authSchema.table('sessions', {
|
|
14
|
+
id: text('id').primaryKey(),
|
|
15
|
+
userId: text('userId')
|
|
16
|
+
.notNull()
|
|
17
|
+
.references(() => authUserTable.id),
|
|
18
|
+
scope: scope('scope').notNull().default('ANON'),
|
|
19
|
+
expiresAt: timestamp('expiresAt').notNull(),
|
|
20
|
+
});
|
|
21
|
+
export const authResetTable = authSchema.table('resets', {
|
|
22
|
+
id: text('id').primaryKey(),
|
|
23
|
+
userId: text('userId')
|
|
24
|
+
.notNull()
|
|
25
|
+
.references(() => authUserTable.id),
|
|
26
|
+
expiresAt: timestamp('expiresAt').notNull(),
|
|
27
|
+
});
|
|
28
|
+
export const authMFATable = authSchema.table('mfas', {
|
|
29
|
+
id: text('id').primaryKey(),
|
|
30
|
+
name: text('name').notNull(),
|
|
31
|
+
userId: text('userId')
|
|
32
|
+
.notNull()
|
|
33
|
+
.references(() => authUserTable.id),
|
|
34
|
+
type: mfaType('type').notNull().default('TOTP'),
|
|
35
|
+
secret: text('secret').notNull(),
|
|
36
|
+
verifiedAt: timestamp('verifiedAt'),
|
|
37
|
+
});
|
|
38
|
+
export const authClientTable = authSchema.table('client_credentials', {
|
|
39
|
+
id: text('id').primaryKey(),
|
|
40
|
+
alias: text('alias').notNull().unique(),
|
|
41
|
+
secret: text('secret').notNull().unique(),
|
|
42
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
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 {};
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
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>;
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
}
|