@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.
Files changed (84) hide show
  1. package/auth.d.ts +1 -1
  2. package/auth.js +1 -1
  3. package/cache.d.ts +1 -1
  4. package/cache.js +1 -1
  5. package/dist/auth/AuthService.d.ts +14 -0
  6. package/dist/auth/AuthService.js +135 -0
  7. package/dist/auth/ClientService.d.ts +11 -0
  8. package/dist/auth/ClientService.js +47 -0
  9. package/dist/auth/LoginRequest.d.ts +4 -0
  10. package/dist/auth/LoginRequest.js +8 -0
  11. package/dist/auth/MFARequest.d.ts +4 -0
  12. package/dist/auth/MFARequest.js +9 -0
  13. package/dist/auth/MFAService.d.ts +6 -0
  14. package/dist/auth/MFAService.js +105 -0
  15. package/dist/auth/PasswordRequest.d.ts +4 -0
  16. package/dist/auth/PasswordRequest.js +12 -0
  17. package/dist/auth/PasswordResetRequest.d.ts +4 -0
  18. package/dist/auth/PasswordResetRequest.js +13 -0
  19. package/dist/auth/PasswordService.d.ts +8 -0
  20. package/dist/auth/PasswordService.js +54 -0
  21. package/dist/auth/SessionService.d.ts +42 -0
  22. package/dist/auth/SessionService.js +127 -0
  23. package/dist/auth/index.d.ts +6 -0
  24. package/dist/auth/index.js +6 -0
  25. package/dist/auth/interfaces.d.ts +20 -0
  26. package/dist/auth/interfaces.js +1 -0
  27. package/dist/cache/CacheService.d.ts +2 -0
  28. package/dist/cache/CacheService.js +14 -0
  29. package/dist/cache/index.d.ts +1 -0
  30. package/dist/cache/index.js +1 -0
  31. package/dist/database/DatabaseService.d.ts +7 -0
  32. package/dist/database/DatabaseService.js +12 -0
  33. package/dist/{schema.d.ts → database/schema.d.ts} +34 -38
  34. package/dist/database/schema.js +42 -0
  35. package/dist/forms/FormService.d.ts +16 -0
  36. package/dist/forms/FormService.js +78 -0
  37. package/dist/forms/ImageService.d.ts +7 -0
  38. package/dist/forms/ImageService.js +19 -0
  39. package/dist/forms/ValidationError.d.ts +4 -0
  40. package/dist/forms/ValidationError.js +7 -0
  41. package/dist/forms/ValidationService.d.ts +20 -0
  42. package/dist/forms/ValidationService.js +59 -0
  43. package/dist/forms/index.d.ts +3 -0
  44. package/dist/forms/index.js +3 -0
  45. package/dist/forms/lang.d.ts +2 -0
  46. package/dist/forms/lang.js +115 -0
  47. package/dist/{lists.d.ts → lists/ListService.d.ts} +3 -5
  48. package/dist/lists/ListService.js +28 -0
  49. package/dist/lists/index.d.ts +1 -0
  50. package/dist/lists/index.js +1 -0
  51. package/dist/mail/MailService.d.ts +12 -0
  52. package/dist/mail/MailService.js +55 -0
  53. package/dist/mail/index.d.ts +1 -0
  54. package/dist/mail/index.js +1 -0
  55. package/dist/middleware.d.ts +3 -5
  56. package/dist/middleware.js +22 -58
  57. package/dist/{url.d.ts → url/URLService.d.ts} +2 -4
  58. package/dist/url/URLService.js +48 -0
  59. package/dist/url/index.d.ts +1 -0
  60. package/dist/url/index.js +1 -0
  61. package/forms.d.ts +1 -1
  62. package/forms.js +1 -1
  63. package/lists.d.ts +1 -1
  64. package/lists.js +1 -1
  65. package/mail.d.ts +1 -1
  66. package/mail.js +1 -1
  67. package/middleware.d.ts +1 -1
  68. package/middleware.js +1 -1
  69. package/package.json +2 -2
  70. package/schema.d.ts +1 -1
  71. package/schema.js +1 -1
  72. package/url.d.ts +1 -1
  73. package/url.js +1 -1
  74. package/dist/auth.d.ts +0 -100
  75. package/dist/auth.js +0 -891
  76. package/dist/cache.d.ts +0 -4
  77. package/dist/cache.js +0 -46
  78. package/dist/forms.d.ts +0 -46
  79. package/dist/forms.js +0 -327
  80. package/dist/lists.js +0 -61
  81. package/dist/mail.d.ts +0 -12
  82. package/dist/mail.js +0 -97
  83. package/dist/schema.js +0 -77
  84. 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,2 @@
1
+ export declare function getFromCache(key: string): Promise<string | null>;
2
+ export declare function setToCache(key: string, value: string): Promise<void>;
@@ -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,7 @@
1
+ import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';
2
+ declare global {
3
+ var db: ReturnType<typeof createSingleton> | undefined;
4
+ }
5
+ declare function createSingleton(): PostgresJsDatabase;
6
+ export declare const db: PostgresJsDatabase;
7
+ export {};
@@ -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
- import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
2
-
3
- declare const mfaType: drizzle_orm_pg_core.PgEnum<["TOTP", "HARDWARE"]>;
4
- declare const scope: drizzle_orm_pg_core.PgEnum<["ANON", "MFA", "AUTHED"]>;
5
- type Scope = (typeof scope.enumValues)[number];
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgTableWithColumns<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgTableWithColumns<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgTableWithColumns<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgTableWithColumns<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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: drizzle_orm_pg_core.PgColumn<{
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,7 @@
1
+ import type { Errorable } from '@sqrzro/interfaces';
2
+ interface ImageValidationConfig {
3
+ maxSize?: number;
4
+ types?: string[];
5
+ }
6
+ export declare function validateImage(image: File | null, config?: ImageValidationConfig): Promise<Errorable<File>>;
7
+ export {};
@@ -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,4 @@
1
+ declare class ValidationError extends Error {
2
+ constructor(messages: Record<string, string>);
3
+ }
4
+ export default ValidationError;
@@ -0,0 +1,7 @@
1
+ class ValidationError extends Error {
2
+ constructor(messages) {
3
+ super(JSON.stringify(messages));
4
+ this.name = 'ValidationError';
5
+ }
6
+ }
7
+ export default ValidationError;
@@ -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
+ }
@@ -0,0 +1,3 @@
1
+ export * from './FormService';
2
+ export * from './ImageService';
3
+ export * from './ValidationService';
@@ -0,0 +1,3 @@
1
+ export * from './FormService';
2
+ export * from './ImageService';
3
+ export * from './ValidationService';
@@ -0,0 +1,2 @@
1
+ declare const messages: Record<string, string>;
2
+ export default messages;