@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/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 captured at the end of onboarding
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 presence is gated by `UserRole.Recruiter` in the user's `roles`,
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 presence is gated by `UserRole.Coordinator` in the user's
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 it's unused. Backend (user-social-accounts.service.ts) just strips it before saving.
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 object12, string as string9 } from "yup";
404
- var SkillSchema = object12({
405
- name: string9().trim().required().label("Skill Name"),
406
- logo: object12({
407
- light: string9().required().label("Light Logo"),
408
- dark: string9().optional().nullable().label("Dark Logo")
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(string9().max(50)).max(20).optional().label("Tags")
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 object24, string as string22 } from "yup";
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 object13, string as string10 } from "yup";
497
- var WorkExperienceSchema = object13().shape({
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: string10().trim().required().label("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: string10().trim().max(3e3).optional().label("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 object14, string as string11 } from "yup";
512
- var EducationSchema = object14({
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: string11().trim().required().label("Course"),
515
- fieldOfStudy: string11().trim().required().label("Field of Study"),
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: string11().trim().max(3e3).optional().label("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: string11().oneOf(SupportedStudyTypes).trim().max(50).required().label("Study Type")
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 object15, string as string12 } from "yup";
529
- var UserSkillSchema = object15({
530
- name: string12().required().label("Name"),
531
- proficiencyLevel: string12().oneOf(SupportedProficiencyLevels).required().label("Proficiency Level"),
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 object16, string as string13 } from "yup";
537
- var UserProjectSchema = object16({
538
- name: string13().trim().max(50).required().label("Name"),
539
- url: string13().optional().label("URL"),
540
- description: string13().trim().min(100).max(3e3).required().label("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 object17, string as string14 } from "yup";
550
- var UserCertificationSchema = object17({
551
- name: string14().trim().max(100).required().label("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: string14().trim().max(100).required().label("Authority"),
554
- licenseNumber: string14().trim().max(50).optional().label("License Number"),
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: string14().optional().label("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 string15 } from "yup";
565
- var UserInterestSchema = string15().trim().required().label("Interest");
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 object18, string as string16 } from "yup";
569
- var UserLanguageSchema = object18({
570
- name: string16().trim().required().label("Name"),
571
- proficiencyLevel: string16().oneOf(SupportedProficiencyLevels).trim().max(50).required().label("Proficiency Level")
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 object19, string as string17 } from "yup";
576
- var UserAdditionalInfoSchema = object19({
577
- title: string17().trim().max(60).required().label("Title"),
578
- description: string17().trim().max(1e3).required().label("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 object20, string as string18 } from "yup";
583
- var UserGeneralDetailSchema = object20({
584
- id: string18().optional().label("ID"),
585
- name: object20().shape({
586
- first: string18().trim().max(50).required().label("First Name"),
587
- last: string18().trim().max(50).optional().label("Last Name")
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: string18().trim().max(200).optional().label("Headline"),
590
- image: string18().optional().label("Image"),
591
- aboutMe: string18().trim().max(3e3).optional().label("About Me"),
592
- email: string18().required().label("Email"),
593
- mobile: string18().nullable().optional().label("Mobile"),
594
- emailVerified: string18().nullable().optional().label("Email Verified"),
595
- mobileVerified: string18().nullable().optional().label("Mobile Verified"),
596
- experienceLevel: string18().oneOf(SupportedExperienceLevels).required().label("Experience level"),
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: object20().shape({
599
- country: string18().trim().required().label("Region Country"),
600
- lang: string18().trim().required().label("Region Language")
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: string18().oneOf(SupportedUserProfileVisibilities).default("public" /* Public */).label("Profile Visibility")
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 object21, string as string19 } from "yup";
607
- var UserJobPreferencesSchema = object21({
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` users must opt in.
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: string19().oneOf(SupportedJobSearchUrgencies).required().label("Job Search Urgency"),
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`) that field captures the user's
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(string19().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"),
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 free-form titles.
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(string19().trim().max(120).required()).min(1, "Pick at least one role.").required().label("Job Roles"),
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 every job-seeker
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: string19().oneOf(SupportedSalaryCurrencies).default("USD").required().label("Minimum Salary Currency"),
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: string19().oneOf(SupportedReferralSources).required().label("Referral Source"),
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) they're cheap to denormalize, every wizard step that
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 onboarding uploads land here, AI-built resumes
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
- object21({
673
- // Stable id assigned on upload used to address a specific entry
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: string19().required().label("ID"),
677
- url: string19().required().label("Resume URL"),
678
- filename: string19().trim().max(255).optional().label("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: string19().trim().max(120).optional().label("MIME Type"),
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 including profile-shaped
724
+ * flow. Every parser-derived field lands here - including profile-shaped
693
725
  * fields (headline, aboutMe, mobile, location, experienceLevel,
694
- * socialAccounts, workExperiences, educations) so nothing reaches the
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 strict:
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 it's an
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: object21({
710
- headline: string19().trim().optional().label("Pending Headline"),
711
- aboutMe: string19().trim().optional().label("Pending About Me"),
712
- mobile: string19().trim().optional().label("Pending 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: string19().oneOf(SupportedExperienceLevels).optional().label("Pending Experience Level"),
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 object22, string as string20 } from "yup";
723
- var RecruiterPageLinkSchema = object22({
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: string20().trim().max(100).optional().label("Job Title")
757
+ jobTitle: string21().trim().max(100).optional().label("Job Title")
726
758
  }).noUnknown().strict().label("Recruiter Page Link");
727
- var UserRecruiterProfileSchema = object22({
728
- recruiterProfile: object22({
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 object23, string as string21 } from "yup";
735
- var CoordinatorPageLinkSchema = object23({
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: string21().trim().max(100).optional().label("Job Title")
769
+ jobTitle: string22().trim().max(100).optional().label("Job Title")
738
770
  }).noUnknown().strict().label("Coordinator Page Link");
739
- var UserCoordinatorProfileSchema = object23({
740
- coordinatorProfile: object23({
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 = object24({
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: string22().required().label("Auth Account ID"),
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: string22().oneOf(SupportedUserStatuses).required().label("Status"),
822
+ status: string23().oneOf(SupportedUserStatuses).required().label("Status"),
791
823
  /**
792
824
  * Roles assigned to the user
793
825
  */
794
- roles: array10().of(string22().oneOf(SupportedUserRoles)).required().default(DefaultUserRoles).label("Roles"),
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: object24({
832
+ embedding: object25({
801
833
  vector: array10(number7().required()).optional().label("Embedding vector"),
802
- model: string22().optional().label("Embedding 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 object25 } from "yup";
808
- var UserCompletenessSchema = object25({
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thejob/schema",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -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 only the `type` label changes.
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 it's unused. Backend (user-social-accounts.service.ts) just strips it before saving.
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 presence is gated by `UserRole.Coordinator` in the user's
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({