@thejob/schema 1.0.5 → 1.0.7

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.
@@ -6,11 +6,25 @@ import { JobStatus, SupportedJobStatuses } from "./job.constant";
6
6
  import { getSchemaByQuestion } from "./utils";
7
7
  export const JobSchema = object()
8
8
  .shape({
9
- // Headline section
9
+ /*
10
+ * Job headline defines the title of the job post.
11
+ * It is required and should be a string with a minimum length of 10 characters and a maximum length of 100 characters.
12
+ * This field is used to display the job title in job listings and search results.
13
+ */
10
14
  headline: string().required().min(10).max(150).label("Headline"),
11
- slug: string().optional().max(250).label("Slug"),
12
- // TODO: Make shortId required
13
- // Application receive preference section
15
+ /*
16
+ * Job slug is a unique identifier for the job post.
17
+ * It is required and should be a string with a maximum length of 250 characters.
18
+ * This field is used to create a user-friendly URL for the job post.
19
+ */
20
+ slug: string().required().max(250).label("Slug"),
21
+ /*
22
+ * Application receive preference defines how the job applications are received.
23
+ * It is required and should be one of the following values:
24
+ * - Inbox: Applications are received in the job portal's inbox.
25
+ * - ExternalWebsite: Applications are received on an external website.
26
+ * This field is used to determine how the job applications are processed.
27
+ */
14
28
  applicationReceivePreference: mixed()
15
29
  .oneOf([
16
30
  ApplicationReceivePreference.Inbox,
@@ -18,27 +32,54 @@ export const JobSchema = object()
18
32
  ])
19
33
  .required()
20
34
  .label("Preference"),
21
- // External apply link section
35
+ /*
36
+ * External apply link is the link to the external website where the job applications are received.
37
+ * It is required if the application receive preference is set to ExternalWebsite.
38
+ * It should be a valid URL.
39
+ * This field is used to redirect users to the external website for job applications.
40
+ */
22
41
  externalApplyLink: string().when("applicationReceivePreference", {
23
42
  is: (value) => value === ApplicationReceivePreference.ExternalWebsite,
24
43
  then: (schema) => schema.url().required().label("Apply for Job link"),
25
44
  otherwise: (schema) => schema.optional(),
26
45
  }),
27
- // Company section
46
+ /*
47
+ * This property is required and can be used to specify the company associated with the job post.
48
+ * It can be a predefined company (NameIdLogoSchema) or an other value (OtherValueSchema).
49
+ * The value should be an object with name, id, and logo properties.
50
+ */
28
51
  company: mixed()
29
52
  .oneOfSchema([NameIdLogoSchema, OtherValueSchema])
30
53
  .required()
31
54
  .label("Company"),
32
- // Designation section
55
+ /*
56
+ * This property is required and can be used to specify the designation associated with the job post.
57
+ * It can be a predefined designation (NameIdLogoSchema) or an other value (OtherValueSchema).
58
+ * The value should be an object with name, id, and logo properties.
59
+ */
33
60
  designation: mixed()
34
61
  .oneOfSchema([NameIdLogoSchema, OtherValueSchema])
35
62
  .required()
36
63
  .label("Designation"),
37
- // Employment type section
64
+ /*
65
+ * Employment type defines the type of employment for the job post.
66
+ * It is required and should be a string with a maximum length of 50 characters.
67
+ * This field is used to categorize the job based on employment type, such as full-time, part-time, contract, etc.
68
+ */
38
69
  employmentType: string().required().label("Employment type"),
39
- // Work mode section
70
+ /*
71
+ * Work mode defines the mode of work for the job post.
72
+ * It is required and should be a string with a maximum length of 50 characters.
73
+ * This field is used to categorize the job based on work mode, such as remote, on-site, or hybrid.
74
+ */
40
75
  workMode: string().required().label("Work mode"),
41
- // Skill section
76
+ /*
77
+ * This section is optional and can be used to specify the skills required for the job.
78
+ * It is useful for jobs that require specific skills, such as programming languages, frameworks, etc.
79
+ * The value should be an array of skills, each skill can be a predefined skill (NameIdLogoSchema) or an other value (OtherValueSchema).
80
+ *
81
+ * TODO: Add knockout skills that if not present in the application should immediately disqualify the application.
82
+ */
42
83
  skills: array()
43
84
  .of(mixed().oneOfSchema([
44
85
  NameIdLogoSchema,
@@ -47,7 +88,10 @@ export const JobSchema = object()
47
88
  .optional()
48
89
  .max(20)
49
90
  .label("Skills"),
50
- // TODO: Add knockout skills that if not present in the application should immediately disqualify the application.
91
+ /*
92
+ * This field will store the information about users who have bookmarked the job post.
93
+ * It is optional and can be used to track the users who are interested in the job
94
+ */
51
95
  bookmarks: array()
52
96
  .of(object().shape({
53
97
  userId: string().required().label("Use Id"),
@@ -55,6 +99,12 @@ export const JobSchema = object()
55
99
  }))
56
100
  .optional()
57
101
  .label("Bookmarks"),
102
+ /*
103
+ * This field will store the information about users who have applied for the job post using Direct/Quick Apply feature.
104
+ * It is optional and can be used to track the users who have applied for the job.
105
+ * It includes the user ID and the date when the application was made.
106
+ * It is also useful for analytics and reporting purposes.
107
+ */
58
108
  applicants: array()
59
109
  .of(object({
60
110
  userId: string().required().label("User Id"),
@@ -62,6 +112,11 @@ export const JobSchema = object()
62
112
  }))
63
113
  .optional()
64
114
  .label("Applicants"),
115
+ /*
116
+ * This field is optional and can be used to track the users who have applied for the job through an external website.
117
+ * It includes the user ID and the date when the application was made.
118
+ * It is also useful for analytics and reporting purposes.
119
+ */
65
120
  externalApplicants: array()
66
121
  .of(object({
67
122
  userId: string().required().label("User Id"),
@@ -69,57 +124,123 @@ export const JobSchema = object()
69
124
  }))
70
125
  .optional()
71
126
  .label("External Applicants"),
72
- // Description section
127
+ /*
128
+ * This field is required and should be used to store the job description.
129
+ * It is useful for providing detailed information about the job responsibilities, requirements, and other relevant details.
130
+ * It is recommended to use a Markdown editor to write the job description.
131
+ */
73
132
  description: string().required().min(250).max(10000).label("Description"),
74
- descriptionHTML: string().optional().label("Description Markup"),
133
+ /*
134
+ * This field is required and can be used to specify the job description.
135
+ * It is useful for providing detailed information about the job responsibilities, requirements, and other relevant details.
136
+ */
75
137
  descriptionMarkdown: string().optional().label("Description Markdown"),
76
- promoted: boolean().optional().label("Promoted"),
77
- // Location section
138
+ /*
139
+ * This field is require and should be used to store generated HTML string after parsing Markdown description.
140
+ * The value should be a string in HTML format.
141
+ * It is recommended to use a Markdown editor to convert the Markdown description to HTML.
142
+ *
143
+ * Note: This field is required to ensure that the job description is always available in HTML format for rendering.
144
+ * It is important to keep this field in sync with the Markdown description field.
145
+ * If the Markdown description is updated, the HTML description should also be updated accordingly.
146
+ * This can be done using a Markdown parser library that converts Markdown to HTML.
147
+ * For example, you can use libraries like `marked`, `markdown-it`, or `showdown` to convert Markdown to HTML.
148
+ * Ensure that the HTML is sanitized to prevent XSS attacks and other security vulnerabilities.
149
+ */
150
+ descriptionHTML: string().required().label("Description Markup"),
151
+ /*
152
+ * Location section
153
+ * This section is required and can be used to specify the location of the job.
154
+ * It is useful for jobs that are location-specific, such as on-site jobs.
155
+ * The value should be an array of locations.
156
+ *
157
+ * NOTE: Location is also required even if the job is remote, This is to comply with compliance and legal requirements.
158
+ */
78
159
  locations: array()
79
160
  .of(LocationSchema)
80
161
  .required()
81
162
  .min(1)
82
163
  .label("Location"),
83
- // // Category section TODO: Remove this section
84
- // category: array().optional().default([]).max(3).label("Category"),
85
- // Education level section
164
+ /*
165
+ * Educational level section
166
+ * This section is optional and can be used to specify the educational level required for the job.
167
+ * It is useful for jobs that require specific educational qualifications, such as Bachelor's, Master's, etc.
168
+ * The value should be an array of supported education levels.
169
+ */
86
170
  educationLevel: array(string().oneOf(SupportedEducationLevels))
87
171
  .required()
88
172
  .min(1)
89
173
  .label("Educational level"),
90
- // Job post validity section
174
+ /*
175
+ * Validity section
176
+ * This section is optional and can be used to specify the validity of the job post.
177
+ * This can be useful for jobs that have a specific duration or deadline.
178
+ * The value should be an object with start and end dates.
179
+ */
91
180
  validity: DurationSchema({
92
181
  format: SystemDateFormat,
93
182
  startLabel: "Start Date",
94
183
  endLabel: "Expiry Date",
95
184
  }).label("Validity"),
96
- // // Experience level section
185
+ /*
186
+ * Experience level section
187
+ * This section is optional and can be used to specify the experience level required for the job.
188
+ * It is useful for jobs that require specific levels of experience, such as entry-level, mid-level, or senior-level positions.
189
+ * The value should be one of the supported experience levels.
190
+ */
97
191
  experienceLevel: string()
98
192
  .oneOf(SupportedExperienceLevels)
99
193
  .optional()
100
194
  .label("Experience level"),
101
- // Contact section
195
+ /*
196
+ * Contact email section
197
+ * This section is optional and can be used to specify the contact email for the job post.
198
+ * It is useful for jobs that require direct communication with the employer.
199
+ */
102
200
  contactEmail: string().email().optional().label("Contact email"),
103
- // Career level section
104
- // careerLevel: string()
105
- // .oneOf(SupportedCareerLevels)
106
- // .optional()
107
- // .label("Career level"),
108
- // Working hours per week section
201
+ /*
202
+ * Working hours per week section
203
+ * This section is optional and can be used to specify the number of working hours per week for the job.
204
+ * It is useful for jobs that have a fixed number of hours per week, such as part-time or full-time jobs.
205
+ * The value should be a number between 1 and 168 (24 hours * 7 days).
206
+ */
109
207
  workingHoursPerWeek: number()
110
208
  .optional()
111
209
  .min(1)
112
210
  .max(24 * 7)
113
211
  .label("Working hours per week"),
114
- // Tags section
212
+ /*
213
+ * Tags are used to categorize the job post.
214
+ * They are optional and can be used to filter job posts.
215
+ */
115
216
  tags: array().max(50).optional().label("Tags"),
116
- //TODO: Add questionnaire section
217
+ /*
218
+ * Questionnaire section
219
+ * This section contains a list of questions that the user must answer when applying for the job through Direct/Quick Apply.
220
+ * It is optional and can be used to gather additional information from the applicants.
221
+ */
117
222
  questionnaire: array().of(lazy((question) => getSchemaByQuestion(question.type))),
223
+ /**
224
+ * Status of the job post.
225
+ * This is required and can be one of the supported job statuses.
226
+ * It defaults to 'Draft' if not provided.
227
+ * This field is used to track the current state of the job post.
228
+ * Possible values include:
229
+ * - Draft: The job post is in draft mode and not yet published.
230
+ * - Published: The job post is live and visible to users.
231
+ * - Closed: The job post is closed and no longer accepting applications.
232
+ * - Deleted: The job post has been deleted and is no longer available.
233
+ */
118
234
  status: string()
119
235
  .oneOf(SupportedJobStatuses)
120
236
  .default(JobStatus.Draft)
121
237
  .required()
122
238
  .label("Status"),
239
+ /**
240
+ * SEO tags for the job post.
241
+ * This is optional and can be used to improve the visibility of the job post in search engines.
242
+ * It includes meta tags for description and keywords.
243
+ */
123
244
  seoTags: object()
124
245
  .shape({
125
246
  meta: object().shape({
@@ -129,17 +250,70 @@ export const JobSchema = object()
129
250
  })
130
251
  .optional()
131
252
  .label("SEO Tags"),
253
+ /**
254
+ * Short job summary.
255
+ * This is optional and can be used to provide a brief overview of the job post.
256
+ * It is displayed in job listings and search results.
257
+ */
132
258
  jdSummary: string().optional().label("JD Summary"),
133
- // Addidional properties
259
+ /*
260
+ * Indicates if the job can be bookmarked by the user.
261
+ * This is optional and can be used to determine if the job supports bookmarking.
262
+ */
134
263
  canCreateAlert: boolean().optional().label("Can create alert"),
264
+ /*
265
+ * Indicates if the job can be directly applied to without going through an external website.
266
+ * This is optional and can be used to determine if the job supports direct applications.
267
+ */
135
268
  canDirectApply: boolean().optional().label("Can direct apply"),
269
+ /*
270
+ * Indicates if the user has applied for the job.
271
+ * This is optional and can be used to determine if the user has already applied.
272
+ */
136
273
  hasApplied: boolean().optional().label("Has applied"),
274
+ /**
275
+ * Indicates if the user is the owner of the job.
276
+ * This is optional and can be used to determine if the user has permissions to edit/delete the job.
277
+ */
137
278
  isOwner: boolean().optional().label("Is owner"),
279
+ /**
280
+ * Has the job been bookmarked by the user.
281
+ */
138
282
  hasBookmarked: boolean().optional().label("Has bookmarked"),
283
+ /**
284
+ * Number of applicants for the job (Direct Apply/Quick Apply).
285
+ * This is optional and can be used to track the number of applicants.
286
+ */
139
287
  applicantCount: number().optional().label("Applicant count"),
288
+ /**
289
+ * Rate per hour for the job.
290
+ * This is optional and can be used for freelance or contract jobs.
291
+ */
292
+ ratePerHour: number().optional().min(0).label("Rate per hour"),
293
+ /**
294
+ * Number of external applicants for the job.
295
+ */
140
296
  externalApplicantCount: number()
141
297
  .optional()
142
298
  .label("External applicant count"),
299
+ /**
300
+ * Indicates if the job is promoted.
301
+ * This is optional and can be used to determine if the job is featured or highlighted.
302
+ */
303
+ isPromoted: boolean().optional().label("Is promoted"),
304
+ /**
305
+ * Salary range for the job.
306
+ * This is optional and can be used to specify the salary range for the job.
307
+ * It includes currency, minimum, and maximum salary.
308
+ */
309
+ salaryRange: object()
310
+ .shape({
311
+ currency: string().required().label("Currency").default("USD"), // Default to USD if not provided
312
+ min: number().optional().min(0).label("Minimum Salary"),
313
+ max: number().optional().min(0).label("Maximum Salary"),
314
+ })
315
+ .optional()
316
+ .label("Salary Range"),
143
317
  // TODO: Add termsAccepted section to the schema
144
318
  // termsAccepted: boolean()
145
319
  // .oneOf([true], "Accept terms before proceeding")
@@ -56,9 +56,8 @@ export declare const JobRoleTemplateSchema: import("yup").ObjectSchema<{
56
56
  applicants: "";
57
57
  externalApplicants: "";
58
58
  description: undefined;
59
- descriptionHTML: undefined;
60
59
  descriptionMarkdown: undefined;
61
- promoted: undefined;
60
+ descriptionHTML: undefined;
62
61
  locations: "";
63
62
  educationLevel: undefined;
64
63
  validity: any;
@@ -81,7 +80,14 @@ export declare const JobRoleTemplateSchema: import("yup").ObjectSchema<{
81
80
  isOwner: undefined;
82
81
  hasBookmarked: undefined;
83
82
  applicantCount: undefined;
83
+ ratePerHour: undefined;
84
84
  externalApplicantCount: undefined;
85
+ isPromoted: undefined;
86
+ salaryRange: {
87
+ currency: "USD";
88
+ min: undefined;
89
+ max: undefined;
90
+ };
85
91
  id: undefined;
86
92
  shortId: undefined;
87
93
  createdBy: undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"job-role-template.schema.d.ts","sourceRoot":"","sources":["../../../src/job-role-template/job-role-template.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAQhC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,SAAS,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"job-role-template.schema.d.ts","sourceRoot":"","sources":["../../../src/job-role-template/job-role-template.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAQhC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,SAAS,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -270,7 +270,6 @@ export declare const NewResumePromptSchema: (host?: string) => import("yup").Obj
270
270
  image?: string | undefined;
271
271
  aboutMe?: string | undefined;
272
272
  emailVerified?: string | null | undefined;
273
- roles?: (import("../common").UserRole | undefined)[] | undefined;
274
273
  email: string;
275
274
  name: {
276
275
  first: string;
@@ -445,6 +444,7 @@ export declare const NewResumePromptSchema: (host?: string) => import("yup").Obj
445
444
  };
446
445
  };
447
446
  status: NonNullable<import("../common").UserStatus | undefined>;
447
+ roles: (import("../common").UserRole | undefined)[];
448
448
  };
449
449
  title: string;
450
450
  jobUrl: string | undefined;
@@ -461,7 +461,7 @@ export declare const NewResumePromptSchema: (host?: string) => import("yup").Obj
461
461
  languages: never[];
462
462
  additionalInfo: never[];
463
463
  status: undefined;
464
- roles: "";
464
+ roles: import("../common").UserRole[];
465
465
  id: undefined;
466
466
  name: {
467
467
  first: undefined;
@@ -146,7 +146,7 @@ export declare const UserSchema: import("yup").ObjectSchema<{
146
146
  title: string;
147
147
  }[];
148
148
  status: NonNullable<import("../common").UserStatus | undefined>;
149
- roles: (import("../common").UserRole | undefined)[] | undefined;
149
+ roles: (import("../common").UserRole | undefined)[];
150
150
  } & {
151
151
  id: string | undefined;
152
152
  name: {
@@ -192,7 +192,7 @@ export declare const UserSchema: import("yup").ObjectSchema<{
192
192
  languages: never[];
193
193
  additionalInfo: never[];
194
194
  status: undefined;
195
- roles: "";
195
+ roles: import("../common").UserRole[];
196
196
  id: undefined;
197
197
  name: {
198
198
  first: undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"user.schema.d.ts","sourceRoot":"","sources":["../../../src/user/user.schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAC;AAWnE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MA6EA,CAAC;AAExB,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAAC"}
1
+ {"version":3,"file":"user.schema.d.ts","sourceRoot":"","sources":["../../../src/user/user.schema.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAC;AAWnE,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAiFA,CAAC;AAExB,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAAC"}
@@ -1,4 +1,4 @@
1
- import { SupportedUserRoles, SupportedUserStatuses } from "../common";
1
+ import { DefaultUserRoles, SupportedUserRoles, SupportedUserStatuses, } from "../common";
2
2
  import { array, object, string } from "../yup-extended";
3
3
  import { EducationSchema } from "./education";
4
4
  import { UserGeneralDetailSchema } from "./general-detail/general-detail.schema";
@@ -80,7 +80,11 @@ export const UserSchema = object()
80
80
  /**
81
81
  * Roles assigned to the user
82
82
  */
83
- roles: array().of(string().oneOf(SupportedUserRoles)).label("Roles"),
83
+ roles: array()
84
+ .of(string().oneOf(SupportedUserRoles))
85
+ .required()
86
+ .default(DefaultUserRoles)
87
+ .label("Roles"),
84
88
  })
85
89
  .concat(UserGeneralDetailSchema)
86
90
  .noUnknown()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thejob/schema",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "types": "dist/esm/index.d.ts",