@thejob/schema 2.5.0 → 2.7.0
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.md +6 -0
- package/dist/index.cjs +1063 -568
- package/dist/index.d.cts +602 -7
- package/dist/index.d.ts +602 -7
- package/dist/index.js +1002 -552
- package/package.json +1 -1
- package/src/index.ts +11 -0
- package/src/job/job.schema.ts +28 -5
- package/src/taxonomy/taxonomy-filter.schema.ts +84 -0
- package/src/taxonomy/taxonomy.constant.ts +127 -0
- package/src/taxonomy/taxonomy.schema.ts +404 -0
package/dist/index.cjs
CHANGED
|
@@ -32,10 +32,14 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AnswerChoiceType: () => AnswerChoiceType,
|
|
34
34
|
ApplicationReceivePreference: () => ApplicationReceivePreference,
|
|
35
|
+
AuditFilterSchema: () => AuditFilterSchema,
|
|
36
|
+
AuditSchema: () => AuditSchema,
|
|
35
37
|
BillingPeriod: () => BillingPeriod,
|
|
36
38
|
BillingSubscriptionSchema: () => BillingSubscriptionSchema,
|
|
37
39
|
BillingTransactionSchema: () => BillingTransactionSchema,
|
|
38
40
|
CAMPAIGN_MAX_RECIPIENTS_CEILING: () => CAMPAIGN_MAX_RECIPIENTS_CEILING,
|
|
41
|
+
CONCEPT_ID_PATTERN: () => CONCEPT_ID_PATTERN,
|
|
42
|
+
CONCEPT_TYPE_PATTERN: () => CONCEPT_TYPE_PATTERN,
|
|
39
43
|
CONSUME_MAX_UNITS: () => CONSUME_MAX_UNITS,
|
|
40
44
|
CampaignDataSourceSchema: () => CampaignDataSourceSchema,
|
|
41
45
|
CampaignEndKind: () => CampaignEndKind,
|
|
@@ -51,6 +55,11 @@ __export(index_exports, {
|
|
|
51
55
|
Common: () => Common,
|
|
52
56
|
CompensationType: () => CompensationType,
|
|
53
57
|
CompletenessScoreSchema: () => CompletenessScoreSchema,
|
|
58
|
+
ConceptFilterSchema: () => ConceptFilterSchema,
|
|
59
|
+
ConceptMembershipSchema: () => ConceptMembershipSchema,
|
|
60
|
+
ConceptProposalFilterSchema: () => ConceptProposalFilterSchema,
|
|
61
|
+
ConceptProposalSchema: () => ConceptProposalSchema,
|
|
62
|
+
ConceptSchema: () => ConceptSchema,
|
|
54
63
|
ContactTypes: () => ContactTypes,
|
|
55
64
|
CoordinatorPageLinkSchema: () => CoordinatorPageLinkSchema,
|
|
56
65
|
CountryFilterSchema: () => CountryFilterSchema,
|
|
@@ -116,6 +125,7 @@ __export(index_exports, {
|
|
|
116
125
|
MailingListFilterSchema: () => MailingListFilterSchema,
|
|
117
126
|
MailingListSchema: () => MailingListSchema,
|
|
118
127
|
MoneySchema: () => MoneySchema,
|
|
128
|
+
NormalizeContextSchema: () => NormalizeContextSchema,
|
|
119
129
|
NotificationType: () => NotificationType,
|
|
120
130
|
OccurrenceStatus: () => OccurrenceStatus,
|
|
121
131
|
PREFILL_MIRRORED_KEYS: () => PREFILL_MIRRORED_KEYS,
|
|
@@ -135,6 +145,8 @@ __export(index_exports, {
|
|
|
135
145
|
PostSchema: () => PostSchema,
|
|
136
146
|
PostStatus: () => PostStatus,
|
|
137
147
|
ProficiencyLevel: () => ProficiencyLevel,
|
|
148
|
+
ProposalCandidateSchema: () => ProposalCandidateSchema,
|
|
149
|
+
ProposalMessageSchema: () => ProposalMessageSchema,
|
|
138
150
|
PushSubscriptionSchema: () => PushSubscriptionSchema,
|
|
139
151
|
QuestionSchema: () => QuestionSchema,
|
|
140
152
|
QuestionType: () => QuestionType,
|
|
@@ -142,9 +154,15 @@ __export(index_exports, {
|
|
|
142
154
|
ReadAndAcknowledgeQuestionSchema: () => ReadAndAcknowledgeQuestionSchema,
|
|
143
155
|
RecruiterPageLinkSchema: () => RecruiterPageLinkSchema,
|
|
144
156
|
ReferralSource: () => ReferralSource,
|
|
157
|
+
ReleaseFilterSchema: () => ReleaseFilterSchema,
|
|
158
|
+
ReleaseSchema: () => ReleaseSchema,
|
|
145
159
|
ReportReason: () => ReportReason,
|
|
146
160
|
ReportSchema: () => ReportSchema,
|
|
161
|
+
ResolverSettingsSchema: () => ResolverSettingsSchema,
|
|
162
|
+
ResolverVerificationSchema: () => ResolverVerificationSchema,
|
|
147
163
|
ResourceType: () => ResourceType,
|
|
164
|
+
SCHEDULE_MAX_HOURS: () => SCHEDULE_MAX_HOURS,
|
|
165
|
+
SCHEDULE_MIN_HOURS: () => SCHEDULE_MIN_HOURS,
|
|
148
166
|
SITEMAP_FORMAT: () => SITEMAP_FORMAT,
|
|
149
167
|
SYSTEM_DATE_FORMAT: () => SYSTEM_DATE_FORMAT,
|
|
150
168
|
SavedSearchSchema: () => SavedSearchSchema,
|
|
@@ -159,14 +177,17 @@ __export(index_exports, {
|
|
|
159
177
|
StudentCompletenessSchema: () => StudentCompletenessSchema,
|
|
160
178
|
StudyType: () => StudyType,
|
|
161
179
|
SubscriptionStatus: () => SubscriptionStatus,
|
|
180
|
+
SuggestedHomeSchema: () => SuggestedHomeSchema,
|
|
162
181
|
SupportedAnswerChoiceTypes: () => SupportedAnswerChoiceTypes,
|
|
163
182
|
SupportedApplicationReceivePreferences: () => SupportedApplicationReceivePreferences,
|
|
183
|
+
SupportedAuditStatuses: () => SupportedAuditStatuses,
|
|
164
184
|
SupportedBillingPeriods: () => SupportedBillingPeriods,
|
|
165
185
|
SupportedCampaignEndKinds: () => SupportedCampaignEndKinds,
|
|
166
186
|
SupportedCampaignIntervalUnits: () => SupportedCampaignIntervalUnits,
|
|
167
187
|
SupportedCampaignStatuses: () => SupportedCampaignStatuses,
|
|
168
188
|
SupportedCampaignTriggerKinds: () => SupportedCampaignTriggerKinds,
|
|
169
189
|
SupportedCompensationTypes: () => SupportedCompensationTypes,
|
|
190
|
+
SupportedConceptSources: () => SupportedConceptSources,
|
|
170
191
|
SupportedContactTypes: () => SupportedContactTypes,
|
|
171
192
|
SupportedEducationLevels: () => SupportedEducationLevels,
|
|
172
193
|
SupportedEmployeeCounts: () => SupportedEmployeeCounts,
|
|
@@ -191,6 +212,7 @@ __export(index_exports, {
|
|
|
191
212
|
SupportedJobSearchUrgencies: () => SupportedJobSearchUrgencies,
|
|
192
213
|
SupportedJobStatuses: () => SupportedJobStatuses,
|
|
193
214
|
SupportedJobSubCategories: () => SupportedJobSubCategories,
|
|
215
|
+
SupportedMatchTypes: () => SupportedMatchTypes,
|
|
194
216
|
SupportedNotificationTypes: () => SupportedNotificationTypes,
|
|
195
217
|
SupportedOccurrenceStatuses: () => SupportedOccurrenceStatuses,
|
|
196
218
|
SupportedPaddleEnvironments: () => SupportedPaddleEnvironments,
|
|
@@ -200,11 +222,19 @@ __export(index_exports, {
|
|
|
200
222
|
SupportedPlanKinds: () => SupportedPlanKinds,
|
|
201
223
|
SupportedPlanStatuses: () => SupportedPlanStatuses,
|
|
202
224
|
SupportedPostStatuses: () => SupportedPostStatuses,
|
|
225
|
+
SupportedPrefilterRules: () => SupportedPrefilterRules,
|
|
203
226
|
SupportedProficiencyLevels: () => SupportedProficiencyLevels,
|
|
227
|
+
SupportedProposalFilters: () => SupportedProposalFilters,
|
|
228
|
+
SupportedProposalKinds: () => SupportedProposalKinds,
|
|
229
|
+
SupportedProposalMessageRoles: () => SupportedProposalMessageRoles,
|
|
230
|
+
SupportedProposalStatuses: () => SupportedProposalStatuses,
|
|
204
231
|
SupportedQuestionTypes: () => SupportedQuestionTypes,
|
|
205
232
|
SupportedQuotaPeriods: () => SupportedQuotaPeriods,
|
|
206
233
|
SupportedReferralSources: () => SupportedReferralSources,
|
|
234
|
+
SupportedReleaseKinds: () => SupportedReleaseKinds,
|
|
235
|
+
SupportedReleaseStatuses: () => SupportedReleaseStatuses,
|
|
207
236
|
SupportedReportReasons: () => SupportedReportReasons,
|
|
237
|
+
SupportedResolverVerdicts: () => SupportedResolverVerdicts,
|
|
208
238
|
SupportedResourceTypes: () => SupportedResourceTypes,
|
|
209
239
|
SupportedSalaryCurrencies: () => SupportedSalaryCurrencies,
|
|
210
240
|
SupportedSavedSearchStatuses: () => SupportedSavedSearchStatuses,
|
|
@@ -212,19 +242,31 @@ __export(index_exports, {
|
|
|
212
242
|
SupportedSocialAccounts: () => SupportedSocialAccounts,
|
|
213
243
|
SupportedStudyTypes: () => SupportedStudyTypes,
|
|
214
244
|
SupportedSubscriptionStatuses: () => SupportedSubscriptionStatuses,
|
|
245
|
+
SupportedTaxonomyJobKinds: () => SupportedTaxonomyJobKinds,
|
|
246
|
+
SupportedTaxonomyJobStates: () => SupportedTaxonomyJobStates,
|
|
247
|
+
SupportedTaxonomyNodeKinds: () => SupportedTaxonomyNodeKinds,
|
|
248
|
+
SupportedTaxonomySources: () => SupportedTaxonomySources,
|
|
215
249
|
SupportedTemplateVariableBindingKinds: () => SupportedTemplateVariableBindingKinds,
|
|
216
250
|
SupportedTransactionStatuses: () => SupportedTransactionStatuses,
|
|
251
|
+
SupportedUnmatchedReasons: () => SupportedUnmatchedReasons,
|
|
252
|
+
SupportedUnmatchedResolutions: () => SupportedUnmatchedResolutions,
|
|
217
253
|
SupportedUserProfileVisibilities: () => SupportedUserProfileVisibilities,
|
|
218
254
|
SupportedUserRoles: () => SupportedUserRoles,
|
|
219
255
|
SupportedUserStatuses: () => SupportedUserStatuses,
|
|
220
256
|
SupportedWorkModes: () => SupportedWorkModes,
|
|
221
257
|
TAXONOMY_LABELS: () => TAXONOMY_LABELS,
|
|
258
|
+
TAXONOMY_NODE_ID_PATTERN: () => TAXONOMY_NODE_ID_PATTERN,
|
|
259
|
+
TaxonomyNodeFilterSchema: () => TaxonomyNodeFilterSchema,
|
|
260
|
+
TaxonomyNodeSchema: () => TaxonomyNodeSchema,
|
|
261
|
+
TaxonomyScheduleSchema: () => TaxonomyScheduleSchema,
|
|
222
262
|
TemplateVariableBindingKind: () => TemplateVariableBindingKind,
|
|
223
263
|
TemplateVariableBindingSchema: () => TemplateVariableBindingSchema,
|
|
224
264
|
TerminalCampaignStatuses: () => TerminalCampaignStatuses,
|
|
225
265
|
TerminalGeoSyncStatuses: () => TerminalGeoSyncStatuses,
|
|
226
266
|
TermsAcceptedSchema: () => TermsAcceptedSchema,
|
|
227
267
|
TransactionStatus: () => TransactionStatus,
|
|
268
|
+
UnmatchedFilterSchema: () => UnmatchedFilterSchema,
|
|
269
|
+
UnmatchedTermSchema: () => UnmatchedTermSchema,
|
|
228
270
|
UserAdditionalInfoSchema: () => UserAdditionalInfoSchema,
|
|
229
271
|
UserCertificationSchema: () => UserCertificationSchema,
|
|
230
272
|
UserCompletenessSchema: () => UserCompletenessSchema,
|
|
@@ -243,6 +285,9 @@ __export(index_exports, {
|
|
|
243
285
|
UserSchema: () => UserSchema,
|
|
244
286
|
UserSkillSchema: () => UserSkillSchema,
|
|
245
287
|
UserStatus: () => UserStatus,
|
|
288
|
+
VOCABULARY_ID_PATTERN: () => VOCABULARY_ID_PATTERN,
|
|
289
|
+
VocabularySchema: () => VocabularySchema,
|
|
290
|
+
VocabularyTypeSchema: () => VocabularyTypeSchema,
|
|
246
291
|
WorkExperienceSchema: () => WorkExperienceSchema,
|
|
247
292
|
WorkMode: () => WorkMode,
|
|
248
293
|
canTransitionCampaign: () => canTransitionCampaign,
|
|
@@ -640,7 +685,7 @@ var GroupFilterSchema = rejectUnknownKeys(
|
|
|
640
685
|
);
|
|
641
686
|
|
|
642
687
|
// src/job/job.schema.ts
|
|
643
|
-
var
|
|
688
|
+
var import_yup21 = require("yup");
|
|
644
689
|
|
|
645
690
|
// src/location/location.schema.ts
|
|
646
691
|
var import_yup7 = require("yup");
|
|
@@ -859,6 +904,338 @@ var SkillSchema = (0, import_yup15.object)({
|
|
|
859
904
|
tags: (0, import_yup15.array)().of((0, import_yup15.string)().max(50)).max(20).optional().label("Tags")
|
|
860
905
|
}).concat(DbDefaultSchema).noUnknown().strict().label("Skill");
|
|
861
906
|
|
|
907
|
+
// src/taxonomy/taxonomy.schema.ts
|
|
908
|
+
var import_yup16 = require("yup");
|
|
909
|
+
|
|
910
|
+
// src/taxonomy/taxonomy.constant.ts
|
|
911
|
+
var SupportedConceptSources = ["seed", "manual", "import"];
|
|
912
|
+
var SupportedTaxonomySources = ["seed", "manual"];
|
|
913
|
+
var SupportedTaxonomyNodeKinds = ["category", "subcategory", "group"];
|
|
914
|
+
var SupportedPrefilterRules = [
|
|
915
|
+
"spoken_language",
|
|
916
|
+
"no_letters",
|
|
917
|
+
"url_or_email",
|
|
918
|
+
"fragment"
|
|
919
|
+
];
|
|
920
|
+
var SupportedUnmatchedResolutions = ["pending", "added", "rejected"];
|
|
921
|
+
var SupportedUnmatchedReasons = ["ambiguous"];
|
|
922
|
+
var SupportedProposalKinds = ["concept", "alias", "placement"];
|
|
923
|
+
var SupportedProposalFilters = [...SupportedProposalKinds, "uncategorized"];
|
|
924
|
+
var SupportedProposalStatuses = ["draft", "approved", "discarded"];
|
|
925
|
+
var SupportedProposalMessageRoles = ["operator", "model"];
|
|
926
|
+
var SupportedResolverVerdicts = [
|
|
927
|
+
"same",
|
|
928
|
+
"narrower",
|
|
929
|
+
"broader",
|
|
930
|
+
"related",
|
|
931
|
+
"new_concept",
|
|
932
|
+
"out_of_scope"
|
|
933
|
+
];
|
|
934
|
+
var SupportedAuditStatuses = ["pending", "correct", "wrong"];
|
|
935
|
+
var SupportedReleaseKinds = ["seed", "manual", "review", "auto"];
|
|
936
|
+
var SupportedReleaseStatuses = ["open", "rolled_back"];
|
|
937
|
+
var SupportedMatchTypes = ["exact", "canonical", "fuzzy", "none"];
|
|
938
|
+
var SupportedTaxonomyJobKinds = [
|
|
939
|
+
"describe-concepts",
|
|
940
|
+
"retype-concepts",
|
|
941
|
+
"generate-aliases",
|
|
942
|
+
"alias-backfill",
|
|
943
|
+
"close-gaps",
|
|
944
|
+
"propose-placements",
|
|
945
|
+
"place-unplaced",
|
|
946
|
+
"calibrate-placement",
|
|
947
|
+
"reseed",
|
|
948
|
+
"reindex",
|
|
949
|
+
"calibrate-resolver",
|
|
950
|
+
"golden",
|
|
951
|
+
"resolve-backlog"
|
|
952
|
+
];
|
|
953
|
+
var SupportedTaxonomyJobStates = ["running", "succeeded", "failed", "cancelled"];
|
|
954
|
+
var CONCEPT_ID_PATTERN = /^[a-z][a-z0-9-]*_[a-z0-9-]+$/;
|
|
955
|
+
var VOCABULARY_ID_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
|
|
956
|
+
var TAXONOMY_NODE_ID_PATTERN = /^[A-Za-z0-9_]{1,64}$/;
|
|
957
|
+
var CONCEPT_TYPE_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;
|
|
958
|
+
var SCHEDULE_MIN_HOURS = 1;
|
|
959
|
+
var SCHEDULE_MAX_HOURS = 24 * 30;
|
|
960
|
+
|
|
961
|
+
// src/taxonomy/taxonomy.schema.ts
|
|
962
|
+
var conceptId = () => (0, import_yup16.string)().matches(CONCEPT_ID_PATTERN, "conceptId must look like <vocabulary>_<slug>");
|
|
963
|
+
var vocabularyId = () => (0, import_yup16.string)().matches(VOCABULARY_ID_PATTERN, "vocabulary must match [a-z][a-z0-9-]{0,31}");
|
|
964
|
+
var nodeId = () => (0, import_yup16.string)().matches(TAXONOMY_NODE_ID_PATTERN, "node ids look like CAT_01_TECH");
|
|
965
|
+
var strings = () => (0, import_yup16.array)((0, import_yup16.string)().trim().min(1).required());
|
|
966
|
+
var VocabularyTypeSchema = (0, import_yup16.object)({
|
|
967
|
+
id: (0, import_yup16.string)().matches(CONCEPT_TYPE_PATTERN, "type ids match [a-z][a-z0-9_]*").required().label("Type ID"),
|
|
968
|
+
/** Shown to the model when it classifies a concept; include examples. */
|
|
969
|
+
description: (0, import_yup16.string)().defined().label("Description")
|
|
970
|
+
}).label("Vocabulary Type");
|
|
971
|
+
var VocabularySchema = (0, import_yup16.object)({
|
|
972
|
+
vocabularyId: vocabularyId().required().label("Vocabulary ID"),
|
|
973
|
+
name: (0, import_yup16.string)().trim().min(1).required().label("Name"),
|
|
974
|
+
/** What one concept is called in prompts and messages: "skill", "role". */
|
|
975
|
+
noun: (0, import_yup16.string)().trim().min(1).required().label("Noun"),
|
|
976
|
+
nounPlural: (0, import_yup16.string)().trim().min(1).required().label("Noun (plural)"),
|
|
977
|
+
/** What belongs in this vocabulary, for prompts. */
|
|
978
|
+
description: (0, import_yup16.string)().trim().min(1).required().label("Description"),
|
|
979
|
+
/** Where its terms are written, for the "swap it in" test: "a job posting". */
|
|
980
|
+
appearsIn: (0, import_yup16.string)().trim().min(1).required().label("Appears In"),
|
|
981
|
+
/** Things that are NOT concepts of this vocabulary, for prompts. */
|
|
982
|
+
outOfScope: (0, import_yup16.string)().trim().min(1).required().label("Out of Scope"),
|
|
983
|
+
types: (0, import_yup16.array)(VocabularyTypeSchema.required()).min(1).required().test(
|
|
984
|
+
"unique-type-ids",
|
|
985
|
+
"type ids must be unique",
|
|
986
|
+
(types) => !types || new Set(types.map((t) => t.id)).size === types.length
|
|
987
|
+
).label("Types"),
|
|
988
|
+
/** The type a concept gets when nothing more specific is known. One of `types`. */
|
|
989
|
+
defaultType: (0, import_yup16.string)().required().test("default-type-listed", "defaultType must be one of the type ids", function(value) {
|
|
990
|
+
const types = this.parent.types ?? [];
|
|
991
|
+
return types.some((t) => t.id === value);
|
|
992
|
+
}).label("Default Type"),
|
|
993
|
+
prefilter: (0, import_yup16.array)((0, import_yup16.string)().oneOf(SupportedPrefilterRules).required()).default([]).label("Prefilter"),
|
|
994
|
+
/**
|
|
995
|
+
* Words that qualify a term without changing what it names ("fluent",
|
|
996
|
+
* "native"), dropped from its canonical lookup form in THIS vocabulary only.
|
|
997
|
+
*/
|
|
998
|
+
qualifiers: strings().optional().label("Qualifiers"),
|
|
999
|
+
/** Extra instructions per model task; each is optional. */
|
|
1000
|
+
guidance: (0, import_yup16.object)({
|
|
1001
|
+
describe: (0, import_yup16.string)().optional(),
|
|
1002
|
+
classify: (0, import_yup16.string)().optional(),
|
|
1003
|
+
aliases: (0, import_yup16.string)().optional(),
|
|
1004
|
+
verify: (0, import_yup16.string)().optional(),
|
|
1005
|
+
place: (0, import_yup16.string)().optional()
|
|
1006
|
+
}).label("Guidance"),
|
|
1007
|
+
source: (0, import_yup16.string)().oneOf(SupportedTaxonomySources).required().label("Source"),
|
|
1008
|
+
createdAt: (0, import_yup16.number)().required().label("Created At"),
|
|
1009
|
+
updatedAt: (0, import_yup16.number)().required().label("Updated At")
|
|
1010
|
+
}).label("Vocabulary");
|
|
1011
|
+
var TaxonomyNodeSchema = (0, import_yup16.object)({
|
|
1012
|
+
nodeId: nodeId().required().label("Node ID"),
|
|
1013
|
+
vocabulary: vocabularyId().required().label("Vocabulary"),
|
|
1014
|
+
kind: (0, import_yup16.string)().oneOf(SupportedTaxonomyNodeKinds).required().label("Kind"),
|
|
1015
|
+
name: (0, import_yup16.string)().trim().min(1).required().label("Name"),
|
|
1016
|
+
/** Groups carry a description; categories and subcategories usually do not. */
|
|
1017
|
+
description: (0, import_yup16.string)().optional().label("Description"),
|
|
1018
|
+
aliases: strings().default([]).label("Aliases"),
|
|
1019
|
+
/** null for categories (the roots). */
|
|
1020
|
+
parentId: (0, import_yup16.string)().nullable().defined().label("Parent ID"),
|
|
1021
|
+
/** Ancestor ids from the root down to and including this node. */
|
|
1022
|
+
path: (0, import_yup16.array)((0, import_yup16.string)().required()).default([]).label("Path"),
|
|
1023
|
+
source: (0, import_yup16.string)().oneOf(SupportedTaxonomySources).optional().label("Source"),
|
|
1024
|
+
createdAt: (0, import_yup16.number)().required().label("Created At"),
|
|
1025
|
+
updatedAt: (0, import_yup16.number)().required().label("Updated At")
|
|
1026
|
+
}).label("Taxonomy Node");
|
|
1027
|
+
var ConceptMembershipSchema = (0, import_yup16.object)({
|
|
1028
|
+
categoryId: (0, import_yup16.string)().required().label("Category ID"),
|
|
1029
|
+
categoryName: (0, import_yup16.string)().required().label("Category Name"),
|
|
1030
|
+
subcategoryId: (0, import_yup16.string)().required().label("Subcategory ID"),
|
|
1031
|
+
subcategoryName: (0, import_yup16.string)().required().label("Subcategory Name"),
|
|
1032
|
+
groupId: (0, import_yup16.string)().required().label("Group ID"),
|
|
1033
|
+
groupName: (0, import_yup16.string)().required().label("Group Name"),
|
|
1034
|
+
/** The source record this membership came from; '' when written by hand. */
|
|
1035
|
+
sourceId: (0, import_yup16.string)().default("").label("Source ID")
|
|
1036
|
+
}).label("Concept Membership");
|
|
1037
|
+
var ConceptSchema = (0, import_yup16.object)({
|
|
1038
|
+
/** `<vocabulary>_<slug>`, e.g. `skills_power-bi`. Primary key. */
|
|
1039
|
+
conceptId: conceptId().required().label("Concept ID"),
|
|
1040
|
+
vocabulary: vocabularyId().required().label("Vocabulary"),
|
|
1041
|
+
name: (0, import_yup16.string)().trim().min(1).max(200).required().label("Name"),
|
|
1042
|
+
/** One of the vocabulary's type ids; checked against the vocabulary by the service. */
|
|
1043
|
+
type: (0, import_yup16.string)().trim().matches(CONCEPT_TYPE_PATTERN, "type must be a type id").required().label("Type"),
|
|
1044
|
+
description: (0, import_yup16.string)().trim().max(2e3).default("").label("Description"),
|
|
1045
|
+
aliases: strings().default([]).label("Aliases"),
|
|
1046
|
+
memberships: (0, import_yup16.array)(ConceptMembershipSchema.required()).default([]).label("Memberships"),
|
|
1047
|
+
/** Always concepts of the same vocabulary. */
|
|
1048
|
+
relatedConceptIds: strings().default([]).label("Related Concepts"),
|
|
1049
|
+
source: (0, import_yup16.string)().oneOf(SupportedConceptSources).required().label("Source"),
|
|
1050
|
+
createdAt: (0, import_yup16.number)().required().label("Created At"),
|
|
1051
|
+
updatedAt: (0, import_yup16.number)().required().label("Updated At"),
|
|
1052
|
+
/** Resume marker of `retype-concepts`: set once the type was examined. */
|
|
1053
|
+
retypedAt: (0, import_yup16.number)().optional().label("Retyped At"),
|
|
1054
|
+
/** Resume marker of `generate-aliases`: set even when no alias was added. */
|
|
1055
|
+
aliasedAt: (0, import_yup16.number)().optional().label("Aliased At"),
|
|
1056
|
+
/** Set while `description` is a stand-in; removed once a real one is written. */
|
|
1057
|
+
descriptionPending: (0, import_yup16.boolean)().isTrue().optional().label("Description Pending")
|
|
1058
|
+
}).label("Concept");
|
|
1059
|
+
var UnmatchedTermSchema = (0, import_yup16.object)({
|
|
1060
|
+
vocabulary: vocabularyId().required().label("Vocabulary"),
|
|
1061
|
+
/** The raw input as first received. */
|
|
1062
|
+
term: (0, import_yup16.string)().required().label("Term"),
|
|
1063
|
+
/** The dedupe key, so "React JS" and "react.js" share a row. */
|
|
1064
|
+
normalizedTerm: (0, import_yup16.string)().required().label("Normalized Term"),
|
|
1065
|
+
count: (0, import_yup16.number)().integer().min(0).required().label("Count"),
|
|
1066
|
+
firstSeenAt: (0, import_yup16.number)().required().label("First Seen At"),
|
|
1067
|
+
lastSeenAt: (0, import_yup16.number)().required().label("Last Seen At"),
|
|
1068
|
+
/** Which callers sent it, capped. */
|
|
1069
|
+
sources: (0, import_yup16.array)(
|
|
1070
|
+
(0, import_yup16.object)({
|
|
1071
|
+
service: (0, import_yup16.string)().required(),
|
|
1072
|
+
context: (0, import_yup16.string)().optional()
|
|
1073
|
+
}).required()
|
|
1074
|
+
).default([]).label("Sources"),
|
|
1075
|
+
resolution: (0, import_yup16.string)().oneOf(SupportedUnmatchedResolutions).required().label("Resolution"),
|
|
1076
|
+
resolvedConceptId: (0, import_yup16.string)().optional().label("Resolved Concept"),
|
|
1077
|
+
/** `ambiguous`: the concept exists; the caller gave no context that picked one. */
|
|
1078
|
+
reason: (0, import_yup16.string)().oneOf(SupportedUnmatchedReasons).optional().label("Reason"),
|
|
1079
|
+
/** The concepts an ambiguous term could mean. */
|
|
1080
|
+
candidates: (0, import_yup16.array)((0, import_yup16.string)().required()).optional().label("Candidates"),
|
|
1081
|
+
/** Who rejected it when it was not a human: `prefilter:<rule>` or `model`. */
|
|
1082
|
+
rejectedBy: (0, import_yup16.string)().optional().label("Rejected By")
|
|
1083
|
+
}).label("Unmatched Term");
|
|
1084
|
+
var ProposalCandidateSchema = (0, import_yup16.object)({
|
|
1085
|
+
groupId: (0, import_yup16.string)().required(),
|
|
1086
|
+
groupName: (0, import_yup16.string)().required(),
|
|
1087
|
+
subcategoryId: (0, import_yup16.string)().required(),
|
|
1088
|
+
subcategoryName: (0, import_yup16.string)().required(),
|
|
1089
|
+
categoryId: (0, import_yup16.string)().required(),
|
|
1090
|
+
categoryName: (0, import_yup16.string)().required(),
|
|
1091
|
+
score: (0, import_yup16.number)().required(),
|
|
1092
|
+
nearestMembers: (0, import_yup16.array)((0, import_yup16.string)().required()).default([])
|
|
1093
|
+
}).label("Proposal Candidate");
|
|
1094
|
+
var ProposalMessageSchema = (0, import_yup16.object)({
|
|
1095
|
+
role: (0, import_yup16.string)().oneOf(SupportedProposalMessageRoles).required(),
|
|
1096
|
+
/** The operator's instruction, or the model's note on what it changed and why. */
|
|
1097
|
+
content: (0, import_yup16.string)().defined(),
|
|
1098
|
+
/** Which model answered. Absent on operator turns. */
|
|
1099
|
+
model: (0, import_yup16.string)().optional(),
|
|
1100
|
+
at: (0, import_yup16.number)().required()
|
|
1101
|
+
}).label("Proposal Message");
|
|
1102
|
+
var SuggestedHomeSchema = (0, import_yup16.object)({
|
|
1103
|
+
categoryName: (0, import_yup16.string)().defined(),
|
|
1104
|
+
subcategoryName: (0, import_yup16.string)().defined(),
|
|
1105
|
+
groupName: (0, import_yup16.string)().defined()
|
|
1106
|
+
}).label("Suggested Home");
|
|
1107
|
+
var ResolverVerificationSchema = (0, import_yup16.object)({
|
|
1108
|
+
verdict: (0, import_yup16.string)().oneOf(SupportedResolverVerdicts).required(),
|
|
1109
|
+
/** The shown concept the verdict is about; null for `new_concept` / `out_of_scope`. */
|
|
1110
|
+
conceptId: (0, import_yup16.string)().nullable().defined(),
|
|
1111
|
+
evidence: (0, import_yup16.string)().defined(),
|
|
1112
|
+
/** What the judge took the term to mean, abbreviations expanded. */
|
|
1113
|
+
means: (0, import_yup16.string)().optional(),
|
|
1114
|
+
/** For `same`: did the independent confirm step agree? */
|
|
1115
|
+
consistent: (0, import_yup16.boolean)().optional(),
|
|
1116
|
+
confirm: (0, import_yup16.object)({
|
|
1117
|
+
answer: (0, import_yup16.string)().oneOf(["yes", "no"]).required(),
|
|
1118
|
+
evidence: (0, import_yup16.string)().defined()
|
|
1119
|
+
}).optional().default(void 0)
|
|
1120
|
+
}).label("Resolver Verification");
|
|
1121
|
+
var ConceptProposalSchema = (0, import_yup16.object)({
|
|
1122
|
+
proposalId: (0, import_yup16.string)().required().label("Proposal ID"),
|
|
1123
|
+
vocabulary: vocabularyId().required().label("Vocabulary"),
|
|
1124
|
+
/** The miss this closes; `normalizedTerm` links back to its unmatched row. */
|
|
1125
|
+
term: (0, import_yup16.string)().required().label("Term"),
|
|
1126
|
+
normalizedTerm: (0, import_yup16.string)().required().label("Normalized Term"),
|
|
1127
|
+
/** Demand at proposal time, so the queue ranks without a join. */
|
|
1128
|
+
count: (0, import_yup16.number)().integer().min(0).required().label("Count"),
|
|
1129
|
+
/** Other misses folded into this draft because they name the same new concept. */
|
|
1130
|
+
mergedTerms: (0, import_yup16.array)(
|
|
1131
|
+
(0, import_yup16.object)({
|
|
1132
|
+
term: (0, import_yup16.string)().required(),
|
|
1133
|
+
normalizedTerm: (0, import_yup16.string)().required(),
|
|
1134
|
+
count: (0, import_yup16.number)().integer().min(0).required()
|
|
1135
|
+
}).required()
|
|
1136
|
+
).optional().label("Merged Terms"),
|
|
1137
|
+
/** Absent on drafts that predate the field: read as `concept`. */
|
|
1138
|
+
kind: (0, import_yup16.string)().oneOf(SupportedProposalKinds).optional().label("Kind"),
|
|
1139
|
+
/** For `alias`: the concept the term names. For `placement`: the concept to place. */
|
|
1140
|
+
targetConceptId: (0, import_yup16.string)().optional().label("Target Concept"),
|
|
1141
|
+
targetName: (0, import_yup16.string)().optional().label("Target Name"),
|
|
1142
|
+
// The draft concept, editable until approved. Empty strings are valid here:
|
|
1143
|
+
// an alias draft carries no draft concept of its own.
|
|
1144
|
+
name: (0, import_yup16.string)().defined().label("Name"),
|
|
1145
|
+
type: (0, import_yup16.string)().defined().label("Type"),
|
|
1146
|
+
description: (0, import_yup16.string)().defined().label("Description"),
|
|
1147
|
+
aliases: (0, import_yup16.array)((0, import_yup16.string)().required()).default([]).label("Aliases"),
|
|
1148
|
+
/** Empty when no group fits: approved that way, the concept goes live uncategorized. */
|
|
1149
|
+
memberships: (0, import_yup16.array)(ConceptMembershipSchema.required()).default([]).label("Memberships"),
|
|
1150
|
+
suggestedHome: SuggestedHomeSchema.nullable().optional().default(void 0).label("Suggested Home"),
|
|
1151
|
+
/** Resolved to concepts that exist; names that matched nothing are dropped. */
|
|
1152
|
+
relatedConceptIds: (0, import_yup16.array)((0, import_yup16.string)().required()).default([]).label("Related Concepts"),
|
|
1153
|
+
/** Every placement candidate considered, best first. */
|
|
1154
|
+
candidates: (0, import_yup16.array)(ProposalCandidateSchema.required()).default([]).label("Candidates"),
|
|
1155
|
+
needsReview: (0, import_yup16.boolean)().required().label("Needs Review"),
|
|
1156
|
+
reason: (0, import_yup16.string)().optional().label("Reason"),
|
|
1157
|
+
verification: ResolverVerificationSchema.optional().default(void 0).label("Verification"),
|
|
1158
|
+
/** What the auto-accept gate decided for an alias verdict. */
|
|
1159
|
+
autoAccept: (0, import_yup16.object)({
|
|
1160
|
+
accepted: (0, import_yup16.boolean)().required(),
|
|
1161
|
+
reason: (0, import_yup16.string)().optional(),
|
|
1162
|
+
tier: (0, import_yup16.string)().optional(),
|
|
1163
|
+
calibrationId: (0, import_yup16.string)().optional(),
|
|
1164
|
+
releaseId: (0, import_yup16.string)().optional()
|
|
1165
|
+
}).optional().default(void 0).label("Auto Accept"),
|
|
1166
|
+
/** Which model drafted it. */
|
|
1167
|
+
model: (0, import_yup16.string)().defined().label("Model"),
|
|
1168
|
+
/** The refinement conversation, oldest first. */
|
|
1169
|
+
messages: (0, import_yup16.array)(ProposalMessageSchema.required()).default([]).label("Messages"),
|
|
1170
|
+
status: (0, import_yup16.string)().oneOf(SupportedProposalStatuses).required().label("Status"),
|
|
1171
|
+
/** Set when approved: the concept this became. */
|
|
1172
|
+
resolvedConceptId: (0, import_yup16.string)().optional().label("Resolved Concept"),
|
|
1173
|
+
createdAt: (0, import_yup16.number)().required().label("Created At"),
|
|
1174
|
+
updatedAt: (0, import_yup16.number)().required().label("Updated At")
|
|
1175
|
+
}).label("Concept Proposal");
|
|
1176
|
+
var ReleaseSchema = (0, import_yup16.object)({
|
|
1177
|
+
releaseId: (0, import_yup16.string)().required().label("Release ID"),
|
|
1178
|
+
kind: (0, import_yup16.string)().oneOf(SupportedReleaseKinds).required().label("Kind"),
|
|
1179
|
+
status: (0, import_yup16.string)().oneOf(SupportedReleaseStatuses).required().label("Status"),
|
|
1180
|
+
createdBy: (0, import_yup16.string)().required().label("Created By"),
|
|
1181
|
+
createdAt: (0, import_yup16.number)().required().label("Created At"),
|
|
1182
|
+
note: (0, import_yup16.string)().optional().label("Note"),
|
|
1183
|
+
rolledBackAt: (0, import_yup16.number)().optional().label("Rolled Back At"),
|
|
1184
|
+
rolledBackBy: (0, import_yup16.string)().optional().label("Rolled Back By")
|
|
1185
|
+
}).label("Release");
|
|
1186
|
+
var AuditSchema = (0, import_yup16.object)({
|
|
1187
|
+
auditId: (0, import_yup16.string)().required().label("Audit ID"),
|
|
1188
|
+
releaseId: (0, import_yup16.string)().required().label("Release ID"),
|
|
1189
|
+
key: (0, import_yup16.string)().required().label("Key"),
|
|
1190
|
+
term: (0, import_yup16.string)().required().label("Term"),
|
|
1191
|
+
conceptId: (0, import_yup16.string)().required().label("Concept ID"),
|
|
1192
|
+
tier: (0, import_yup16.string)().optional().label("Tier"),
|
|
1193
|
+
status: (0, import_yup16.string)().oneOf(SupportedAuditStatuses).required().label("Status"),
|
|
1194
|
+
createdAt: (0, import_yup16.number)().required().label("Created At"),
|
|
1195
|
+
resolvedAt: (0, import_yup16.number)().optional().label("Resolved At"),
|
|
1196
|
+
resolvedBy: (0, import_yup16.string)().optional().label("Resolved By")
|
|
1197
|
+
}).label("Audit");
|
|
1198
|
+
var ResolverSettingsSchema = (0, import_yup16.object)({
|
|
1199
|
+
autoAccept: (0, import_yup16.object)({
|
|
1200
|
+
/** Stop switch for WRITING auto keys. Off until a calibration passes. */
|
|
1201
|
+
enabled: (0, import_yup16.boolean)().required(),
|
|
1202
|
+
/** Minimum calibrated precision (Wilson 95% lower bound) for a tier to auto-accept. */
|
|
1203
|
+
target: (0, import_yup16.number)().min(0.5).lessThan(1).required(),
|
|
1204
|
+
maxPerRun: (0, import_yup16.number)().integer().min(0).required(),
|
|
1205
|
+
maxPerDay: (0, import_yup16.number)().integer().min(0).required(),
|
|
1206
|
+
/** Share of each auto release sampled into the audit queue (0..1). */
|
|
1207
|
+
auditRate: (0, import_yup16.number)().min(0).max(1).required()
|
|
1208
|
+
}).label("Auto Accept"),
|
|
1209
|
+
/** Stop switch for SERVING auto keys: false hides them from lookups at once. */
|
|
1210
|
+
serveAutoKeys: (0, import_yup16.boolean)().required().label("Serve Auto Keys"),
|
|
1211
|
+
/** Minimum Meilisearch ranking score (0..1) for a fuzzy hit to be considered. */
|
|
1212
|
+
fuzzyMinScore: (0, import_yup16.number)().min(0).max(1).required().label("Fuzzy Min Score"),
|
|
1213
|
+
/** Per-client limit on public search, per minute per replica. 0 disables it. */
|
|
1214
|
+
searchRateLimitPerMin: (0, import_yup16.number)().integer().min(0).required().label("Search Rate Limit"),
|
|
1215
|
+
/** Master switch for scheduled maintenance jobs. */
|
|
1216
|
+
scheduledJobs: (0, import_yup16.boolean)().required().label("Scheduled Jobs"),
|
|
1217
|
+
updatedAt: (0, import_yup16.number)().optional().label("Updated At"),
|
|
1218
|
+
updatedBy: (0, import_yup16.string)().optional().label("Updated By"),
|
|
1219
|
+
/** Why auto-accept was last switched off automatically. */
|
|
1220
|
+
trippedReason: (0, import_yup16.string)().optional().label("Tripped Reason")
|
|
1221
|
+
}).label("Resolver Settings");
|
|
1222
|
+
var TaxonomyScheduleSchema = (0, import_yup16.object)({
|
|
1223
|
+
kind: (0, import_yup16.string)().oneOf(SupportedTaxonomyJobKinds).required().label("Job"),
|
|
1224
|
+
enabled: (0, import_yup16.boolean)().required().label("Enabled"),
|
|
1225
|
+
everyHours: (0, import_yup16.number)().min(SCHEDULE_MIN_HOURS).max(SCHEDULE_MAX_HOURS).required().label("Every (hours)"),
|
|
1226
|
+
/** Last time the scheduler fired this job. */
|
|
1227
|
+
lastRunAt: (0, import_yup16.number)().optional().label("Last Run At"),
|
|
1228
|
+
updatedAt: (0, import_yup16.number)().required().label("Updated At")
|
|
1229
|
+
}).label("Taxonomy Schedule");
|
|
1230
|
+
var NormalizeContextSchema = (0, import_yup16.object)({
|
|
1231
|
+
/** The title of the record the terms come from. */
|
|
1232
|
+
title: (0, import_yup16.string)().max(200).optional(),
|
|
1233
|
+
/** Backbone node ids (category, subcategory or group). */
|
|
1234
|
+
categoryIds: (0, import_yup16.array)(nodeId().required()).max(10).optional(),
|
|
1235
|
+
/** Other terms from the same record, in the same vocabulary. */
|
|
1236
|
+
siblings: (0, import_yup16.array)((0, import_yup16.string)().max(200).required()).max(50).optional()
|
|
1237
|
+
}).label("Normalize Context");
|
|
1238
|
+
|
|
862
1239
|
// src/question/question.constant.ts
|
|
863
1240
|
var QuestionType = /* @__PURE__ */ ((QuestionType2) => {
|
|
864
1241
|
QuestionType2["Input"] = "input";
|
|
@@ -875,24 +1252,24 @@ var AnswerChoiceType = /* @__PURE__ */ ((AnswerChoiceType2) => {
|
|
|
875
1252
|
var SupportedAnswerChoiceTypes = Object.values(AnswerChoiceType);
|
|
876
1253
|
|
|
877
1254
|
// src/question/question.schema.ts
|
|
878
|
-
var
|
|
879
|
-
var QuestionSchema = (0,
|
|
880
|
-
label: (0,
|
|
881
|
-
default: (0,
|
|
882
|
-
title: (0,
|
|
883
|
-
type: (0,
|
|
884
|
-
isOptional: (0,
|
|
885
|
-
readonly: (0,
|
|
886
|
-
isNew: (0,
|
|
1255
|
+
var import_yup17 = require("yup");
|
|
1256
|
+
var QuestionSchema = (0, import_yup17.object)().shape({
|
|
1257
|
+
label: (0, import_yup17.string)().max(50).optional().label("Label"),
|
|
1258
|
+
default: (0, import_yup17.boolean)().optional().default(false).label("Default"),
|
|
1259
|
+
title: (0, import_yup17.string)().required().max(200).label("Title"),
|
|
1260
|
+
type: (0, import_yup17.string)().oneOf(SupportedQuestionTypes).required().label("Type"),
|
|
1261
|
+
isOptional: (0, import_yup17.boolean)().optional().label("Mark if the question is optional"),
|
|
1262
|
+
readonly: (0, import_yup17.boolean)().optional().label("Readonly"),
|
|
1263
|
+
isNew: (0, import_yup17.boolean)().optional().label("Is New")
|
|
887
1264
|
});
|
|
888
1265
|
|
|
889
1266
|
// src/question/input-question.schema.ts
|
|
890
|
-
var
|
|
1267
|
+
var import_yup18 = require("yup");
|
|
891
1268
|
var InputQuestionSchema = QuestionSchema.concat(
|
|
892
|
-
(0,
|
|
893
|
-
type: (0,
|
|
894
|
-
preferredAnswer: (0,
|
|
895
|
-
answers: (0,
|
|
1269
|
+
(0, import_yup18.object)().shape({
|
|
1270
|
+
type: (0, import_yup18.string)().oneOf(["input" /* Input */]).required().label("Question type"),
|
|
1271
|
+
preferredAnswer: (0, import_yup18.string)().max(100).optional().label("Preferred Answer"),
|
|
1272
|
+
answers: (0, import_yup18.string)().max(500).when("isOptional", {
|
|
896
1273
|
is: (isOptional) => Boolean(isOptional),
|
|
897
1274
|
then: (schema) => schema.optional(),
|
|
898
1275
|
otherwise: (schema) => schema.required()
|
|
@@ -901,10 +1278,10 @@ var InputQuestionSchema = QuestionSchema.concat(
|
|
|
901
1278
|
);
|
|
902
1279
|
|
|
903
1280
|
// src/question/choice-question.schema.ts
|
|
904
|
-
var
|
|
905
|
-
var ChoicePreferredAnswerSchema = (label = "Preferred answer") => (0,
|
|
1281
|
+
var import_yup19 = require("yup");
|
|
1282
|
+
var ChoicePreferredAnswerSchema = (label = "Preferred answer") => (0, import_yup19.mixed)().when("answerChoiceType", {
|
|
906
1283
|
is: (value) => value === "multiple" /* Multiple */,
|
|
907
|
-
then: () => (0,
|
|
1284
|
+
then: () => (0, import_yup19.array)((0, import_yup19.string)()).test(
|
|
908
1285
|
"is-valid-option",
|
|
909
1286
|
`${label} must be from the provided options`,
|
|
910
1287
|
function(answer) {
|
|
@@ -915,7 +1292,7 @@ var ChoicePreferredAnswerSchema = (label = "Preferred answer") => (0, import_yup
|
|
|
915
1292
|
return true;
|
|
916
1293
|
}
|
|
917
1294
|
).optional().label(label),
|
|
918
|
-
otherwise: () => (0,
|
|
1295
|
+
otherwise: () => (0, import_yup19.string)().test(
|
|
919
1296
|
"is-valid-option",
|
|
920
1297
|
`${label} must be from the provided options`,
|
|
921
1298
|
function(answer) {
|
|
@@ -926,20 +1303,20 @@ var ChoicePreferredAnswerSchema = (label = "Preferred answer") => (0, import_yup
|
|
|
926
1303
|
});
|
|
927
1304
|
var getChoiceAnswerSchema = (answerChoiceType, isOptional) => {
|
|
928
1305
|
if (answerChoiceType === "multiple" /* Multiple */) {
|
|
929
|
-
const multiAnswerSchema = (0,
|
|
1306
|
+
const multiAnswerSchema = (0, import_yup19.array)((0, import_yup19.string)().max(500));
|
|
930
1307
|
return isOptional ? multiAnswerSchema.optional().default([]) : multiAnswerSchema.min(1, "Select at least one option.").required("Select at least one option.").default([]);
|
|
931
1308
|
}
|
|
932
|
-
const singleAnswerSchema = (0,
|
|
1309
|
+
const singleAnswerSchema = (0, import_yup19.string)().max(500);
|
|
933
1310
|
return isOptional ? singleAnswerSchema.optional() : singleAnswerSchema.required("Select an option.");
|
|
934
1311
|
};
|
|
935
1312
|
var ChoiceQuestionSchema = QuestionSchema.concat(
|
|
936
|
-
(0,
|
|
937
|
-
type: (0,
|
|
938
|
-
optionsFrom: (0,
|
|
939
|
-
options: (0,
|
|
940
|
-
answerChoiceType: (0,
|
|
1313
|
+
(0, import_yup19.object)().shape({
|
|
1314
|
+
type: (0, import_yup19.string)().oneOf(["choice" /* Choice */]).required().label("Question type"),
|
|
1315
|
+
optionsFrom: (0, import_yup19.string)().oneOf(["skill" /* Skill */, "education_level" /* EducationLevel */, "experience_level" /* ExperienceLevel */]).optional().label("Option field"),
|
|
1316
|
+
options: (0, import_yup19.array)((0, import_yup19.string)().required()).min(1).required().label("Options"),
|
|
1317
|
+
answerChoiceType: (0, import_yup19.string)().oneOf(SupportedAnswerChoiceTypes).required().default("single" /* Single */).label("Type"),
|
|
941
1318
|
preferredAnswer: ChoicePreferredAnswerSchema("Preferred answer"),
|
|
942
|
-
answers: (0,
|
|
1319
|
+
answers: (0, import_yup19.mixed)().when(
|
|
943
1320
|
["answerChoiceType", "isOptional"],
|
|
944
1321
|
([answerChoiceType, isOptional]) => getChoiceAnswerSchema(answerChoiceType, isOptional)
|
|
945
1322
|
)
|
|
@@ -947,12 +1324,12 @@ var ChoiceQuestionSchema = QuestionSchema.concat(
|
|
|
947
1324
|
);
|
|
948
1325
|
|
|
949
1326
|
// src/question/read-and-acknowledge.schema.ts
|
|
950
|
-
var
|
|
951
|
-
var AcknowledgeAnswerSchema = (0,
|
|
1327
|
+
var import_yup20 = require("yup");
|
|
1328
|
+
var AcknowledgeAnswerSchema = (0, import_yup20.string)().oneOf(["yes" /* Yes */, "no" /* No */]).required("This question must be acknowledged.");
|
|
952
1329
|
var ReadAndAcknowledgeQuestionSchema = QuestionSchema.concat(
|
|
953
|
-
(0,
|
|
954
|
-
type: (0,
|
|
955
|
-
description: (0,
|
|
1330
|
+
(0, import_yup20.object)().shape({
|
|
1331
|
+
type: (0, import_yup20.string)().oneOf(["readAndAcknowledge" /* ReadAndAcknowledge */]).required().label("Question type"),
|
|
1332
|
+
description: (0, import_yup20.string)().max(1e4).required().label("Content"),
|
|
956
1333
|
preferredAnswer: AcknowledgeAnswerSchema.label("Preferred Answer"),
|
|
957
1334
|
answers: AcknowledgeAnswerSchema.label("Answer")
|
|
958
1335
|
})
|
|
@@ -1033,20 +1410,20 @@ var SupportedApplicationReceivePreferences = Object.values(
|
|
|
1033
1410
|
);
|
|
1034
1411
|
|
|
1035
1412
|
// src/job/job.schema.ts
|
|
1036
|
-
var JobSchema = (0,
|
|
1413
|
+
var JobSchema = (0, import_yup21.object)({
|
|
1037
1414
|
/** Unique id usable by external systems to reference the job. */
|
|
1038
|
-
uniqueId: (0,
|
|
1415
|
+
uniqueId: (0, import_yup21.string)().optional().label("Unique ID"),
|
|
1039
1416
|
/** Job title shown in listings and search. */
|
|
1040
|
-
headline: (0,
|
|
1417
|
+
headline: (0, import_yup21.string)().required().min(5).max(150).label("Headline"),
|
|
1041
1418
|
/** User-friendly, unique URL identifier. */
|
|
1042
|
-
slug: (0,
|
|
1419
|
+
slug: (0, import_yup21.string)().required().max(250).label("Slug"),
|
|
1043
1420
|
/** How applications are received (inbox vs external website). */
|
|
1044
|
-
applicationReceivePreference: (0,
|
|
1421
|
+
applicationReceivePreference: (0, import_yup21.mixed)().oneOf([
|
|
1045
1422
|
"inbox" /* Inbox */,
|
|
1046
1423
|
"external_website" /* ExternalWebsite */
|
|
1047
1424
|
]).required().label("Preference"),
|
|
1048
1425
|
/** Required when applicationReceivePreference is ExternalWebsite. */
|
|
1049
|
-
externalApplyLink: (0,
|
|
1426
|
+
externalApplyLink: (0, import_yup21.string)().when("applicationReceivePreference", {
|
|
1050
1427
|
is: (value) => value === "external_website" /* ExternalWebsite */,
|
|
1051
1428
|
then: (schema) => schema.url().required().label("Apply for Job link"),
|
|
1052
1429
|
otherwise: (schema) => schema.optional()
|
|
@@ -1054,35 +1431,44 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1054
1431
|
/** Company the job belongs to (subset of PageSchema). */
|
|
1055
1432
|
company: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Company"),
|
|
1056
1433
|
/** @deprecated kept for backwards compatibility. */
|
|
1057
|
-
designation: (0,
|
|
1058
|
-
employmentType: (0,
|
|
1059
|
-
workMode: (0,
|
|
1434
|
+
designation: (0, import_yup21.string)().optional().nullable().label("Designation"),
|
|
1435
|
+
employmentType: (0, import_yup21.string)().required().label("Employment type"),
|
|
1436
|
+
workMode: (0, import_yup21.string)().required().label("Work mode"),
|
|
1060
1437
|
/**
|
|
1061
|
-
* `
|
|
1062
|
-
*
|
|
1063
|
-
*
|
|
1064
|
-
*
|
|
1438
|
+
* `name` is the skill exactly as posted. `concept` is what thejob-taxonomy-service
|
|
1439
|
+
* resolved it to (`vocabulary: skills`), written by jobs-service, never by the
|
|
1440
|
+
* poster: enough of the concept to filter by id and display the canonical name
|
|
1441
|
+
* without a lookup. A copy, so it can go stale after a taxonomy release; see
|
|
1442
|
+
* `taxonomyVersion`.
|
|
1443
|
+
*
|
|
1444
|
+
* Additive, never authoritative: the raw `name` is always kept, so a wrong
|
|
1445
|
+
* match, a taxonomy release or an outage is recoverable by re-normalizing.
|
|
1446
|
+
* `concept` is absent when the term did not resolve (a normal outcome, logged
|
|
1447
|
+
* as a miss on the taxonomy side) or the job predates normalization, so read
|
|
1448
|
+
* `concept?.name ?? name`.
|
|
1065
1449
|
*/
|
|
1066
|
-
skills: (0,
|
|
1067
|
-
SkillSchema.pick(["name", "logo"
|
|
1450
|
+
skills: (0, import_yup21.array)().of(
|
|
1451
|
+
SkillSchema.pick(["name", "logo"]).shape({
|
|
1452
|
+
concept: ConceptSchema.pick(["conceptId", "vocabulary", "name", "type"]).nullable().optional().default(void 0)
|
|
1453
|
+
}).required().label("Skill")
|
|
1068
1454
|
).nullable().optional().label("Skills"),
|
|
1069
|
-
bookmarks: (0,
|
|
1070
|
-
embedding: (0,
|
|
1071
|
-
vector: (0,
|
|
1072
|
-
model: (0,
|
|
1455
|
+
bookmarks: (0, import_yup21.array)().of(UserIdAndCreatedAtSchema).optional().label("Bookmarks"),
|
|
1456
|
+
embedding: (0, import_yup21.object)({
|
|
1457
|
+
vector: (0, import_yup21.array)((0, import_yup21.number)().required()).optional().label("Embedding vector"),
|
|
1458
|
+
model: (0, import_yup21.string)().optional().label("Embedding model")
|
|
1073
1459
|
}).nullable().optional().label("Embedding"),
|
|
1074
|
-
applicants: (0,
|
|
1075
|
-
applicantCount: (0,
|
|
1076
|
-
externalApplicationLinkClickCount: (0,
|
|
1077
|
-
description: (0,
|
|
1078
|
-
descriptionMarkdown: (0,
|
|
1079
|
-
descriptionHTML: (0,
|
|
1460
|
+
applicants: (0, import_yup21.array)().of(UserIdAndCreatedAtSchema).optional().label("Applicants"),
|
|
1461
|
+
applicantCount: (0, import_yup21.number)().optional().label("Applicant count"),
|
|
1462
|
+
externalApplicationLinkClickCount: (0, import_yup21.number)().optional().label("External application link click count"),
|
|
1463
|
+
description: (0, import_yup21.string)().required().min(100).max(5e4).label("Description"),
|
|
1464
|
+
descriptionMarkdown: (0, import_yup21.string)().required().label("Description Markdown"),
|
|
1465
|
+
descriptionHTML: (0, import_yup21.string)().optional().label("Description HTML"),
|
|
1080
1466
|
/**
|
|
1081
1467
|
* Job locations. Required even for remote roles (compliance/legal). Defaults
|
|
1082
1468
|
* to an empty array; min(1) is intentionally not enforced yet.
|
|
1083
1469
|
*/
|
|
1084
|
-
locations: (0,
|
|
1085
|
-
educationLevel: (0,
|
|
1470
|
+
locations: (0, import_yup21.array)().of(LocationSchema).default([]).label("Location"),
|
|
1471
|
+
educationLevel: (0, import_yup21.array)((0, import_yup21.string)().oneOf(SupportedEducationLevels)).required().min(1).label("Educational level"),
|
|
1086
1472
|
/** Posting validity window (start/expiry). */
|
|
1087
1473
|
validity: DurationSchema({
|
|
1088
1474
|
format: SYSTEM_DATE_FORMAT,
|
|
@@ -1095,22 +1481,22 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1095
1481
|
* has no `validity.endDate` and must be verified by crawling its page. Guards
|
|
1096
1482
|
* re-check cadence so the same job is not re-crawled on every sweep.
|
|
1097
1483
|
*/
|
|
1098
|
-
lastExpiryCheckAt: (0,
|
|
1484
|
+
lastExpiryCheckAt: (0, import_yup21.number)().optional().nullable().label("Last expiry check at"),
|
|
1099
1485
|
/**
|
|
1100
1486
|
* When this job transitioned to `status: closed` (epoch ms). Server-owned
|
|
1101
1487
|
* operational field: stamped by every jobs-service close path (expiry
|
|
1102
1488
|
* auto-close and the dated lapse sweep). Distinct from `updatedAt` so a later
|
|
1103
1489
|
* edit to a closed job does not move it.
|
|
1104
1490
|
*/
|
|
1105
|
-
closedAt: (0,
|
|
1106
|
-
experienceLevel: (0,
|
|
1107
|
-
contactEmail: (0,
|
|
1108
|
-
workingHoursPerWeek: (0,
|
|
1109
|
-
tags: (0,
|
|
1491
|
+
closedAt: (0, import_yup21.number)().optional().nullable().label("Closed at"),
|
|
1492
|
+
experienceLevel: (0, import_yup21.string)().oneOf(SupportedExperienceLevels).nullable().optional().label("Experience level"),
|
|
1493
|
+
contactEmail: (0, import_yup21.string)().email().nullable().optional().label("Contact email"),
|
|
1494
|
+
workingHoursPerWeek: (0, import_yup21.number)().nullable().optional().min(1).max(24 * 7).label("Working hours per week"),
|
|
1495
|
+
tags: (0, import_yup21.array)().max(50).optional().label("Tags"),
|
|
1110
1496
|
/** Direct/Quick-apply questionnaire. Each item is validated against the
|
|
1111
1497
|
* concrete question schema for its `type`, with the stored `answers` omitted. */
|
|
1112
|
-
questionnaire: (0,
|
|
1113
|
-
(0,
|
|
1498
|
+
questionnaire: (0, import_yup21.array)().of(
|
|
1499
|
+
(0, import_yup21.lazy)((question) => {
|
|
1114
1500
|
const schema = getSchemaByQuestion(question.type);
|
|
1115
1501
|
if (question.type === "input" /* Input */) {
|
|
1116
1502
|
return schema.omit([
|
|
@@ -1126,12 +1512,12 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1126
1512
|
return schema;
|
|
1127
1513
|
})
|
|
1128
1514
|
).label("Questionnaire"),
|
|
1129
|
-
status: (0,
|
|
1130
|
-
seoTags: (0,
|
|
1131
|
-
description: (0,
|
|
1132
|
-
keywords: (0,
|
|
1515
|
+
status: (0, import_yup21.string)().oneOf(SupportedJobStatuses).default("draft" /* Draft */).required().label("Status"),
|
|
1516
|
+
seoTags: (0, import_yup21.object)({
|
|
1517
|
+
description: (0, import_yup21.string)().optional().label("Description"),
|
|
1518
|
+
keywords: (0, import_yup21.array)().of((0, import_yup21.string)()).optional().label("Keywords")
|
|
1133
1519
|
}).nullable().optional().label("SEO Tags"),
|
|
1134
|
-
jdSummary: (0,
|
|
1520
|
+
jdSummary: (0, import_yup21.string)().optional().label("JD Summary"),
|
|
1135
1521
|
/**
|
|
1136
1522
|
* Structured, model-extracted sections of the posting, re-organized into clean
|
|
1137
1523
|
* bullet points. This is our OWN unique presentation of the job (rendered as the
|
|
@@ -1140,28 +1526,28 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1140
1526
|
* optional: absent on jobs not yet (re-)enriched, and any section is `[]`/omitted
|
|
1141
1527
|
* when the posting genuinely has none.
|
|
1142
1528
|
*/
|
|
1143
|
-
jobHighlights: (0,
|
|
1144
|
-
responsibilities: (0,
|
|
1145
|
-
requirements: (0,
|
|
1146
|
-
benefits: (0,
|
|
1147
|
-
qualifications: (0,
|
|
1529
|
+
jobHighlights: (0, import_yup21.object)({
|
|
1530
|
+
responsibilities: (0, import_yup21.array)().of((0, import_yup21.string)()).optional().label("Responsibilities"),
|
|
1531
|
+
requirements: (0, import_yup21.array)().of((0, import_yup21.string)()).optional().label("Requirements"),
|
|
1532
|
+
benefits: (0, import_yup21.array)().of((0, import_yup21.string)()).optional().label("Benefits"),
|
|
1533
|
+
qualifications: (0, import_yup21.array)().of((0, import_yup21.string)()).optional().label("Qualifications")
|
|
1148
1534
|
}).nullable().optional().label("Job Highlights"),
|
|
1149
|
-
canCreateAlert: (0,
|
|
1150
|
-
canDirectApply: (0,
|
|
1151
|
-
hasApplied: (0,
|
|
1152
|
-
isOwner: (0,
|
|
1153
|
-
hasBookmarked: (0,
|
|
1154
|
-
hasReported: (0,
|
|
1155
|
-
ratePerHour: (0,
|
|
1156
|
-
isPromoted: (0,
|
|
1157
|
-
salaryRange: (0,
|
|
1158
|
-
currency: (0,
|
|
1159
|
-
min: (0,
|
|
1160
|
-
max: (0,
|
|
1161
|
-
compensationType: (0,
|
|
1162
|
-
isNegotiable: (0,
|
|
1535
|
+
canCreateAlert: (0, import_yup21.boolean)().optional().label("Can create alert"),
|
|
1536
|
+
canDirectApply: (0, import_yup21.boolean)().optional().label("Can direct apply"),
|
|
1537
|
+
hasApplied: (0, import_yup21.boolean)().optional().label("Has applied"),
|
|
1538
|
+
isOwner: (0, import_yup21.boolean)().optional().label("Is owner"),
|
|
1539
|
+
hasBookmarked: (0, import_yup21.boolean)().optional().label("Has bookmarked"),
|
|
1540
|
+
hasReported: (0, import_yup21.boolean)().optional().label("Has reported"),
|
|
1541
|
+
ratePerHour: (0, import_yup21.number)().optional().min(0).label("Rate per hour"),
|
|
1542
|
+
isPromoted: (0, import_yup21.boolean)().optional().label("Is promoted"),
|
|
1543
|
+
salaryRange: (0, import_yup21.object)({
|
|
1544
|
+
currency: (0, import_yup21.string)().required().label("Currency").default("USD"),
|
|
1545
|
+
min: (0, import_yup21.number)().nullable().optional().min(0).label("Minimum Salary"),
|
|
1546
|
+
max: (0, import_yup21.number)().nullable().optional().min(0).label("Maximum Salary"),
|
|
1547
|
+
compensationType: (0, import_yup21.string)().oneOf(SupportedCompensationTypes).nullable().optional().label("Compensation Type"),
|
|
1548
|
+
isNegotiable: (0, import_yup21.boolean)().nullable().optional().default(true).label("Is Negotiable")
|
|
1163
1549
|
}).nullable().optional().label("Salary Range"),
|
|
1164
|
-
reports: (0,
|
|
1550
|
+
reports: (0, import_yup21.array)().of(UserIdAndCreatedAtSchema).optional().label("Reports"),
|
|
1165
1551
|
// Taxonomy fields are constants (see job-taxonomy.constant.ts), stored as slugs and
|
|
1166
1552
|
// translated for display. They are deliberately NOT `oneOf`-constrained here: a value
|
|
1167
1553
|
// outside the taxonomy must be DROPPED, never a reason to reject the posting. Yup
|
|
@@ -1174,17 +1560,25 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1174
1560
|
// time (values get renamed, retired, added), so stored jobs will always outlive the
|
|
1175
1561
|
// enum — being lenient here is what lets the taxonomy evolve without a migration
|
|
1176
1562
|
// gate on every write.
|
|
1177
|
-
category: (0,
|
|
1178
|
-
industry: (0,
|
|
1179
|
-
subCategories: (0,
|
|
1180
|
-
|
|
1181
|
-
|
|
1563
|
+
category: (0, import_yup21.string)().nullable().optional().label("Category"),
|
|
1564
|
+
industry: (0, import_yup21.string)().nullable().optional().label("Industry"),
|
|
1565
|
+
subCategories: (0, import_yup21.array)().of((0, import_yup21.string)().trim().required()).nullable().optional().label("Sub Categories"),
|
|
1566
|
+
/**
|
|
1567
|
+
* The taxonomy state `skills[].concept` was resolved against (the service's
|
|
1568
|
+
* `taxonomyVersion`, bumped by every release and rollback); behind the current
|
|
1569
|
+
* version means the concepts may be stale. Written by jobs-service with every
|
|
1570
|
+
* skills write: `null` when that write could not be normalized (taxonomy down
|
|
1571
|
+
* or unconfigured), absent on jobs that predate normalization.
|
|
1572
|
+
*/
|
|
1573
|
+
taxonomyVersion: (0, import_yup21.number)().integer().min(0).nullable().optional().label("Taxonomy Version"),
|
|
1574
|
+
termsAccepted: (0, import_yup21.boolean)().oneOf([true], "Accept terms before proceeding").required("Accept terms before proceeding").label("Terms accepted"),
|
|
1575
|
+
isFeatured: (0, import_yup21.boolean)().optional().default(false).label("Is featured"),
|
|
1182
1576
|
/** Market country codes to feature this job in; empty = global. */
|
|
1183
|
-
featuredMarkets: (0,
|
|
1577
|
+
featuredMarkets: (0, import_yup21.array)().of((0, import_yup21.string)().required()).optional().default([]).label("Featured markets")
|
|
1184
1578
|
}).concat(DbDefaultSchema).noUnknown().label("Job");
|
|
1185
1579
|
|
|
1186
1580
|
// src/job/job-filter.schema.ts
|
|
1187
|
-
var
|
|
1581
|
+
var import_yup22 = require("yup");
|
|
1188
1582
|
|
|
1189
1583
|
// src/user/user.constant.ts
|
|
1190
1584
|
var UserRole = /* @__PURE__ */ ((UserRole2) => {
|
|
@@ -2372,7 +2766,7 @@ var TAXONOMY_LABELS = {
|
|
|
2372
2766
|
|
|
2373
2767
|
// src/job/job-filter.schema.ts
|
|
2374
2768
|
var GEO_GROUP = "Geo";
|
|
2375
|
-
var JobFilterShape = (0,
|
|
2769
|
+
var JobFilterShape = (0, import_yup22.object)({
|
|
2376
2770
|
// ── Classification ──────────────────────────────────────────────────────────
|
|
2377
2771
|
// Closed vocabularies, sent verbatim and matched exactly: a partial match
|
|
2378
2772
|
// would make "remote" also match a hypothetical "remote_first".
|
|
@@ -2515,8 +2909,8 @@ var JobFilterShape = (0, import_yup21.object)({
|
|
|
2515
2909
|
// ── Flags ───────────────────────────────────────────────────────────────────
|
|
2516
2910
|
// No `.default(false)`: an unchecked box must mean "no constraint", not "only
|
|
2517
2911
|
// the non-featured ones", so absent simply omits the clause.
|
|
2518
|
-
isFeatured: (0,
|
|
2519
|
-
isPromoted: (0,
|
|
2912
|
+
isFeatured: (0, import_yup22.boolean)().optional().label("Featured Only"),
|
|
2913
|
+
isPromoted: (0, import_yup22.boolean)().optional().label("Promoted Only"),
|
|
2520
2914
|
featuredMarkets: tokens("Featured Markets"),
|
|
2521
2915
|
// ── Ranges ──────────────────────────────────────────────────────────────────
|
|
2522
2916
|
/**
|
|
@@ -2527,10 +2921,10 @@ var JobFilterShape = (0, import_yup21.object)({
|
|
|
2527
2921
|
// can be selected and a bound is meaningless across them. Here the currency is
|
|
2528
2922
|
// a single sibling field, so the bound is plain and the currency simply
|
|
2529
2923
|
// narrows which jobs are compared.
|
|
2530
|
-
salary: (0,
|
|
2531
|
-
min: (0,
|
|
2532
|
-
max: (0,
|
|
2533
|
-
currency: (0,
|
|
2924
|
+
salary: (0, import_yup22.object)({
|
|
2925
|
+
min: (0, import_yup22.number)().integer().min(0).optional().default(void 0).label("Salary \u2265"),
|
|
2926
|
+
max: (0, import_yup22.number)().integer().min(0).optional().default(void 0).label("Salary \u2264"),
|
|
2927
|
+
currency: (0, import_yup22.string)().oneOf(SupportedSalaryCurrencies).optional().label("Currency")
|
|
2534
2928
|
}).optional().default(void 0).label("Salary"),
|
|
2535
2929
|
/** Posted within this many days. Relative, so a saved filter does not rot. */
|
|
2536
2930
|
postedWithinDays: days("Posted Within (days)"),
|
|
@@ -2539,7 +2933,7 @@ var JobFilterShape = (0, import_yup21.object)({
|
|
|
2539
2933
|
* relative `postedWithinDays`. EPOCH MS, matching how the field is stored — a
|
|
2540
2934
|
* coerced date string would not compare.
|
|
2541
2935
|
*/
|
|
2542
|
-
createdAt: (0,
|
|
2936
|
+
createdAt: (0, import_yup22.object)({
|
|
2543
2937
|
min: epoch("Posted After"),
|
|
2544
2938
|
max: epoch("Posted Before")
|
|
2545
2939
|
}).optional().default(void 0).label("Posted Between")
|
|
@@ -2593,7 +2987,7 @@ function deriveIndustry(category, subCategories) {
|
|
|
2593
2987
|
}
|
|
2594
2988
|
|
|
2595
2989
|
// src/post/post.schema.ts
|
|
2596
|
-
var
|
|
2990
|
+
var import_yup23 = require("yup");
|
|
2597
2991
|
|
|
2598
2992
|
// src/post/post.constant.ts
|
|
2599
2993
|
var PostStatus = /* @__PURE__ */ ((PostStatus2) => {
|
|
@@ -2605,41 +2999,41 @@ var PostStatus = /* @__PURE__ */ ((PostStatus2) => {
|
|
|
2605
2999
|
var SupportedPostStatuses = Object.values(PostStatus);
|
|
2606
3000
|
|
|
2607
3001
|
// src/post/post.schema.ts
|
|
2608
|
-
var PostSchema = (0,
|
|
3002
|
+
var PostSchema = (0, import_yup23.object)({
|
|
2609
3003
|
/** Headline shown in listings and at the top of the post. */
|
|
2610
|
-
title: (0,
|
|
3004
|
+
title: (0, import_yup23.string)().required().min(5).max(200).label("Title"),
|
|
2611
3005
|
/** User-friendly, unique URL identifier. */
|
|
2612
|
-
slug: (0,
|
|
3006
|
+
slug: (0, import_yup23.string)().required().max(250).label("Slug"),
|
|
2613
3007
|
/** Short summary used in listings and meta description fallback. */
|
|
2614
|
-
excerpt: (0,
|
|
3008
|
+
excerpt: (0, import_yup23.string)().max(500).optional().label("Excerpt"),
|
|
2615
3009
|
/** Rendered HTML source of truth for the post body (sanitized on write/render).
|
|
2616
3010
|
* Supports rich formatting markdown can't express (image size/alignment, etc). */
|
|
2617
|
-
bodyHTML: (0,
|
|
3011
|
+
bodyHTML: (0, import_yup23.string)().required().min(1).label("Body (HTML)"),
|
|
2618
3012
|
/** Optional Markdown mirror of the body (portable text / search fallback).
|
|
2619
3013
|
* Kept for back-compat and plain-text derivation; bodyHTML is authoritative. */
|
|
2620
|
-
bodyMarkdown: (0,
|
|
3014
|
+
bodyMarkdown: (0, import_yup23.string)().optional().label("Body (Markdown)"),
|
|
2621
3015
|
/** Cover/hero image URL. Not `.url()`-validated: the value is either an
|
|
2622
3016
|
* uploaded file URL served by this platform (which may be a bare host like
|
|
2623
3017
|
* `http://localhost:3082/...` in dev, that yup's `.url()` wrongly rejects) or
|
|
2624
3018
|
* an admin-pasted link. Kept as a plain string; empty ⇒ null. */
|
|
2625
|
-
coverImage: (0,
|
|
3019
|
+
coverImage: (0, import_yup23.string)().nullable().optional().label("Cover image"),
|
|
2626
3020
|
/** Author (user id). */
|
|
2627
|
-
authorId: (0,
|
|
3021
|
+
authorId: (0, import_yup23.string)().required().label("Author ID"),
|
|
2628
3022
|
/** Free-form tags for filtering and related-posts. */
|
|
2629
|
-
tags: (0,
|
|
3023
|
+
tags: (0, import_yup23.array)().of((0, import_yup23.string)().trim().required()).default([]).label("Tags"),
|
|
2630
3024
|
/** Estimated reading time in minutes (server-derived from body length). */
|
|
2631
|
-
readingTimeMinutes: (0,
|
|
3025
|
+
readingTimeMinutes: (0, import_yup23.number)().min(0).optional().label("Reading time (minutes)"),
|
|
2632
3026
|
/** SEO overrides. */
|
|
2633
|
-
seoTags: (0,
|
|
2634
|
-
description: (0,
|
|
2635
|
-
keywords: (0,
|
|
3027
|
+
seoTags: (0, import_yup23.object)({
|
|
3028
|
+
description: (0, import_yup23.string)().optional().label("Description"),
|
|
3029
|
+
keywords: (0, import_yup23.array)().of((0, import_yup23.string)().required()).optional().label("Keywords")
|
|
2636
3030
|
}).nullable().optional().label("SEO Tags"),
|
|
2637
3031
|
/** When the post was first published (epoch ms). Server-owned. */
|
|
2638
|
-
publishedAt: (0,
|
|
3032
|
+
publishedAt: (0, import_yup23.number)().nullable().optional().label("Published at"),
|
|
2639
3033
|
/** Whether the post is featured in the blog listing. */
|
|
2640
|
-
isFeatured: (0,
|
|
3034
|
+
isFeatured: (0, import_yup23.boolean)().default(false).optional().label("Is featured"),
|
|
2641
3035
|
/** Publication state. */
|
|
2642
|
-
status: (0,
|
|
3036
|
+
status: (0, import_yup23.string)().oneOf(SupportedPostStatuses).default("draft" /* Draft */).required().label("Status")
|
|
2643
3037
|
}).concat(DbDefaultSchema).noUnknown().label("Post");
|
|
2644
3038
|
|
|
2645
3039
|
// src/geo/geo.constant.ts
|
|
@@ -2689,11 +3083,11 @@ var GEO_COLLECTIONS = {
|
|
|
2689
3083
|
var GEO_SEARCH_MAX = 64;
|
|
2690
3084
|
|
|
2691
3085
|
// src/geo/country.schema.ts
|
|
2692
|
-
var
|
|
2693
|
-
var CountrySchema = (0,
|
|
3086
|
+
var import_yup24 = require("yup");
|
|
3087
|
+
var CountrySchema = (0, import_yup24.object)({
|
|
2694
3088
|
/** The upstream dr5hn id. Stable, and the key every upsert matches on. */
|
|
2695
|
-
id: (0,
|
|
2696
|
-
name: (0,
|
|
3089
|
+
id: (0, import_yup24.number)().integer().required().label("ID"),
|
|
3090
|
+
name: (0, import_yup24.string)().trim().required().label("Name"),
|
|
2697
3091
|
/**
|
|
2698
3092
|
* ISO 3166-1 alpha-2, UPPERCASE (`IN`, `SE`).
|
|
2699
3093
|
*
|
|
@@ -2702,34 +3096,34 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2702
3096
|
* already clean uppercase alpha-2. A lowercase value here would compare
|
|
2703
3097
|
* unequal to all of them and silently match nothing.
|
|
2704
3098
|
*/
|
|
2705
|
-
countryCode: (0,
|
|
2706
|
-
iso3: (0,
|
|
2707
|
-
numericCode: (0,
|
|
2708
|
-
phonecode: (0,
|
|
2709
|
-
capital: (0,
|
|
2710
|
-
currency: (0,
|
|
2711
|
-
currencyName: (0,
|
|
2712
|
-
currencySymbol: (0,
|
|
2713
|
-
tld: (0,
|
|
3099
|
+
countryCode: (0, import_yup24.string)().trim().uppercase().length(2).required().label("Country Code"),
|
|
3100
|
+
iso3: (0, import_yup24.string)().trim().uppercase().length(3).optional().nullable().label("ISO3"),
|
|
3101
|
+
numericCode: (0, import_yup24.string)().trim().optional().nullable().label("Numeric Code"),
|
|
3102
|
+
phonecode: (0, import_yup24.string)().trim().optional().nullable().label("Phone Code"),
|
|
3103
|
+
capital: (0, import_yup24.string)().trim().optional().nullable().label("Capital"),
|
|
3104
|
+
currency: (0, import_yup24.string)().trim().optional().nullable().label("Currency"),
|
|
3105
|
+
currencyName: (0, import_yup24.string)().trim().optional().nullable().label("Currency Name"),
|
|
3106
|
+
currencySymbol: (0, import_yup24.string)().trim().optional().nullable().label("Currency Symbol"),
|
|
3107
|
+
tld: (0, import_yup24.string)().trim().optional().nullable().label("TLD"),
|
|
2714
3108
|
/** The name in its own script, e.g. "भारत". Stored, but NOT searchable; see `searchByLocale`. */
|
|
2715
|
-
native: (0,
|
|
2716
|
-
population: (0,
|
|
2717
|
-
gdp: (0,
|
|
2718
|
-
region: (0,
|
|
2719
|
-
regionId: (0,
|
|
2720
|
-
subregion: (0,
|
|
2721
|
-
subregionId: (0,
|
|
2722
|
-
nationality: (0,
|
|
2723
|
-
areaSqKm: (0,
|
|
2724
|
-
postalCodeFormat: (0,
|
|
2725
|
-
postalCodeRegex: (0,
|
|
2726
|
-
timezones: (0,
|
|
2727
|
-
(0,
|
|
2728
|
-
zoneName: (0,
|
|
2729
|
-
gmtOffset: (0,
|
|
2730
|
-
gmtOffsetName: (0,
|
|
2731
|
-
abbreviation: (0,
|
|
2732
|
-
tzName: (0,
|
|
3109
|
+
native: (0, import_yup24.string)().trim().optional().nullable().label("Native Name"),
|
|
3110
|
+
population: (0, import_yup24.number)().optional().nullable().label("Population"),
|
|
3111
|
+
gdp: (0, import_yup24.number)().optional().nullable().label("GDP"),
|
|
3112
|
+
region: (0, import_yup24.string)().trim().optional().nullable().label("Region"),
|
|
3113
|
+
regionId: (0, import_yup24.number)().integer().optional().nullable().label("Region ID"),
|
|
3114
|
+
subregion: (0, import_yup24.string)().trim().optional().nullable().label("Subregion"),
|
|
3115
|
+
subregionId: (0, import_yup24.number)().integer().optional().nullable().label("Subregion ID"),
|
|
3116
|
+
nationality: (0, import_yup24.string)().trim().optional().nullable().label("Nationality"),
|
|
3117
|
+
areaSqKm: (0, import_yup24.number)().optional().nullable().label("Area (sq km)"),
|
|
3118
|
+
postalCodeFormat: (0, import_yup24.string)().trim().optional().nullable().label("Postal Code Format"),
|
|
3119
|
+
postalCodeRegex: (0, import_yup24.string)().optional().nullable().label("Postal Code Regex"),
|
|
3120
|
+
timezones: (0, import_yup24.array)().of(
|
|
3121
|
+
(0, import_yup24.object)({
|
|
3122
|
+
zoneName: (0, import_yup24.string)().optional().nullable().label("Zone Name"),
|
|
3123
|
+
gmtOffset: (0, import_yup24.number)().optional().nullable().label("GMT Offset"),
|
|
3124
|
+
gmtOffsetName: (0, import_yup24.string)().optional().nullable().label("GMT Offset Name"),
|
|
3125
|
+
abbreviation: (0, import_yup24.string)().optional().nullable().label("Abbreviation"),
|
|
3126
|
+
tzName: (0, import_yup24.string)().optional().nullable().label("TZ Name")
|
|
2733
3127
|
})
|
|
2734
3128
|
).optional().nullable().label("Timezones"),
|
|
2735
3129
|
/**
|
|
@@ -2738,7 +3132,7 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2738
3132
|
* declaring it here would turn a new locale into a validation failure. The
|
|
2739
3133
|
* VALUES are split per-locale into `searchByLocale`.
|
|
2740
3134
|
*/
|
|
2741
|
-
translations: (0,
|
|
3135
|
+
translations: (0, import_yup24.object)().optional().nullable().label("Translations"),
|
|
2742
3136
|
/**
|
|
2743
3137
|
* Coordinates as NUMBERS.
|
|
2744
3138
|
*
|
|
@@ -2747,10 +3141,10 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2747
3141
|
* `"9" > "10"` is true, so a bounding-box filter would be quietly wrong rather
|
|
2748
3142
|
* than failing loudly.
|
|
2749
3143
|
*/
|
|
2750
|
-
latitude: (0,
|
|
2751
|
-
longitude: (0,
|
|
2752
|
-
emoji: (0,
|
|
2753
|
-
emojiU: (0,
|
|
3144
|
+
latitude: (0, import_yup24.number)().optional().nullable().label("Latitude"),
|
|
3145
|
+
longitude: (0, import_yup24.number)().optional().nullable().label("Longitude"),
|
|
3146
|
+
emoji: (0, import_yup24.string)().optional().nullable().label("Emoji"),
|
|
3147
|
+
emojiU: (0, import_yup24.string)().optional().nullable().label("Emoji Unicode"),
|
|
2754
3148
|
/**
|
|
2755
3149
|
* The name field searched for the DEFAULT (English) locale: the canonical
|
|
2756
3150
|
* `name`, and nothing else.
|
|
@@ -2760,7 +3154,7 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2760
3154
|
* field would make every locale's search implicitly a search of all 19
|
|
2761
3155
|
* languages: a French UI searching "Inde" would also match German "Indien".
|
|
2762
3156
|
*/
|
|
2763
|
-
searchDefault: (0,
|
|
3157
|
+
searchDefault: (0, import_yup24.array)().of((0, import_yup24.string)().required()).optional().default([]).label("Search Default"),
|
|
2764
3158
|
/**
|
|
2765
3159
|
* Per-locale name fields, keyed by lowercased BCP-47 tag (`de`, `pt-br`).
|
|
2766
3160
|
* Each carries ONLY that locale's translation, which is what makes
|
|
@@ -2778,21 +3172,21 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2778
3172
|
* it, zh-CN, tr, ru, uk, pl, hi, ar. **`sv` is absent**, so a Swedish search
|
|
2779
3173
|
* matches nothing. That is the accepted cost of strict scoping.
|
|
2780
3174
|
*/
|
|
2781
|
-
searchByLocale: (0,
|
|
3175
|
+
searchByLocale: (0, import_yup24.object)().optional().nullable().label("Search By Locale"),
|
|
2782
3176
|
/** Epoch ms of the run that last wrote this row. Drives the stale-row prune. */
|
|
2783
|
-
syncedAt: (0,
|
|
3177
|
+
syncedAt: (0, import_yup24.number)().optional().nullable().label("Synced At")
|
|
2784
3178
|
}).label("Country");
|
|
2785
3179
|
|
|
2786
3180
|
// src/geo/state.schema.ts
|
|
2787
|
-
var
|
|
2788
|
-
var StateSchema = (0,
|
|
3181
|
+
var import_yup25 = require("yup");
|
|
3182
|
+
var StateSchema = (0, import_yup25.object)({
|
|
2789
3183
|
/** The upstream dr5hn id. Stable, and the key every upsert matches on. */
|
|
2790
|
-
id: (0,
|
|
2791
|
-
name: (0,
|
|
2792
|
-
countryId: (0,
|
|
3184
|
+
id: (0, import_yup25.number)().integer().required().label("ID"),
|
|
3185
|
+
name: (0, import_yup25.string)().trim().required().label("Name"),
|
|
3186
|
+
countryId: (0, import_yup25.number)().integer().optional().nullable().label("Country ID"),
|
|
2793
3187
|
/** ISO 3166-1 alpha-2 of the parent, UPPERCASE. See `CountrySchema.countryCode`. */
|
|
2794
|
-
countryCode: (0,
|
|
2795
|
-
countryName: (0,
|
|
3188
|
+
countryCode: (0, import_yup25.string)().trim().uppercase().length(2).required().label("Country Code"),
|
|
3189
|
+
countryName: (0, import_yup25.string)().trim().optional().nullable().label("Country Name"),
|
|
2796
3190
|
/**
|
|
2797
3191
|
* The BARE subdivision code, e.g. `KA` (upstream `iso2`).
|
|
2798
3192
|
*
|
|
@@ -2804,22 +3198,22 @@ var StateSchema = (0, import_yup24.object)({
|
|
|
2804
3198
|
* both are stored so the migration has its destination present before any
|
|
2805
3199
|
* consumer moves.
|
|
2806
3200
|
*/
|
|
2807
|
-
stateCode: (0,
|
|
3201
|
+
stateCode: (0, import_yup25.string)().trim().uppercase().optional().nullable().label("State Code"),
|
|
2808
3202
|
/** Fully-qualified ISO 3166-2, e.g. `IN-KA` (upstream `iso3166_2`). */
|
|
2809
|
-
stateCodeIso: (0,
|
|
2810
|
-
fipsCode: (0,
|
|
3203
|
+
stateCodeIso: (0, import_yup25.string)().trim().uppercase().optional().nullable().label("ISO 3166-2 Code"),
|
|
3204
|
+
fipsCode: (0, import_yup25.string)().trim().optional().nullable().label("FIPS Code"),
|
|
2811
3205
|
/** Upstream's own word for the subdivision: "province", "state", "district", … */
|
|
2812
|
-
type: (0,
|
|
2813
|
-
level: (0,
|
|
2814
|
-
parentId: (0,
|
|
3206
|
+
type: (0, import_yup25.string)().trim().optional().nullable().label("Type"),
|
|
3207
|
+
level: (0, import_yup25.number)().integer().optional().nullable().label("Level"),
|
|
3208
|
+
parentId: (0, import_yup25.number)().integer().optional().nullable().label("Parent ID"),
|
|
2815
3209
|
/** The name in its own script. Stored, but NOT searchable; see `searchByLocale`. */
|
|
2816
|
-
native: (0,
|
|
3210
|
+
native: (0, import_yup25.string)().trim().optional().nullable().label("Native Name"),
|
|
2817
3211
|
/** Numbers, not the strings upstream ships. See `CountrySchema.latitude`. */
|
|
2818
|
-
latitude: (0,
|
|
2819
|
-
longitude: (0,
|
|
2820
|
-
timezone: (0,
|
|
3212
|
+
latitude: (0, import_yup25.number)().optional().nullable().label("Latitude"),
|
|
3213
|
+
longitude: (0, import_yup25.number)().optional().nullable().label("Longitude"),
|
|
3214
|
+
timezone: (0, import_yup25.string)().trim().optional().nullable().label("Timezone"),
|
|
2821
3215
|
/** Localized names keyed by locale. Unshaped; see `CountrySchema.translations`. */
|
|
2822
|
-
translations: (0,
|
|
3216
|
+
translations: (0, import_yup25.object)().optional().nullable().label("Translations"),
|
|
2823
3217
|
/**
|
|
2824
3218
|
* The name field searched for the DEFAULT (English) locale: the canonical
|
|
2825
3219
|
* `name`, and nothing else.
|
|
@@ -2829,7 +3223,7 @@ var StateSchema = (0, import_yup24.object)({
|
|
|
2829
3223
|
* field would make every locale's search implicitly a search of all 19
|
|
2830
3224
|
* languages: a French UI searching "Inde" would also match German "Indien".
|
|
2831
3225
|
*/
|
|
2832
|
-
searchDefault: (0,
|
|
3226
|
+
searchDefault: (0, import_yup25.array)().of((0, import_yup25.string)().required()).optional().default([]).label("Search Default"),
|
|
2833
3227
|
/**
|
|
2834
3228
|
* Per-locale name fields, keyed by lowercased BCP-47 tag (`de`, `pt-br`).
|
|
2835
3229
|
* Each carries ONLY that locale's translation, which is what makes
|
|
@@ -2847,20 +3241,20 @@ var StateSchema = (0, import_yup24.object)({
|
|
|
2847
3241
|
* it, zh-CN, tr, ru, uk, pl, hi, ar. **`sv` is absent**, so a Swedish search
|
|
2848
3242
|
* matches nothing. That is the accepted cost of strict scoping.
|
|
2849
3243
|
*/
|
|
2850
|
-
searchByLocale: (0,
|
|
3244
|
+
searchByLocale: (0, import_yup25.object)().optional().nullable().label("Search By Locale"),
|
|
2851
3245
|
/** Epoch ms of the run that last wrote this row. Drives the stale-row prune. */
|
|
2852
|
-
syncedAt: (0,
|
|
3246
|
+
syncedAt: (0, import_yup25.number)().optional().nullable().label("Synced At")
|
|
2853
3247
|
}).label("State");
|
|
2854
3248
|
|
|
2855
3249
|
// src/geo/city.schema.ts
|
|
2856
|
-
var
|
|
2857
|
-
var CitySchema = (0,
|
|
3250
|
+
var import_yup26 = require("yup");
|
|
3251
|
+
var CitySchema = (0, import_yup26.object)({
|
|
2858
3252
|
/** The upstream dr5hn id. Stable, and the key every upsert matches on. */
|
|
2859
|
-
id: (0,
|
|
2860
|
-
name: (0,
|
|
2861
|
-
stateId: (0,
|
|
3253
|
+
id: (0, import_yup26.number)().integer().required().label("ID"),
|
|
3254
|
+
name: (0, import_yup26.string)().trim().required().label("Name"),
|
|
3255
|
+
stateId: (0, import_yup26.number)().integer().optional().nullable().label("State ID"),
|
|
2862
3256
|
/** The BARE subdivision code. Only meaningful paired with `countryCode`; see `StateSchema`. */
|
|
2863
|
-
stateCode: (0,
|
|
3257
|
+
stateCode: (0, import_yup26.string)().trim().uppercase().optional().nullable().label("State Code"),
|
|
2864
3258
|
/**
|
|
2865
3259
|
* Fully-qualified ISO 3166-2, e.g. `IN-KA`.
|
|
2866
3260
|
*
|
|
@@ -2870,29 +3264,29 @@ var CitySchema = (0, import_yup25.object)({
|
|
|
2870
3264
|
* migration can re-point the cities route without a 153k-row re-ingest.
|
|
2871
3265
|
* Null when either half is missing.
|
|
2872
3266
|
*/
|
|
2873
|
-
stateCodeIso: (0,
|
|
2874
|
-
stateName: (0,
|
|
2875
|
-
countryId: (0,
|
|
3267
|
+
stateCodeIso: (0, import_yup26.string)().trim().uppercase().optional().nullable().label("ISO 3166-2 Code"),
|
|
3268
|
+
stateName: (0, import_yup26.string)().trim().optional().nullable().label("State Name"),
|
|
3269
|
+
countryId: (0, import_yup26.number)().integer().optional().nullable().label("Country ID"),
|
|
2876
3270
|
/** ISO 3166-1 alpha-2 of the parent, UPPERCASE. See `CountrySchema.countryCode`. */
|
|
2877
|
-
countryCode: (0,
|
|
2878
|
-
countryName: (0,
|
|
3271
|
+
countryCode: (0, import_yup26.string)().trim().uppercase().length(2).required().label("Country Code"),
|
|
3272
|
+
countryName: (0, import_yup26.string)().trim().optional().nullable().label("Country Name"),
|
|
2879
3273
|
/** Numbers, not the strings upstream ships. See `CountrySchema.latitude`. */
|
|
2880
|
-
latitude: (0,
|
|
2881
|
-
longitude: (0,
|
|
3274
|
+
latitude: (0, import_yup26.number)().optional().nullable().label("Latitude"),
|
|
3275
|
+
longitude: (0, import_yup26.number)().optional().nullable().label("Longitude"),
|
|
2882
3276
|
/** The name in its own script. Stored, but NOT searchable; see `searchByLocale`. */
|
|
2883
|
-
native: (0,
|
|
2884
|
-
type: (0,
|
|
2885
|
-
level: (0,
|
|
2886
|
-
parentId: (0,
|
|
3277
|
+
native: (0, import_yup26.string)().trim().optional().nullable().label("Native Name"),
|
|
3278
|
+
type: (0, import_yup26.string)().trim().optional().nullable().label("Type"),
|
|
3279
|
+
level: (0, import_yup26.number)().integer().optional().nullable().label("Level"),
|
|
3280
|
+
parentId: (0, import_yup26.number)().integer().optional().nullable().label("Parent ID"),
|
|
2887
3281
|
/**
|
|
2888
3282
|
* Null on most rows. Worth keeping (it is a good relevance signal when
|
|
2889
3283
|
* present) but never worth SORTING by alone, since a null-heavy sort buries
|
|
2890
3284
|
* every city upstream has no figure for.
|
|
2891
3285
|
*/
|
|
2892
|
-
population: (0,
|
|
2893
|
-
timezone: (0,
|
|
3286
|
+
population: (0, import_yup26.number)().optional().nullable().label("Population"),
|
|
3287
|
+
timezone: (0, import_yup26.string)().trim().optional().nullable().label("Timezone"),
|
|
2894
3288
|
/** Localized names keyed by locale. Unshaped; see `CountrySchema.translations`. */
|
|
2895
|
-
translations: (0,
|
|
3289
|
+
translations: (0, import_yup26.object)().optional().nullable().label("Translations"),
|
|
2896
3290
|
/**
|
|
2897
3291
|
* The name field searched for the DEFAULT (English) locale: the canonical
|
|
2898
3292
|
* `name`, and nothing else.
|
|
@@ -2902,7 +3296,7 @@ var CitySchema = (0, import_yup25.object)({
|
|
|
2902
3296
|
* field would make every locale's search implicitly a search of all 19
|
|
2903
3297
|
* languages: a French UI searching "Inde" would also match German "Indien".
|
|
2904
3298
|
*/
|
|
2905
|
-
searchDefault: (0,
|
|
3299
|
+
searchDefault: (0, import_yup26.array)().of((0, import_yup26.string)().required()).optional().default([]).label("Search Default"),
|
|
2906
3300
|
/**
|
|
2907
3301
|
* Per-locale name fields, keyed by lowercased BCP-47 tag (`de`, `pt-br`).
|
|
2908
3302
|
* Each carries ONLY that locale's translation, which is what makes
|
|
@@ -2920,14 +3314,14 @@ var CitySchema = (0, import_yup25.object)({
|
|
|
2920
3314
|
* it, zh-CN, tr, ru, uk, pl, hi, ar. **`sv` is absent**, so a Swedish search
|
|
2921
3315
|
* matches nothing. That is the accepted cost of strict scoping.
|
|
2922
3316
|
*/
|
|
2923
|
-
searchByLocale: (0,
|
|
3317
|
+
searchByLocale: (0, import_yup26.object)().optional().nullable().label("Search By Locale"),
|
|
2924
3318
|
/** Epoch ms of the run that last wrote this row. Drives the stale-row prune. */
|
|
2925
|
-
syncedAt: (0,
|
|
3319
|
+
syncedAt: (0, import_yup26.number)().optional().nullable().label("Synced At")
|
|
2926
3320
|
}).label("City");
|
|
2927
3321
|
|
|
2928
3322
|
// src/geo/country-filter.schema.ts
|
|
2929
|
-
var
|
|
2930
|
-
var CountryFilterShape = (0,
|
|
3323
|
+
var import_yup27 = require("yup");
|
|
3324
|
+
var CountryFilterShape = (0, import_yup27.object)({
|
|
2931
3325
|
/** ISO 3166-1 alpha-2 codes, e.g. `IN`. Uppercased, matching how they are stored. */
|
|
2932
3326
|
countryCodes: codeTokens("Country Codes"),
|
|
2933
3327
|
/** ISO 3166-1 alpha-3 codes, e.g. `IND`. */
|
|
@@ -2947,8 +3341,8 @@ var CountryFilterSchema = rejectUnknownKeys(
|
|
|
2947
3341
|
);
|
|
2948
3342
|
|
|
2949
3343
|
// src/geo/state-filter.schema.ts
|
|
2950
|
-
var
|
|
2951
|
-
var StateFilterShape = (0,
|
|
3344
|
+
var import_yup28 = require("yup");
|
|
3345
|
+
var StateFilterShape = (0, import_yup28.object)({
|
|
2952
3346
|
/** ISO 3166-1 alpha-2 of the parent country, e.g. `IN`. */
|
|
2953
3347
|
countryCodes: codeTokens("Country Codes"),
|
|
2954
3348
|
/**
|
|
@@ -2978,8 +3372,8 @@ var StateFilterSchema = rejectUnknownKeys(
|
|
|
2978
3372
|
);
|
|
2979
3373
|
|
|
2980
3374
|
// src/geo/city-filter.schema.ts
|
|
2981
|
-
var
|
|
2982
|
-
var CityFilterShape = (0,
|
|
3375
|
+
var import_yup29 = require("yup");
|
|
3376
|
+
var CityFilterShape = (0, import_yup29.object)({
|
|
2983
3377
|
/** ISO 3166-1 alpha-2 of the parent country, e.g. `IN`. */
|
|
2984
3378
|
countryCodes: codeTokens("Country Codes"),
|
|
2985
3379
|
/**
|
|
@@ -2996,28 +3390,28 @@ var CityFilterSchema = rejectUnknownKeys(
|
|
|
2996
3390
|
);
|
|
2997
3391
|
|
|
2998
3392
|
// src/geo/geo-sync.schema.ts
|
|
2999
|
-
var
|
|
3000
|
-
var GeoSyncCountsSchema = (0,
|
|
3001
|
-
read: (0,
|
|
3002
|
-
upserted: (0,
|
|
3003
|
-
modified: (0,
|
|
3004
|
-
matched: (0,
|
|
3393
|
+
var import_yup30 = require("yup");
|
|
3394
|
+
var GeoSyncCountsSchema = (0, import_yup30.object)({
|
|
3395
|
+
read: (0, import_yup30.number)().integer().min(0).default(0).label("Read"),
|
|
3396
|
+
upserted: (0, import_yup30.number)().integer().min(0).default(0).label("Upserted"),
|
|
3397
|
+
modified: (0, import_yup30.number)().integer().min(0).default(0).label("Modified"),
|
|
3398
|
+
matched: (0, import_yup30.number)().integer().min(0).default(0).label("Matched"),
|
|
3005
3399
|
/** Rows removed because upstream dropped them. See `prunedSkipped`. */
|
|
3006
|
-
pruned: (0,
|
|
3400
|
+
pruned: (0, import_yup30.number)().integer().min(0).default(0).label("Pruned"),
|
|
3007
3401
|
/**
|
|
3008
3402
|
* True when the stale-row prune was REFUSED because it would have removed more
|
|
3009
3403
|
* than its safety threshold of the collection. A partial fetch that looked
|
|
3010
3404
|
* like a success must not be able to empty the table, so the run reports the
|
|
3011
3405
|
* refusal rather than acting on it.
|
|
3012
3406
|
*/
|
|
3013
|
-
prunedSkipped: (0,
|
|
3407
|
+
prunedSkipped: (0, import_yup30.boolean)().default(false).label("Prune Skipped")
|
|
3014
3408
|
}).label("Sync Counts");
|
|
3015
|
-
var GeoSyncRunSchema = (0,
|
|
3016
|
-
jobId: (0,
|
|
3017
|
-
status: (0,
|
|
3018
|
-
trigger: (0,
|
|
3409
|
+
var GeoSyncRunSchema = (0, import_yup30.object)({
|
|
3410
|
+
jobId: (0, import_yup30.string)().required().label("Job ID"),
|
|
3411
|
+
status: (0, import_yup30.mixed)().oneOf(SupportedGeoSyncStatuses).required().label("Status"),
|
|
3412
|
+
trigger: (0, import_yup30.mixed)().oneOf(SupportedGeoSyncTriggers).optional().label("Trigger"),
|
|
3019
3413
|
/** Whether the caller asked to run even though the release tag was unchanged. */
|
|
3020
|
-
force: (0,
|
|
3414
|
+
force: (0, import_yup30.boolean)().default(false).label("Force"),
|
|
3021
3415
|
/**
|
|
3022
3416
|
* The upstream release tag this run fetched, e.g. `v3.2-export.7`.
|
|
3023
3417
|
*
|
|
@@ -3025,13 +3419,13 @@ var GeoSyncRunSchema = (0, import_yup29.object)({
|
|
|
3025
3419
|
* cannot tell what version it is fetching is otherwise a failure, not a
|
|
3026
3420
|
* refresh, so it is not allowed to proceed unattended.
|
|
3027
3421
|
*/
|
|
3028
|
-
releaseTag: (0,
|
|
3422
|
+
releaseTag: (0, import_yup30.string)().optional().nullable().label("Release Tag"),
|
|
3029
3423
|
/** The tag of the last successful run, i.e. what this one is replacing. */
|
|
3030
|
-
previousReleaseTag: (0,
|
|
3031
|
-
startedAt: (0,
|
|
3032
|
-
finishedAt: (0,
|
|
3033
|
-
durationMs: (0,
|
|
3034
|
-
phase: (0,
|
|
3424
|
+
previousReleaseTag: (0, import_yup30.string)().optional().nullable().label("Previous Release Tag"),
|
|
3425
|
+
startedAt: (0, import_yup30.number)().required().label("Started At"),
|
|
3426
|
+
finishedAt: (0, import_yup30.number)().optional().nullable().label("Finished At"),
|
|
3427
|
+
durationMs: (0, import_yup30.number)().optional().nullable().label("Duration (ms)"),
|
|
3428
|
+
phase: (0, import_yup30.mixed)().oneOf(SupportedGeoSyncPhases).optional().nullable().label("Phase"),
|
|
3035
3429
|
/**
|
|
3036
3430
|
* Live progress for the dashboard bar.
|
|
3037
3431
|
*
|
|
@@ -3039,25 +3433,25 @@ var GeoSyncRunSchema = (0, import_yup29.object)({
|
|
|
3039
3433
|
* collection, or a hardcoded fallback on the very first run, since the true
|
|
3040
3434
|
* total is not known until the stream ends. The UI should render it as one.
|
|
3041
3435
|
*/
|
|
3042
|
-
progress: (0,
|
|
3043
|
-
collection: (0,
|
|
3044
|
-
processed: (0,
|
|
3045
|
-
total: (0,
|
|
3436
|
+
progress: (0, import_yup30.object)({
|
|
3437
|
+
collection: (0, import_yup30.string)().optional().nullable().label("Collection"),
|
|
3438
|
+
processed: (0, import_yup30.number)().integer().min(0).default(0).label("Processed"),
|
|
3439
|
+
total: (0, import_yup30.number)().integer().min(0).optional().nullable().label("Total")
|
|
3046
3440
|
}).optional().nullable().label("Progress"),
|
|
3047
|
-
counts: (0,
|
|
3441
|
+
counts: (0, import_yup30.object)({
|
|
3048
3442
|
countries: GeoSyncCountsSchema.optional().nullable().label("Countries"),
|
|
3049
3443
|
states: GeoSyncCountsSchema.optional().nullable().label("States"),
|
|
3050
3444
|
cities: GeoSyncCountsSchema.optional().nullable().label("Cities")
|
|
3051
3445
|
}).optional().nullable().label("Counts"),
|
|
3052
3446
|
/** Why a `skipped` run was skipped, in words the dashboard can show verbatim. */
|
|
3053
|
-
reason: (0,
|
|
3447
|
+
reason: (0, import_yup30.string)().optional().nullable().label("Reason"),
|
|
3054
3448
|
/** The failure message on a `failed` run. Surfaced verbatim to the admin. */
|
|
3055
|
-
error: (0,
|
|
3449
|
+
error: (0, import_yup30.string)().optional().nullable().label("Error")
|
|
3056
3450
|
}).label("Geo Sync Run");
|
|
3057
3451
|
|
|
3058
3452
|
// src/language/language-filter.schema.ts
|
|
3059
|
-
var
|
|
3060
|
-
var LanguageFilterShape = (0,
|
|
3453
|
+
var import_yup31 = require("yup");
|
|
3454
|
+
var LanguageFilterShape = (0, import_yup31.object)({
|
|
3061
3455
|
/** Language names, matched exactly. Free-text matching is `?search=`. */
|
|
3062
3456
|
names: tokens("Names")
|
|
3063
3457
|
}).label("Language Filter");
|
|
@@ -3067,8 +3461,8 @@ var LanguageFilterSchema = rejectUnknownKeys(
|
|
|
3067
3461
|
);
|
|
3068
3462
|
|
|
3069
3463
|
// src/page/page-filter.schema.ts
|
|
3070
|
-
var
|
|
3071
|
-
var PageFilterShape = (0,
|
|
3464
|
+
var import_yup32 = require("yup");
|
|
3465
|
+
var PageFilterShape = (0, import_yup32.object)({
|
|
3072
3466
|
/**
|
|
3073
3467
|
* `type`, NOT `pageType`.
|
|
3074
3468
|
*
|
|
@@ -3088,7 +3482,7 @@ var PageFilterShape = (0, import_yup31.object)({
|
|
|
3088
3482
|
// No `.default(false)`: absent means no constraint. Note `isFeatured` is
|
|
3089
3483
|
// present on only 55 documents, so combining it with `status: ['published']`
|
|
3090
3484
|
// leaves 11 pages — a legitimate filter that returns almost nothing.
|
|
3091
|
-
isFeatured: (0,
|
|
3485
|
+
isFeatured: (0, import_yup32.boolean)().optional().label("Featured Only"),
|
|
3092
3486
|
/** Lowercase (`in`, `se`, `ww`), like groups. See `GroupFilterSchema`. */
|
|
3093
3487
|
featuredMarkets: tokens("Featured Markets"),
|
|
3094
3488
|
/** Page SLUGS. A company is matched by slug: a display name breaks on rename. */
|
|
@@ -3101,7 +3495,7 @@ var PageFilterSchema = rejectUnknownKeys(
|
|
|
3101
3495
|
);
|
|
3102
3496
|
|
|
3103
3497
|
// src/marketing/marketing.schema.ts
|
|
3104
|
-
var
|
|
3498
|
+
var import_yup34 = require("yup");
|
|
3105
3499
|
|
|
3106
3500
|
// src/marketing/marketing.constant.ts
|
|
3107
3501
|
var CampaignStatus = /* @__PURE__ */ ((CampaignStatus2) => {
|
|
@@ -3178,8 +3572,8 @@ var SupportedOccurrenceStatuses = Object.values(OccurrenceStatus);
|
|
|
3178
3572
|
var CAMPAIGN_MAX_RECIPIENTS_CEILING = 5e3;
|
|
3179
3573
|
|
|
3180
3574
|
// src/user/user-filter.schema.ts
|
|
3181
|
-
var
|
|
3182
|
-
var UserFilterBranchShape = (0,
|
|
3575
|
+
var import_yup33 = require("yup");
|
|
3576
|
+
var UserFilterBranchShape = (0, import_yup33.object)({
|
|
3183
3577
|
/**
|
|
3184
3578
|
* Exact email addresses. An IDENTITY lookup, not a search.
|
|
3185
3579
|
*
|
|
@@ -3199,7 +3593,7 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3199
3593
|
* the input keeps the match an indexed equality instead of a regex that would
|
|
3200
3594
|
* put the scan straight back.
|
|
3201
3595
|
*/
|
|
3202
|
-
emails: (0,
|
|
3596
|
+
emails: (0, import_yup33.array)().of((0, import_yup33.string)().required()).optional().default([]).label("Email Addresses"),
|
|
3203
3597
|
/**
|
|
3204
3598
|
* Better Auth account ids. An IDENTITY lookup like `emails`, and for the same
|
|
3205
3599
|
* reason: the caller already knows the exact value.
|
|
@@ -3218,9 +3612,9 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3218
3612
|
* The admin filter panel builds its controls explicitly rather than from this
|
|
3219
3613
|
* shape, so declaring it here does not put an account-id box in the UI.
|
|
3220
3614
|
*/
|
|
3221
|
-
authAccountIds: (0,
|
|
3615
|
+
authAccountIds: (0, import_yup33.array)().of((0, import_yup33.string)().required()).optional().default([]).label("Auth Account IDs"),
|
|
3222
3616
|
// ── Enum facets (closed vocabularies, chip pickers) ─────────────────────────
|
|
3223
|
-
countries: (0,
|
|
3617
|
+
countries: (0, import_yup33.array)().of((0, import_yup33.string)().required()).optional().default([]).label("Countries"),
|
|
3224
3618
|
roles: enumFacet(SupportedUserRoles, "Roles"),
|
|
3225
3619
|
// The user's own current seniority (UserSchema.experienceLevel).
|
|
3226
3620
|
experienceLevels: enumFacet(SupportedExperienceLevels, "Experience Levels"),
|
|
@@ -3353,12 +3747,12 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3353
3747
|
// it, so the dependency is stated rather than assumed.
|
|
3354
3748
|
minSalaryFloor: currencyBound("Min Salary \u2265", "salaryCurrencies"),
|
|
3355
3749
|
minSalaryCeil: currencyBound("Min Salary \u2264", "salaryCurrencies"),
|
|
3356
|
-
openToWorkOnly: (0,
|
|
3357
|
-
remoteExperienceOnly: (0,
|
|
3358
|
-
hasResumeOnly: (0,
|
|
3359
|
-
onboardingCompletedOnly: (0,
|
|
3360
|
-
emailVerifiedOnly: (0,
|
|
3361
|
-
mobileVerifiedOnly: (0,
|
|
3750
|
+
openToWorkOnly: (0, import_yup33.boolean)().optional().default(false).label("Open to Work Only"),
|
|
3751
|
+
remoteExperienceOnly: (0, import_yup33.boolean)().optional().default(false).label("Has Remote Experience"),
|
|
3752
|
+
hasResumeOnly: (0, import_yup33.boolean)().optional().default(false).label("Has Resume"),
|
|
3753
|
+
onboardingCompletedOnly: (0, import_yup33.boolean)().optional().default(false).label("Onboarding Completed"),
|
|
3754
|
+
emailVerifiedOnly: (0, import_yup33.boolean)().optional().default(false).label("Email Verified Only"),
|
|
3755
|
+
mobileVerifiedOnly: (0, import_yup33.boolean)().optional().default(false).label("Mobile Verified Only"),
|
|
3362
3756
|
// ── Lifecycle windows ───────────────────────────────────────────────────────
|
|
3363
3757
|
// Relative, because a saved list is resolved fresh on every send: a stored
|
|
3364
3758
|
// absolute epoch would freeze at authoring time and the audience would decay
|
|
@@ -3386,10 +3780,10 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3386
3780
|
// Radius search around a point, against location.geo. All three required
|
|
3387
3781
|
// together; validated as a group rather than field-by-field so a half-filled
|
|
3388
3782
|
// radius cannot silently match everyone.
|
|
3389
|
-
withinRadius: (0,
|
|
3390
|
-
lat: (0,
|
|
3391
|
-
lng: (0,
|
|
3392
|
-
km: (0,
|
|
3783
|
+
withinRadius: (0, import_yup33.object)({
|
|
3784
|
+
lat: (0, import_yup33.number)().min(-90).max(90).required().label("Latitude"),
|
|
3785
|
+
lng: (0, import_yup33.number)().min(-180).max(180).required().label("Longitude"),
|
|
3786
|
+
km: (0, import_yup33.number)().moreThan(0).max(2e4).required().label("Radius (km)")
|
|
3393
3787
|
}).optional().default(void 0).label("Within Radius"),
|
|
3394
3788
|
// ── Signup context (immutable market / locale) ──────────────────────────────
|
|
3395
3789
|
signupCountries: tokens("Signup Countries"),
|
|
@@ -3412,7 +3806,7 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3412
3806
|
// materialise the second case on every list that never chose it.
|
|
3413
3807
|
//
|
|
3414
3808
|
// @todo CONSENT-FILTER-ENFORCEMENT — nothing enforces consent anywhere now.
|
|
3415
|
-
marketingSubscribed: (0,
|
|
3809
|
+
marketingSubscribed: (0, import_yup33.boolean)().optional().label("Marketing Subscribed"),
|
|
3416
3810
|
jobAlertFrequencies: enumFacet(
|
|
3417
3811
|
SupportedJobAlertFrequencies,
|
|
3418
3812
|
"Job Alert Frequency"
|
|
@@ -3433,7 +3827,7 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3433
3827
|
),
|
|
3434
3828
|
// ── Tenure / recency ────────────────────────────────────────────────────────
|
|
3435
3829
|
// Against workExperiences[].duration and educations[].duration ("YYYY-MM").
|
|
3436
|
-
currentlyEmployed: (0,
|
|
3830
|
+
currentlyEmployed: (0, import_yup33.boolean)().optional().default(false).label("Currently Employed"),
|
|
3437
3831
|
graduatedWithinMonths: months("Graduated Within (months)"),
|
|
3438
3832
|
skillUsedWithinMonths: months("Skill Used Within (months)"),
|
|
3439
3833
|
// The ABSOLUTE bounds the three relative windows above resolve into
|
|
@@ -3446,13 +3840,13 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3446
3840
|
// meaning that forever, while "within 18 months" keeps meaning what the admin
|
|
3447
3841
|
// intended. They are declared because the vocabulary must be complete, not
|
|
3448
3842
|
// because a list should store one.
|
|
3449
|
-
graduatedAfter: (0,
|
|
3450
|
-
skillUsedAfter: (0,
|
|
3843
|
+
graduatedAfter: (0, import_yup33.string)().trim().optional().label("Graduated After"),
|
|
3844
|
+
skillUsedAfter: (0, import_yup33.string)().trim().optional().label("Skill Used After"),
|
|
3451
3845
|
// ── Profile richness ────────────────────────────────────────────────────────
|
|
3452
|
-
hasImage: (0,
|
|
3453
|
-
hasHeadline: (0,
|
|
3454
|
-
hasAboutMe: (0,
|
|
3455
|
-
hasMobile: (0,
|
|
3846
|
+
hasImage: (0, import_yup33.boolean)().optional().default(false).label("Has Photo"),
|
|
3847
|
+
hasHeadline: (0, import_yup33.boolean)().optional().default(false).label("Has Headline"),
|
|
3848
|
+
hasAboutMe: (0, import_yup33.boolean)().optional().default(false).label("Has About Me"),
|
|
3849
|
+
hasMobile: (0, import_yup33.boolean)().optional().default(false).label("Has Mobile Number"),
|
|
3456
3850
|
// Segment by WHICH profile section is missing (profileCompleteness.missing[]),
|
|
3457
3851
|
// rather than only by the overall percentage.
|
|
3458
3852
|
missingSections: tokens("Missing Profile Sections"),
|
|
@@ -3464,8 +3858,8 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3464
3858
|
// data lives in other services' collections. Tri-state: `false` is a real
|
|
3465
3859
|
// filter ("has NO job alert"), which is the audience an alert nudge wants, so
|
|
3466
3860
|
// these are `undefined` when unset rather than defaulting to false.
|
|
3467
|
-
hasJobAlert: (0,
|
|
3468
|
-
hasApplied: (0,
|
|
3861
|
+
hasJobAlert: (0, import_yup33.boolean)().optional().default(void 0).label("Has a Job Alert"),
|
|
3862
|
+
hasApplied: (0, import_yup33.boolean)().optional().default(void 0).label("Has Applied"),
|
|
3469
3863
|
appliedWithinDays: days("Applied Within (days)")
|
|
3470
3864
|
// `search` is NOT here. It is free text over name/email, not a facet: it names
|
|
3471
3865
|
// no field on a user document, user-service treats it as a RESERVED PARAM
|
|
@@ -3478,25 +3872,25 @@ var BRANCH_KEYS = Object.keys(UserFilterBranchShape.fields);
|
|
|
3478
3872
|
var UserFilterBranch = rejectUnknownKeys(UserFilterBranchShape, () => BRANCH_KEYS);
|
|
3479
3873
|
var UserFilterSchema = rejectUnknownKeys(
|
|
3480
3874
|
UserFilterBranchShape.shape({
|
|
3481
|
-
or: (0,
|
|
3875
|
+
or: (0, import_yup33.array)().of(UserFilterBranch).optional().default([]).label("Or Any Of")
|
|
3482
3876
|
}).label("User Filter"),
|
|
3483
3877
|
() => [...BRANCH_KEYS, "or"]
|
|
3484
3878
|
);
|
|
3485
3879
|
|
|
3486
3880
|
// src/marketing/marketing.schema.ts
|
|
3487
3881
|
var MailingListFilterSchema = UserFilterSchema;
|
|
3488
|
-
var MailingListSchema = (0,
|
|
3489
|
-
name: (0,
|
|
3490
|
-
description: (0,
|
|
3882
|
+
var MailingListSchema = (0, import_yup34.object)({
|
|
3883
|
+
name: (0, import_yup34.string)().required().min(1).max(120).label("Name"),
|
|
3884
|
+
description: (0, import_yup34.string)().optional().max(500).label("Description"),
|
|
3491
3885
|
filter: MailingListFilterSchema.default(
|
|
3492
3886
|
() => MailingListFilterSchema.getDefault()
|
|
3493
3887
|
)
|
|
3494
3888
|
}).label("Mailing List");
|
|
3495
|
-
var CampaignTriggerSchema = (0,
|
|
3496
|
-
kind: (0,
|
|
3889
|
+
var CampaignTriggerSchema = (0, import_yup34.object)({
|
|
3890
|
+
kind: (0, import_yup34.string)().oneOf(SupportedCampaignTriggerKinds).required().default("manual" /* Manual */).label("Trigger"),
|
|
3497
3891
|
// IANA zone, e.g. "Asia/Kolkata". Local wall-clock times are interpreted in it,
|
|
3498
3892
|
// so occurrences land at the intended hour across DST rather than drifting.
|
|
3499
|
-
timezone: (0,
|
|
3893
|
+
timezone: (0, import_yup34.string)().optional().default("UTC").label("Timezone").when("kind", {
|
|
3500
3894
|
is: (k) => k !== "manual" /* Manual */,
|
|
3501
3895
|
then: (s) => s.required()
|
|
3502
3896
|
}),
|
|
@@ -3510,26 +3904,26 @@ var CampaignTriggerSchema = (0, import_yup33.object)({
|
|
|
3510
3904
|
is: "schedule" /* Schedule */,
|
|
3511
3905
|
then: (s) => s.required()
|
|
3512
3906
|
}),
|
|
3513
|
-
interval: (0,
|
|
3514
|
-
every: (0,
|
|
3515
|
-
unit: (0,
|
|
3907
|
+
interval: (0, import_yup34.object)({
|
|
3908
|
+
every: (0, import_yup34.number)().integer().min(1).max(365).required().label("Every"),
|
|
3909
|
+
unit: (0, import_yup34.string)().oneOf(SupportedCampaignIntervalUnits).required().label("Unit")
|
|
3516
3910
|
}).optional().default(void 0).label("Repeats").when("kind", {
|
|
3517
3911
|
is: "schedule" /* Schedule */,
|
|
3518
3912
|
then: (s) => s.required()
|
|
3519
3913
|
}),
|
|
3520
3914
|
/** Local wall-clock send time, "HH:mm" in `timezone`. */
|
|
3521
|
-
timeOfDay: (0,
|
|
3915
|
+
timeOfDay: (0, import_yup34.string)().matches(/^([01]\d|2[0-3]):[0-5]\d$/, "Use HH:mm").optional().default("09:00").label("Time of Day"),
|
|
3522
3916
|
/** For weekly intervals: ISO weekdays, 1 = Monday .. 7 = Sunday. */
|
|
3523
|
-
byWeekday: (0,
|
|
3917
|
+
byWeekday: (0, import_yup34.array)().of((0, import_yup34.number)().integer().min(1).max(7).required()).optional().default([]).label("On Days"),
|
|
3524
3918
|
/**
|
|
3525
3919
|
* For monthly intervals: 1-31, or -1 meaning "last day of the month". A month
|
|
3526
3920
|
* shorter than the chosen day is clamped to its last day, so 31 in February
|
|
3527
3921
|
* fires on the 28th/29th rather than being skipped.
|
|
3528
3922
|
*/
|
|
3529
|
-
byMonthday: (0,
|
|
3530
|
-
end: (0,
|
|
3531
|
-
kind: (0,
|
|
3532
|
-
occurrences: (0,
|
|
3923
|
+
byMonthday: (0, import_yup34.number)().integer().min(-1).max(31).notOneOf([0]).optional().default(void 0).label("Day of Month"),
|
|
3924
|
+
end: (0, import_yup34.object)({
|
|
3925
|
+
kind: (0, import_yup34.string)().oneOf(SupportedCampaignEndKinds).required().label("Ends"),
|
|
3926
|
+
occurrences: (0, import_yup34.number)().integer().min(1).max(1e4).optional().default(void 0).label("After N Sends").when("kind", {
|
|
3533
3927
|
is: "afterOccurrences" /* AfterOccurrences */,
|
|
3534
3928
|
then: (s) => s.required()
|
|
3535
3929
|
}),
|
|
@@ -3539,8 +3933,8 @@ var CampaignTriggerSchema = (0, import_yup33.object)({
|
|
|
3539
3933
|
})
|
|
3540
3934
|
}).optional().default(() => ({ kind: "never" /* Never */ })).label("End Condition")
|
|
3541
3935
|
}).label("Trigger");
|
|
3542
|
-
var CampaignDataSourceSchema = (0,
|
|
3543
|
-
id: (0,
|
|
3936
|
+
var CampaignDataSourceSchema = (0, import_yup34.object)({
|
|
3937
|
+
id: (0, import_yup34.string)().required().label("Data Source"),
|
|
3544
3938
|
/**
|
|
3545
3939
|
* Derive this source's filter per recipient from their profile, instead of
|
|
3546
3940
|
* using the admin-entered `params` for everyone.
|
|
@@ -3555,7 +3949,7 @@ var CampaignDataSourceSchema = (0, import_yup33.object)({
|
|
|
3555
3949
|
* un-personalised. Whether a source can honour it at all is declared by the
|
|
3556
3950
|
* source itself (`supportsPersonalisation`), which this package cannot see.
|
|
3557
3951
|
*/
|
|
3558
|
-
personalised: (0,
|
|
3952
|
+
personalised: (0, import_yup34.boolean)().optional().label("Personalised"),
|
|
3559
3953
|
/**
|
|
3560
3954
|
* A free-form bag whose keys are defined by the chosen source's OWN
|
|
3561
3955
|
* `paramsSchema`, which this package cannot see. Same `lazy` treatment as
|
|
@@ -3568,22 +3962,22 @@ var CampaignDataSourceSchema = (0, import_yup33.object)({
|
|
|
3568
3962
|
* them against the real source schema in `checkCampaignConfig`, which is the
|
|
3569
3963
|
* only place that knows what a given source accepts.
|
|
3570
3964
|
*/
|
|
3571
|
-
params: (0,
|
|
3965
|
+
params: (0, import_yup34.lazy)((value) => {
|
|
3572
3966
|
const keys = value && typeof value === "object" ? Object.keys(value) : [];
|
|
3573
|
-
return (0,
|
|
3574
|
-
Object.fromEntries(keys.map((k) => [k, (0,
|
|
3967
|
+
return (0, import_yup34.object)(
|
|
3968
|
+
Object.fromEntries(keys.map((k) => [k, (0, import_yup34.mixed)().optional()]))
|
|
3575
3969
|
).optional().default(() => ({})).label("Parameters");
|
|
3576
3970
|
})
|
|
3577
3971
|
}).label("Data Source");
|
|
3578
|
-
var TemplateVariableBindingSchema = (0,
|
|
3579
|
-
kind: (0,
|
|
3580
|
-
value: (0,
|
|
3972
|
+
var TemplateVariableBindingSchema = (0, import_yup34.object)({
|
|
3973
|
+
kind: (0, import_yup34.string)().oneOf(SupportedTemplateVariableBindingKinds).required().label("Source"),
|
|
3974
|
+
value: (0, import_yup34.string)().required().min(1).max(2e3).label("Value")
|
|
3581
3975
|
}).label("Template Variable Binding");
|
|
3582
|
-
var CampaignSchema = (0,
|
|
3583
|
-
name: (0,
|
|
3976
|
+
var CampaignSchema = (0, import_yup34.object)({
|
|
3977
|
+
name: (0, import_yup34.string)().required().min(1).max(200).label("Campaign Name"),
|
|
3584
3978
|
// The template renders its own subject; an override is only needed for the
|
|
3585
3979
|
// inline-HTML path, hence not required when a template is chosen.
|
|
3586
|
-
subject: (0,
|
|
3980
|
+
subject: (0, import_yup34.string)().optional().max(255).label("Subject").when("templateKey", {
|
|
3587
3981
|
is: (v) => !v,
|
|
3588
3982
|
then: (s) => s.required().min(1)
|
|
3589
3983
|
}),
|
|
@@ -3594,12 +3988,12 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3594
3988
|
* one with a compliance-checked footer and a render test,
|
|
3595
3989
|
* and hand-pasted HTML that repeats forever is a mistake that repeats forever.
|
|
3596
3990
|
*/
|
|
3597
|
-
html: (0,
|
|
3991
|
+
html: (0, import_yup34.string)().optional().label("HTML Body").when("templateKey", {
|
|
3598
3992
|
is: (v) => !v,
|
|
3599
3993
|
then: (s) => s.required().min(1)
|
|
3600
3994
|
}),
|
|
3601
|
-
text: (0,
|
|
3602
|
-
listId: (0,
|
|
3995
|
+
text: (0, import_yup34.string)().optional().label("Plain-text Body"),
|
|
3996
|
+
listId: (0, import_yup34.string)().required().label("Mailing List"),
|
|
3603
3997
|
/**
|
|
3604
3998
|
* Where the campaign is in its life. See `CampaignStatus` for the transitions.
|
|
3605
3999
|
*
|
|
@@ -3608,9 +4002,9 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3608
4002
|
* value the enum never contained (`scheduled`) reached production rows and
|
|
3609
4003
|
* rendered in the admin list as though it were real.
|
|
3610
4004
|
*/
|
|
3611
|
-
status: (0,
|
|
4005
|
+
status: (0, import_yup34.string)().oneOf(SupportedCampaignStatuses).optional().default("draft" /* Draft */).label("Status"),
|
|
3612
4006
|
/** Key from email-service's template registry. Mutually exclusive with `html`. */
|
|
3613
|
-
templateKey: (0,
|
|
4007
|
+
templateKey: (0, import_yup34.string)().optional().label("Email Template"),
|
|
3614
4008
|
/**
|
|
3615
4009
|
* One entry per variable the chosen template declares. Validated at save time
|
|
3616
4010
|
* against the template's own `variables`, so a missing required binding is a
|
|
@@ -3625,9 +4019,9 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3625
4019
|
* whose required variables all appear unbound. Shaping each entry also means a
|
|
3626
4020
|
* malformed binding is rejected here rather than at send time.
|
|
3627
4021
|
*/
|
|
3628
|
-
bindings: (0,
|
|
4022
|
+
bindings: (0, import_yup34.lazy)((value) => {
|
|
3629
4023
|
const keys = value && typeof value === "object" ? Object.keys(value) : [];
|
|
3630
|
-
return (0,
|
|
4024
|
+
return (0, import_yup34.object)(
|
|
3631
4025
|
Object.fromEntries(keys.map((k) => [k, TemplateVariableBindingSchema.required()]))
|
|
3632
4026
|
).optional().default(() => ({})).label("Template Data");
|
|
3633
4027
|
}),
|
|
@@ -3639,7 +4033,7 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3639
4033
|
* `groups.groupCount`), so two sources providing the same name cannot
|
|
3640
4034
|
* overwrite each other and a template says which one it means.
|
|
3641
4035
|
*/
|
|
3642
|
-
dataSources: (0,
|
|
4036
|
+
dataSources: (0, import_yup34.array)().of(CampaignDataSourceSchema).optional().default(void 0).label("Data Sources"),
|
|
3643
4037
|
trigger: CampaignTriggerSchema.default(
|
|
3644
4038
|
() => CampaignTriggerSchema.getDefault()
|
|
3645
4039
|
),
|
|
@@ -3654,7 +4048,7 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3654
4048
|
* representable, and the admin list showed exactly that. Activation is a
|
|
3655
4049
|
* state transition, so it belongs in the state.
|
|
3656
4050
|
*/
|
|
3657
|
-
dryRun: (0,
|
|
4051
|
+
dryRun: (0, import_yup34.boolean)().optional().default(true).label("Dry Run"),
|
|
3658
4052
|
/**
|
|
3659
4053
|
* Re-eligibility: when someone this campaign already mailed may get it again.
|
|
3660
4054
|
*
|
|
@@ -3662,23 +4056,23 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3662
4056
|
* person. `N`: again only after N days. Opt-in, because most recurring
|
|
3663
4057
|
* campaigns exist to mail the same people repeatedly.
|
|
3664
4058
|
*/
|
|
3665
|
-
resendAfterDays: (0,
|
|
3666
|
-
maxRecipients: (0,
|
|
3667
|
-
utm: (0,
|
|
3668
|
-
campaign: (0,
|
|
3669
|
-
content: (0,
|
|
4059
|
+
resendAfterDays: (0, import_yup34.number)().integer().min(0).max(365).nullable().optional().default(void 0).label("Resend After (days)"),
|
|
4060
|
+
maxRecipients: (0, import_yup34.number)().integer().min(1).max(CAMPAIGN_MAX_RECIPIENTS_CEILING).optional().default(void 0).label("Max Recipients"),
|
|
4061
|
+
utm: (0, import_yup34.object)({
|
|
4062
|
+
campaign: (0, import_yup34.string)().optional().max(120).label("utm_campaign"),
|
|
4063
|
+
content: (0, import_yup34.string)().optional().max(120).label("utm_content")
|
|
3670
4064
|
}).optional().default(void 0).label("Link Tagging")
|
|
3671
4065
|
}).label("Campaign");
|
|
3672
4066
|
|
|
3673
4067
|
// src/pagination/pagination.schema.ts
|
|
3674
|
-
var
|
|
3675
|
-
var PaginationSchema = (0,
|
|
3676
|
-
page: (0,
|
|
3677
|
-
limit: (0,
|
|
3678
|
-
sortBy: (0,
|
|
3679
|
-
nextPage: (0,
|
|
3680
|
-
prevPage: (0,
|
|
3681
|
-
sortDirection: (0,
|
|
4068
|
+
var import_yup35 = require("yup");
|
|
4069
|
+
var PaginationSchema = (0, import_yup35.object)().shape({
|
|
4070
|
+
page: (0, import_yup35.number)().required().min(1).label("Page").default(1),
|
|
4071
|
+
limit: (0, import_yup35.number)().required().min(1).max(100).label("Limit").default(10),
|
|
4072
|
+
sortBy: (0, import_yup35.string)().notOneOf([""]).optional().label("SortBy"),
|
|
4073
|
+
nextPage: (0, import_yup35.string)().optional().label("Next Page Token"),
|
|
4074
|
+
prevPage: (0, import_yup35.string)().optional().label("Previous Page Token"),
|
|
4075
|
+
sortDirection: (0, import_yup35.string)().oneOf(["asc", "desc"]).optional().label("Sort Direction")
|
|
3682
4076
|
});
|
|
3683
4077
|
|
|
3684
4078
|
// src/pagination/pagination.constant.ts
|
|
@@ -3694,7 +4088,7 @@ var DefaultPaginationOptions = {
|
|
|
3694
4088
|
};
|
|
3695
4089
|
|
|
3696
4090
|
// src/saved-search/saved-search.schema.ts
|
|
3697
|
-
var
|
|
4091
|
+
var import_yup36 = require("yup");
|
|
3698
4092
|
|
|
3699
4093
|
// src/saved-search/saved-search.constant.ts
|
|
3700
4094
|
var SavedSearchStatus = /* @__PURE__ */ ((SavedSearchStatus2) => {
|
|
@@ -3705,21 +4099,21 @@ var SavedSearchStatus = /* @__PURE__ */ ((SavedSearchStatus2) => {
|
|
|
3705
4099
|
var SupportedSavedSearchStatuses = Object.values(SavedSearchStatus);
|
|
3706
4100
|
|
|
3707
4101
|
// src/saved-search/saved-search.schema.ts
|
|
3708
|
-
var SavedSearchSchema = (0,
|
|
4102
|
+
var SavedSearchSchema = (0, import_yup36.object)({
|
|
3709
4103
|
/** Public identifier. Server-assigned. */
|
|
3710
|
-
shortId: (0,
|
|
4104
|
+
shortId: (0, import_yup36.string)().trim().label("Short Id"),
|
|
3711
4105
|
/**
|
|
3712
4106
|
* Owner's Better Auth account id. Server-assigned from the verified token,
|
|
3713
4107
|
* never accepted from a request body.
|
|
3714
4108
|
*/
|
|
3715
|
-
ownerUserId: (0,
|
|
4109
|
+
ownerUserId: (0, import_yup36.string)().trim().label("Owner"),
|
|
3716
4110
|
/** What the user calls this search, e.g. "Remote React roles". */
|
|
3717
|
-
label: (0,
|
|
4111
|
+
label: (0, import_yup36.string)().trim().max(120).required().label("Label"),
|
|
3718
4112
|
/**
|
|
3719
4113
|
* The free-text query. Optional because a search can be filters-only ("all
|
|
3720
4114
|
* remote jobs in Sweden"), which is a legitimate alert to want.
|
|
3721
4115
|
*/
|
|
3722
|
-
search: (0,
|
|
4116
|
+
search: (0, import_yup36.string)().trim().max(500).optional().label("Search Text"),
|
|
3723
4117
|
/**
|
|
3724
4118
|
* Field filters, in the same `{ field: values }` shape the search endpoint
|
|
3725
4119
|
* parses from `filter[field]=a,b`. Held as a free-form object rather than a
|
|
@@ -3727,7 +4121,7 @@ var SavedSearchSchema = (0, import_yup35.object)({
|
|
|
3727
4121
|
* change independently; validating them here would put this package in the
|
|
3728
4122
|
* business of tracking that vocabulary.
|
|
3729
4123
|
*/
|
|
3730
|
-
filter: (0,
|
|
4124
|
+
filter: (0, import_yup36.object)().optional().default({}).label("Filters"),
|
|
3731
4125
|
/**
|
|
3732
4126
|
* How often to mail matches. `off` keeps the search saved but silent, which is
|
|
3733
4127
|
* the difference between "I don't want mail" and "delete my search".
|
|
@@ -3736,26 +4130,26 @@ var SavedSearchSchema = (0, import_yup35.object)({
|
|
|
3736
4130
|
* than defining a second one: two vocabularies for the same concept is how
|
|
3737
4131
|
* they drift.
|
|
3738
4132
|
*/
|
|
3739
|
-
frequency: (0,
|
|
3740
|
-
status: (0,
|
|
4133
|
+
frequency: (0, import_yup36.string)().oneOf(SupportedJobAlertFrequencies).default("off" /* Off */).label("Alert Frequency"),
|
|
4134
|
+
status: (0, import_yup36.string)().oneOf(SupportedSavedSearchStatuses).default("active" /* Active */).label("Status"),
|
|
3741
4135
|
/**
|
|
3742
4136
|
* Epoch ms of the last alert sent for this search. The matching sweep reads it
|
|
3743
4137
|
* to decide whether the cadence is due, and writes it only AFTER a successful
|
|
3744
4138
|
* publish, so a failed run retries next tick rather than silently skipping a
|
|
3745
4139
|
* period.
|
|
3746
4140
|
*/
|
|
3747
|
-
lastNotifiedAt: (0,
|
|
4141
|
+
lastNotifiedAt: (0, import_yup36.number)().optional().label("Last Notified At"),
|
|
3748
4142
|
/**
|
|
3749
4143
|
* Epoch ms high-water mark: only jobs created after this are "new" for the
|
|
3750
4144
|
* next alert. Kept separate from `lastNotifiedAt` because a run that finds no
|
|
3751
4145
|
* matches should still advance what counts as new, without implying mail was
|
|
3752
4146
|
* sent.
|
|
3753
4147
|
*/
|
|
3754
|
-
lastMatchedAt: (0,
|
|
4148
|
+
lastMatchedAt: (0, import_yup36.number)().optional().label("Last Matched At")
|
|
3755
4149
|
}).noUnknown().strict();
|
|
3756
4150
|
|
|
3757
4151
|
// src/report/report.schema.ts
|
|
3758
|
-
var
|
|
4152
|
+
var import_yup37 = require("yup");
|
|
3759
4153
|
|
|
3760
4154
|
// src/report/report.constant.ts
|
|
3761
4155
|
var ResourceType = /* @__PURE__ */ ((ResourceType3) => {
|
|
@@ -3779,15 +4173,15 @@ var ReportReason = /* @__PURE__ */ ((ReportReason3) => {
|
|
|
3779
4173
|
var SupportedReportReasons = Object.values(ReportReason);
|
|
3780
4174
|
|
|
3781
4175
|
// src/report/report.schema.ts
|
|
3782
|
-
var ReportSchema = (0,
|
|
3783
|
-
type: (0,
|
|
3784
|
-
resourceId: (0,
|
|
3785
|
-
reason: (0,
|
|
3786
|
-
comment: (0,
|
|
4176
|
+
var ReportSchema = (0, import_yup37.object)({
|
|
4177
|
+
type: (0, import_yup37.mixed)().oneOf(SupportedResourceTypes).required().label("Type"),
|
|
4178
|
+
resourceId: (0, import_yup37.string)().required().label("Resource ID"),
|
|
4179
|
+
reason: (0, import_yup37.mixed)().oneOf(SupportedReportReasons).required("Please choose a reason").label("Reason"),
|
|
4180
|
+
comment: (0, import_yup37.string)().max(1e3).optional().label("Comment")
|
|
3787
4181
|
}).label("Report Schema");
|
|
3788
4182
|
|
|
3789
4183
|
// src/feedback/feedback-filter.schema.ts
|
|
3790
|
-
var
|
|
4184
|
+
var import_yup38 = require("yup");
|
|
3791
4185
|
|
|
3792
4186
|
// src/feedback/feedback.constant.ts
|
|
3793
4187
|
var FeedbackType = /* @__PURE__ */ ((FeedbackType3) => {
|
|
@@ -3810,7 +4204,7 @@ var SupportedFeedbackStatuses = Object.values(FeedbackStatus);
|
|
|
3810
4204
|
var FEEDBACK_MESSAGE_MAX = 4e3;
|
|
3811
4205
|
|
|
3812
4206
|
// src/feedback/feedback-filter.schema.ts
|
|
3813
|
-
var FeedbackFilterShape = (0,
|
|
4207
|
+
var FeedbackFilterShape = (0, import_yup38.object)({
|
|
3814
4208
|
type: enumFacet(SupportedFeedbackTypes, "Type"),
|
|
3815
4209
|
status: enumFacet(SupportedFeedbackStatuses, "Status")
|
|
3816
4210
|
}).label("Feedback Filter");
|
|
@@ -3820,18 +4214,18 @@ var FeedbackFilterSchema = rejectUnknownKeys(
|
|
|
3820
4214
|
);
|
|
3821
4215
|
|
|
3822
4216
|
// src/feedback/feedback.schema.ts
|
|
3823
|
-
var
|
|
3824
|
-
var FeedbackSchema = (0,
|
|
3825
|
-
type: (0,
|
|
3826
|
-
message: (0,
|
|
3827
|
-
email: (0,
|
|
3828
|
-
pageUrl: (0,
|
|
3829
|
-
status: (0,
|
|
4217
|
+
var import_yup39 = require("yup");
|
|
4218
|
+
var FeedbackSchema = (0, import_yup39.object)({
|
|
4219
|
+
type: (0, import_yup39.mixed)().oneOf(SupportedFeedbackTypes).required().label("Type"),
|
|
4220
|
+
message: (0, import_yup39.string)().trim().required("Please enter a message").max(FEEDBACK_MESSAGE_MAX).label("Message"),
|
|
4221
|
+
email: (0, import_yup39.string)().email().optional().label("Email"),
|
|
4222
|
+
pageUrl: (0, import_yup39.string)().optional().label("Page URL"),
|
|
4223
|
+
status: (0, import_yup39.mixed)().oneOf(SupportedFeedbackStatuses).optional().label("Status")
|
|
3830
4224
|
}).label("Feedback Schema");
|
|
3831
4225
|
|
|
3832
4226
|
// src/skill/skill-filter.schema.ts
|
|
3833
|
-
var
|
|
3834
|
-
var SkillFilterShape = (0,
|
|
4227
|
+
var import_yup40 = require("yup");
|
|
4228
|
+
var SkillFilterShape = (0, import_yup40.object)({
|
|
3835
4229
|
/** Display names, matched exactly. Free-text matching is `?search=`. */
|
|
3836
4230
|
names: tokens("Names"),
|
|
3837
4231
|
/**
|
|
@@ -3849,7 +4243,7 @@ var SkillFilterSchema = rejectUnknownKeys(
|
|
|
3849
4243
|
);
|
|
3850
4244
|
|
|
3851
4245
|
// src/billing/billing.schema.ts
|
|
3852
|
-
var
|
|
4246
|
+
var import_yup41 = require("yup");
|
|
3853
4247
|
|
|
3854
4248
|
// src/billing/billing.constant.ts
|
|
3855
4249
|
var PlanKind = /* @__PURE__ */ ((PlanKind2) => {
|
|
@@ -3952,60 +4346,60 @@ var GRANT_MAX_LIMIT = 1e5;
|
|
|
3952
4346
|
var CONSUME_MAX_UNITS = 1e3;
|
|
3953
4347
|
|
|
3954
4348
|
// src/billing/billing.schema.ts
|
|
3955
|
-
var MoneySchema = (0,
|
|
3956
|
-
amountMinor: (0,
|
|
4349
|
+
var MoneySchema = (0, import_yup41.object)({
|
|
4350
|
+
amountMinor: (0, import_yup41.number)().integer().min(0).required().label("Amount (minor units)"),
|
|
3957
4351
|
/**
|
|
3958
4352
|
* ISO-4217, as returned by Paddle. Deliberately NOT constrained to
|
|
3959
4353
|
* `SupportedSalaryCurrencies`: that list is the job-salary vocabulary, and
|
|
3960
4354
|
* Paddle bills in currencies it does not contain. Constraining it here would
|
|
3961
4355
|
* reject real payments.
|
|
3962
4356
|
*/
|
|
3963
|
-
currencyCode: (0,
|
|
4357
|
+
currencyCode: (0, import_yup41.string)().trim().uppercase().required().label("Currency")
|
|
3964
4358
|
}).label("Money");
|
|
3965
|
-
var PlanGrantSchema = (0,
|
|
4359
|
+
var PlanGrantSchema = (0, import_yup41.object)({
|
|
3966
4360
|
/**
|
|
3967
4361
|
* The gated capability, e.g. `job.post`. A free string on purpose: see the
|
|
3968
4362
|
* note on `FeatureKey` in `billing.constant.ts`. Adding a feature to the
|
|
3969
4363
|
* paywall must not require releasing this package.
|
|
3970
4364
|
*/
|
|
3971
|
-
feature: (0,
|
|
3972
|
-
type: (0,
|
|
4365
|
+
feature: (0, import_yup41.string)().trim().required().min(1).max(64).label("Feature"),
|
|
4366
|
+
type: (0, import_yup41.string)().oneOf(SupportedGrantTypes).required().default("boolean" /* Boolean */).label("Grant Type"),
|
|
3973
4367
|
/** Uses per period. Required for `quota`, meaningless otherwise. */
|
|
3974
|
-
limit: (0,
|
|
4368
|
+
limit: (0, import_yup41.number)().integer().min(1).max(GRANT_MAX_LIMIT).optional().label("Limit").when("type", {
|
|
3975
4369
|
is: "quota" /* Quota */,
|
|
3976
4370
|
then: (s) => s.required("A quota grant needs a limit")
|
|
3977
4371
|
}),
|
|
3978
|
-
period: (0,
|
|
4372
|
+
period: (0, import_yup41.string)().oneOf(SupportedQuotaPeriods).optional().default("month" /* Month */).label("Period").when("type", {
|
|
3979
4373
|
is: "quota" /* Quota */,
|
|
3980
4374
|
then: (s) => s.required("A quota grant needs a period")
|
|
3981
4375
|
}),
|
|
3982
4376
|
/** Non-expiring uses granted per purchase. Required for `credit`. */
|
|
3983
|
-
amount: (0,
|
|
4377
|
+
amount: (0, import_yup41.number)().integer().min(1).max(GRANT_MAX_LIMIT).optional().label("Amount").when("type", {
|
|
3984
4378
|
is: "credit" /* Credit */,
|
|
3985
4379
|
then: (s) => s.required("A credit grant needs an amount")
|
|
3986
4380
|
})
|
|
3987
4381
|
}).label("Plan Grant");
|
|
3988
|
-
var PaddlePriceIdsSchema = (0,
|
|
3989
|
-
sandbox: (0,
|
|
3990
|
-
live: (0,
|
|
4382
|
+
var PaddlePriceIdsSchema = (0, import_yup41.object)({
|
|
4383
|
+
sandbox: (0, import_yup41.array)().of((0, import_yup41.string)().required()).optional().default([]).label("Sandbox Price IDs"),
|
|
4384
|
+
live: (0, import_yup41.array)().of((0, import_yup41.string)().required()).optional().default([]).label("Live Price IDs")
|
|
3991
4385
|
}).label("Paddle Price IDs");
|
|
3992
|
-
var PlanSchema = (0,
|
|
4386
|
+
var PlanSchema = (0, import_yup41.object)({
|
|
3993
4387
|
/** Stable slug, e.g. `employer-pro`. The identifier everything else references. */
|
|
3994
|
-
key: (0,
|
|
3995
|
-
name: (0,
|
|
3996
|
-
description: (0,
|
|
3997
|
-
kind: (0,
|
|
4388
|
+
key: (0, import_yup41.string)().trim().lowercase().required().min(2).max(64).label("Key"),
|
|
4389
|
+
name: (0, import_yup41.string)().required().min(1).max(120).label("Name"),
|
|
4390
|
+
description: (0, import_yup41.string)().optional().max(500).label("Description"),
|
|
4391
|
+
kind: (0, import_yup41.string)().oneOf(SupportedPlanKinds).required().default("subscription" /* Subscription */).label("Kind"),
|
|
3998
4392
|
/**
|
|
3999
4393
|
* The line this plan belongs to; a user holds one live subscription per line.
|
|
4000
4394
|
* Optional on purpose: absent is the default line, so existing plans need no
|
|
4001
4395
|
* migration and together still read as "one plan at a time".
|
|
4002
4396
|
*/
|
|
4003
|
-
audience: (0,
|
|
4004
|
-
status: (0,
|
|
4397
|
+
audience: (0, import_yup41.string)().oneOf(SupportedPlanAudiences).optional().label("Audience"),
|
|
4398
|
+
status: (0, import_yup41.string)().oneOf(SupportedPlanStatuses).required().default("draft" /* Draft */).label("Status"),
|
|
4005
4399
|
paddlePriceIds: PaddlePriceIdsSchema.default(
|
|
4006
4400
|
() => PaddlePriceIdsSchema.getDefault()
|
|
4007
4401
|
),
|
|
4008
|
-
grants: (0,
|
|
4402
|
+
grants: (0, import_yup41.array)().of(PlanGrantSchema.required()).required().min(1, "A plan must grant at least one feature").label("Grants"),
|
|
4009
4403
|
/** Display price for the pricing page. Billing is always Paddle's own figure. */
|
|
4010
4404
|
price: MoneySchema.optional().default(void 0).label("Price"),
|
|
4011
4405
|
/**
|
|
@@ -4018,133 +4412,189 @@ var PlanSchema = (0, import_yup40.object)({
|
|
|
4018
4412
|
* a subscription as "monthly" at the use site rather than defaulting it here,
|
|
4019
4413
|
* so an unset value stays visible as unset.
|
|
4020
4414
|
*/
|
|
4021
|
-
billingPeriod: (0,
|
|
4415
|
+
billingPeriod: (0, import_yup41.string)().oneOf(SupportedBillingPeriods).optional().label("Billing Period"),
|
|
4022
4416
|
/** Ordering on the pricing page, ascending. */
|
|
4023
|
-
sortOrder: (0,
|
|
4024
|
-
createdAt: (0,
|
|
4025
|
-
updatedAt: (0,
|
|
4417
|
+
sortOrder: (0, import_yup41.number)().integer().optional().default(0).label("Sort Order"),
|
|
4418
|
+
createdAt: (0, import_yup41.number)().optional().label("Created At"),
|
|
4419
|
+
updatedAt: (0, import_yup41.number)().optional().label("Updated At")
|
|
4026
4420
|
}).label("Plan");
|
|
4027
|
-
var BillingSubscriptionSchema = (0,
|
|
4028
|
-
userId: (0,
|
|
4029
|
-
paddleSubscriptionId: (0,
|
|
4030
|
-
paddleCustomerId: (0,
|
|
4031
|
-
planKey: (0,
|
|
4032
|
-
priceIds: (0,
|
|
4033
|
-
status: (0,
|
|
4421
|
+
var BillingSubscriptionSchema = (0, import_yup41.object)({
|
|
4422
|
+
userId: (0, import_yup41.string)().required().label("User ID"),
|
|
4423
|
+
paddleSubscriptionId: (0, import_yup41.string)().required().label("Paddle Subscription ID"),
|
|
4424
|
+
paddleCustomerId: (0, import_yup41.string)().required().label("Paddle Customer ID"),
|
|
4425
|
+
planKey: (0, import_yup41.string)().required().label("Plan Key"),
|
|
4426
|
+
priceIds: (0, import_yup41.array)().of((0, import_yup41.string)().required()).required().label("Price IDs"),
|
|
4427
|
+
status: (0, import_yup41.string)().oneOf(SupportedSubscriptionStatuses).required().label("Status"),
|
|
4034
4428
|
/** Start of the period the quota is anchored to. */
|
|
4035
|
-
currentPeriodStart: (0,
|
|
4036
|
-
currentPeriodEnd: (0,
|
|
4429
|
+
currentPeriodStart: (0, import_yup41.number)().optional().label("Current Period Start"),
|
|
4430
|
+
currentPeriodEnd: (0, import_yup41.number)().optional().label("Current Period End"),
|
|
4037
4431
|
/** Set when a cancellation is scheduled; access continues until the period ends. */
|
|
4038
|
-
canceledAt: (0,
|
|
4432
|
+
canceledAt: (0, import_yup41.number)().optional().label("Canceled At"),
|
|
4039
4433
|
/**
|
|
4040
4434
|
* A downgrade booked for the end of the current period: the plan key it moves
|
|
4041
4435
|
* to at renewal. Upgrades never set this; they apply immediately. Mirrored
|
|
4042
4436
|
* from the Paddle subscription's own `customData`, so Paddle stays the source
|
|
4043
4437
|
* of truth.
|
|
4044
4438
|
*/
|
|
4045
|
-
pendingPlanKey: (0,
|
|
4439
|
+
pendingPlanKey: (0, import_yup41.string)().optional().label("Pending Plan Key"),
|
|
4046
4440
|
/** `occurred_at` of the newest Paddle event applied. Guards out-of-order writes. */
|
|
4047
|
-
lastEventAt: (0,
|
|
4048
|
-
createdAt: (0,
|
|
4049
|
-
updatedAt: (0,
|
|
4441
|
+
lastEventAt: (0, import_yup41.number)().required().default(0).label("Last Event At"),
|
|
4442
|
+
createdAt: (0, import_yup41.number)().optional().label("Created At"),
|
|
4443
|
+
updatedAt: (0, import_yup41.number)().optional().label("Updated At")
|
|
4050
4444
|
}).label("Billing Subscription");
|
|
4051
|
-
var BillingTransactionSchema = (0,
|
|
4052
|
-
userId: (0,
|
|
4053
|
-
paddleTransactionId: (0,
|
|
4054
|
-
paddleCustomerId: (0,
|
|
4055
|
-
paddleSubscriptionId: (0,
|
|
4056
|
-
planKey: (0,
|
|
4057
|
-
priceIds: (0,
|
|
4058
|
-
status: (0,
|
|
4445
|
+
var BillingTransactionSchema = (0, import_yup41.object)({
|
|
4446
|
+
userId: (0, import_yup41.string)().required().label("User ID"),
|
|
4447
|
+
paddleTransactionId: (0, import_yup41.string)().required().label("Paddle Transaction ID"),
|
|
4448
|
+
paddleCustomerId: (0, import_yup41.string)().optional().label("Paddle Customer ID"),
|
|
4449
|
+
paddleSubscriptionId: (0, import_yup41.string)().optional().label("Paddle Subscription ID"),
|
|
4450
|
+
planKey: (0, import_yup41.string)().optional().label("Plan Key"),
|
|
4451
|
+
priceIds: (0, import_yup41.array)().of((0, import_yup41.string)().required()).required().label("Price IDs"),
|
|
4452
|
+
status: (0, import_yup41.string)().oneOf(SupportedTransactionStatuses).required().label("Status"),
|
|
4059
4453
|
total: MoneySchema.optional().default(void 0).label("Total"),
|
|
4060
|
-
billedAt: (0,
|
|
4061
|
-
lastEventAt: (0,
|
|
4062
|
-
createdAt: (0,
|
|
4063
|
-
updatedAt: (0,
|
|
4454
|
+
billedAt: (0, import_yup41.number)().optional().label("Billed At"),
|
|
4455
|
+
lastEventAt: (0, import_yup41.number)().required().default(0).label("Last Event At"),
|
|
4456
|
+
createdAt: (0, import_yup41.number)().optional().label("Created At"),
|
|
4457
|
+
updatedAt: (0, import_yup41.number)().optional().label("Updated At")
|
|
4064
4458
|
}).label("Billing Transaction");
|
|
4065
|
-
var FeatureEntitlementSchema = (0,
|
|
4066
|
-
feature: (0,
|
|
4067
|
-
type: (0,
|
|
4459
|
+
var FeatureEntitlementSchema = (0, import_yup41.object)({
|
|
4460
|
+
feature: (0, import_yup41.string)().required().label("Feature"),
|
|
4461
|
+
type: (0, import_yup41.string)().oneOf(SupportedGrantTypes).required().label("Grant Type"),
|
|
4068
4462
|
/** Whether the feature may be used AT ALL right now. */
|
|
4069
|
-
allowed: (0,
|
|
4463
|
+
allowed: (0, import_yup41.boolean)().required().default(false).label("Allowed"),
|
|
4070
4464
|
/** Quota ceiling for the period. Absent for boolean grants. */
|
|
4071
|
-
limit: (0,
|
|
4072
|
-
used: (0,
|
|
4465
|
+
limit: (0, import_yup41.number)().integer().optional().label("Limit"),
|
|
4466
|
+
used: (0, import_yup41.number)().integer().optional().label("Used"),
|
|
4073
4467
|
/** Quota remaining plus any credit balance. Absent for boolean grants. */
|
|
4074
|
-
remaining: (0,
|
|
4468
|
+
remaining: (0, import_yup41.number)().integer().optional().label("Remaining"),
|
|
4075
4469
|
/** Non-expiring balance from one-off purchases. */
|
|
4076
|
-
credits: (0,
|
|
4470
|
+
credits: (0, import_yup41.number)().integer().optional().label("Credits"),
|
|
4077
4471
|
/** When the quota next refreshes. */
|
|
4078
|
-
resetsAt: (0,
|
|
4472
|
+
resetsAt: (0, import_yup41.number)().optional().label("Resets At")
|
|
4079
4473
|
}).label("Feature Entitlement");
|
|
4080
|
-
var EntitlementDenialSchema = (0,
|
|
4081
|
-
feature: (0,
|
|
4082
|
-
reason: (0,
|
|
4083
|
-
limit: (0,
|
|
4084
|
-
used: (0,
|
|
4085
|
-
resetsAt: (0,
|
|
4086
|
-
upgradeUrl: (0,
|
|
4474
|
+
var EntitlementDenialSchema = (0, import_yup41.object)({
|
|
4475
|
+
feature: (0, import_yup41.string)().required().label("Feature"),
|
|
4476
|
+
reason: (0, import_yup41.string)().oneOf(SupportedEntitlementDenialReasons).required().label("Reason"),
|
|
4477
|
+
limit: (0, import_yup41.number)().integer().optional().label("Limit"),
|
|
4478
|
+
used: (0, import_yup41.number)().integer().optional().label("Used"),
|
|
4479
|
+
resetsAt: (0, import_yup41.number)().optional().label("Resets At"),
|
|
4480
|
+
upgradeUrl: (0, import_yup41.string)().optional().label("Upgrade URL")
|
|
4087
4481
|
}).label("Entitlement Denial");
|
|
4088
|
-
var EntitlementConsumeSchema = (0,
|
|
4089
|
-
userId: (0,
|
|
4090
|
-
feature: (0,
|
|
4091
|
-
units: (0,
|
|
4482
|
+
var EntitlementConsumeSchema = (0, import_yup41.object)({
|
|
4483
|
+
userId: (0, import_yup41.string)().required().label("User ID"),
|
|
4484
|
+
feature: (0, import_yup41.string)().trim().required().min(1).max(64).label("Feature"),
|
|
4485
|
+
units: (0, import_yup41.number)().integer().min(1).max(CONSUME_MAX_UNITS).required().default(1).label("Units"),
|
|
4092
4486
|
/**
|
|
4093
4487
|
* Caller-supplied de-duplication key. Makes a spend exactly-once across the
|
|
4094
4488
|
* retries that at-least-once delivery and ordinary network failures produce.
|
|
4095
4489
|
*/
|
|
4096
|
-
idempotencyKey: (0,
|
|
4490
|
+
idempotencyKey: (0, import_yup41.string)().trim().required().min(8).max(128).label("Idempotency Key")
|
|
4097
4491
|
}).label("Entitlement Consume");
|
|
4098
4492
|
|
|
4493
|
+
// src/taxonomy/taxonomy-filter.schema.ts
|
|
4494
|
+
var import_yup42 = require("yup");
|
|
4495
|
+
var ConceptFilterShape = (0, import_yup42.object)({
|
|
4496
|
+
/** Type ids. Open: which types exist is the vocabulary's data. */
|
|
4497
|
+
type: tokens("Type"),
|
|
4498
|
+
/** Category node ids the concept is placed under (`memberships.categoryId`). */
|
|
4499
|
+
categoryId: tokens("Category"),
|
|
4500
|
+
/** True: only live concepts with no backbone home (the uncategorized backlog). */
|
|
4501
|
+
unplaced: (0, import_yup42.boolean)().optional().label("Unplaced")
|
|
4502
|
+
}).label("Concept Filter");
|
|
4503
|
+
var ConceptFilterSchema = rejectUnknownKeys(
|
|
4504
|
+
ConceptFilterShape,
|
|
4505
|
+
() => Object.keys(ConceptFilterShape.fields)
|
|
4506
|
+
);
|
|
4507
|
+
var TaxonomyNodeFilterShape = (0, import_yup42.object)({
|
|
4508
|
+
kind: enumFacet(SupportedTaxonomyNodeKinds, "Kind"),
|
|
4509
|
+
/** Parent node ids: a node's children. */
|
|
4510
|
+
parentId: tokens("Parent")
|
|
4511
|
+
}).label("Taxonomy Node Filter");
|
|
4512
|
+
var TaxonomyNodeFilterSchema = rejectUnknownKeys(
|
|
4513
|
+
TaxonomyNodeFilterShape,
|
|
4514
|
+
() => Object.keys(TaxonomyNodeFilterShape.fields)
|
|
4515
|
+
);
|
|
4516
|
+
var UnmatchedFilterShape = (0, import_yup42.object)({
|
|
4517
|
+
resolution: enumFacet(SupportedUnmatchedResolutions, "Resolution"),
|
|
4518
|
+
reason: enumFacet(SupportedUnmatchedReasons, "Reason")
|
|
4519
|
+
}).label("Unmatched Filter");
|
|
4520
|
+
var UnmatchedFilterSchema = rejectUnknownKeys(
|
|
4521
|
+
UnmatchedFilterShape,
|
|
4522
|
+
() => Object.keys(UnmatchedFilterShape.fields)
|
|
4523
|
+
);
|
|
4524
|
+
var ConceptProposalFilterShape = (0, import_yup42.object)({
|
|
4525
|
+
status: enumFacet(SupportedProposalStatuses, "Status"),
|
|
4526
|
+
/** A kind, or `uncategorized`: concept and placement drafts with no home yet. */
|
|
4527
|
+
kind: enumFacet(SupportedProposalFilters, "Kind")
|
|
4528
|
+
}).label("Concept Proposal Filter");
|
|
4529
|
+
var ConceptProposalFilterSchema = rejectUnknownKeys(
|
|
4530
|
+
ConceptProposalFilterShape,
|
|
4531
|
+
() => Object.keys(ConceptProposalFilterShape.fields)
|
|
4532
|
+
);
|
|
4533
|
+
var ReleaseFilterShape = (0, import_yup42.object)({
|
|
4534
|
+
kind: enumFacet(SupportedReleaseKinds, "Kind"),
|
|
4535
|
+
status: enumFacet(SupportedReleaseStatuses, "Status")
|
|
4536
|
+
}).label("Release Filter");
|
|
4537
|
+
var ReleaseFilterSchema = rejectUnknownKeys(
|
|
4538
|
+
ReleaseFilterShape,
|
|
4539
|
+
() => Object.keys(ReleaseFilterShape.fields)
|
|
4540
|
+
);
|
|
4541
|
+
var AuditFilterShape = (0, import_yup42.object)({
|
|
4542
|
+
status: enumFacet(SupportedAuditStatuses, "Status")
|
|
4543
|
+
}).label("Audit Filter");
|
|
4544
|
+
var AuditFilterSchema = rejectUnknownKeys(
|
|
4545
|
+
AuditFilterShape,
|
|
4546
|
+
() => Object.keys(AuditFilterShape.fields)
|
|
4547
|
+
);
|
|
4548
|
+
|
|
4099
4549
|
// src/user/user.schema.ts
|
|
4100
|
-
var
|
|
4550
|
+
var import_yup55 = require("yup");
|
|
4101
4551
|
|
|
4102
4552
|
// src/user/work-experience.schema.ts
|
|
4103
|
-
var
|
|
4104
|
-
var WorkExperienceSchema = (0,
|
|
4553
|
+
var import_yup43 = require("yup");
|
|
4554
|
+
var WorkExperienceSchema = (0, import_yup43.object)().shape({
|
|
4105
4555
|
company: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Company"),
|
|
4106
|
-
designation: (0,
|
|
4556
|
+
designation: (0, import_yup43.string)().trim().required().label("Designation"),
|
|
4107
4557
|
duration: DurationSchema({
|
|
4108
4558
|
format: "YYYY-MM",
|
|
4109
4559
|
startLabel: "Start Date",
|
|
4110
4560
|
endLabel: "End Date"
|
|
4111
4561
|
}).required().label("Duration"),
|
|
4112
|
-
description: (0,
|
|
4562
|
+
description: (0, import_yup43.string)().trim().max(3e3).optional().label("Description"),
|
|
4113
4563
|
location: LocationSchema.required().label("Location"),
|
|
4114
|
-
isRemote: (0,
|
|
4564
|
+
isRemote: (0, import_yup43.boolean)().oneOf([true, false]).default(false).label("Is Remote")
|
|
4115
4565
|
}).noUnknown().strict().label("Work Experience");
|
|
4116
4566
|
|
|
4117
4567
|
// src/user/education.schema.ts
|
|
4118
|
-
var
|
|
4119
|
-
var EducationSchema = (0,
|
|
4568
|
+
var import_yup44 = require("yup");
|
|
4569
|
+
var EducationSchema = (0, import_yup44.object)({
|
|
4120
4570
|
institute: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Institute"),
|
|
4121
|
-
course: (0,
|
|
4122
|
-
fieldOfStudy: (0,
|
|
4571
|
+
course: (0, import_yup44.string)().trim().required().label("Course"),
|
|
4572
|
+
fieldOfStudy: (0, import_yup44.string)().trim().required().label("Field of Study"),
|
|
4123
4573
|
duration: DurationSchema({
|
|
4124
4574
|
format: "YYYY-MM",
|
|
4125
4575
|
startLabel: "Start Date",
|
|
4126
4576
|
endLabel: "End Date"
|
|
4127
4577
|
}).required().label("Duration"),
|
|
4128
|
-
description: (0,
|
|
4129
|
-
isDistanceLearning: (0,
|
|
4578
|
+
description: (0, import_yup44.string)().trim().max(3e3).optional().label("Description"),
|
|
4579
|
+
isDistanceLearning: (0, import_yup44.boolean)().default(false).label("Is Distance Learning"),
|
|
4130
4580
|
location: LocationSchema.required().label("Location"),
|
|
4131
|
-
studyType: (0,
|
|
4581
|
+
studyType: (0, import_yup44.string)().oneOf(SupportedStudyTypes).trim().max(50).required().label("Study Type")
|
|
4132
4582
|
}).noUnknown().strict().label("Education");
|
|
4133
4583
|
|
|
4134
4584
|
// src/user/user-skill.schema.ts
|
|
4135
|
-
var
|
|
4136
|
-
var UserSkillSchema = (0,
|
|
4137
|
-
name: (0,
|
|
4138
|
-
proficiencyLevel: (0,
|
|
4585
|
+
var import_yup45 = require("yup");
|
|
4586
|
+
var UserSkillSchema = (0, import_yup45.object)({
|
|
4587
|
+
name: (0, import_yup45.string)().required().label("Name"),
|
|
4588
|
+
proficiencyLevel: (0, import_yup45.string)().oneOf(SupportedProficiencyLevels).required().label("Proficiency Level"),
|
|
4139
4589
|
lastUsed: dateString().format("YYYY-MM").nullable().optional().label("Last Used")
|
|
4140
4590
|
}).noUnknown().strict().label("Skill");
|
|
4141
4591
|
|
|
4142
4592
|
// src/user/project.schema.ts
|
|
4143
|
-
var
|
|
4144
|
-
var UserProjectSchema = (0,
|
|
4145
|
-
name: (0,
|
|
4146
|
-
url: (0,
|
|
4147
|
-
description: (0,
|
|
4593
|
+
var import_yup46 = require("yup");
|
|
4594
|
+
var UserProjectSchema = (0, import_yup46.object)({
|
|
4595
|
+
name: (0, import_yup46.string)().trim().max(50).required().label("Name"),
|
|
4596
|
+
url: (0, import_yup46.string)().optional().label("URL"),
|
|
4597
|
+
description: (0, import_yup46.string)().trim().min(100).max(3e3).required().label("Description"),
|
|
4148
4598
|
duration: DurationSchema({
|
|
4149
4599
|
format: "YYYY-MM",
|
|
4150
4600
|
startLabel: "Start Date",
|
|
@@ -4153,68 +4603,68 @@ var UserProjectSchema = (0, import_yup44.object)({
|
|
|
4153
4603
|
}).noUnknown().strict().label("Project");
|
|
4154
4604
|
|
|
4155
4605
|
// src/user/user-certification.schema.ts
|
|
4156
|
-
var
|
|
4157
|
-
var UserCertificationSchema = (0,
|
|
4158
|
-
name: (0,
|
|
4606
|
+
var import_yup47 = require("yup");
|
|
4607
|
+
var UserCertificationSchema = (0, import_yup47.object)({
|
|
4608
|
+
name: (0, import_yup47.string)().trim().max(100).required().label("Name"),
|
|
4159
4609
|
// TODO: Add validation for authority
|
|
4160
|
-
authority: (0,
|
|
4161
|
-
licenseNumber: (0,
|
|
4610
|
+
authority: (0, import_yup47.string)().trim().max(100).required().label("Authority"),
|
|
4611
|
+
licenseNumber: (0, import_yup47.string)().trim().max(50).optional().label("License Number"),
|
|
4162
4612
|
duration: DurationSchema({
|
|
4163
4613
|
format: "YYYY-MM",
|
|
4164
4614
|
startLabel: "Start Date",
|
|
4165
4615
|
endLabel: "End Date"
|
|
4166
4616
|
}).optional().nullable().label("Duration"),
|
|
4167
|
-
url: (0,
|
|
4617
|
+
url: (0, import_yup47.string)().optional().label("URL")
|
|
4168
4618
|
}).noUnknown().strict().label("Certification");
|
|
4169
4619
|
|
|
4170
4620
|
// src/user/user-interest.schema.ts
|
|
4171
|
-
var
|
|
4172
|
-
var UserInterestSchema = (0,
|
|
4621
|
+
var import_yup48 = require("yup");
|
|
4622
|
+
var UserInterestSchema = (0, import_yup48.object)({
|
|
4173
4623
|
/** The taxonomy entry's id. */
|
|
4174
|
-
id: (0,
|
|
4624
|
+
id: (0, import_yup48.string)().trim().required().label("Interest Id"),
|
|
4175
4625
|
/** Display name, e.g. "Cloud Computing". */
|
|
4176
|
-
name: (0,
|
|
4626
|
+
name: (0, import_yup48.string)().trim().required().label("Interest"),
|
|
4177
4627
|
/** Material-symbols icon name, e.g. "cloud". */
|
|
4178
|
-
logo: (0,
|
|
4628
|
+
logo: (0, import_yup48.string)().trim().required().label("Interest Logo")
|
|
4179
4629
|
}).required().label("Interest");
|
|
4180
4630
|
|
|
4181
4631
|
// src/user/user-language.schema.ts
|
|
4182
|
-
var
|
|
4183
|
-
var UserLanguageSchema = (0,
|
|
4184
|
-
name: (0,
|
|
4185
|
-
proficiencyLevel: (0,
|
|
4632
|
+
var import_yup49 = require("yup");
|
|
4633
|
+
var UserLanguageSchema = (0, import_yup49.object)({
|
|
4634
|
+
name: (0, import_yup49.string)().trim().required().label("Name"),
|
|
4635
|
+
proficiencyLevel: (0, import_yup49.string)().oneOf(SupportedProficiencyLevels).trim().max(50).required().label("Proficiency Level")
|
|
4186
4636
|
}).noUnknown().strict().label("Language");
|
|
4187
4637
|
|
|
4188
4638
|
// src/user/user-additional-info.schema.ts
|
|
4189
|
-
var
|
|
4190
|
-
var UserAdditionalInfoSchema = (0,
|
|
4191
|
-
title: (0,
|
|
4192
|
-
description: (0,
|
|
4639
|
+
var import_yup50 = require("yup");
|
|
4640
|
+
var UserAdditionalInfoSchema = (0, import_yup50.object)({
|
|
4641
|
+
title: (0, import_yup50.string)().trim().max(60).required().label("Title"),
|
|
4642
|
+
description: (0, import_yup50.string)().trim().max(1e3).required().label("Description")
|
|
4193
4643
|
}).noUnknown().strict().label("User Additional Info");
|
|
4194
4644
|
|
|
4195
4645
|
// src/user/general-detail.schema.ts
|
|
4196
|
-
var
|
|
4197
|
-
var UserGeneralDetailSchema = (0,
|
|
4198
|
-
id: (0,
|
|
4199
|
-
name: (0,
|
|
4200
|
-
first: (0,
|
|
4201
|
-
last: (0,
|
|
4646
|
+
var import_yup51 = require("yup");
|
|
4647
|
+
var UserGeneralDetailSchema = (0, import_yup51.object)({
|
|
4648
|
+
id: (0, import_yup51.string)().optional().label("ID"),
|
|
4649
|
+
name: (0, import_yup51.object)().shape({
|
|
4650
|
+
first: (0, import_yup51.string)().trim().max(50).required().label("First Name"),
|
|
4651
|
+
last: (0, import_yup51.string)().trim().max(50).optional().label("Last Name")
|
|
4202
4652
|
}).required().label("Name"),
|
|
4203
|
-
headline: (0,
|
|
4204
|
-
image: (0,
|
|
4653
|
+
headline: (0, import_yup51.string)().trim().max(200).optional().label("Headline"),
|
|
4654
|
+
image: (0, import_yup51.string)().optional().label("Image"),
|
|
4205
4655
|
// The DISPLAYED avatar (`image`) is a flattened export with any status frame
|
|
4206
4656
|
// ("#OpenToWork", …) already burned into the pixels. `imageOriginal` keeps the
|
|
4207
4657
|
// un-framed source the user uploaded, so the image builder can reopen it and
|
|
4208
4658
|
// apply a DIFFERENT frame instead of stacking a second one on top of the first.
|
|
4209
4659
|
// Optional and absent on every pre-existing user: treat a missing value as
|
|
4210
4660
|
// "only the flattened image is available".
|
|
4211
|
-
imageOriginal: (0,
|
|
4212
|
-
aboutMe: (0,
|
|
4213
|
-
email: (0,
|
|
4214
|
-
mobile: (0,
|
|
4215
|
-
emailVerified: (0,
|
|
4216
|
-
mobileVerified: (0,
|
|
4217
|
-
experienceLevel: (0,
|
|
4661
|
+
imageOriginal: (0, import_yup51.string)().optional().label("Original Image"),
|
|
4662
|
+
aboutMe: (0, import_yup51.string)().trim().max(3e3).optional().label("About Me"),
|
|
4663
|
+
email: (0, import_yup51.string)().required().label("Email"),
|
|
4664
|
+
mobile: (0, import_yup51.string)().nullable().optional().label("Mobile"),
|
|
4665
|
+
emailVerified: (0, import_yup51.string)().nullable().optional().label("Email Verified"),
|
|
4666
|
+
mobileVerified: (0, import_yup51.string)().nullable().optional().label("Mobile Verified"),
|
|
4667
|
+
experienceLevel: (0, import_yup51.string)().oneOf(SupportedExperienceLevels).required().label("Experience level"),
|
|
4218
4668
|
/**
|
|
4219
4669
|
* The user's HIGHEST qualification, e.g. `bachelor`.
|
|
4220
4670
|
*
|
|
@@ -4233,7 +4683,7 @@ var UserGeneralDetailSchema = (0, import_yup49.object)({
|
|
|
4233
4683
|
* UNCONSTRAINED on education rather than filtering the user out — the same
|
|
4234
4684
|
* opt-out reasoning `notificationPrefs` uses.
|
|
4235
4685
|
*/
|
|
4236
|
-
educationLevel: (0,
|
|
4686
|
+
educationLevel: (0, import_yup51.string)().oneOf(SupportedEducationLevels).optional().label("Education level"),
|
|
4237
4687
|
location: LocationSchema.required().label("Location"),
|
|
4238
4688
|
/**
|
|
4239
4689
|
* Where the account was created, captured once and never rewritten.
|
|
@@ -4249,38 +4699,38 @@ var UserGeneralDetailSchema = (0, import_yup49.object)({
|
|
|
4249
4699
|
* - `location` derived from the user's self-entered profile location
|
|
4250
4700
|
* - `default` assumed (no signal available); presumption, not evidence
|
|
4251
4701
|
*/
|
|
4252
|
-
signupContext: (0,
|
|
4702
|
+
signupContext: (0, import_yup51.object)().shape({
|
|
4253
4703
|
// ISO 3166-1 alpha-2, uppercase — the shape `cf-ipcountry` returns, so
|
|
4254
4704
|
// measured and inferred values are directly comparable.
|
|
4255
|
-
country: (0,
|
|
4256
|
-
locale: (0,
|
|
4257
|
-
source: (0,
|
|
4258
|
-
at: (0,
|
|
4705
|
+
country: (0, import_yup51.string)().trim().uppercase().length(2).required().label("Signup Country"),
|
|
4706
|
+
locale: (0, import_yup51.string)().trim().required().label("Signup Locale"),
|
|
4707
|
+
source: (0, import_yup51.string)().oneOf(SupportedSignupContextSources).required().label("Signup Context Source"),
|
|
4708
|
+
at: (0, import_yup51.number)().required().label("Signup Context At")
|
|
4259
4709
|
}).optional().default(void 0).label("Signup Context"),
|
|
4260
|
-
profileVisibility: (0,
|
|
4710
|
+
profileVisibility: (0, import_yup51.string)().oneOf(SupportedUserProfileVisibilities).default("public" /* Public */).label("Profile Visibility")
|
|
4261
4711
|
}).noUnknown().strict().label("General Detail");
|
|
4262
4712
|
|
|
4263
4713
|
// src/user/user-job-preferences.schema.ts
|
|
4264
|
-
var
|
|
4265
|
-
var UserJobPreferencesSchema = (0,
|
|
4714
|
+
var import_yup52 = require("yup");
|
|
4715
|
+
var UserJobPreferencesSchema = (0, import_yup52.object)({
|
|
4266
4716
|
/**
|
|
4267
4717
|
* Whether the job seeker is openly signalling availability. Surfaces the
|
|
4268
4718
|
* "Open to work" badge on the public profile and boosts visibility in
|
|
4269
4719
|
* recruiter search. Defaults to `false` - users must opt in.
|
|
4270
4720
|
*/
|
|
4271
|
-
openToWork: (0,
|
|
4721
|
+
openToWork: (0, import_yup52.boolean)().default(false).label("Open to Work"),
|
|
4272
4722
|
/**
|
|
4273
4723
|
* How urgently the user is looking for their next job. Drives match scoring
|
|
4274
4724
|
* and can downgrade the visibility of expired or low-relevance postings for
|
|
4275
4725
|
* users in `passively_browsing` mode.
|
|
4276
4726
|
*/
|
|
4277
|
-
jobSearchUrgency: (0,
|
|
4727
|
+
jobSearchUrgency: (0, import_yup52.string)().oneOf(SupportedJobSearchUrgencies).required().label("Job Search Urgency"),
|
|
4278
4728
|
/**
|
|
4279
4729
|
* Locations the user wants to work in. Stores the full `LocationSchema`
|
|
4280
4730
|
* shape (country, city, state, geo, etc.) as returned by the locations
|
|
4281
4731
|
* autocomplete API.
|
|
4282
4732
|
*/
|
|
4283
|
-
jobLocations: (0,
|
|
4733
|
+
jobLocations: (0, import_yup52.array)().of(LocationSchema.required().label("Job Location")).min(1, "Pick at least one preferred location.").required().label("Job Locations"),
|
|
4284
4734
|
/**
|
|
4285
4735
|
* Seniority levels the user wants jobs to be matched against. Multi-select
|
|
4286
4736
|
* (up to 2) for borderline candidates.
|
|
@@ -4291,7 +4741,7 @@ var UserJobPreferencesSchema = (0, import_yup50.object)({
|
|
|
4291
4741
|
* Both reuse the same `ExperienceLevel` taxonomy from `common.constant.ts`
|
|
4292
4742
|
* so search/match logic doesn't have to translate between two vocabularies.
|
|
4293
4743
|
*/
|
|
4294
|
-
targetExperienceLevels: (0,
|
|
4744
|
+
targetExperienceLevels: (0, import_yup52.array)().of((0, import_yup52.string)().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"),
|
|
4295
4745
|
/**
|
|
4296
4746
|
* Specializations the user is searching for - free-form titles.
|
|
4297
4747
|
*
|
|
@@ -4300,19 +4750,19 @@ var UserJobPreferencesSchema = (0, import_yup50.object)({
|
|
|
4300
4750
|
* surfaces a curated "Popular Roles" picker for discovery, but the user
|
|
4301
4751
|
* can ultimately add any title; matching/normalization happens downstream.
|
|
4302
4752
|
*/
|
|
4303
|
-
jobRoles: (0,
|
|
4753
|
+
jobRoles: (0, import_yup52.array)().of((0, import_yup52.string)().trim().max(120).required()).min(1, "Pick at least one role.").required().label("Job Roles"),
|
|
4304
4754
|
/**
|
|
4305
4755
|
* Minimum acceptable annual base salary, in `minSalaryCurrency`.
|
|
4306
4756
|
* Stored as an integer in the currency's major unit (e.g. dollars, not cents).
|
|
4307
4757
|
* Defaults to 0 ("any salary") rather than being optional - every job-seeker
|
|
4308
4758
|
* has a floor, even if it's zero.
|
|
4309
4759
|
*/
|
|
4310
|
-
minSalary: (0,
|
|
4311
|
-
minSalaryCurrency: (0,
|
|
4760
|
+
minSalary: (0, import_yup52.number)().integer().min(MIN_SALARY_LOWER_BOUND).max(MIN_SALARY_UPPER_BOUND).default(0).required().label("Minimum Salary"),
|
|
4761
|
+
minSalaryCurrency: (0, import_yup52.string)().oneOf(SupportedSalaryCurrencies).default("USD").required().label("Minimum Salary Currency"),
|
|
4312
4762
|
/**
|
|
4313
4763
|
* Marketing-attribution capture from the final onboarding step.
|
|
4314
4764
|
*/
|
|
4315
|
-
referralSource: (0,
|
|
4765
|
+
referralSource: (0, import_yup52.string)().oneOf(SupportedReferralSources).required().label("Referral Source"),
|
|
4316
4766
|
/**
|
|
4317
4767
|
* Resumes the user has uploaded. Embedded directly on the user document
|
|
4318
4768
|
* (capped at 5) - they're cheap to denormalize, every wizard step that
|
|
@@ -4326,25 +4776,25 @@ var UserJobPreferencesSchema = (0, import_yup50.object)({
|
|
|
4326
4776
|
* AI resume-builder flow - onboarding uploads land here, AI-built resumes
|
|
4327
4777
|
* live in their own collection.
|
|
4328
4778
|
*/
|
|
4329
|
-
resumes: (0,
|
|
4330
|
-
(0,
|
|
4779
|
+
resumes: (0, import_yup52.array)().of(
|
|
4780
|
+
(0, import_yup52.object)({
|
|
4331
4781
|
// Stable id assigned on upload - used to address a specific entry
|
|
4332
4782
|
// for delete / set-primary operations without exposing the GCS URL
|
|
4333
4783
|
// as a route key.
|
|
4334
|
-
id: (0,
|
|
4335
|
-
url: (0,
|
|
4336
|
-
filename: (0,
|
|
4337
|
-
sizeBytes: (0,
|
|
4338
|
-
mimeType: (0,
|
|
4339
|
-
uploadedAt: (0,
|
|
4340
|
-
isPrimary: (0,
|
|
4784
|
+
id: (0, import_yup52.string)().required().label("ID"),
|
|
4785
|
+
url: (0, import_yup52.string)().required().label("Resume URL"),
|
|
4786
|
+
filename: (0, import_yup52.string)().trim().max(255).optional().label("Filename"),
|
|
4787
|
+
sizeBytes: (0, import_yup52.number)().integer().min(0).optional().label("Size (bytes)"),
|
|
4788
|
+
mimeType: (0, import_yup52.string)().trim().max(120).optional().label("MIME Type"),
|
|
4789
|
+
uploadedAt: (0, import_yup52.date)().required().label("Uploaded At"),
|
|
4790
|
+
isPrimary: (0, import_yup52.boolean)().default(false).label("Is Primary")
|
|
4341
4791
|
}).noUnknown().strict().label("Resume")
|
|
4342
4792
|
).max(5, "You can keep at most 5 resumes on file.").default([]).label("Resumes"),
|
|
4343
4793
|
/**
|
|
4344
4794
|
* Set when the user finishes the wizard's last step. Acts as the gate the
|
|
4345
4795
|
* onboarding hook checks to redirect users who haven't completed setup.
|
|
4346
4796
|
*/
|
|
4347
|
-
onboardingCompletedAt: (0,
|
|
4797
|
+
onboardingCompletedAt: (0, import_yup52.date)().nullable().optional().label("Onboarding Completed At"),
|
|
4348
4798
|
/**
|
|
4349
4799
|
* Parser-suggested values for wizard fields, written by the resume-upload
|
|
4350
4800
|
* flow. Every parser-derived field lands here - including profile-shaped
|
|
@@ -4364,92 +4814,92 @@ var UserJobPreferencesSchema = (0, import_yup50.object)({
|
|
|
4364
4814
|
* APIs. If `user.<field>` is empty there, the correct behavior is empty,
|
|
4365
4815
|
* because the user has not confirmed it yet.
|
|
4366
4816
|
*/
|
|
4367
|
-
pendingPrefill: (0,
|
|
4368
|
-
headline: (0,
|
|
4369
|
-
aboutMe: (0,
|
|
4370
|
-
mobile: (0,
|
|
4817
|
+
pendingPrefill: (0, import_yup52.object)({
|
|
4818
|
+
headline: (0, import_yup52.string)().trim().optional().label("Pending Headline"),
|
|
4819
|
+
aboutMe: (0, import_yup52.string)().trim().optional().label("Pending About Me"),
|
|
4820
|
+
mobile: (0, import_yup52.string)().trim().optional().label("Pending Mobile"),
|
|
4371
4821
|
location: LocationSchema.optional().default(void 0).label("Pending Location"),
|
|
4372
|
-
experienceLevel: (0,
|
|
4373
|
-
socialAccounts: (0,
|
|
4374
|
-
workExperiences: (0,
|
|
4375
|
-
educations: (0,
|
|
4822
|
+
experienceLevel: (0, import_yup52.string)().oneOf(SupportedExperienceLevels).optional().label("Pending Experience Level"),
|
|
4823
|
+
socialAccounts: (0, import_yup52.array)().of(SocialAccountSchema.required()).optional().label("Pending Social Accounts"),
|
|
4824
|
+
workExperiences: (0, import_yup52.array)().of(WorkExperienceSchema.required()).optional().label("Pending Work Experiences"),
|
|
4825
|
+
educations: (0, import_yup52.array)().of(EducationSchema.required()).optional().label("Pending Educations")
|
|
4376
4826
|
}).nullable().optional().default(void 0).label("Pending Prefill")
|
|
4377
4827
|
}).noUnknown().strict().label("User Job Preferences Schema");
|
|
4378
4828
|
|
|
4379
4829
|
// src/user/user-recruiter-profile.schema.ts
|
|
4380
|
-
var
|
|
4381
|
-
var RecruiterPageLinkSchema = (0,
|
|
4830
|
+
var import_yup53 = require("yup");
|
|
4831
|
+
var RecruiterPageLinkSchema = (0, import_yup53.object)({
|
|
4382
4832
|
page: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Company Page"),
|
|
4383
|
-
jobTitle: (0,
|
|
4833
|
+
jobTitle: (0, import_yup53.string)().trim().max(100).optional().label("Job Title")
|
|
4384
4834
|
}).noUnknown().strict().label("Recruiter Page Link");
|
|
4385
|
-
var UserRecruiterProfileSchema = (0,
|
|
4386
|
-
recruiterProfile: (0,
|
|
4387
|
-
hiringFor: (0,
|
|
4835
|
+
var UserRecruiterProfileSchema = (0, import_yup53.object)({
|
|
4836
|
+
recruiterProfile: (0, import_yup53.object)({
|
|
4837
|
+
hiringFor: (0, import_yup53.array)().of(RecruiterPageLinkSchema).default([]).label("Hiring For")
|
|
4388
4838
|
}).optional().default(void 0).label("Recruiter Profile")
|
|
4389
4839
|
}).noUnknown().strict().label("User Recruiter Profile");
|
|
4390
4840
|
|
|
4391
4841
|
// src/user/user-coordinator-profile.schema.ts
|
|
4392
|
-
var
|
|
4393
|
-
var CoordinatorPageLinkSchema = (0,
|
|
4842
|
+
var import_yup54 = require("yup");
|
|
4843
|
+
var CoordinatorPageLinkSchema = (0, import_yup54.object)({
|
|
4394
4844
|
page: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Institute Page"),
|
|
4395
|
-
jobTitle: (0,
|
|
4845
|
+
jobTitle: (0, import_yup54.string)().trim().max(100).optional().label("Job Title")
|
|
4396
4846
|
}).noUnknown().strict().label("Coordinator Page Link");
|
|
4397
|
-
var UserCoordinatorProfileSchema = (0,
|
|
4398
|
-
coordinatorProfile: (0,
|
|
4399
|
-
coordinatesAt: (0,
|
|
4847
|
+
var UserCoordinatorProfileSchema = (0, import_yup54.object)({
|
|
4848
|
+
coordinatorProfile: (0, import_yup54.object)({
|
|
4849
|
+
coordinatesAt: (0, import_yup54.array)().of(CoordinatorPageLinkSchema).default([]).label("Coordinates At")
|
|
4400
4850
|
}).optional().default(void 0).label("Coordinator Profile")
|
|
4401
4851
|
}).noUnknown().strict().label("User Coordinator Profile");
|
|
4402
4852
|
|
|
4403
4853
|
// src/user/user.schema.ts
|
|
4404
|
-
var UserSchema = (0,
|
|
4854
|
+
var UserSchema = (0, import_yup55.object)({
|
|
4405
4855
|
/**
|
|
4406
4856
|
* Related auth account id from auth Server (e.g. Better auth https://auth.thejob.dev)
|
|
4407
4857
|
*/
|
|
4408
|
-
authAccountId: (0,
|
|
4858
|
+
authAccountId: (0, import_yup55.string)().required().label("Auth Account ID"),
|
|
4409
4859
|
/**
|
|
4410
4860
|
* Social media information about the user (e.g. LinkedIn, GitHub, etc.)
|
|
4411
4861
|
*/
|
|
4412
|
-
socialAccounts: (0,
|
|
4862
|
+
socialAccounts: (0, import_yup55.array)().of(SocialAccountSchema).default([]).label("Social Accounts"),
|
|
4413
4863
|
/**
|
|
4414
4864
|
* Work experience information about the user
|
|
4415
4865
|
*/
|
|
4416
|
-
workExperiences: (0,
|
|
4866
|
+
workExperiences: (0, import_yup55.array)().of(WorkExperienceSchema).required().default([]).label("Work Experiences"),
|
|
4417
4867
|
/**
|
|
4418
4868
|
* Education information about the user
|
|
4419
4869
|
*/
|
|
4420
|
-
educations: (0,
|
|
4870
|
+
educations: (0, import_yup55.array)().of(EducationSchema).required().default([]).label("Educations"),
|
|
4421
4871
|
/**
|
|
4422
4872
|
* Skills information about the user
|
|
4423
4873
|
*/
|
|
4424
|
-
skills: (0,
|
|
4874
|
+
skills: (0, import_yup55.array)().of(UserSkillSchema).required().default([]).label("Skills"),
|
|
4425
4875
|
/**
|
|
4426
4876
|
* Projects information about the user
|
|
4427
4877
|
*/
|
|
4428
|
-
projects: (0,
|
|
4878
|
+
projects: (0, import_yup55.array)().of(UserProjectSchema).default([]).label("Projects"),
|
|
4429
4879
|
/**
|
|
4430
4880
|
* Certifications information about the user
|
|
4431
4881
|
*/
|
|
4432
|
-
certifications: (0,
|
|
4882
|
+
certifications: (0, import_yup55.array)().of(UserCertificationSchema).default([]).label("Certifications"),
|
|
4433
4883
|
/**
|
|
4434
4884
|
* Interests information about the user.
|
|
4435
4885
|
*/
|
|
4436
|
-
interests: (0,
|
|
4886
|
+
interests: (0, import_yup55.array)().of(UserInterestSchema).optional().default([]).label("Interests"),
|
|
4437
4887
|
/**
|
|
4438
4888
|
* Languages information about the user
|
|
4439
4889
|
*/
|
|
4440
|
-
languages: (0,
|
|
4890
|
+
languages: (0, import_yup55.array)().of(UserLanguageSchema).required().default([]).label("Languages"),
|
|
4441
4891
|
/**
|
|
4442
4892
|
* Additional information about the user
|
|
4443
4893
|
*/
|
|
4444
|
-
additionalInfo: (0,
|
|
4894
|
+
additionalInfo: (0, import_yup55.array)().of(UserAdditionalInfoSchema).default([]).label("Additional Information"),
|
|
4445
4895
|
/**
|
|
4446
4896
|
* Status of the user account
|
|
4447
4897
|
*/
|
|
4448
|
-
status: (0,
|
|
4898
|
+
status: (0, import_yup55.string)().oneOf(SupportedUserStatuses).required().label("Status"),
|
|
4449
4899
|
/**
|
|
4450
4900
|
* Roles assigned to the user
|
|
4451
4901
|
*/
|
|
4452
|
-
roles: (0,
|
|
4902
|
+
roles: (0, import_yup55.array)().of((0, import_yup55.string)().oneOf(SupportedUserRoles)).required().default(DefaultUserRoles).label("Roles"),
|
|
4453
4903
|
/**
|
|
4454
4904
|
* Explicit consent to receive marketing email (newsletters, job alerts by
|
|
4455
4905
|
* broadcast, product updates). Marketing sends are HARD-GATED on
|
|
@@ -4461,18 +4911,18 @@ var UserSchema = (0, import_yup53.object)({
|
|
|
4461
4911
|
* unsubscribe sets `subscribed=false` so consent and the email-service
|
|
4462
4912
|
* suppression list stay consistent. Defaults to NOT subscribed (opt-in).
|
|
4463
4913
|
*/
|
|
4464
|
-
marketingConsent: (0,
|
|
4465
|
-
subscribed: (0,
|
|
4914
|
+
marketingConsent: (0, import_yup55.object)({
|
|
4915
|
+
subscribed: (0, import_yup55.boolean)().default(false).label("Subscribed to marketing email"),
|
|
4466
4916
|
/** Epoch ms of the last consent change (opt-in or opt-out). */
|
|
4467
|
-
updatedAt: (0,
|
|
4917
|
+
updatedAt: (0, import_yup55.number)().optional().label("Consent updated at"),
|
|
4468
4918
|
/** Where the consent change originated, e.g. `onboarding`, `unsubscribe`, `settings`. */
|
|
4469
|
-
source: (0,
|
|
4919
|
+
source: (0, import_yup55.string)().optional().label("Consent source"),
|
|
4470
4920
|
/**
|
|
4471
4921
|
* How often the user receives job-alert emails. `off` disables job alerts
|
|
4472
4922
|
* only; other marketing stays governed by `subscribed`. Unset means the
|
|
4473
4923
|
* user has not chosen a cadence yet.
|
|
4474
4924
|
*/
|
|
4475
|
-
jobAlertFrequency: (0,
|
|
4925
|
+
jobAlertFrequency: (0, import_yup55.string)().oneOf(SupportedJobAlertFrequencies).optional().label("Job alert frequency")
|
|
4476
4926
|
}).default({ subscribed: false }).label("Marketing Consent"),
|
|
4477
4927
|
/**
|
|
4478
4928
|
* Per-channel toggles for NOTIFICATION email — mail about activity on the
|
|
@@ -4487,11 +4937,11 @@ var UserSchema = (0, import_yup53.object)({
|
|
|
4487
4937
|
*
|
|
4488
4938
|
* Transactional mail (magic-link, verification) ignores this object entirely.
|
|
4489
4939
|
*/
|
|
4490
|
-
notificationPrefs: (0,
|
|
4491
|
-
groupActivity: (0,
|
|
4492
|
-
jobActivity: (0,
|
|
4493
|
-
applicationUpdates: (0,
|
|
4494
|
-
productUpdates: (0,
|
|
4940
|
+
notificationPrefs: (0, import_yup55.object)({
|
|
4941
|
+
groupActivity: (0, import_yup55.boolean)().default(true).label("Group activity email"),
|
|
4942
|
+
jobActivity: (0, import_yup55.boolean)().default(true).label("Job activity email"),
|
|
4943
|
+
applicationUpdates: (0, import_yup55.boolean)().default(true).label("Application update email"),
|
|
4944
|
+
productUpdates: (0, import_yup55.boolean)().default(false).label("Product update email")
|
|
4495
4945
|
}).default({
|
|
4496
4946
|
groupActivity: true,
|
|
4497
4947
|
jobActivity: true,
|
|
@@ -4518,21 +4968,21 @@ var UserSchema = (0, import_yup53.object)({
|
|
|
4518
4968
|
* subscription (see `PushSubscriptionSchema`). This flag is the user's
|
|
4519
4969
|
* intent, the subscription is the browser grant, and both are required.
|
|
4520
4970
|
*/
|
|
4521
|
-
pushConsent: (0,
|
|
4522
|
-
subscribed: (0,
|
|
4971
|
+
pushConsent: (0, import_yup55.object)({
|
|
4972
|
+
subscribed: (0, import_yup55.boolean)().default(false).label("Subscribed to push notifications"),
|
|
4523
4973
|
/** Epoch ms of the last consent change (opt-in or opt-out). */
|
|
4524
|
-
updatedAt: (0,
|
|
4974
|
+
updatedAt: (0, import_yup55.number)().optional().label("Push consent updated at"),
|
|
4525
4975
|
/** Where the change originated, e.g. `onboarding`, `settings`, `prompt`. */
|
|
4526
|
-
source: (0,
|
|
4976
|
+
source: (0, import_yup55.string)().optional().label("Push consent source")
|
|
4527
4977
|
}).default({ subscribed: false }).label("Push Consent"),
|
|
4528
4978
|
/**
|
|
4529
4979
|
* Vector embedding of the user's profile for semantic/hybrid search.
|
|
4530
4980
|
* Generated from a structured summary of skills, experience, education, etc.
|
|
4531
4981
|
* Only generated for public profiles with sufficient completeness (≥60%).
|
|
4532
4982
|
*/
|
|
4533
|
-
embedding: (0,
|
|
4534
|
-
vector: (0,
|
|
4535
|
-
model: (0,
|
|
4983
|
+
embedding: (0, import_yup55.object)({
|
|
4984
|
+
vector: (0, import_yup55.array)((0, import_yup55.number)().required()).optional().label("Embedding vector"),
|
|
4985
|
+
model: (0, import_yup55.string)().optional().label("Embedding model")
|
|
4536
4986
|
}).nullable().optional().label("Embedding"),
|
|
4537
4987
|
/**
|
|
4538
4988
|
* Epoch ms the account was created, assigned by the storing service.
|
|
@@ -4547,12 +4997,12 @@ var UserSchema = (0, import_yup53.object)({
|
|
|
4547
4997
|
* `updatedAt` is deliberately NOT added alongside it: nothing derives from it
|
|
4548
4998
|
* yet, and an optional field is only safe to add when something needs it.
|
|
4549
4999
|
*/
|
|
4550
|
-
createdAt: (0,
|
|
5000
|
+
createdAt: (0, import_yup55.number)().optional().label("Created At")
|
|
4551
5001
|
}).concat(UserGeneralDetailSchema).concat(UserJobPreferencesSchema).concat(UserRecruiterProfileSchema).concat(UserCoordinatorProfileSchema).noUnknown().strict().label("User Schema");
|
|
4552
5002
|
|
|
4553
5003
|
// src/user/push-subscription.schema.ts
|
|
4554
|
-
var
|
|
4555
|
-
var PushSubscriptionSchema = (0,
|
|
5004
|
+
var import_yup56 = require("yup");
|
|
5005
|
+
var PushSubscriptionSchema = (0, import_yup56.object)({
|
|
4556
5006
|
/**
|
|
4557
5007
|
* The user this subscription belongs to, by the `shortId` every service
|
|
4558
5008
|
* keys a user on, matching `UserSchema.shortId`.
|
|
@@ -4566,7 +5016,7 @@ var PushSubscriptionSchema = (0, import_yup54.object)({
|
|
|
4566
5016
|
* `shortId` of its OWN (see `PushSubscriptionRecord`); one field cannot be
|
|
4567
5017
|
* both the row's id and its owner's.
|
|
4568
5018
|
*/
|
|
4569
|
-
userShortId: (0,
|
|
5019
|
+
userShortId: (0, import_yup56.string)().required().label("User Short ID"),
|
|
4570
5020
|
/**
|
|
4571
5021
|
* The push service URL the browser issued. Vendor-specific (FCM, Mozilla,
|
|
4572
5022
|
* Apple) and effectively unbounded in length, so it carries no length cap.
|
|
@@ -4575,16 +5025,16 @@ var PushSubscriptionSchema = (0, import_yup54.object)({
|
|
|
4575
5025
|
* browser sends back unchanged, and what a 404/410 response identifies as
|
|
4576
5026
|
* dead. Upserts and deletes both key on it.
|
|
4577
5027
|
*/
|
|
4578
|
-
endpoint: (0,
|
|
5028
|
+
endpoint: (0, import_yup56.string)().required().label("Push Endpoint"),
|
|
4579
5029
|
/**
|
|
4580
5030
|
* Encryption material from the browser. Web Push payloads are encrypted to
|
|
4581
5031
|
* these keys, so a row missing either one cannot be delivered to at all.
|
|
4582
5032
|
*/
|
|
4583
|
-
keys: (0,
|
|
5033
|
+
keys: (0, import_yup56.object)({
|
|
4584
5034
|
/** Client public key, base64url. */
|
|
4585
|
-
p256dh: (0,
|
|
5035
|
+
p256dh: (0, import_yup56.string)().required().label("P256DH Key"),
|
|
4586
5036
|
/** Client auth secret, base64url. */
|
|
4587
|
-
auth: (0,
|
|
5037
|
+
auth: (0, import_yup56.string)().required().label("Auth Secret")
|
|
4588
5038
|
}).required().label("Push Keys"),
|
|
4589
5039
|
/**
|
|
4590
5040
|
* Epoch ms the push service says the subscription expires, when it says
|
|
@@ -4592,22 +5042,22 @@ var PushSubscriptionSchema = (0, import_yup54.object)({
|
|
|
4592
5042
|
* informational and never the basis for pruning. A 404/410 on send is the
|
|
4593
5043
|
* only reliable death signal.
|
|
4594
5044
|
*/
|
|
4595
|
-
expirationTime: (0,
|
|
5045
|
+
expirationTime: (0, import_yup56.number)().nullable().optional().label("Expiration Time"),
|
|
4596
5046
|
/**
|
|
4597
5047
|
* The subscribing browser's user agent, kept so a user can recognise their
|
|
4598
5048
|
* own devices in a "where you receive notifications" list. Display only:
|
|
4599
5049
|
* never parsed, and never used to decide delivery.
|
|
4600
5050
|
*/
|
|
4601
|
-
userAgent: (0,
|
|
5051
|
+
userAgent: (0, import_yup56.string)().optional().label("User Agent"),
|
|
4602
5052
|
/** Epoch ms the subscription was first registered. */
|
|
4603
|
-
createdAt: (0,
|
|
5053
|
+
createdAt: (0, import_yup56.number)().optional().label("Created At"),
|
|
4604
5054
|
/**
|
|
4605
5055
|
* Epoch ms this subscription was last confirmed live, refreshed when the
|
|
4606
5056
|
* browser re-registers it. A subscription that stops being refreshed is a
|
|
4607
5057
|
* device that stopped visiting, which is useful for pruning rows that never
|
|
4608
5058
|
* fail loudly enough to be caught by a 410.
|
|
4609
5059
|
*/
|
|
4610
|
-
lastSeenAt: (0,
|
|
5060
|
+
lastSeenAt: (0, import_yup56.number)().optional().label("Last Seen At"),
|
|
4611
5061
|
/**
|
|
4612
5062
|
* Epoch ms the owner explicitly signed out on this device, or absent.
|
|
4613
5063
|
*
|
|
@@ -4617,12 +5067,12 @@ var PushSubscriptionSchema = (0, import_yup54.object)({
|
|
|
4617
5067
|
* so that a MISSING row keeps one meaning to the browser ("stop, this device
|
|
4618
5068
|
* was removed"), which it acts on by dropping its own subscription.
|
|
4619
5069
|
*/
|
|
4620
|
-
signedOutAt: (0,
|
|
5070
|
+
signedOutAt: (0, import_yup56.number)().nullable().optional().label("Signed Out At")
|
|
4621
5071
|
}).noUnknown().strict().label("Push Subscription Schema");
|
|
4622
5072
|
|
|
4623
5073
|
// src/user/user-completeness.schema.ts
|
|
4624
|
-
var
|
|
4625
|
-
var UserCompletenessSchema = (0,
|
|
5074
|
+
var import_yup57 = require("yup");
|
|
5075
|
+
var UserCompletenessSchema = (0, import_yup57.object)({
|
|
4626
5076
|
additionalInfo: CompletenessScoreSchema(0).label("Additional Info"),
|
|
4627
5077
|
// Optional
|
|
4628
5078
|
certifications: CompletenessScoreSchema(0).label("Certifications"),
|
|
@@ -4647,10 +5097,14 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4647
5097
|
0 && (module.exports = {
|
|
4648
5098
|
AnswerChoiceType,
|
|
4649
5099
|
ApplicationReceivePreference,
|
|
5100
|
+
AuditFilterSchema,
|
|
5101
|
+
AuditSchema,
|
|
4650
5102
|
BillingPeriod,
|
|
4651
5103
|
BillingSubscriptionSchema,
|
|
4652
5104
|
BillingTransactionSchema,
|
|
4653
5105
|
CAMPAIGN_MAX_RECIPIENTS_CEILING,
|
|
5106
|
+
CONCEPT_ID_PATTERN,
|
|
5107
|
+
CONCEPT_TYPE_PATTERN,
|
|
4654
5108
|
CONSUME_MAX_UNITS,
|
|
4655
5109
|
CampaignDataSourceSchema,
|
|
4656
5110
|
CampaignEndKind,
|
|
@@ -4666,6 +5120,11 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4666
5120
|
Common,
|
|
4667
5121
|
CompensationType,
|
|
4668
5122
|
CompletenessScoreSchema,
|
|
5123
|
+
ConceptFilterSchema,
|
|
5124
|
+
ConceptMembershipSchema,
|
|
5125
|
+
ConceptProposalFilterSchema,
|
|
5126
|
+
ConceptProposalSchema,
|
|
5127
|
+
ConceptSchema,
|
|
4669
5128
|
ContactTypes,
|
|
4670
5129
|
CoordinatorPageLinkSchema,
|
|
4671
5130
|
CountryFilterSchema,
|
|
@@ -4731,6 +5190,7 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4731
5190
|
MailingListFilterSchema,
|
|
4732
5191
|
MailingListSchema,
|
|
4733
5192
|
MoneySchema,
|
|
5193
|
+
NormalizeContextSchema,
|
|
4734
5194
|
NotificationType,
|
|
4735
5195
|
OccurrenceStatus,
|
|
4736
5196
|
PREFILL_MIRRORED_KEYS,
|
|
@@ -4750,6 +5210,8 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4750
5210
|
PostSchema,
|
|
4751
5211
|
PostStatus,
|
|
4752
5212
|
ProficiencyLevel,
|
|
5213
|
+
ProposalCandidateSchema,
|
|
5214
|
+
ProposalMessageSchema,
|
|
4753
5215
|
PushSubscriptionSchema,
|
|
4754
5216
|
QuestionSchema,
|
|
4755
5217
|
QuestionType,
|
|
@@ -4757,9 +5219,15 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4757
5219
|
ReadAndAcknowledgeQuestionSchema,
|
|
4758
5220
|
RecruiterPageLinkSchema,
|
|
4759
5221
|
ReferralSource,
|
|
5222
|
+
ReleaseFilterSchema,
|
|
5223
|
+
ReleaseSchema,
|
|
4760
5224
|
ReportReason,
|
|
4761
5225
|
ReportSchema,
|
|
5226
|
+
ResolverSettingsSchema,
|
|
5227
|
+
ResolverVerificationSchema,
|
|
4762
5228
|
ResourceType,
|
|
5229
|
+
SCHEDULE_MAX_HOURS,
|
|
5230
|
+
SCHEDULE_MIN_HOURS,
|
|
4763
5231
|
SITEMAP_FORMAT,
|
|
4764
5232
|
SYSTEM_DATE_FORMAT,
|
|
4765
5233
|
SavedSearchSchema,
|
|
@@ -4774,14 +5242,17 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4774
5242
|
StudentCompletenessSchema,
|
|
4775
5243
|
StudyType,
|
|
4776
5244
|
SubscriptionStatus,
|
|
5245
|
+
SuggestedHomeSchema,
|
|
4777
5246
|
SupportedAnswerChoiceTypes,
|
|
4778
5247
|
SupportedApplicationReceivePreferences,
|
|
5248
|
+
SupportedAuditStatuses,
|
|
4779
5249
|
SupportedBillingPeriods,
|
|
4780
5250
|
SupportedCampaignEndKinds,
|
|
4781
5251
|
SupportedCampaignIntervalUnits,
|
|
4782
5252
|
SupportedCampaignStatuses,
|
|
4783
5253
|
SupportedCampaignTriggerKinds,
|
|
4784
5254
|
SupportedCompensationTypes,
|
|
5255
|
+
SupportedConceptSources,
|
|
4785
5256
|
SupportedContactTypes,
|
|
4786
5257
|
SupportedEducationLevels,
|
|
4787
5258
|
SupportedEmployeeCounts,
|
|
@@ -4806,6 +5277,7 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4806
5277
|
SupportedJobSearchUrgencies,
|
|
4807
5278
|
SupportedJobStatuses,
|
|
4808
5279
|
SupportedJobSubCategories,
|
|
5280
|
+
SupportedMatchTypes,
|
|
4809
5281
|
SupportedNotificationTypes,
|
|
4810
5282
|
SupportedOccurrenceStatuses,
|
|
4811
5283
|
SupportedPaddleEnvironments,
|
|
@@ -4815,11 +5287,19 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4815
5287
|
SupportedPlanKinds,
|
|
4816
5288
|
SupportedPlanStatuses,
|
|
4817
5289
|
SupportedPostStatuses,
|
|
5290
|
+
SupportedPrefilterRules,
|
|
4818
5291
|
SupportedProficiencyLevels,
|
|
5292
|
+
SupportedProposalFilters,
|
|
5293
|
+
SupportedProposalKinds,
|
|
5294
|
+
SupportedProposalMessageRoles,
|
|
5295
|
+
SupportedProposalStatuses,
|
|
4819
5296
|
SupportedQuestionTypes,
|
|
4820
5297
|
SupportedQuotaPeriods,
|
|
4821
5298
|
SupportedReferralSources,
|
|
5299
|
+
SupportedReleaseKinds,
|
|
5300
|
+
SupportedReleaseStatuses,
|
|
4822
5301
|
SupportedReportReasons,
|
|
5302
|
+
SupportedResolverVerdicts,
|
|
4823
5303
|
SupportedResourceTypes,
|
|
4824
5304
|
SupportedSalaryCurrencies,
|
|
4825
5305
|
SupportedSavedSearchStatuses,
|
|
@@ -4827,19 +5307,31 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4827
5307
|
SupportedSocialAccounts,
|
|
4828
5308
|
SupportedStudyTypes,
|
|
4829
5309
|
SupportedSubscriptionStatuses,
|
|
5310
|
+
SupportedTaxonomyJobKinds,
|
|
5311
|
+
SupportedTaxonomyJobStates,
|
|
5312
|
+
SupportedTaxonomyNodeKinds,
|
|
5313
|
+
SupportedTaxonomySources,
|
|
4830
5314
|
SupportedTemplateVariableBindingKinds,
|
|
4831
5315
|
SupportedTransactionStatuses,
|
|
5316
|
+
SupportedUnmatchedReasons,
|
|
5317
|
+
SupportedUnmatchedResolutions,
|
|
4832
5318
|
SupportedUserProfileVisibilities,
|
|
4833
5319
|
SupportedUserRoles,
|
|
4834
5320
|
SupportedUserStatuses,
|
|
4835
5321
|
SupportedWorkModes,
|
|
4836
5322
|
TAXONOMY_LABELS,
|
|
5323
|
+
TAXONOMY_NODE_ID_PATTERN,
|
|
5324
|
+
TaxonomyNodeFilterSchema,
|
|
5325
|
+
TaxonomyNodeSchema,
|
|
5326
|
+
TaxonomyScheduleSchema,
|
|
4837
5327
|
TemplateVariableBindingKind,
|
|
4838
5328
|
TemplateVariableBindingSchema,
|
|
4839
5329
|
TerminalCampaignStatuses,
|
|
4840
5330
|
TerminalGeoSyncStatuses,
|
|
4841
5331
|
TermsAcceptedSchema,
|
|
4842
5332
|
TransactionStatus,
|
|
5333
|
+
UnmatchedFilterSchema,
|
|
5334
|
+
UnmatchedTermSchema,
|
|
4843
5335
|
UserAdditionalInfoSchema,
|
|
4844
5336
|
UserCertificationSchema,
|
|
4845
5337
|
UserCompletenessSchema,
|
|
@@ -4858,6 +5350,9 @@ var StudentCompletenessSchema = UserCompletenessSchema.omit([
|
|
|
4858
5350
|
UserSchema,
|
|
4859
5351
|
UserSkillSchema,
|
|
4860
5352
|
UserStatus,
|
|
5353
|
+
VOCABULARY_ID_PATTERN,
|
|
5354
|
+
VocabularySchema,
|
|
5355
|
+
VocabularyTypeSchema,
|
|
4861
5356
|
WorkExperienceSchema,
|
|
4862
5357
|
WorkMode,
|
|
4863
5358
|
canTransitionCampaign,
|