@unedio/types 0.0.1
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/package.json +18 -0
- package/src/types/api.types.ts +423 -0
- package/src/types/database.types.ts +375 -0
- package/src/types/enums.ts +62 -0
- package/src/types/hono.types.ts +32 -0
- package/src/utils/ai.ts +70 -0
- package/src/utils/email.ts +26 -0
- package/src/utils/errors.ts +60 -0
- package/src/utils/json.ts +26 -0
- package/src/utils/pagination.ts +44 -0
- package/src/utils/storage.ts +57 -0
- package/src/utils/stripe.ts +240 -0
- package/src/validators/application.validator.ts +61 -0
- package/src/validators/candidate.validator.ts +52 -0
- package/src/validators/client.validator.ts +29 -0
- package/src/validators/common.validator.ts +16 -0
- package/src/validators/contact.validator.ts +29 -0
- package/src/validators/email-template.validator.ts +28 -0
- package/src/validators/job.validator.ts +61 -0
- package/src/validators/parse-cv.validator.ts +28 -0
- package/src/validators/saved-candidate.validator.ts +27 -0
- package/src/validators/seeker.validator.ts +29 -0
- package/src/validators/subscription.validator.ts +21 -0
- package/src/validators/user.validator.ts +86 -0
- package/src/validators/waitlist.validator.ts +8 -0
- package/src/validators/workspace.validator.ts +93 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation schemas for user-related operations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from '@hono/zod-openapi';
|
|
6
|
+
|
|
7
|
+
// Email validation
|
|
8
|
+
export const emailSchema = z
|
|
9
|
+
.string()
|
|
10
|
+
.email('Invalid email format')
|
|
11
|
+
.min(1, 'Email is required')
|
|
12
|
+
.transform((val) => val.toLowerCase().trim());
|
|
13
|
+
|
|
14
|
+
// User type validation
|
|
15
|
+
export const userTypeSchema = z.enum(['recruiter', 'seeker'], {
|
|
16
|
+
message: 'User type must be either "recruiter" or "seeker"',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Update user profile
|
|
20
|
+
export const updateUserSchema = z.object({
|
|
21
|
+
name: z.string().min(1, 'Name cannot be empty').max(255).optional(),
|
|
22
|
+
avatar_url: z.string().url('Invalid URL format').optional().nullable(),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Register validation
|
|
26
|
+
export const registerSchema = z.object({
|
|
27
|
+
email: emailSchema,
|
|
28
|
+
password: z.string().min(8, 'Password must be at least 8 characters'),
|
|
29
|
+
name: z.string().min(1, 'Name is required').max(255),
|
|
30
|
+
type: userTypeSchema,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Login validation
|
|
34
|
+
export const loginSchema = z.object({
|
|
35
|
+
email: emailSchema,
|
|
36
|
+
password: z.string().min(1, 'Password is required'),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Update seeker profile
|
|
40
|
+
export const updateSeekerProfileSchema = z.object({
|
|
41
|
+
full_name: z.string().min(1).max(255).optional(),
|
|
42
|
+
phone: z.string().max(50).optional().nullable(),
|
|
43
|
+
linkedin_url: z.string().url('Invalid LinkedIn URL').optional().nullable(),
|
|
44
|
+
city: z.string().max(100).optional().nullable(),
|
|
45
|
+
country: z.string().max(100).optional().nullable(),
|
|
46
|
+
summary: z.string().max(2000).optional().nullable(),
|
|
47
|
+
skills: z.array(z.string()).optional(),
|
|
48
|
+
experience_years: z.number().min(0).max(100).optional().nullable(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Search seekers
|
|
52
|
+
export const searchSeekersSchema = z.object({
|
|
53
|
+
skills: z.array(z.string()).optional(),
|
|
54
|
+
city: z.string().optional(),
|
|
55
|
+
country: z.string().optional(),
|
|
56
|
+
min_experience: z.coerce.number().min(0).optional(),
|
|
57
|
+
max_experience: z.coerce.number().min(0).optional(),
|
|
58
|
+
page: z.coerce.number().min(1).optional().default(1),
|
|
59
|
+
limit: z.coerce.number().min(1).max(100).optional().default(20),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// OTP Register validation
|
|
63
|
+
export const otpRegisterSchema = z.object({
|
|
64
|
+
email: emailSchema,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// OTP Login validation
|
|
68
|
+
export const otpLoginSchema = z.object({
|
|
69
|
+
email: emailSchema,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// OTP Verify validation
|
|
73
|
+
export const otpVerifySchema = z.object({
|
|
74
|
+
email: emailSchema,
|
|
75
|
+
code: z.string().min(1, 'Code is required'),
|
|
76
|
+
state: z.enum(['register', 'login']),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export type UpdateUserInput = z.infer<typeof updateUserSchema>;
|
|
80
|
+
export type RegisterInput = z.infer<typeof registerSchema>;
|
|
81
|
+
export type LoginInput = z.infer<typeof loginSchema>;
|
|
82
|
+
export type UpdateSeekerProfileInput = z.infer<typeof updateSeekerProfileSchema>;
|
|
83
|
+
export type SearchSeekersInput = z.infer<typeof searchSeekersSchema>;
|
|
84
|
+
export type OtpRegisterInput = z.infer<typeof otpRegisterSchema>;
|
|
85
|
+
export type OtpLoginInput = z.infer<typeof otpLoginSchema>;
|
|
86
|
+
export type OtpVerifyInput = z.infer<typeof otpVerifySchema>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation schemas for workspace-related operations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { z } from '@hono/zod-openapi';
|
|
6
|
+
|
|
7
|
+
// Subdomain validation (alphanumeric and hyphens only)
|
|
8
|
+
const subdomainSchema = z
|
|
9
|
+
.string()
|
|
10
|
+
.min(3, 'Subdomain must be at least 3 characters')
|
|
11
|
+
.max(63, 'Subdomain must not exceed 63 characters')
|
|
12
|
+
.regex(
|
|
13
|
+
/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/,
|
|
14
|
+
'Subdomain must contain only lowercase letters, numbers, and hyphens',
|
|
15
|
+
)
|
|
16
|
+
.transform((val) => val.toLowerCase());
|
|
17
|
+
|
|
18
|
+
// Domain validation
|
|
19
|
+
const domainSchema = z
|
|
20
|
+
.string()
|
|
21
|
+
.min(3, 'Domain must be at least 3 characters')
|
|
22
|
+
.max(255, 'Domain must not exceed 255 characters')
|
|
23
|
+
.regex(/^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?(\.[a-zA-Z]{2,})+$/, 'Invalid domain format')
|
|
24
|
+
.transform((val) => val.toLowerCase());
|
|
25
|
+
|
|
26
|
+
// Create workspace
|
|
27
|
+
export const createWorkspaceSchema = z.object({
|
|
28
|
+
name: z.string().min(1, 'Workspace name is required').max(255),
|
|
29
|
+
domain: domainSchema.nullable(),
|
|
30
|
+
subdomain: subdomainSchema.nullable(),
|
|
31
|
+
workspace_mode: z.enum(['company', 'agency']).default('company').optional(),
|
|
32
|
+
language: z.string().min(2).max(10).default('en'),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Update workspace
|
|
36
|
+
export const updateWorkspaceSchema = z.object({
|
|
37
|
+
name: z.string().min(1, 'Workspace name cannot be empty').max(255).optional(),
|
|
38
|
+
domain: domainSchema.optional().nullable(),
|
|
39
|
+
subdomain: subdomainSchema.optional().nullable(),
|
|
40
|
+
workspace_mode: z.enum(['company', 'agency']).optional(),
|
|
41
|
+
language: z.string().min(2).max(10).optional(),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Invite user to workspace
|
|
45
|
+
export const inviteUserSchema = z.object({
|
|
46
|
+
email: z
|
|
47
|
+
.string()
|
|
48
|
+
.email('Invalid email format')
|
|
49
|
+
.transform((val) => val.toLowerCase().trim()),
|
|
50
|
+
role: z
|
|
51
|
+
.enum(['owner', 'member'], {
|
|
52
|
+
message: 'Role must be either "owner" or "member"',
|
|
53
|
+
})
|
|
54
|
+
.default('member'),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Update member role
|
|
58
|
+
export const updateMemberRoleSchema = z.object({
|
|
59
|
+
role: z.enum(['owner', 'member'], {
|
|
60
|
+
message: 'Role must be either "owner" or "member"',
|
|
61
|
+
}),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Update workspace branding
|
|
65
|
+
export const updateBrandingSchema = z.object({
|
|
66
|
+
primary_color: z
|
|
67
|
+
.string()
|
|
68
|
+
.regex(/^#[0-9A-Fa-f]{6}$/, 'Primary color must be a valid hex color (e.g., #6366f1)')
|
|
69
|
+
.optional(),
|
|
70
|
+
secondary_color: z
|
|
71
|
+
.string()
|
|
72
|
+
.regex(/^#[0-9A-Fa-f]{6}$/, 'Secondary color must be a valid hex color (e.g., #1e293b)')
|
|
73
|
+
.optional(),
|
|
74
|
+
font_family: z.string().min(1, 'Font family cannot be empty').max(100).optional(),
|
|
75
|
+
logo_url: z.string().url('Invalid logo URL').optional().nullable(),
|
|
76
|
+
favicon_url: z.string().url('Invalid favicon URL').optional().nullable(),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Upload branding asset
|
|
80
|
+
export const uploadBrandingAssetSchema = z.object({
|
|
81
|
+
file: z
|
|
82
|
+
.instanceof(File, { message: 'File is required' })
|
|
83
|
+
.refine((file) => file.type.startsWith('image/'), { message: 'Only image files are allowed' })
|
|
84
|
+
.refine((file) => file.size <= 2 * 1024 * 1024, { message: 'File size must be less than 2MB' }),
|
|
85
|
+
type: z.enum(['logo', 'favicon'], { message: 'Type must be logo or favicon' }),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
export type CreateWorkspaceInput = z.infer<typeof createWorkspaceSchema>;
|
|
89
|
+
export type UpdateWorkspaceInput = z.infer<typeof updateWorkspaceSchema>;
|
|
90
|
+
export type InviteUserInput = z.infer<typeof inviteUserSchema>;
|
|
91
|
+
export type UpdateMemberRoleInput = z.infer<typeof updateMemberRoleSchema>;
|
|
92
|
+
export type UpdateBrandingInput = z.infer<typeof updateBrandingSchema>;
|
|
93
|
+
export type UploadBrandingAssetInput = z.infer<typeof uploadBrandingAssetSchema>;
|
package/tsconfig.json
ADDED