@thejob/schema 2.0.0 → 2.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/.claude/settings.local.json +138 -2
- package/dist/index.cjs +175 -133
- package/dist/index.d.cts +34 -4
- package/dist/index.d.ts +34 -4
- package/dist/index.js +145 -108
- package/package.json +1 -1
- package/src/extensions/date-string.extension.ts +1 -1
- package/src/index.ts +6 -0
- package/src/report/report.constant.ts +20 -0
- package/src/report/report.schema.ts +20 -0
- package/src/social-account/social-account.schema.ts +1 -1
- package/src/user/user-coordinator-profile.schema.ts +1 -1
- package/src/user/user-job-preferences.schema.ts +11 -11
- package/src/user/user-recruiter-profile.schema.ts +1 -1
- package/src/user/user.constant.ts +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -377,6 +377,36 @@ declare const DefaultPaginationOptions: {
|
|
|
377
377
|
limit: number;
|
|
378
378
|
};
|
|
379
379
|
|
|
380
|
+
declare enum ResourceType {
|
|
381
|
+
Job = "job",
|
|
382
|
+
User = "user",
|
|
383
|
+
Resume = "resume",
|
|
384
|
+
Company = "company"
|
|
385
|
+
}
|
|
386
|
+
declare const SupportedResourceTypes: ResourceType[];
|
|
387
|
+
declare enum ReportReason {
|
|
388
|
+
OffensiveOrHarassing = "offensive_or_harassing",
|
|
389
|
+
JobExpired = "job_expired",
|
|
390
|
+
AskingMoney = "asking_money",
|
|
391
|
+
FakeJob = "fake_job",
|
|
392
|
+
IncorrectJobDetails = "incorrect_job_details",
|
|
393
|
+
SellingSomething = "selling_something",
|
|
394
|
+
Other = "other"
|
|
395
|
+
}
|
|
396
|
+
declare const SupportedReportReasons: ReportReason[];
|
|
397
|
+
|
|
398
|
+
declare const ReportSchema: yup.ObjectSchema<{
|
|
399
|
+
type: NonNullable<ResourceType | undefined>;
|
|
400
|
+
resourceId: string;
|
|
401
|
+
reason: NonNullable<ReportReason | undefined>;
|
|
402
|
+
comment: string | undefined;
|
|
403
|
+
}, yup.AnyObject, {
|
|
404
|
+
type: undefined;
|
|
405
|
+
resourceId: undefined;
|
|
406
|
+
reason: undefined;
|
|
407
|
+
comment: undefined;
|
|
408
|
+
}, "">;
|
|
409
|
+
|
|
380
410
|
declare const SkillSchema: yup.ObjectSchema<{
|
|
381
411
|
name: string;
|
|
382
412
|
logo: {
|
|
@@ -499,7 +529,7 @@ declare enum JobSearchUrgency {
|
|
|
499
529
|
}
|
|
500
530
|
declare const SupportedJobSearchUrgencies: JobSearchUrgency[];
|
|
501
531
|
/**
|
|
502
|
-
* How the user heard about the platform
|
|
532
|
+
* How the user heard about the platform - captured at the end of onboarding
|
|
503
533
|
* for marketing attribution.
|
|
504
534
|
*/
|
|
505
535
|
declare enum ReferralSource {
|
|
@@ -1365,7 +1395,7 @@ declare const RecruiterPageLinkSchema: yup.ObjectSchema<{
|
|
|
1365
1395
|
}, "">;
|
|
1366
1396
|
/**
|
|
1367
1397
|
* Recruiter-role-specific fields on UserSchema. All optional at the field
|
|
1368
|
-
* level
|
|
1398
|
+
* level - presence is gated by `UserRole.Recruiter` in the user's `roles`,
|
|
1369
1399
|
* not by schema branching, so the user shape stays flat.
|
|
1370
1400
|
*/
|
|
1371
1401
|
declare const UserRecruiterProfileSchema: yup.ObjectSchema<{
|
|
@@ -1443,7 +1473,7 @@ declare const CoordinatorPageLinkSchema: yup.ObjectSchema<{
|
|
|
1443
1473
|
}, "">;
|
|
1444
1474
|
/**
|
|
1445
1475
|
* Coordinator-role-specific fields on UserSchema. All optional at the field
|
|
1446
|
-
* level
|
|
1476
|
+
* level - presence is gated by `UserRole.Coordinator` in the user's
|
|
1447
1477
|
* `roles`, not by schema branching, so the user shape stays flat.
|
|
1448
1478
|
*/
|
|
1449
1479
|
declare const UserCoordinatorProfileSchema: yup.ObjectSchema<{
|
|
@@ -1703,4 +1733,4 @@ declare const StudentCompletenessSchema: yup.ObjectSchema<{
|
|
|
1703
1733
|
};
|
|
1704
1734
|
}, "">;
|
|
1705
1735
|
|
|
1706
|
-
export { CompletenessScoreSchema, ContactTypes, CoordinatorPageLinkSchema, DateStringSchema, DbDefaultSchema, DefaultPaginatedResponse, DefaultPaginationOptions, DefaultUserRoles, DurationSchema, EducationLevel, EducationSchema, ExperienceLevel, GeneraDetailFields, GroupManagedBy, GroupMembershipSchema, GroupMembershipStatus, GroupSchema, GroupStatus, GroupTranslationSchema, GroupVisibility, JobSearchUrgency, LocationSchema, MIN_SALARY_LOWER_BOUND, MIN_SALARY_UPPER_BOUND, PageSchema, PageStatus, PageType, type PaginatedResponse, PaginationSchema, ProficiencyLevel, RecruiterPageLinkSchema, ReferralSource, SkillSchema, SocialAccount, SocialAccountSchema, StudentCompletenessSchema, StudyType, SupportedContactTypes, SupportedEducationLevels, SupportedExperienceLevels, SupportedJobSearchUrgencies, SupportedPageStatuses, SupportedPageTypes, SupportedProficiencyLevels, SupportedReferralSources, SupportedSalaryCurrencies, type SupportedSalaryCurrency, SupportedSocialAccounts, SupportedStudyTypes, SupportedUserProfileVisibilities, SupportedUserRoles, SupportedUserStatuses, type TDurationSchema, TermsAcceptedSchema, UserAdditionalInfoSchema, UserCertificationSchema, UserCompletenessSchema, UserCoordinatorProfileSchema, UserDetailType, UserGeneralDetailSchema, UserInterestSchema, UserJobPreferencesSchema, UserLanguageSchema, type UserProfileOverview, UserProfileVisibility, UserProjectSchema, UserRecruiterProfileSchema, UserRole, UserSchema, UserSkillSchema, UserStatus, WorkExperienceSchema, dateString };
|
|
1736
|
+
export { CompletenessScoreSchema, ContactTypes, CoordinatorPageLinkSchema, DateStringSchema, DbDefaultSchema, DefaultPaginatedResponse, DefaultPaginationOptions, DefaultUserRoles, DurationSchema, EducationLevel, EducationSchema, ExperienceLevel, GeneraDetailFields, GroupManagedBy, GroupMembershipSchema, GroupMembershipStatus, GroupSchema, GroupStatus, GroupTranslationSchema, GroupVisibility, JobSearchUrgency, LocationSchema, MIN_SALARY_LOWER_BOUND, MIN_SALARY_UPPER_BOUND, PageSchema, PageStatus, PageType, type PaginatedResponse, PaginationSchema, ProficiencyLevel, RecruiterPageLinkSchema, ReferralSource, ReportReason, ReportSchema, ResourceType, SkillSchema, SocialAccount, SocialAccountSchema, StudentCompletenessSchema, StudyType, SupportedContactTypes, SupportedEducationLevels, SupportedExperienceLevels, SupportedJobSearchUrgencies, SupportedPageStatuses, SupportedPageTypes, SupportedProficiencyLevels, SupportedReferralSources, SupportedReportReasons, SupportedResourceTypes, SupportedSalaryCurrencies, type SupportedSalaryCurrency, SupportedSocialAccounts, SupportedStudyTypes, SupportedUserProfileVisibilities, SupportedUserRoles, SupportedUserStatuses, type TDurationSchema, TermsAcceptedSchema, UserAdditionalInfoSchema, UserCertificationSchema, UserCompletenessSchema, UserCoordinatorProfileSchema, UserDetailType, UserGeneralDetailSchema, UserInterestSchema, UserJobPreferencesSchema, UserLanguageSchema, type UserProfileOverview, UserProfileVisibility, UserProjectSchema, UserRecruiterProfileSchema, UserRole, UserSchema, UserSkillSchema, UserStatus, WorkExperienceSchema, dateString };
|
package/dist/index.js
CHANGED
|
@@ -330,7 +330,7 @@ var SupportedSocialAccounts = Object.values(SocialAccount);
|
|
|
330
330
|
|
|
331
331
|
// src/social-account/social-account.schema.ts
|
|
332
332
|
var SocialAccountSchema = object9().shape({
|
|
333
|
-
// TODO: Remove isNew
|
|
333
|
+
// TODO: Remove isNew - it's unused. Backend (user-social-accounts.service.ts) just strips it before saving.
|
|
334
334
|
isNew: boolean6().default(false).optional().label("Is New"),
|
|
335
335
|
type: string6().oneOf(SupportedSocialAccounts).required().label("Account Type"),
|
|
336
336
|
url: string6().required().label("URL")
|
|
@@ -399,19 +399,51 @@ var DefaultPaginationOptions = {
|
|
|
399
399
|
limit: 10
|
|
400
400
|
};
|
|
401
401
|
|
|
402
|
+
// src/report/report.schema.ts
|
|
403
|
+
import { mixed as mixed2, object as object12, string as string9 } from "yup";
|
|
404
|
+
|
|
405
|
+
// src/report/report.constant.ts
|
|
406
|
+
var ResourceType = /* @__PURE__ */ ((ResourceType3) => {
|
|
407
|
+
ResourceType3["Job"] = "job";
|
|
408
|
+
ResourceType3["User"] = "user";
|
|
409
|
+
ResourceType3["Resume"] = "resume";
|
|
410
|
+
ResourceType3["Company"] = "company";
|
|
411
|
+
return ResourceType3;
|
|
412
|
+
})(ResourceType || {});
|
|
413
|
+
var SupportedResourceTypes = Object.values(ResourceType);
|
|
414
|
+
var ReportReason = /* @__PURE__ */ ((ReportReason3) => {
|
|
415
|
+
ReportReason3["OffensiveOrHarassing"] = "offensive_or_harassing";
|
|
416
|
+
ReportReason3["JobExpired"] = "job_expired";
|
|
417
|
+
ReportReason3["AskingMoney"] = "asking_money";
|
|
418
|
+
ReportReason3["FakeJob"] = "fake_job";
|
|
419
|
+
ReportReason3["IncorrectJobDetails"] = "incorrect_job_details";
|
|
420
|
+
ReportReason3["SellingSomething"] = "selling_something";
|
|
421
|
+
ReportReason3["Other"] = "other";
|
|
422
|
+
return ReportReason3;
|
|
423
|
+
})(ReportReason || {});
|
|
424
|
+
var SupportedReportReasons = Object.values(ReportReason);
|
|
425
|
+
|
|
426
|
+
// src/report/report.schema.ts
|
|
427
|
+
var ReportSchema = object12({
|
|
428
|
+
type: mixed2().oneOf(SupportedResourceTypes).required().label("Type"),
|
|
429
|
+
resourceId: string9().required().label("Resource ID"),
|
|
430
|
+
reason: mixed2().oneOf(SupportedReportReasons).required("Please choose a reason").label("Reason"),
|
|
431
|
+
comment: string9().max(1e3).optional().label("Comment")
|
|
432
|
+
}).label("Report Schema");
|
|
433
|
+
|
|
402
434
|
// src/skill/skill.schema.ts
|
|
403
|
-
import { array as array6, object as
|
|
404
|
-
var SkillSchema =
|
|
405
|
-
name:
|
|
406
|
-
logo:
|
|
407
|
-
light:
|
|
408
|
-
dark:
|
|
435
|
+
import { array as array6, object as object13, string as string10 } from "yup";
|
|
436
|
+
var SkillSchema = object13({
|
|
437
|
+
name: string10().trim().required().label("Skill Name"),
|
|
438
|
+
logo: object13({
|
|
439
|
+
light: string10().required().label("Light Logo"),
|
|
440
|
+
dark: string10().optional().nullable().label("Dark Logo")
|
|
409
441
|
}).optional().nullable().default(null).label("Logo"),
|
|
410
|
-
tags: array6().of(
|
|
442
|
+
tags: array6().of(string10().max(50)).max(20).optional().label("Tags")
|
|
411
443
|
}).concat(DbDefaultSchema).noUnknown().strict().label("Skill");
|
|
412
444
|
|
|
413
445
|
// src/user/user.schema.ts
|
|
414
|
-
import { array as array10, number as number7, object as
|
|
446
|
+
import { array as array10, number as number7, object as object25, string as string23 } from "yup";
|
|
415
447
|
|
|
416
448
|
// src/user/user.constant.ts
|
|
417
449
|
var UserRole = /* @__PURE__ */ ((UserRole2) => {
|
|
@@ -493,51 +525,51 @@ var MIN_SALARY_LOWER_BOUND = 0;
|
|
|
493
525
|
var MIN_SALARY_UPPER_BOUND = 1e6;
|
|
494
526
|
|
|
495
527
|
// src/user/work-experience.schema.ts
|
|
496
|
-
import { boolean as boolean8, object as
|
|
497
|
-
var WorkExperienceSchema =
|
|
528
|
+
import { boolean as boolean8, object as object14, string as string11 } from "yup";
|
|
529
|
+
var WorkExperienceSchema = object14().shape({
|
|
498
530
|
company: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Company"),
|
|
499
|
-
designation:
|
|
531
|
+
designation: string11().trim().required().label("Designation"),
|
|
500
532
|
duration: DurationSchema({
|
|
501
533
|
format: "YYYY-MM",
|
|
502
534
|
startLabel: "Start Date",
|
|
503
535
|
endLabel: "End Date"
|
|
504
536
|
}).required().label("Duration"),
|
|
505
|
-
description:
|
|
537
|
+
description: string11().trim().max(3e3).optional().label("Description"),
|
|
506
538
|
location: LocationSchema.required().label("Location"),
|
|
507
539
|
isRemote: boolean8().oneOf([true, false]).default(false).label("Is Remote")
|
|
508
540
|
}).noUnknown().strict().label("Work Experience");
|
|
509
541
|
|
|
510
542
|
// src/user/education.schema.ts
|
|
511
|
-
import { boolean as boolean9, object as
|
|
512
|
-
var EducationSchema =
|
|
543
|
+
import { boolean as boolean9, object as object15, string as string12 } from "yup";
|
|
544
|
+
var EducationSchema = object15({
|
|
513
545
|
institute: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Institute"),
|
|
514
|
-
course:
|
|
515
|
-
fieldOfStudy:
|
|
546
|
+
course: string12().trim().required().label("Course"),
|
|
547
|
+
fieldOfStudy: string12().trim().required().label("Field of Study"),
|
|
516
548
|
duration: DurationSchema({
|
|
517
549
|
format: "YYYY-MM",
|
|
518
550
|
startLabel: "Start Date",
|
|
519
551
|
endLabel: "End Date"
|
|
520
552
|
}).required().label("Duration"),
|
|
521
|
-
description:
|
|
553
|
+
description: string12().trim().max(3e3).optional().label("Description"),
|
|
522
554
|
isDistanceLearning: boolean9().default(false).label("Is Distance Learning"),
|
|
523
555
|
location: LocationSchema.required().label("Location"),
|
|
524
|
-
studyType:
|
|
556
|
+
studyType: string12().oneOf(SupportedStudyTypes).trim().max(50).required().label("Study Type")
|
|
525
557
|
}).noUnknown().strict().label("Education");
|
|
526
558
|
|
|
527
559
|
// src/user/user-skill.schema.ts
|
|
528
|
-
import { object as
|
|
529
|
-
var UserSkillSchema =
|
|
530
|
-
name:
|
|
531
|
-
proficiencyLevel:
|
|
560
|
+
import { object as object16, string as string13 } from "yup";
|
|
561
|
+
var UserSkillSchema = object16({
|
|
562
|
+
name: string13().required().label("Name"),
|
|
563
|
+
proficiencyLevel: string13().oneOf(SupportedProficiencyLevels).required().label("Proficiency Level"),
|
|
532
564
|
lastUsed: dateString().format("YYYY-MM").nullable().optional().label("Last Used")
|
|
533
565
|
}).noUnknown().strict().label("Skill");
|
|
534
566
|
|
|
535
567
|
// src/user/project.schema.ts
|
|
536
|
-
import { object as
|
|
537
|
-
var UserProjectSchema =
|
|
538
|
-
name:
|
|
539
|
-
url:
|
|
540
|
-
description:
|
|
568
|
+
import { object as object17, string as string14 } from "yup";
|
|
569
|
+
var UserProjectSchema = object17({
|
|
570
|
+
name: string14().trim().max(50).required().label("Name"),
|
|
571
|
+
url: string14().optional().label("URL"),
|
|
572
|
+
description: string14().trim().min(100).max(3e3).required().label("Description"),
|
|
541
573
|
duration: DurationSchema({
|
|
542
574
|
format: "YYYY-MM",
|
|
543
575
|
startLabel: "Start Date",
|
|
@@ -546,69 +578,69 @@ var UserProjectSchema = object16({
|
|
|
546
578
|
}).noUnknown().strict().label("Project");
|
|
547
579
|
|
|
548
580
|
// src/user/user-certification.schema.ts
|
|
549
|
-
import { object as
|
|
550
|
-
var UserCertificationSchema =
|
|
551
|
-
name:
|
|
581
|
+
import { object as object18, string as string15 } from "yup";
|
|
582
|
+
var UserCertificationSchema = object18({
|
|
583
|
+
name: string15().trim().max(100).required().label("Name"),
|
|
552
584
|
// TODO: Add validation for authority
|
|
553
|
-
authority:
|
|
554
|
-
licenseNumber:
|
|
585
|
+
authority: string15().trim().max(100).required().label("Authority"),
|
|
586
|
+
licenseNumber: string15().trim().max(50).optional().label("License Number"),
|
|
555
587
|
duration: DurationSchema({
|
|
556
588
|
format: "YYYY-MM",
|
|
557
589
|
startLabel: "Start Date",
|
|
558
590
|
endLabel: "End Date"
|
|
559
591
|
}).optional().nullable().label("Duration"),
|
|
560
|
-
url:
|
|
592
|
+
url: string15().optional().label("URL")
|
|
561
593
|
}).noUnknown().strict().label("Certification");
|
|
562
594
|
|
|
563
595
|
// src/user/user-interest.schema.ts
|
|
564
|
-
import { string as
|
|
565
|
-
var UserInterestSchema =
|
|
596
|
+
import { string as string16 } from "yup";
|
|
597
|
+
var UserInterestSchema = string16().trim().required().label("Interest");
|
|
566
598
|
|
|
567
599
|
// src/user/user-language.schema.ts
|
|
568
|
-
import { object as
|
|
569
|
-
var UserLanguageSchema =
|
|
570
|
-
name:
|
|
571
|
-
proficiencyLevel:
|
|
600
|
+
import { object as object19, string as string17 } from "yup";
|
|
601
|
+
var UserLanguageSchema = object19({
|
|
602
|
+
name: string17().trim().required().label("Name"),
|
|
603
|
+
proficiencyLevel: string17().oneOf(SupportedProficiencyLevels).trim().max(50).required().label("Proficiency Level")
|
|
572
604
|
}).noUnknown().strict().label("Language");
|
|
573
605
|
|
|
574
606
|
// src/user/user-additional-info.schema.ts
|
|
575
|
-
import { object as
|
|
576
|
-
var UserAdditionalInfoSchema =
|
|
577
|
-
title:
|
|
578
|
-
description:
|
|
607
|
+
import { object as object20, string as string18 } from "yup";
|
|
608
|
+
var UserAdditionalInfoSchema = object20({
|
|
609
|
+
title: string18().trim().max(60).required().label("Title"),
|
|
610
|
+
description: string18().trim().max(1e3).required().label("Description")
|
|
579
611
|
}).noUnknown().strict().label("User Additional Info");
|
|
580
612
|
|
|
581
613
|
// src/user/general-detail.schema.ts
|
|
582
|
-
import { object as
|
|
583
|
-
var UserGeneralDetailSchema =
|
|
584
|
-
id:
|
|
585
|
-
name:
|
|
586
|
-
first:
|
|
587
|
-
last:
|
|
614
|
+
import { object as object21, string as string19 } from "yup";
|
|
615
|
+
var UserGeneralDetailSchema = object21({
|
|
616
|
+
id: string19().optional().label("ID"),
|
|
617
|
+
name: object21().shape({
|
|
618
|
+
first: string19().trim().max(50).required().label("First Name"),
|
|
619
|
+
last: string19().trim().max(50).optional().label("Last Name")
|
|
588
620
|
}).required().label("Name"),
|
|
589
|
-
headline:
|
|
590
|
-
image:
|
|
591
|
-
aboutMe:
|
|
592
|
-
email:
|
|
593
|
-
mobile:
|
|
594
|
-
emailVerified:
|
|
595
|
-
mobileVerified:
|
|
596
|
-
experienceLevel:
|
|
621
|
+
headline: string19().trim().max(200).optional().label("Headline"),
|
|
622
|
+
image: string19().optional().label("Image"),
|
|
623
|
+
aboutMe: string19().trim().max(3e3).optional().label("About Me"),
|
|
624
|
+
email: string19().required().label("Email"),
|
|
625
|
+
mobile: string19().nullable().optional().label("Mobile"),
|
|
626
|
+
emailVerified: string19().nullable().optional().label("Email Verified"),
|
|
627
|
+
mobileVerified: string19().nullable().optional().label("Mobile Verified"),
|
|
628
|
+
experienceLevel: string19().oneOf(SupportedExperienceLevels).required().label("Experience level"),
|
|
597
629
|
location: LocationSchema.required().label("Location"),
|
|
598
|
-
region:
|
|
599
|
-
country:
|
|
600
|
-
lang:
|
|
630
|
+
region: object21().shape({
|
|
631
|
+
country: string19().trim().required().label("Region Country"),
|
|
632
|
+
lang: string19().trim().required().label("Region Language")
|
|
601
633
|
}).optional().default(void 0).label("Region"),
|
|
602
|
-
profileVisibility:
|
|
634
|
+
profileVisibility: string19().oneOf(SupportedUserProfileVisibilities).default("public" /* Public */).label("Profile Visibility")
|
|
603
635
|
}).noUnknown().strict().label("General Detail");
|
|
604
636
|
|
|
605
637
|
// src/user/user-job-preferences.schema.ts
|
|
606
|
-
import { array as array7, boolean as boolean10, date as date2, number as number6, object as
|
|
607
|
-
var UserJobPreferencesSchema =
|
|
638
|
+
import { array as array7, boolean as boolean10, date as date2, number as number6, object as object22, string as string20 } from "yup";
|
|
639
|
+
var UserJobPreferencesSchema = object22({
|
|
608
640
|
/**
|
|
609
641
|
* Whether the job seeker is openly signalling availability. Surfaces the
|
|
610
642
|
* "Open to work" badge on the public profile and boosts visibility in
|
|
611
|
-
* recruiter search. Defaults to `false`
|
|
643
|
+
* recruiter search. Defaults to `false` - users must opt in.
|
|
612
644
|
*/
|
|
613
645
|
openToWork: boolean10().default(false).label("Open to Work"),
|
|
614
646
|
/**
|
|
@@ -616,7 +648,7 @@ var UserJobPreferencesSchema = object21({
|
|
|
616
648
|
* and can downgrade the visibility of expired or low-relevance postings for
|
|
617
649
|
* users in `passively_browsing` mode.
|
|
618
650
|
*/
|
|
619
|
-
jobSearchUrgency:
|
|
651
|
+
jobSearchUrgency: string20().oneOf(SupportedJobSearchUrgencies).required().label("Job Search Urgency"),
|
|
620
652
|
/**
|
|
621
653
|
* Locations the user wants to work in. Stores the full `LocationSchema`
|
|
622
654
|
* shape (country, city, state, geo, etc.) as returned by the locations
|
|
@@ -628,36 +660,36 @@ var UserJobPreferencesSchema = object21({
|
|
|
628
660
|
* (up to 2) for borderline candidates.
|
|
629
661
|
*
|
|
630
662
|
* Distinct from the singular `experienceLevel` field on `UserSchema`
|
|
631
|
-
* (concat'd via `UserGeneralDetailSchema`)
|
|
663
|
+
* (concat'd via `UserGeneralDetailSchema`) - that field captures the user's
|
|
632
664
|
* own current seniority, while these are the levels they want to *target*.
|
|
633
665
|
* Both reuse the same `ExperienceLevel` taxonomy from `common.constant.ts`
|
|
634
666
|
* so search/match logic doesn't have to translate between two vocabularies.
|
|
635
667
|
*/
|
|
636
|
-
targetExperienceLevels: array7().of(
|
|
668
|
+
targetExperienceLevels: array7().of(string20().oneOf(SupportedExperienceLevels).required()).min(1, "Pick at least one experience level.").max(2, "You can select at most 2 experience levels.").required().label("Target Experience Levels"),
|
|
637
669
|
/**
|
|
638
|
-
* Specializations the user is searching for
|
|
670
|
+
* Specializations the user is searching for - free-form titles.
|
|
639
671
|
*
|
|
640
672
|
* Job titles are an open vocabulary (think O*NET, ESCO, LinkedIn's title
|
|
641
673
|
* graph), so the schema only enforces length bounds per entry. The wizard
|
|
642
674
|
* surfaces a curated "Popular Roles" picker for discovery, but the user
|
|
643
675
|
* can ultimately add any title; matching/normalization happens downstream.
|
|
644
676
|
*/
|
|
645
|
-
jobRoles: array7().of(
|
|
677
|
+
jobRoles: array7().of(string20().trim().max(120).required()).min(1, "Pick at least one role.").required().label("Job Roles"),
|
|
646
678
|
/**
|
|
647
679
|
* Minimum acceptable annual base salary, in `minSalaryCurrency`.
|
|
648
680
|
* Stored as an integer in the currency's major unit (e.g. dollars, not cents).
|
|
649
|
-
* Defaults to 0 ("any salary") rather than being optional
|
|
681
|
+
* Defaults to 0 ("any salary") rather than being optional - every job-seeker
|
|
650
682
|
* has a floor, even if it's zero.
|
|
651
683
|
*/
|
|
652
684
|
minSalary: number6().integer().min(MIN_SALARY_LOWER_BOUND).max(MIN_SALARY_UPPER_BOUND).default(0).required().label("Minimum Salary"),
|
|
653
|
-
minSalaryCurrency:
|
|
685
|
+
minSalaryCurrency: string20().oneOf(SupportedSalaryCurrencies).default("USD").required().label("Minimum Salary Currency"),
|
|
654
686
|
/**
|
|
655
687
|
* Marketing-attribution capture from the final onboarding step.
|
|
656
688
|
*/
|
|
657
|
-
referralSource:
|
|
689
|
+
referralSource: string20().oneOf(SupportedReferralSources).required().label("Referral Source"),
|
|
658
690
|
/**
|
|
659
691
|
* Resumes the user has uploaded. Embedded directly on the user document
|
|
660
|
-
* (capped at 5)
|
|
692
|
+
* (capped at 5) - they're cheap to denormalize, every wizard step that
|
|
661
693
|
* cares about them is already loading the user doc, and the cap keeps the
|
|
662
694
|
* subdoc bounded.
|
|
663
695
|
*
|
|
@@ -665,19 +697,19 @@ var UserJobPreferencesSchema = object21({
|
|
|
665
697
|
* the API can sign for download is kept here.
|
|
666
698
|
*
|
|
667
699
|
* Distinct from the `Resumes` collection used by the (currently unused)
|
|
668
|
-
* AI resume-builder flow
|
|
700
|
+
* AI resume-builder flow - onboarding uploads land here, AI-built resumes
|
|
669
701
|
* live in their own collection.
|
|
670
702
|
*/
|
|
671
703
|
resumes: array7().of(
|
|
672
|
-
|
|
673
|
-
// Stable id assigned on upload
|
|
704
|
+
object22({
|
|
705
|
+
// Stable id assigned on upload - used to address a specific entry
|
|
674
706
|
// for delete / set-primary operations without exposing the GCS URL
|
|
675
707
|
// as a route key.
|
|
676
|
-
id:
|
|
677
|
-
url:
|
|
678
|
-
filename:
|
|
708
|
+
id: string20().required().label("ID"),
|
|
709
|
+
url: string20().required().label("Resume URL"),
|
|
710
|
+
filename: string20().trim().max(255).optional().label("Filename"),
|
|
679
711
|
sizeBytes: number6().integer().min(0).optional().label("Size (bytes)"),
|
|
680
|
-
mimeType:
|
|
712
|
+
mimeType: string20().trim().max(120).optional().label("MIME Type"),
|
|
681
713
|
uploadedAt: date2().required().label("Uploaded At"),
|
|
682
714
|
isPrimary: boolean10().default(false).label("Is Primary")
|
|
683
715
|
}).noUnknown().strict().label("Resume")
|
|
@@ -689,29 +721,29 @@ var UserJobPreferencesSchema = object21({
|
|
|
689
721
|
onboardingCompletedAt: date2().nullable().optional().label("Onboarding Completed At"),
|
|
690
722
|
/**
|
|
691
723
|
* Parser-suggested values for wizard fields, written by the resume-upload
|
|
692
|
-
* flow. Every parser-derived field lands here
|
|
724
|
+
* flow. Every parser-derived field lands here - including profile-shaped
|
|
693
725
|
* fields (headline, aboutMe, mobile, location, experienceLevel,
|
|
694
|
-
* socialAccounts, workExperiences, educations)
|
|
726
|
+
* socialAccounts, workExperiences, educations) - so nothing reaches the
|
|
695
727
|
* top-level user document until the user confirms it on the matching
|
|
696
728
|
* wizard step. When a user clicks Next on a step, the API drops the
|
|
697
729
|
* matching key from this sub-doc so a re-uploaded resume can't overwrite
|
|
698
730
|
* confirmed answers.
|
|
699
731
|
*
|
|
700
|
-
* READ RULE
|
|
732
|
+
* READ RULE - strict:
|
|
701
733
|
* `pendingPrefill.<field>` is ONLY for seeding a wizard step's form
|
|
702
734
|
* initial value (e.g. `prefer(user.<field>, user.pendingPrefill?.<field>)`
|
|
703
|
-
* in a step's `load`). It is NOT the user's actual value
|
|
735
|
+
* in a step's `load`). It is NOT the user's actual value - it's an
|
|
704
736
|
* unconfirmed suggestion. Never substitute it as a fallback in profile
|
|
705
737
|
* pages, search/match, recommendations, public profile, dashboards, or
|
|
706
738
|
* APIs. If `user.<field>` is empty there, the correct behavior is empty,
|
|
707
739
|
* because the user has not confirmed it yet.
|
|
708
740
|
*/
|
|
709
|
-
pendingPrefill:
|
|
710
|
-
headline:
|
|
711
|
-
aboutMe:
|
|
712
|
-
mobile:
|
|
741
|
+
pendingPrefill: object22({
|
|
742
|
+
headline: string20().trim().optional().label("Pending Headline"),
|
|
743
|
+
aboutMe: string20().trim().optional().label("Pending About Me"),
|
|
744
|
+
mobile: string20().trim().optional().label("Pending Mobile"),
|
|
713
745
|
location: LocationSchema.optional().default(void 0).label("Pending Location"),
|
|
714
|
-
experienceLevel:
|
|
746
|
+
experienceLevel: string20().oneOf(SupportedExperienceLevels).optional().label("Pending Experience Level"),
|
|
715
747
|
socialAccounts: array7().of(SocialAccountSchema.required()).optional().label("Pending Social Accounts"),
|
|
716
748
|
workExperiences: array7().of(WorkExperienceSchema.required()).optional().label("Pending Work Experiences"),
|
|
717
749
|
educations: array7().of(EducationSchema.required()).optional().label("Pending Educations")
|
|
@@ -719,35 +751,35 @@ var UserJobPreferencesSchema = object21({
|
|
|
719
751
|
}).noUnknown().strict().label("User Job Preferences Schema");
|
|
720
752
|
|
|
721
753
|
// src/user/user-recruiter-profile.schema.ts
|
|
722
|
-
import { array as array8, object as
|
|
723
|
-
var RecruiterPageLinkSchema =
|
|
754
|
+
import { array as array8, object as object23, string as string21 } from "yup";
|
|
755
|
+
var RecruiterPageLinkSchema = object23({
|
|
724
756
|
page: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Company Page"),
|
|
725
|
-
jobTitle:
|
|
757
|
+
jobTitle: string21().trim().max(100).optional().label("Job Title")
|
|
726
758
|
}).noUnknown().strict().label("Recruiter Page Link");
|
|
727
|
-
var UserRecruiterProfileSchema =
|
|
728
|
-
recruiterProfile:
|
|
759
|
+
var UserRecruiterProfileSchema = object23({
|
|
760
|
+
recruiterProfile: object23({
|
|
729
761
|
hiringFor: array8().of(RecruiterPageLinkSchema).default([]).label("Hiring For")
|
|
730
762
|
}).optional().default(void 0).label("Recruiter Profile")
|
|
731
763
|
}).noUnknown().strict().label("User Recruiter Profile");
|
|
732
764
|
|
|
733
765
|
// src/user/user-coordinator-profile.schema.ts
|
|
734
|
-
import { array as array9, object as
|
|
735
|
-
var CoordinatorPageLinkSchema =
|
|
766
|
+
import { array as array9, object as object24, string as string22 } from "yup";
|
|
767
|
+
var CoordinatorPageLinkSchema = object24({
|
|
736
768
|
page: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Institute Page"),
|
|
737
|
-
jobTitle:
|
|
769
|
+
jobTitle: string22().trim().max(100).optional().label("Job Title")
|
|
738
770
|
}).noUnknown().strict().label("Coordinator Page Link");
|
|
739
|
-
var UserCoordinatorProfileSchema =
|
|
740
|
-
coordinatorProfile:
|
|
771
|
+
var UserCoordinatorProfileSchema = object24({
|
|
772
|
+
coordinatorProfile: object24({
|
|
741
773
|
coordinatesAt: array9().of(CoordinatorPageLinkSchema).default([]).label("Coordinates At")
|
|
742
774
|
}).optional().default(void 0).label("Coordinator Profile")
|
|
743
775
|
}).noUnknown().strict().label("User Coordinator Profile");
|
|
744
776
|
|
|
745
777
|
// src/user/user.schema.ts
|
|
746
|
-
var UserSchema =
|
|
778
|
+
var UserSchema = object25({
|
|
747
779
|
/**
|
|
748
780
|
* Related auth account id from auth Server (e.g. Better auth https://auth.thejob.dev)
|
|
749
781
|
*/
|
|
750
|
-
authAccountId:
|
|
782
|
+
authAccountId: string23().required().label("Auth Account ID"),
|
|
751
783
|
/**
|
|
752
784
|
* Social media information about the user (e.g. LinkedIn, GitHub, etc.)
|
|
753
785
|
*/
|
|
@@ -787,25 +819,25 @@ var UserSchema = object24({
|
|
|
787
819
|
/**
|
|
788
820
|
* Status of the user account
|
|
789
821
|
*/
|
|
790
|
-
status:
|
|
822
|
+
status: string23().oneOf(SupportedUserStatuses).required().label("Status"),
|
|
791
823
|
/**
|
|
792
824
|
* Roles assigned to the user
|
|
793
825
|
*/
|
|
794
|
-
roles: array10().of(
|
|
826
|
+
roles: array10().of(string23().oneOf(SupportedUserRoles)).required().default(DefaultUserRoles).label("Roles"),
|
|
795
827
|
/**
|
|
796
828
|
* Vector embedding of the user's profile for semantic/hybrid search.
|
|
797
829
|
* Generated from a structured summary of skills, experience, education, etc.
|
|
798
830
|
* Only generated for public profiles with sufficient completeness (≥60%).
|
|
799
831
|
*/
|
|
800
|
-
embedding:
|
|
832
|
+
embedding: object25({
|
|
801
833
|
vector: array10(number7().required()).optional().label("Embedding vector"),
|
|
802
|
-
model:
|
|
834
|
+
model: string23().optional().label("Embedding model")
|
|
803
835
|
}).nullable().optional().label("Embedding")
|
|
804
836
|
}).concat(UserGeneralDetailSchema).concat(UserJobPreferencesSchema).concat(UserRecruiterProfileSchema).concat(UserCoordinatorProfileSchema).noUnknown().strict().label("User Schema");
|
|
805
837
|
|
|
806
838
|
// src/user/user-completeness.schema.ts
|
|
807
|
-
import { object as
|
|
808
|
-
var UserCompletenessSchema =
|
|
839
|
+
import { object as object26 } from "yup";
|
|
840
|
+
var UserCompletenessSchema = object26({
|
|
809
841
|
additionalInfo: CompletenessScoreSchema(0).label("Additional Info"),
|
|
810
842
|
// Optional
|
|
811
843
|
certifications: CompletenessScoreSchema(0).label("Certifications"),
|
|
@@ -858,6 +890,9 @@ export {
|
|
|
858
890
|
ProficiencyLevel,
|
|
859
891
|
RecruiterPageLinkSchema,
|
|
860
892
|
ReferralSource,
|
|
893
|
+
ReportReason,
|
|
894
|
+
ReportSchema,
|
|
895
|
+
ResourceType,
|
|
861
896
|
SkillSchema,
|
|
862
897
|
SocialAccount,
|
|
863
898
|
SocialAccountSchema,
|
|
@@ -871,6 +906,8 @@ export {
|
|
|
871
906
|
SupportedPageTypes,
|
|
872
907
|
SupportedProficiencyLevels,
|
|
873
908
|
SupportedReferralSources,
|
|
909
|
+
SupportedReportReasons,
|
|
910
|
+
SupportedResourceTypes,
|
|
874
911
|
SupportedSalaryCurrencies,
|
|
875
912
|
SupportedSocialAccounts,
|
|
876
913
|
SupportedStudyTypes,
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ export class DateStringSchema<
|
|
|
10
10
|
// Report as the standard yup "mixed" type so tools that introspect the
|
|
11
11
|
// schema via `.describe()` (e.g. sveltekit-superforms' JSON-schema
|
|
12
12
|
// converter) recognize it. The class still inherits all MixedSchema
|
|
13
|
-
// behavior
|
|
13
|
+
// behavior - only the `type` label changes.
|
|
14
14
|
super({
|
|
15
15
|
type: "mixed",
|
|
16
16
|
check: (value): value is NonNullable<TType> =>
|
package/src/index.ts
CHANGED
|
@@ -37,6 +37,12 @@ export * from "./page/page.constant.js";
|
|
|
37
37
|
export * from "./pagination/pagination.schema.js";
|
|
38
38
|
export * from "./pagination/pagination.constant.js";
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Report schemas and constants.
|
|
42
|
+
*/
|
|
43
|
+
export * from "./report/report.schema.js";
|
|
44
|
+
export * from "./report/report.constant.js";
|
|
45
|
+
|
|
40
46
|
/**
|
|
41
47
|
* Skill schemas and constants.
|
|
42
48
|
*/
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export enum ResourceType {
|
|
2
|
+
Job = "job",
|
|
3
|
+
User = "user",
|
|
4
|
+
Resume = "resume",
|
|
5
|
+
Company = "company",
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const SupportedResourceTypes = Object.values(ResourceType);
|
|
9
|
+
|
|
10
|
+
export enum ReportReason {
|
|
11
|
+
OffensiveOrHarassing = "offensive_or_harassing",
|
|
12
|
+
JobExpired = "job_expired",
|
|
13
|
+
AskingMoney = "asking_money",
|
|
14
|
+
FakeJob = "fake_job",
|
|
15
|
+
IncorrectJobDetails = "incorrect_job_details",
|
|
16
|
+
SellingSomething = "selling_something",
|
|
17
|
+
Other = "other",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const SupportedReportReasons = Object.values(ReportReason);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { mixed, object, string } from "yup";
|
|
2
|
+
import {
|
|
3
|
+
ReportReason,
|
|
4
|
+
ResourceType,
|
|
5
|
+
SupportedReportReasons,
|
|
6
|
+
SupportedResourceTypes,
|
|
7
|
+
} from "./report.constant.js";
|
|
8
|
+
|
|
9
|
+
export const ReportSchema = object({
|
|
10
|
+
type: mixed<ResourceType>()
|
|
11
|
+
.oneOf(SupportedResourceTypes)
|
|
12
|
+
.required()
|
|
13
|
+
.label("Type"),
|
|
14
|
+
resourceId: string().required().label("Resource ID"),
|
|
15
|
+
reason: mixed<ReportReason>()
|
|
16
|
+
.oneOf(SupportedReportReasons)
|
|
17
|
+
.required("Please choose a reason")
|
|
18
|
+
.label("Reason"),
|
|
19
|
+
comment: string().max(1000).optional().label("Comment"),
|
|
20
|
+
}).label("Report Schema");
|
|
@@ -2,7 +2,7 @@ import { boolean, object, string } from "yup";
|
|
|
2
2
|
import { SupportedSocialAccounts } from "./social-account.constant.js";
|
|
3
3
|
export const SocialAccountSchema = object()
|
|
4
4
|
.shape({
|
|
5
|
-
// TODO: Remove isNew
|
|
5
|
+
// TODO: Remove isNew - it's unused. Backend (user-social-accounts.service.ts) just strips it before saving.
|
|
6
6
|
isNew: boolean().default(false).optional().label("Is New"),
|
|
7
7
|
type: string()
|
|
8
8
|
.oneOf(SupportedSocialAccounts)
|
|
@@ -26,7 +26,7 @@ export const CoordinatorPageLinkSchema = object({
|
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Coordinator-role-specific fields on UserSchema. All optional at the field
|
|
29
|
-
* level
|
|
29
|
+
* level - presence is gated by `UserRole.Coordinator` in the user's
|
|
30
30
|
* `roles`, not by schema branching, so the user shape stays flat.
|
|
31
31
|
*/
|
|
32
32
|
export const UserCoordinatorProfileSchema = object({
|