@thejob/schema 2.0.8 → 2.0.9
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.cjs +273 -169
- package/dist/index.d.cts +185 -1
- package/dist/index.d.ts +185 -1
- package/dist/index.js +267 -168
- package/package.json +1 -1
- package/src/index.ts +6 -0
- package/src/marketing/marketing.constant.ts +8 -0
- package/src/marketing/marketing.schema.ts +130 -0
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -50,6 +50,12 @@ export * from "./location/location.schema.js";
|
|
|
50
50
|
export * from "./page/page.schema.js";
|
|
51
51
|
export * from "./page/page.constant.js";
|
|
52
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Marketing schemas and constants (mailing lists, campaigns).
|
|
55
|
+
*/
|
|
56
|
+
export * from "./marketing/marketing.schema.js";
|
|
57
|
+
export * from "./marketing/marketing.constant.js";
|
|
58
|
+
|
|
53
59
|
/**
|
|
54
60
|
* Pagination schemas and constants.
|
|
55
61
|
*/
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { array, boolean, number, object, string } from "yup";
|
|
2
|
+
import {
|
|
3
|
+
SupportedExperienceLevels,
|
|
4
|
+
SupportedStudyTypes,
|
|
5
|
+
} from "../common/common.constant.js";
|
|
6
|
+
import { SupportedSocialAccounts } from "../social-account/social-account.constant.js";
|
|
7
|
+
import {
|
|
8
|
+
SupportedJobSearchUrgencies,
|
|
9
|
+
SupportedProficiencyLevels,
|
|
10
|
+
SupportedReferralSources,
|
|
11
|
+
SupportedSalaryCurrencies,
|
|
12
|
+
SupportedUserProfileVisibilities,
|
|
13
|
+
SupportedUserRoles,
|
|
14
|
+
SupportedUserStatuses,
|
|
15
|
+
} from "../user/user.constant.js";
|
|
16
|
+
|
|
17
|
+
// ─── Audience filter ─────────────────────────────────────────────────────────
|
|
18
|
+
// The saved query a mailing list resolves against the users collection. Every
|
|
19
|
+
// clause is optional and AND-ed; empty groups match everyone.
|
|
20
|
+
//
|
|
21
|
+
// Two kinds of clause:
|
|
22
|
+
// • Enum facets (`.oneOf(...)`) — closed vocabularies rendered as chip pickers.
|
|
23
|
+
// • Free-text token facets — open vocabularies (skills, companies, institutes,
|
|
24
|
+
// …) matched case-insensitively against a nested array/field. Any token in
|
|
25
|
+
// the list matches (OR within a facet), facets AND together.
|
|
26
|
+
|
|
27
|
+
const tokens = (label: string) =>
|
|
28
|
+
array().of(string().trim().required()).optional().default([]).label(label);
|
|
29
|
+
|
|
30
|
+
const enumFacet = (values: readonly string[], label: string) =>
|
|
31
|
+
array()
|
|
32
|
+
.of(string().oneOf(values).required())
|
|
33
|
+
.optional()
|
|
34
|
+
.default([])
|
|
35
|
+
.label(label);
|
|
36
|
+
|
|
37
|
+
export const ListFilterSchema = object({
|
|
38
|
+
// ── Enum facets (closed vocabularies, chip pickers) ─────────────────────────
|
|
39
|
+
countries: array().of(string().required()).optional().default([]).label("Countries"),
|
|
40
|
+
roles: enumFacet(SupportedUserRoles, "Roles"),
|
|
41
|
+
// The user's own current seniority (UserSchema.experienceLevel).
|
|
42
|
+
experienceLevels: enumFacet(SupportedExperienceLevels, "Experience Levels"),
|
|
43
|
+
// Levels the user is *targeting* (distinct from their current experienceLevel).
|
|
44
|
+
targetExperienceLevels: enumFacet(
|
|
45
|
+
SupportedExperienceLevels,
|
|
46
|
+
"Target Experience Levels",
|
|
47
|
+
),
|
|
48
|
+
jobSearchUrgencies: enumFacet(SupportedJobSearchUrgencies, "Job Search Urgency"),
|
|
49
|
+
referralSources: enumFacet(SupportedReferralSources, "Referral Source"),
|
|
50
|
+
statuses: enumFacet(SupportedUserStatuses, "Account Status"),
|
|
51
|
+
profileVisibilities: enumFacet(
|
|
52
|
+
SupportedUserProfileVisibilities,
|
|
53
|
+
"Profile Visibility",
|
|
54
|
+
),
|
|
55
|
+
// Proficiency held on any skill entry (skills[].proficiencyLevel).
|
|
56
|
+
skillProficiencyLevels: enumFacet(
|
|
57
|
+
SupportedProficiencyLevels,
|
|
58
|
+
"Skill Proficiency",
|
|
59
|
+
),
|
|
60
|
+
// Proficiency held on any language entry (languages[].proficiencyLevel).
|
|
61
|
+
languageProficiencyLevels: enumFacet(
|
|
62
|
+
SupportedProficiencyLevels,
|
|
63
|
+
"Language Proficiency",
|
|
64
|
+
),
|
|
65
|
+
// Mode of any education entry (educations[].studyType).
|
|
66
|
+
studyTypes: enumFacet(SupportedStudyTypes, "Study Type"),
|
|
67
|
+
// Platforms the user linked a social account for (socialAccounts[].type).
|
|
68
|
+
socialAccountTypes: enumFacet(SupportedSocialAccounts, "Social Accounts"),
|
|
69
|
+
// Currency of the user's salary floor (minSalaryCurrency).
|
|
70
|
+
salaryCurrencies: enumFacet(SupportedSalaryCurrencies, "Salary Currency"),
|
|
71
|
+
|
|
72
|
+
// ── Free-text token facets (nested profile arrays) ──────────────────────────
|
|
73
|
+
skills: tokens("Skills"),
|
|
74
|
+
languages: tokens("Languages"),
|
|
75
|
+
interests: tokens("Interests"),
|
|
76
|
+
companies: tokens("Companies"),
|
|
77
|
+
designations: tokens("Job Titles / Designations"),
|
|
78
|
+
institutes: tokens("Institutes"),
|
|
79
|
+
courses: tokens("Courses"),
|
|
80
|
+
fieldsOfStudy: tokens("Fields of Study"),
|
|
81
|
+
certifications: tokens("Certifications"),
|
|
82
|
+
certificationAuthorities: tokens("Certification Authorities"),
|
|
83
|
+
projects: tokens("Projects"),
|
|
84
|
+
jobRoles: tokens("Target Roles"),
|
|
85
|
+
jobLocations: tokens("Preferred Job Locations"),
|
|
86
|
+
// Companies a recruiter is hiring for (recruiterProfile.hiringFor[].page.name).
|
|
87
|
+
hiringForCompanies: tokens("Hiring For (Companies)"),
|
|
88
|
+
// Institutes a coordinator works at (coordinatorProfile.coordinatesAt[].page.name).
|
|
89
|
+
coordinatesAtInstitutes: tokens("Coordinates At (Institutes)"),
|
|
90
|
+
// Case-insensitive keyword match against headline + aboutMe.
|
|
91
|
+
keywords: tokens("Profile Keywords"),
|
|
92
|
+
|
|
93
|
+
// ── Range / boolean facets ──────────────────────────────────────────────────
|
|
94
|
+
minSalaryFloor: number().integer().min(0).optional().label("Min Salary ≥"),
|
|
95
|
+
minSalaryCeil: number().integer().min(0).optional().label("Min Salary ≤"),
|
|
96
|
+
openToWorkOnly: boolean().optional().default(false).label("Open to Work Only"),
|
|
97
|
+
remoteExperienceOnly: boolean()
|
|
98
|
+
.optional()
|
|
99
|
+
.default(false)
|
|
100
|
+
.label("Has Remote Experience"),
|
|
101
|
+
hasResumeOnly: boolean().optional().default(false).label("Has Resume"),
|
|
102
|
+
onboardingCompletedOnly: boolean()
|
|
103
|
+
.optional()
|
|
104
|
+
.default(false)
|
|
105
|
+
.label("Onboarding Completed"),
|
|
106
|
+
emailVerifiedOnly: boolean().optional().default(false).label("Email Verified Only"),
|
|
107
|
+
mobileVerifiedOnly: boolean()
|
|
108
|
+
.optional()
|
|
109
|
+
.default(false)
|
|
110
|
+
.label("Mobile Verified Only"),
|
|
111
|
+
}).label("Audience Filter");
|
|
112
|
+
|
|
113
|
+
// ─── Mailing list ────────────────────────────────────────────────────────────
|
|
114
|
+
|
|
115
|
+
export const MailingListSchema = object({
|
|
116
|
+
name: string().required().min(1).max(120).label("Name"),
|
|
117
|
+
description: string().optional().max(500).label("Description"),
|
|
118
|
+
filter: ListFilterSchema.default(() => ListFilterSchema.getDefault()),
|
|
119
|
+
}).label("Mailing List");
|
|
120
|
+
|
|
121
|
+
// ─── Campaign ────────────────────────────────────────────────────────────────
|
|
122
|
+
|
|
123
|
+
export const CampaignSchema = object({
|
|
124
|
+
name: string().required().min(1).max(200).label("Campaign Name"),
|
|
125
|
+
subject: string().required().min(1).max(255).label("Subject"),
|
|
126
|
+
// HTML body; may contain a {{unsubscribe_url}} placeholder.
|
|
127
|
+
html: string().required().min(1).label("HTML Body"),
|
|
128
|
+
text: string().optional().label("Plain-text Body"),
|
|
129
|
+
listId: string().required().label("Mailing List"),
|
|
130
|
+
}).label("Campaign");
|