@thejob/schema 2.6.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/dist/index.cjs +769 -752
- package/dist/index.d.cts +19 -13
- package/dist/index.d.ts +19 -13
- package/dist/index.js +755 -738
- package/package.json +1 -1
- package/src/job/job.schema.ts +28 -5
package/dist/index.cjs
CHANGED
|
@@ -685,7 +685,7 @@ var GroupFilterSchema = rejectUnknownKeys(
|
|
|
685
685
|
);
|
|
686
686
|
|
|
687
687
|
// src/job/job.schema.ts
|
|
688
|
-
var
|
|
688
|
+
var import_yup21 = require("yup");
|
|
689
689
|
|
|
690
690
|
// src/location/location.schema.ts
|
|
691
691
|
var import_yup7 = require("yup");
|
|
@@ -904,6 +904,338 @@ var SkillSchema = (0, import_yup15.object)({
|
|
|
904
904
|
tags: (0, import_yup15.array)().of((0, import_yup15.string)().max(50)).max(20).optional().label("Tags")
|
|
905
905
|
}).concat(DbDefaultSchema).noUnknown().strict().label("Skill");
|
|
906
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
|
+
|
|
907
1239
|
// src/question/question.constant.ts
|
|
908
1240
|
var QuestionType = /* @__PURE__ */ ((QuestionType2) => {
|
|
909
1241
|
QuestionType2["Input"] = "input";
|
|
@@ -920,24 +1252,24 @@ var AnswerChoiceType = /* @__PURE__ */ ((AnswerChoiceType2) => {
|
|
|
920
1252
|
var SupportedAnswerChoiceTypes = Object.values(AnswerChoiceType);
|
|
921
1253
|
|
|
922
1254
|
// src/question/question.schema.ts
|
|
923
|
-
var
|
|
924
|
-
var QuestionSchema = (0,
|
|
925
|
-
label: (0,
|
|
926
|
-
default: (0,
|
|
927
|
-
title: (0,
|
|
928
|
-
type: (0,
|
|
929
|
-
isOptional: (0,
|
|
930
|
-
readonly: (0,
|
|
931
|
-
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")
|
|
932
1264
|
});
|
|
933
1265
|
|
|
934
1266
|
// src/question/input-question.schema.ts
|
|
935
|
-
var
|
|
1267
|
+
var import_yup18 = require("yup");
|
|
936
1268
|
var InputQuestionSchema = QuestionSchema.concat(
|
|
937
|
-
(0,
|
|
938
|
-
type: (0,
|
|
939
|
-
preferredAnswer: (0,
|
|
940
|
-
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", {
|
|
941
1273
|
is: (isOptional) => Boolean(isOptional),
|
|
942
1274
|
then: (schema) => schema.optional(),
|
|
943
1275
|
otherwise: (schema) => schema.required()
|
|
@@ -946,10 +1278,10 @@ var InputQuestionSchema = QuestionSchema.concat(
|
|
|
946
1278
|
);
|
|
947
1279
|
|
|
948
1280
|
// src/question/choice-question.schema.ts
|
|
949
|
-
var
|
|
950
|
-
var ChoicePreferredAnswerSchema = (label = "Preferred answer") => (0,
|
|
1281
|
+
var import_yup19 = require("yup");
|
|
1282
|
+
var ChoicePreferredAnswerSchema = (label = "Preferred answer") => (0, import_yup19.mixed)().when("answerChoiceType", {
|
|
951
1283
|
is: (value) => value === "multiple" /* Multiple */,
|
|
952
|
-
then: () => (0,
|
|
1284
|
+
then: () => (0, import_yup19.array)((0, import_yup19.string)()).test(
|
|
953
1285
|
"is-valid-option",
|
|
954
1286
|
`${label} must be from the provided options`,
|
|
955
1287
|
function(answer) {
|
|
@@ -960,7 +1292,7 @@ var ChoicePreferredAnswerSchema = (label = "Preferred answer") => (0, import_yup
|
|
|
960
1292
|
return true;
|
|
961
1293
|
}
|
|
962
1294
|
).optional().label(label),
|
|
963
|
-
otherwise: () => (0,
|
|
1295
|
+
otherwise: () => (0, import_yup19.string)().test(
|
|
964
1296
|
"is-valid-option",
|
|
965
1297
|
`${label} must be from the provided options`,
|
|
966
1298
|
function(answer) {
|
|
@@ -971,20 +1303,20 @@ var ChoicePreferredAnswerSchema = (label = "Preferred answer") => (0, import_yup
|
|
|
971
1303
|
});
|
|
972
1304
|
var getChoiceAnswerSchema = (answerChoiceType, isOptional) => {
|
|
973
1305
|
if (answerChoiceType === "multiple" /* Multiple */) {
|
|
974
|
-
const multiAnswerSchema = (0,
|
|
1306
|
+
const multiAnswerSchema = (0, import_yup19.array)((0, import_yup19.string)().max(500));
|
|
975
1307
|
return isOptional ? multiAnswerSchema.optional().default([]) : multiAnswerSchema.min(1, "Select at least one option.").required("Select at least one option.").default([]);
|
|
976
1308
|
}
|
|
977
|
-
const singleAnswerSchema = (0,
|
|
1309
|
+
const singleAnswerSchema = (0, import_yup19.string)().max(500);
|
|
978
1310
|
return isOptional ? singleAnswerSchema.optional() : singleAnswerSchema.required("Select an option.");
|
|
979
1311
|
};
|
|
980
1312
|
var ChoiceQuestionSchema = QuestionSchema.concat(
|
|
981
|
-
(0,
|
|
982
|
-
type: (0,
|
|
983
|
-
optionsFrom: (0,
|
|
984
|
-
options: (0,
|
|
985
|
-
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"),
|
|
986
1318
|
preferredAnswer: ChoicePreferredAnswerSchema("Preferred answer"),
|
|
987
|
-
answers: (0,
|
|
1319
|
+
answers: (0, import_yup19.mixed)().when(
|
|
988
1320
|
["answerChoiceType", "isOptional"],
|
|
989
1321
|
([answerChoiceType, isOptional]) => getChoiceAnswerSchema(answerChoiceType, isOptional)
|
|
990
1322
|
)
|
|
@@ -992,12 +1324,12 @@ var ChoiceQuestionSchema = QuestionSchema.concat(
|
|
|
992
1324
|
);
|
|
993
1325
|
|
|
994
1326
|
// src/question/read-and-acknowledge.schema.ts
|
|
995
|
-
var
|
|
996
|
-
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.");
|
|
997
1329
|
var ReadAndAcknowledgeQuestionSchema = QuestionSchema.concat(
|
|
998
|
-
(0,
|
|
999
|
-
type: (0,
|
|
1000
|
-
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"),
|
|
1001
1333
|
preferredAnswer: AcknowledgeAnswerSchema.label("Preferred Answer"),
|
|
1002
1334
|
answers: AcknowledgeAnswerSchema.label("Answer")
|
|
1003
1335
|
})
|
|
@@ -1078,20 +1410,20 @@ var SupportedApplicationReceivePreferences = Object.values(
|
|
|
1078
1410
|
);
|
|
1079
1411
|
|
|
1080
1412
|
// src/job/job.schema.ts
|
|
1081
|
-
var JobSchema = (0,
|
|
1413
|
+
var JobSchema = (0, import_yup21.object)({
|
|
1082
1414
|
/** Unique id usable by external systems to reference the job. */
|
|
1083
|
-
uniqueId: (0,
|
|
1415
|
+
uniqueId: (0, import_yup21.string)().optional().label("Unique ID"),
|
|
1084
1416
|
/** Job title shown in listings and search. */
|
|
1085
|
-
headline: (0,
|
|
1417
|
+
headline: (0, import_yup21.string)().required().min(5).max(150).label("Headline"),
|
|
1086
1418
|
/** User-friendly, unique URL identifier. */
|
|
1087
|
-
slug: (0,
|
|
1419
|
+
slug: (0, import_yup21.string)().required().max(250).label("Slug"),
|
|
1088
1420
|
/** How applications are received (inbox vs external website). */
|
|
1089
|
-
applicationReceivePreference: (0,
|
|
1421
|
+
applicationReceivePreference: (0, import_yup21.mixed)().oneOf([
|
|
1090
1422
|
"inbox" /* Inbox */,
|
|
1091
1423
|
"external_website" /* ExternalWebsite */
|
|
1092
1424
|
]).required().label("Preference"),
|
|
1093
1425
|
/** Required when applicationReceivePreference is ExternalWebsite. */
|
|
1094
|
-
externalApplyLink: (0,
|
|
1426
|
+
externalApplyLink: (0, import_yup21.string)().when("applicationReceivePreference", {
|
|
1095
1427
|
is: (value) => value === "external_website" /* ExternalWebsite */,
|
|
1096
1428
|
then: (schema) => schema.url().required().label("Apply for Job link"),
|
|
1097
1429
|
otherwise: (schema) => schema.optional()
|
|
@@ -1099,35 +1431,44 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1099
1431
|
/** Company the job belongs to (subset of PageSchema). */
|
|
1100
1432
|
company: PageSchema.pick(["name", "slug", "type", "logo"]).deepPartial().concat(PageSchema.pick(["name", "type"])).required().label("Company"),
|
|
1101
1433
|
/** @deprecated kept for backwards compatibility. */
|
|
1102
|
-
designation: (0,
|
|
1103
|
-
employmentType: (0,
|
|
1104
|
-
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"),
|
|
1105
1437
|
/**
|
|
1106
|
-
* `
|
|
1107
|
-
*
|
|
1108
|
-
*
|
|
1109
|
-
*
|
|
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`.
|
|
1110
1449
|
*/
|
|
1111
|
-
skills: (0,
|
|
1112
|
-
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")
|
|
1113
1454
|
).nullable().optional().label("Skills"),
|
|
1114
|
-
bookmarks: (0,
|
|
1115
|
-
embedding: (0,
|
|
1116
|
-
vector: (0,
|
|
1117
|
-
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")
|
|
1118
1459
|
}).nullable().optional().label("Embedding"),
|
|
1119
|
-
applicants: (0,
|
|
1120
|
-
applicantCount: (0,
|
|
1121
|
-
externalApplicationLinkClickCount: (0,
|
|
1122
|
-
description: (0,
|
|
1123
|
-
descriptionMarkdown: (0,
|
|
1124
|
-
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"),
|
|
1125
1466
|
/**
|
|
1126
1467
|
* Job locations. Required even for remote roles (compliance/legal). Defaults
|
|
1127
1468
|
* to an empty array; min(1) is intentionally not enforced yet.
|
|
1128
1469
|
*/
|
|
1129
|
-
locations: (0,
|
|
1130
|
-
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"),
|
|
1131
1472
|
/** Posting validity window (start/expiry). */
|
|
1132
1473
|
validity: DurationSchema({
|
|
1133
1474
|
format: SYSTEM_DATE_FORMAT,
|
|
@@ -1140,22 +1481,22 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1140
1481
|
* has no `validity.endDate` and must be verified by crawling its page. Guards
|
|
1141
1482
|
* re-check cadence so the same job is not re-crawled on every sweep.
|
|
1142
1483
|
*/
|
|
1143
|
-
lastExpiryCheckAt: (0,
|
|
1484
|
+
lastExpiryCheckAt: (0, import_yup21.number)().optional().nullable().label("Last expiry check at"),
|
|
1144
1485
|
/**
|
|
1145
1486
|
* When this job transitioned to `status: closed` (epoch ms). Server-owned
|
|
1146
1487
|
* operational field: stamped by every jobs-service close path (expiry
|
|
1147
1488
|
* auto-close and the dated lapse sweep). Distinct from `updatedAt` so a later
|
|
1148
1489
|
* edit to a closed job does not move it.
|
|
1149
1490
|
*/
|
|
1150
|
-
closedAt: (0,
|
|
1151
|
-
experienceLevel: (0,
|
|
1152
|
-
contactEmail: (0,
|
|
1153
|
-
workingHoursPerWeek: (0,
|
|
1154
|
-
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"),
|
|
1155
1496
|
/** Direct/Quick-apply questionnaire. Each item is validated against the
|
|
1156
1497
|
* concrete question schema for its `type`, with the stored `answers` omitted. */
|
|
1157
|
-
questionnaire: (0,
|
|
1158
|
-
(0,
|
|
1498
|
+
questionnaire: (0, import_yup21.array)().of(
|
|
1499
|
+
(0, import_yup21.lazy)((question) => {
|
|
1159
1500
|
const schema = getSchemaByQuestion(question.type);
|
|
1160
1501
|
if (question.type === "input" /* Input */) {
|
|
1161
1502
|
return schema.omit([
|
|
@@ -1171,12 +1512,12 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1171
1512
|
return schema;
|
|
1172
1513
|
})
|
|
1173
1514
|
).label("Questionnaire"),
|
|
1174
|
-
status: (0,
|
|
1175
|
-
seoTags: (0,
|
|
1176
|
-
description: (0,
|
|
1177
|
-
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")
|
|
1178
1519
|
}).nullable().optional().label("SEO Tags"),
|
|
1179
|
-
jdSummary: (0,
|
|
1520
|
+
jdSummary: (0, import_yup21.string)().optional().label("JD Summary"),
|
|
1180
1521
|
/**
|
|
1181
1522
|
* Structured, model-extracted sections of the posting, re-organized into clean
|
|
1182
1523
|
* bullet points. This is our OWN unique presentation of the job (rendered as the
|
|
@@ -1185,28 +1526,28 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1185
1526
|
* optional: absent on jobs not yet (re-)enriched, and any section is `[]`/omitted
|
|
1186
1527
|
* when the posting genuinely has none.
|
|
1187
1528
|
*/
|
|
1188
|
-
jobHighlights: (0,
|
|
1189
|
-
responsibilities: (0,
|
|
1190
|
-
requirements: (0,
|
|
1191
|
-
benefits: (0,
|
|
1192
|
-
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")
|
|
1193
1534
|
}).nullable().optional().label("Job Highlights"),
|
|
1194
|
-
canCreateAlert: (0,
|
|
1195
|
-
canDirectApply: (0,
|
|
1196
|
-
hasApplied: (0,
|
|
1197
|
-
isOwner: (0,
|
|
1198
|
-
hasBookmarked: (0,
|
|
1199
|
-
hasReported: (0,
|
|
1200
|
-
ratePerHour: (0,
|
|
1201
|
-
isPromoted: (0,
|
|
1202
|
-
salaryRange: (0,
|
|
1203
|
-
currency: (0,
|
|
1204
|
-
min: (0,
|
|
1205
|
-
max: (0,
|
|
1206
|
-
compensationType: (0,
|
|
1207
|
-
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")
|
|
1208
1549
|
}).nullable().optional().label("Salary Range"),
|
|
1209
|
-
reports: (0,
|
|
1550
|
+
reports: (0, import_yup21.array)().of(UserIdAndCreatedAtSchema).optional().label("Reports"),
|
|
1210
1551
|
// Taxonomy fields are constants (see job-taxonomy.constant.ts), stored as slugs and
|
|
1211
1552
|
// translated for display. They are deliberately NOT `oneOf`-constrained here: a value
|
|
1212
1553
|
// outside the taxonomy must be DROPPED, never a reason to reject the posting. Yup
|
|
@@ -1219,17 +1560,25 @@ var JobSchema = (0, import_yup20.object)({
|
|
|
1219
1560
|
// time (values get renamed, retired, added), so stored jobs will always outlive the
|
|
1220
1561
|
// enum — being lenient here is what lets the taxonomy evolve without a migration
|
|
1221
1562
|
// gate on every write.
|
|
1222
|
-
category: (0,
|
|
1223
|
-
industry: (0,
|
|
1224
|
-
subCategories: (0,
|
|
1225
|
-
|
|
1226
|
-
|
|
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"),
|
|
1227
1576
|
/** Market country codes to feature this job in; empty = global. */
|
|
1228
|
-
featuredMarkets: (0,
|
|
1577
|
+
featuredMarkets: (0, import_yup21.array)().of((0, import_yup21.string)().required()).optional().default([]).label("Featured markets")
|
|
1229
1578
|
}).concat(DbDefaultSchema).noUnknown().label("Job");
|
|
1230
1579
|
|
|
1231
1580
|
// src/job/job-filter.schema.ts
|
|
1232
|
-
var
|
|
1581
|
+
var import_yup22 = require("yup");
|
|
1233
1582
|
|
|
1234
1583
|
// src/user/user.constant.ts
|
|
1235
1584
|
var UserRole = /* @__PURE__ */ ((UserRole2) => {
|
|
@@ -2417,7 +2766,7 @@ var TAXONOMY_LABELS = {
|
|
|
2417
2766
|
|
|
2418
2767
|
// src/job/job-filter.schema.ts
|
|
2419
2768
|
var GEO_GROUP = "Geo";
|
|
2420
|
-
var JobFilterShape = (0,
|
|
2769
|
+
var JobFilterShape = (0, import_yup22.object)({
|
|
2421
2770
|
// ── Classification ──────────────────────────────────────────────────────────
|
|
2422
2771
|
// Closed vocabularies, sent verbatim and matched exactly: a partial match
|
|
2423
2772
|
// would make "remote" also match a hypothetical "remote_first".
|
|
@@ -2560,8 +2909,8 @@ var JobFilterShape = (0, import_yup21.object)({
|
|
|
2560
2909
|
// ── Flags ───────────────────────────────────────────────────────────────────
|
|
2561
2910
|
// No `.default(false)`: an unchecked box must mean "no constraint", not "only
|
|
2562
2911
|
// the non-featured ones", so absent simply omits the clause.
|
|
2563
|
-
isFeatured: (0,
|
|
2564
|
-
isPromoted: (0,
|
|
2912
|
+
isFeatured: (0, import_yup22.boolean)().optional().label("Featured Only"),
|
|
2913
|
+
isPromoted: (0, import_yup22.boolean)().optional().label("Promoted Only"),
|
|
2565
2914
|
featuredMarkets: tokens("Featured Markets"),
|
|
2566
2915
|
// ── Ranges ──────────────────────────────────────────────────────────────────
|
|
2567
2916
|
/**
|
|
@@ -2572,10 +2921,10 @@ var JobFilterShape = (0, import_yup21.object)({
|
|
|
2572
2921
|
// can be selected and a bound is meaningless across them. Here the currency is
|
|
2573
2922
|
// a single sibling field, so the bound is plain and the currency simply
|
|
2574
2923
|
// narrows which jobs are compared.
|
|
2575
|
-
salary: (0,
|
|
2576
|
-
min: (0,
|
|
2577
|
-
max: (0,
|
|
2578
|
-
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")
|
|
2579
2928
|
}).optional().default(void 0).label("Salary"),
|
|
2580
2929
|
/** Posted within this many days. Relative, so a saved filter does not rot. */
|
|
2581
2930
|
postedWithinDays: days("Posted Within (days)"),
|
|
@@ -2584,7 +2933,7 @@ var JobFilterShape = (0, import_yup21.object)({
|
|
|
2584
2933
|
* relative `postedWithinDays`. EPOCH MS, matching how the field is stored — a
|
|
2585
2934
|
* coerced date string would not compare.
|
|
2586
2935
|
*/
|
|
2587
|
-
createdAt: (0,
|
|
2936
|
+
createdAt: (0, import_yup22.object)({
|
|
2588
2937
|
min: epoch("Posted After"),
|
|
2589
2938
|
max: epoch("Posted Before")
|
|
2590
2939
|
}).optional().default(void 0).label("Posted Between")
|
|
@@ -2638,7 +2987,7 @@ function deriveIndustry(category, subCategories) {
|
|
|
2638
2987
|
}
|
|
2639
2988
|
|
|
2640
2989
|
// src/post/post.schema.ts
|
|
2641
|
-
var
|
|
2990
|
+
var import_yup23 = require("yup");
|
|
2642
2991
|
|
|
2643
2992
|
// src/post/post.constant.ts
|
|
2644
2993
|
var PostStatus = /* @__PURE__ */ ((PostStatus2) => {
|
|
@@ -2650,41 +2999,41 @@ var PostStatus = /* @__PURE__ */ ((PostStatus2) => {
|
|
|
2650
2999
|
var SupportedPostStatuses = Object.values(PostStatus);
|
|
2651
3000
|
|
|
2652
3001
|
// src/post/post.schema.ts
|
|
2653
|
-
var PostSchema = (0,
|
|
3002
|
+
var PostSchema = (0, import_yup23.object)({
|
|
2654
3003
|
/** Headline shown in listings and at the top of the post. */
|
|
2655
|
-
title: (0,
|
|
3004
|
+
title: (0, import_yup23.string)().required().min(5).max(200).label("Title"),
|
|
2656
3005
|
/** User-friendly, unique URL identifier. */
|
|
2657
|
-
slug: (0,
|
|
3006
|
+
slug: (0, import_yup23.string)().required().max(250).label("Slug"),
|
|
2658
3007
|
/** Short summary used in listings and meta description fallback. */
|
|
2659
|
-
excerpt: (0,
|
|
3008
|
+
excerpt: (0, import_yup23.string)().max(500).optional().label("Excerpt"),
|
|
2660
3009
|
/** Rendered HTML source of truth for the post body (sanitized on write/render).
|
|
2661
3010
|
* Supports rich formatting markdown can't express (image size/alignment, etc). */
|
|
2662
|
-
bodyHTML: (0,
|
|
3011
|
+
bodyHTML: (0, import_yup23.string)().required().min(1).label("Body (HTML)"),
|
|
2663
3012
|
/** Optional Markdown mirror of the body (portable text / search fallback).
|
|
2664
3013
|
* Kept for back-compat and plain-text derivation; bodyHTML is authoritative. */
|
|
2665
|
-
bodyMarkdown: (0,
|
|
3014
|
+
bodyMarkdown: (0, import_yup23.string)().optional().label("Body (Markdown)"),
|
|
2666
3015
|
/** Cover/hero image URL. Not `.url()`-validated: the value is either an
|
|
2667
3016
|
* uploaded file URL served by this platform (which may be a bare host like
|
|
2668
3017
|
* `http://localhost:3082/...` in dev, that yup's `.url()` wrongly rejects) or
|
|
2669
3018
|
* an admin-pasted link. Kept as a plain string; empty ⇒ null. */
|
|
2670
|
-
coverImage: (0,
|
|
3019
|
+
coverImage: (0, import_yup23.string)().nullable().optional().label("Cover image"),
|
|
2671
3020
|
/** Author (user id). */
|
|
2672
|
-
authorId: (0,
|
|
3021
|
+
authorId: (0, import_yup23.string)().required().label("Author ID"),
|
|
2673
3022
|
/** Free-form tags for filtering and related-posts. */
|
|
2674
|
-
tags: (0,
|
|
3023
|
+
tags: (0, import_yup23.array)().of((0, import_yup23.string)().trim().required()).default([]).label("Tags"),
|
|
2675
3024
|
/** Estimated reading time in minutes (server-derived from body length). */
|
|
2676
|
-
readingTimeMinutes: (0,
|
|
3025
|
+
readingTimeMinutes: (0, import_yup23.number)().min(0).optional().label("Reading time (minutes)"),
|
|
2677
3026
|
/** SEO overrides. */
|
|
2678
|
-
seoTags: (0,
|
|
2679
|
-
description: (0,
|
|
2680
|
-
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")
|
|
2681
3030
|
}).nullable().optional().label("SEO Tags"),
|
|
2682
3031
|
/** When the post was first published (epoch ms). Server-owned. */
|
|
2683
|
-
publishedAt: (0,
|
|
3032
|
+
publishedAt: (0, import_yup23.number)().nullable().optional().label("Published at"),
|
|
2684
3033
|
/** Whether the post is featured in the blog listing. */
|
|
2685
|
-
isFeatured: (0,
|
|
3034
|
+
isFeatured: (0, import_yup23.boolean)().default(false).optional().label("Is featured"),
|
|
2686
3035
|
/** Publication state. */
|
|
2687
|
-
status: (0,
|
|
3036
|
+
status: (0, import_yup23.string)().oneOf(SupportedPostStatuses).default("draft" /* Draft */).required().label("Status")
|
|
2688
3037
|
}).concat(DbDefaultSchema).noUnknown().label("Post");
|
|
2689
3038
|
|
|
2690
3039
|
// src/geo/geo.constant.ts
|
|
@@ -2734,11 +3083,11 @@ var GEO_COLLECTIONS = {
|
|
|
2734
3083
|
var GEO_SEARCH_MAX = 64;
|
|
2735
3084
|
|
|
2736
3085
|
// src/geo/country.schema.ts
|
|
2737
|
-
var
|
|
2738
|
-
var CountrySchema = (0,
|
|
3086
|
+
var import_yup24 = require("yup");
|
|
3087
|
+
var CountrySchema = (0, import_yup24.object)({
|
|
2739
3088
|
/** The upstream dr5hn id. Stable, and the key every upsert matches on. */
|
|
2740
|
-
id: (0,
|
|
2741
|
-
name: (0,
|
|
3089
|
+
id: (0, import_yup24.number)().integer().required().label("ID"),
|
|
3090
|
+
name: (0, import_yup24.string)().trim().required().label("Name"),
|
|
2742
3091
|
/**
|
|
2743
3092
|
* ISO 3166-1 alpha-2, UPPERCASE (`IN`, `SE`).
|
|
2744
3093
|
*
|
|
@@ -2747,34 +3096,34 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2747
3096
|
* already clean uppercase alpha-2. A lowercase value here would compare
|
|
2748
3097
|
* unequal to all of them and silently match nothing.
|
|
2749
3098
|
*/
|
|
2750
|
-
countryCode: (0,
|
|
2751
|
-
iso3: (0,
|
|
2752
|
-
numericCode: (0,
|
|
2753
|
-
phonecode: (0,
|
|
2754
|
-
capital: (0,
|
|
2755
|
-
currency: (0,
|
|
2756
|
-
currencyName: (0,
|
|
2757
|
-
currencySymbol: (0,
|
|
2758
|
-
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"),
|
|
2759
3108
|
/** The name in its own script, e.g. "भारत". Stored, but NOT searchable; see `searchByLocale`. */
|
|
2760
|
-
native: (0,
|
|
2761
|
-
population: (0,
|
|
2762
|
-
gdp: (0,
|
|
2763
|
-
region: (0,
|
|
2764
|
-
regionId: (0,
|
|
2765
|
-
subregion: (0,
|
|
2766
|
-
subregionId: (0,
|
|
2767
|
-
nationality: (0,
|
|
2768
|
-
areaSqKm: (0,
|
|
2769
|
-
postalCodeFormat: (0,
|
|
2770
|
-
postalCodeRegex: (0,
|
|
2771
|
-
timezones: (0,
|
|
2772
|
-
(0,
|
|
2773
|
-
zoneName: (0,
|
|
2774
|
-
gmtOffset: (0,
|
|
2775
|
-
gmtOffsetName: (0,
|
|
2776
|
-
abbreviation: (0,
|
|
2777
|
-
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")
|
|
2778
3127
|
})
|
|
2779
3128
|
).optional().nullable().label("Timezones"),
|
|
2780
3129
|
/**
|
|
@@ -2783,7 +3132,7 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2783
3132
|
* declaring it here would turn a new locale into a validation failure. The
|
|
2784
3133
|
* VALUES are split per-locale into `searchByLocale`.
|
|
2785
3134
|
*/
|
|
2786
|
-
translations: (0,
|
|
3135
|
+
translations: (0, import_yup24.object)().optional().nullable().label("Translations"),
|
|
2787
3136
|
/**
|
|
2788
3137
|
* Coordinates as NUMBERS.
|
|
2789
3138
|
*
|
|
@@ -2792,10 +3141,10 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2792
3141
|
* `"9" > "10"` is true, so a bounding-box filter would be quietly wrong rather
|
|
2793
3142
|
* than failing loudly.
|
|
2794
3143
|
*/
|
|
2795
|
-
latitude: (0,
|
|
2796
|
-
longitude: (0,
|
|
2797
|
-
emoji: (0,
|
|
2798
|
-
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"),
|
|
2799
3148
|
/**
|
|
2800
3149
|
* The name field searched for the DEFAULT (English) locale: the canonical
|
|
2801
3150
|
* `name`, and nothing else.
|
|
@@ -2805,7 +3154,7 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2805
3154
|
* field would make every locale's search implicitly a search of all 19
|
|
2806
3155
|
* languages: a French UI searching "Inde" would also match German "Indien".
|
|
2807
3156
|
*/
|
|
2808
|
-
searchDefault: (0,
|
|
3157
|
+
searchDefault: (0, import_yup24.array)().of((0, import_yup24.string)().required()).optional().default([]).label("Search Default"),
|
|
2809
3158
|
/**
|
|
2810
3159
|
* Per-locale name fields, keyed by lowercased BCP-47 tag (`de`, `pt-br`).
|
|
2811
3160
|
* Each carries ONLY that locale's translation, which is what makes
|
|
@@ -2823,21 +3172,21 @@ var CountrySchema = (0, import_yup23.object)({
|
|
|
2823
3172
|
* it, zh-CN, tr, ru, uk, pl, hi, ar. **`sv` is absent**, so a Swedish search
|
|
2824
3173
|
* matches nothing. That is the accepted cost of strict scoping.
|
|
2825
3174
|
*/
|
|
2826
|
-
searchByLocale: (0,
|
|
3175
|
+
searchByLocale: (0, import_yup24.object)().optional().nullable().label("Search By Locale"),
|
|
2827
3176
|
/** Epoch ms of the run that last wrote this row. Drives the stale-row prune. */
|
|
2828
|
-
syncedAt: (0,
|
|
3177
|
+
syncedAt: (0, import_yup24.number)().optional().nullable().label("Synced At")
|
|
2829
3178
|
}).label("Country");
|
|
2830
3179
|
|
|
2831
3180
|
// src/geo/state.schema.ts
|
|
2832
|
-
var
|
|
2833
|
-
var StateSchema = (0,
|
|
3181
|
+
var import_yup25 = require("yup");
|
|
3182
|
+
var StateSchema = (0, import_yup25.object)({
|
|
2834
3183
|
/** The upstream dr5hn id. Stable, and the key every upsert matches on. */
|
|
2835
|
-
id: (0,
|
|
2836
|
-
name: (0,
|
|
2837
|
-
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"),
|
|
2838
3187
|
/** ISO 3166-1 alpha-2 of the parent, UPPERCASE. See `CountrySchema.countryCode`. */
|
|
2839
|
-
countryCode: (0,
|
|
2840
|
-
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"),
|
|
2841
3190
|
/**
|
|
2842
3191
|
* The BARE subdivision code, e.g. `KA` (upstream `iso2`).
|
|
2843
3192
|
*
|
|
@@ -2849,22 +3198,22 @@ var StateSchema = (0, import_yup24.object)({
|
|
|
2849
3198
|
* both are stored so the migration has its destination present before any
|
|
2850
3199
|
* consumer moves.
|
|
2851
3200
|
*/
|
|
2852
|
-
stateCode: (0,
|
|
3201
|
+
stateCode: (0, import_yup25.string)().trim().uppercase().optional().nullable().label("State Code"),
|
|
2853
3202
|
/** Fully-qualified ISO 3166-2, e.g. `IN-KA` (upstream `iso3166_2`). */
|
|
2854
|
-
stateCodeIso: (0,
|
|
2855
|
-
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"),
|
|
2856
3205
|
/** Upstream's own word for the subdivision: "province", "state", "district", … */
|
|
2857
|
-
type: (0,
|
|
2858
|
-
level: (0,
|
|
2859
|
-
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"),
|
|
2860
3209
|
/** The name in its own script. Stored, but NOT searchable; see `searchByLocale`. */
|
|
2861
|
-
native: (0,
|
|
3210
|
+
native: (0, import_yup25.string)().trim().optional().nullable().label("Native Name"),
|
|
2862
3211
|
/** Numbers, not the strings upstream ships. See `CountrySchema.latitude`. */
|
|
2863
|
-
latitude: (0,
|
|
2864
|
-
longitude: (0,
|
|
2865
|
-
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"),
|
|
2866
3215
|
/** Localized names keyed by locale. Unshaped; see `CountrySchema.translations`. */
|
|
2867
|
-
translations: (0,
|
|
3216
|
+
translations: (0, import_yup25.object)().optional().nullable().label("Translations"),
|
|
2868
3217
|
/**
|
|
2869
3218
|
* The name field searched for the DEFAULT (English) locale: the canonical
|
|
2870
3219
|
* `name`, and nothing else.
|
|
@@ -2874,7 +3223,7 @@ var StateSchema = (0, import_yup24.object)({
|
|
|
2874
3223
|
* field would make every locale's search implicitly a search of all 19
|
|
2875
3224
|
* languages: a French UI searching "Inde" would also match German "Indien".
|
|
2876
3225
|
*/
|
|
2877
|
-
searchDefault: (0,
|
|
3226
|
+
searchDefault: (0, import_yup25.array)().of((0, import_yup25.string)().required()).optional().default([]).label("Search Default"),
|
|
2878
3227
|
/**
|
|
2879
3228
|
* Per-locale name fields, keyed by lowercased BCP-47 tag (`de`, `pt-br`).
|
|
2880
3229
|
* Each carries ONLY that locale's translation, which is what makes
|
|
@@ -2892,20 +3241,20 @@ var StateSchema = (0, import_yup24.object)({
|
|
|
2892
3241
|
* it, zh-CN, tr, ru, uk, pl, hi, ar. **`sv` is absent**, so a Swedish search
|
|
2893
3242
|
* matches nothing. That is the accepted cost of strict scoping.
|
|
2894
3243
|
*/
|
|
2895
|
-
searchByLocale: (0,
|
|
3244
|
+
searchByLocale: (0, import_yup25.object)().optional().nullable().label("Search By Locale"),
|
|
2896
3245
|
/** Epoch ms of the run that last wrote this row. Drives the stale-row prune. */
|
|
2897
|
-
syncedAt: (0,
|
|
3246
|
+
syncedAt: (0, import_yup25.number)().optional().nullable().label("Synced At")
|
|
2898
3247
|
}).label("State");
|
|
2899
3248
|
|
|
2900
3249
|
// src/geo/city.schema.ts
|
|
2901
|
-
var
|
|
2902
|
-
var CitySchema = (0,
|
|
3250
|
+
var import_yup26 = require("yup");
|
|
3251
|
+
var CitySchema = (0, import_yup26.object)({
|
|
2903
3252
|
/** The upstream dr5hn id. Stable, and the key every upsert matches on. */
|
|
2904
|
-
id: (0,
|
|
2905
|
-
name: (0,
|
|
2906
|
-
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"),
|
|
2907
3256
|
/** The BARE subdivision code. Only meaningful paired with `countryCode`; see `StateSchema`. */
|
|
2908
|
-
stateCode: (0,
|
|
3257
|
+
stateCode: (0, import_yup26.string)().trim().uppercase().optional().nullable().label("State Code"),
|
|
2909
3258
|
/**
|
|
2910
3259
|
* Fully-qualified ISO 3166-2, e.g. `IN-KA`.
|
|
2911
3260
|
*
|
|
@@ -2915,29 +3264,29 @@ var CitySchema = (0, import_yup25.object)({
|
|
|
2915
3264
|
* migration can re-point the cities route without a 153k-row re-ingest.
|
|
2916
3265
|
* Null when either half is missing.
|
|
2917
3266
|
*/
|
|
2918
|
-
stateCodeIso: (0,
|
|
2919
|
-
stateName: (0,
|
|
2920
|
-
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"),
|
|
2921
3270
|
/** ISO 3166-1 alpha-2 of the parent, UPPERCASE. See `CountrySchema.countryCode`. */
|
|
2922
|
-
countryCode: (0,
|
|
2923
|
-
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"),
|
|
2924
3273
|
/** Numbers, not the strings upstream ships. See `CountrySchema.latitude`. */
|
|
2925
|
-
latitude: (0,
|
|
2926
|
-
longitude: (0,
|
|
3274
|
+
latitude: (0, import_yup26.number)().optional().nullable().label("Latitude"),
|
|
3275
|
+
longitude: (0, import_yup26.number)().optional().nullable().label("Longitude"),
|
|
2927
3276
|
/** The name in its own script. Stored, but NOT searchable; see `searchByLocale`. */
|
|
2928
|
-
native: (0,
|
|
2929
|
-
type: (0,
|
|
2930
|
-
level: (0,
|
|
2931
|
-
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"),
|
|
2932
3281
|
/**
|
|
2933
3282
|
* Null on most rows. Worth keeping (it is a good relevance signal when
|
|
2934
3283
|
* present) but never worth SORTING by alone, since a null-heavy sort buries
|
|
2935
3284
|
* every city upstream has no figure for.
|
|
2936
3285
|
*/
|
|
2937
|
-
population: (0,
|
|
2938
|
-
timezone: (0,
|
|
3286
|
+
population: (0, import_yup26.number)().optional().nullable().label("Population"),
|
|
3287
|
+
timezone: (0, import_yup26.string)().trim().optional().nullable().label("Timezone"),
|
|
2939
3288
|
/** Localized names keyed by locale. Unshaped; see `CountrySchema.translations`. */
|
|
2940
|
-
translations: (0,
|
|
3289
|
+
translations: (0, import_yup26.object)().optional().nullable().label("Translations"),
|
|
2941
3290
|
/**
|
|
2942
3291
|
* The name field searched for the DEFAULT (English) locale: the canonical
|
|
2943
3292
|
* `name`, and nothing else.
|
|
@@ -2947,7 +3296,7 @@ var CitySchema = (0, import_yup25.object)({
|
|
|
2947
3296
|
* field would make every locale's search implicitly a search of all 19
|
|
2948
3297
|
* languages: a French UI searching "Inde" would also match German "Indien".
|
|
2949
3298
|
*/
|
|
2950
|
-
searchDefault: (0,
|
|
3299
|
+
searchDefault: (0, import_yup26.array)().of((0, import_yup26.string)().required()).optional().default([]).label("Search Default"),
|
|
2951
3300
|
/**
|
|
2952
3301
|
* Per-locale name fields, keyed by lowercased BCP-47 tag (`de`, `pt-br`).
|
|
2953
3302
|
* Each carries ONLY that locale's translation, which is what makes
|
|
@@ -2965,14 +3314,14 @@ var CitySchema = (0, import_yup25.object)({
|
|
|
2965
3314
|
* it, zh-CN, tr, ru, uk, pl, hi, ar. **`sv` is absent**, so a Swedish search
|
|
2966
3315
|
* matches nothing. That is the accepted cost of strict scoping.
|
|
2967
3316
|
*/
|
|
2968
|
-
searchByLocale: (0,
|
|
3317
|
+
searchByLocale: (0, import_yup26.object)().optional().nullable().label("Search By Locale"),
|
|
2969
3318
|
/** Epoch ms of the run that last wrote this row. Drives the stale-row prune. */
|
|
2970
|
-
syncedAt: (0,
|
|
3319
|
+
syncedAt: (0, import_yup26.number)().optional().nullable().label("Synced At")
|
|
2971
3320
|
}).label("City");
|
|
2972
3321
|
|
|
2973
3322
|
// src/geo/country-filter.schema.ts
|
|
2974
|
-
var
|
|
2975
|
-
var CountryFilterShape = (0,
|
|
3323
|
+
var import_yup27 = require("yup");
|
|
3324
|
+
var CountryFilterShape = (0, import_yup27.object)({
|
|
2976
3325
|
/** ISO 3166-1 alpha-2 codes, e.g. `IN`. Uppercased, matching how they are stored. */
|
|
2977
3326
|
countryCodes: codeTokens("Country Codes"),
|
|
2978
3327
|
/** ISO 3166-1 alpha-3 codes, e.g. `IND`. */
|
|
@@ -2992,8 +3341,8 @@ var CountryFilterSchema = rejectUnknownKeys(
|
|
|
2992
3341
|
);
|
|
2993
3342
|
|
|
2994
3343
|
// src/geo/state-filter.schema.ts
|
|
2995
|
-
var
|
|
2996
|
-
var StateFilterShape = (0,
|
|
3344
|
+
var import_yup28 = require("yup");
|
|
3345
|
+
var StateFilterShape = (0, import_yup28.object)({
|
|
2997
3346
|
/** ISO 3166-1 alpha-2 of the parent country, e.g. `IN`. */
|
|
2998
3347
|
countryCodes: codeTokens("Country Codes"),
|
|
2999
3348
|
/**
|
|
@@ -3023,8 +3372,8 @@ var StateFilterSchema = rejectUnknownKeys(
|
|
|
3023
3372
|
);
|
|
3024
3373
|
|
|
3025
3374
|
// src/geo/city-filter.schema.ts
|
|
3026
|
-
var
|
|
3027
|
-
var CityFilterShape = (0,
|
|
3375
|
+
var import_yup29 = require("yup");
|
|
3376
|
+
var CityFilterShape = (0, import_yup29.object)({
|
|
3028
3377
|
/** ISO 3166-1 alpha-2 of the parent country, e.g. `IN`. */
|
|
3029
3378
|
countryCodes: codeTokens("Country Codes"),
|
|
3030
3379
|
/**
|
|
@@ -3041,28 +3390,28 @@ var CityFilterSchema = rejectUnknownKeys(
|
|
|
3041
3390
|
);
|
|
3042
3391
|
|
|
3043
3392
|
// src/geo/geo-sync.schema.ts
|
|
3044
|
-
var
|
|
3045
|
-
var GeoSyncCountsSchema = (0,
|
|
3046
|
-
read: (0,
|
|
3047
|
-
upserted: (0,
|
|
3048
|
-
modified: (0,
|
|
3049
|
-
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"),
|
|
3050
3399
|
/** Rows removed because upstream dropped them. See `prunedSkipped`. */
|
|
3051
|
-
pruned: (0,
|
|
3400
|
+
pruned: (0, import_yup30.number)().integer().min(0).default(0).label("Pruned"),
|
|
3052
3401
|
/**
|
|
3053
3402
|
* True when the stale-row prune was REFUSED because it would have removed more
|
|
3054
3403
|
* than its safety threshold of the collection. A partial fetch that looked
|
|
3055
3404
|
* like a success must not be able to empty the table, so the run reports the
|
|
3056
3405
|
* refusal rather than acting on it.
|
|
3057
3406
|
*/
|
|
3058
|
-
prunedSkipped: (0,
|
|
3407
|
+
prunedSkipped: (0, import_yup30.boolean)().default(false).label("Prune Skipped")
|
|
3059
3408
|
}).label("Sync Counts");
|
|
3060
|
-
var GeoSyncRunSchema = (0,
|
|
3061
|
-
jobId: (0,
|
|
3062
|
-
status: (0,
|
|
3063
|
-
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"),
|
|
3064
3413
|
/** Whether the caller asked to run even though the release tag was unchanged. */
|
|
3065
|
-
force: (0,
|
|
3414
|
+
force: (0, import_yup30.boolean)().default(false).label("Force"),
|
|
3066
3415
|
/**
|
|
3067
3416
|
* The upstream release tag this run fetched, e.g. `v3.2-export.7`.
|
|
3068
3417
|
*
|
|
@@ -3070,13 +3419,13 @@ var GeoSyncRunSchema = (0, import_yup29.object)({
|
|
|
3070
3419
|
* cannot tell what version it is fetching is otherwise a failure, not a
|
|
3071
3420
|
* refresh, so it is not allowed to proceed unattended.
|
|
3072
3421
|
*/
|
|
3073
|
-
releaseTag: (0,
|
|
3422
|
+
releaseTag: (0, import_yup30.string)().optional().nullable().label("Release Tag"),
|
|
3074
3423
|
/** The tag of the last successful run, i.e. what this one is replacing. */
|
|
3075
|
-
previousReleaseTag: (0,
|
|
3076
|
-
startedAt: (0,
|
|
3077
|
-
finishedAt: (0,
|
|
3078
|
-
durationMs: (0,
|
|
3079
|
-
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"),
|
|
3080
3429
|
/**
|
|
3081
3430
|
* Live progress for the dashboard bar.
|
|
3082
3431
|
*
|
|
@@ -3084,25 +3433,25 @@ var GeoSyncRunSchema = (0, import_yup29.object)({
|
|
|
3084
3433
|
* collection, or a hardcoded fallback on the very first run, since the true
|
|
3085
3434
|
* total is not known until the stream ends. The UI should render it as one.
|
|
3086
3435
|
*/
|
|
3087
|
-
progress: (0,
|
|
3088
|
-
collection: (0,
|
|
3089
|
-
processed: (0,
|
|
3090
|
-
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")
|
|
3091
3440
|
}).optional().nullable().label("Progress"),
|
|
3092
|
-
counts: (0,
|
|
3441
|
+
counts: (0, import_yup30.object)({
|
|
3093
3442
|
countries: GeoSyncCountsSchema.optional().nullable().label("Countries"),
|
|
3094
3443
|
states: GeoSyncCountsSchema.optional().nullable().label("States"),
|
|
3095
3444
|
cities: GeoSyncCountsSchema.optional().nullable().label("Cities")
|
|
3096
3445
|
}).optional().nullable().label("Counts"),
|
|
3097
3446
|
/** Why a `skipped` run was skipped, in words the dashboard can show verbatim. */
|
|
3098
|
-
reason: (0,
|
|
3447
|
+
reason: (0, import_yup30.string)().optional().nullable().label("Reason"),
|
|
3099
3448
|
/** The failure message on a `failed` run. Surfaced verbatim to the admin. */
|
|
3100
|
-
error: (0,
|
|
3449
|
+
error: (0, import_yup30.string)().optional().nullable().label("Error")
|
|
3101
3450
|
}).label("Geo Sync Run");
|
|
3102
3451
|
|
|
3103
3452
|
// src/language/language-filter.schema.ts
|
|
3104
|
-
var
|
|
3105
|
-
var LanguageFilterShape = (0,
|
|
3453
|
+
var import_yup31 = require("yup");
|
|
3454
|
+
var LanguageFilterShape = (0, import_yup31.object)({
|
|
3106
3455
|
/** Language names, matched exactly. Free-text matching is `?search=`. */
|
|
3107
3456
|
names: tokens("Names")
|
|
3108
3457
|
}).label("Language Filter");
|
|
@@ -3112,8 +3461,8 @@ var LanguageFilterSchema = rejectUnknownKeys(
|
|
|
3112
3461
|
);
|
|
3113
3462
|
|
|
3114
3463
|
// src/page/page-filter.schema.ts
|
|
3115
|
-
var
|
|
3116
|
-
var PageFilterShape = (0,
|
|
3464
|
+
var import_yup32 = require("yup");
|
|
3465
|
+
var PageFilterShape = (0, import_yup32.object)({
|
|
3117
3466
|
/**
|
|
3118
3467
|
* `type`, NOT `pageType`.
|
|
3119
3468
|
*
|
|
@@ -3133,7 +3482,7 @@ var PageFilterShape = (0, import_yup31.object)({
|
|
|
3133
3482
|
// No `.default(false)`: absent means no constraint. Note `isFeatured` is
|
|
3134
3483
|
// present on only 55 documents, so combining it with `status: ['published']`
|
|
3135
3484
|
// leaves 11 pages — a legitimate filter that returns almost nothing.
|
|
3136
|
-
isFeatured: (0,
|
|
3485
|
+
isFeatured: (0, import_yup32.boolean)().optional().label("Featured Only"),
|
|
3137
3486
|
/** Lowercase (`in`, `se`, `ww`), like groups. See `GroupFilterSchema`. */
|
|
3138
3487
|
featuredMarkets: tokens("Featured Markets"),
|
|
3139
3488
|
/** Page SLUGS. A company is matched by slug: a display name breaks on rename. */
|
|
@@ -3146,7 +3495,7 @@ var PageFilterSchema = rejectUnknownKeys(
|
|
|
3146
3495
|
);
|
|
3147
3496
|
|
|
3148
3497
|
// src/marketing/marketing.schema.ts
|
|
3149
|
-
var
|
|
3498
|
+
var import_yup34 = require("yup");
|
|
3150
3499
|
|
|
3151
3500
|
// src/marketing/marketing.constant.ts
|
|
3152
3501
|
var CampaignStatus = /* @__PURE__ */ ((CampaignStatus2) => {
|
|
@@ -3223,8 +3572,8 @@ var SupportedOccurrenceStatuses = Object.values(OccurrenceStatus);
|
|
|
3223
3572
|
var CAMPAIGN_MAX_RECIPIENTS_CEILING = 5e3;
|
|
3224
3573
|
|
|
3225
3574
|
// src/user/user-filter.schema.ts
|
|
3226
|
-
var
|
|
3227
|
-
var UserFilterBranchShape = (0,
|
|
3575
|
+
var import_yup33 = require("yup");
|
|
3576
|
+
var UserFilterBranchShape = (0, import_yup33.object)({
|
|
3228
3577
|
/**
|
|
3229
3578
|
* Exact email addresses. An IDENTITY lookup, not a search.
|
|
3230
3579
|
*
|
|
@@ -3244,7 +3593,7 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3244
3593
|
* the input keeps the match an indexed equality instead of a regex that would
|
|
3245
3594
|
* put the scan straight back.
|
|
3246
3595
|
*/
|
|
3247
|
-
emails: (0,
|
|
3596
|
+
emails: (0, import_yup33.array)().of((0, import_yup33.string)().required()).optional().default([]).label("Email Addresses"),
|
|
3248
3597
|
/**
|
|
3249
3598
|
* Better Auth account ids. An IDENTITY lookup like `emails`, and for the same
|
|
3250
3599
|
* reason: the caller already knows the exact value.
|
|
@@ -3263,9 +3612,9 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3263
3612
|
* The admin filter panel builds its controls explicitly rather than from this
|
|
3264
3613
|
* shape, so declaring it here does not put an account-id box in the UI.
|
|
3265
3614
|
*/
|
|
3266
|
-
authAccountIds: (0,
|
|
3615
|
+
authAccountIds: (0, import_yup33.array)().of((0, import_yup33.string)().required()).optional().default([]).label("Auth Account IDs"),
|
|
3267
3616
|
// ── Enum facets (closed vocabularies, chip pickers) ─────────────────────────
|
|
3268
|
-
countries: (0,
|
|
3617
|
+
countries: (0, import_yup33.array)().of((0, import_yup33.string)().required()).optional().default([]).label("Countries"),
|
|
3269
3618
|
roles: enumFacet(SupportedUserRoles, "Roles"),
|
|
3270
3619
|
// The user's own current seniority (UserSchema.experienceLevel).
|
|
3271
3620
|
experienceLevels: enumFacet(SupportedExperienceLevels, "Experience Levels"),
|
|
@@ -3398,12 +3747,12 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3398
3747
|
// it, so the dependency is stated rather than assumed.
|
|
3399
3748
|
minSalaryFloor: currencyBound("Min Salary \u2265", "salaryCurrencies"),
|
|
3400
3749
|
minSalaryCeil: currencyBound("Min Salary \u2264", "salaryCurrencies"),
|
|
3401
|
-
openToWorkOnly: (0,
|
|
3402
|
-
remoteExperienceOnly: (0,
|
|
3403
|
-
hasResumeOnly: (0,
|
|
3404
|
-
onboardingCompletedOnly: (0,
|
|
3405
|
-
emailVerifiedOnly: (0,
|
|
3406
|
-
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"),
|
|
3407
3756
|
// ── Lifecycle windows ───────────────────────────────────────────────────────
|
|
3408
3757
|
// Relative, because a saved list is resolved fresh on every send: a stored
|
|
3409
3758
|
// absolute epoch would freeze at authoring time and the audience would decay
|
|
@@ -3431,10 +3780,10 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3431
3780
|
// Radius search around a point, against location.geo. All three required
|
|
3432
3781
|
// together; validated as a group rather than field-by-field so a half-filled
|
|
3433
3782
|
// radius cannot silently match everyone.
|
|
3434
|
-
withinRadius: (0,
|
|
3435
|
-
lat: (0,
|
|
3436
|
-
lng: (0,
|
|
3437
|
-
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)")
|
|
3438
3787
|
}).optional().default(void 0).label("Within Radius"),
|
|
3439
3788
|
// ── Signup context (immutable market / locale) ──────────────────────────────
|
|
3440
3789
|
signupCountries: tokens("Signup Countries"),
|
|
@@ -3457,7 +3806,7 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3457
3806
|
// materialise the second case on every list that never chose it.
|
|
3458
3807
|
//
|
|
3459
3808
|
// @todo CONSENT-FILTER-ENFORCEMENT — nothing enforces consent anywhere now.
|
|
3460
|
-
marketingSubscribed: (0,
|
|
3809
|
+
marketingSubscribed: (0, import_yup33.boolean)().optional().label("Marketing Subscribed"),
|
|
3461
3810
|
jobAlertFrequencies: enumFacet(
|
|
3462
3811
|
SupportedJobAlertFrequencies,
|
|
3463
3812
|
"Job Alert Frequency"
|
|
@@ -3478,7 +3827,7 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3478
3827
|
),
|
|
3479
3828
|
// ── Tenure / recency ────────────────────────────────────────────────────────
|
|
3480
3829
|
// Against workExperiences[].duration and educations[].duration ("YYYY-MM").
|
|
3481
|
-
currentlyEmployed: (0,
|
|
3830
|
+
currentlyEmployed: (0, import_yup33.boolean)().optional().default(false).label("Currently Employed"),
|
|
3482
3831
|
graduatedWithinMonths: months("Graduated Within (months)"),
|
|
3483
3832
|
skillUsedWithinMonths: months("Skill Used Within (months)"),
|
|
3484
3833
|
// The ABSOLUTE bounds the three relative windows above resolve into
|
|
@@ -3491,13 +3840,13 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3491
3840
|
// meaning that forever, while "within 18 months" keeps meaning what the admin
|
|
3492
3841
|
// intended. They are declared because the vocabulary must be complete, not
|
|
3493
3842
|
// because a list should store one.
|
|
3494
|
-
graduatedAfter: (0,
|
|
3495
|
-
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"),
|
|
3496
3845
|
// ── Profile richness ────────────────────────────────────────────────────────
|
|
3497
|
-
hasImage: (0,
|
|
3498
|
-
hasHeadline: (0,
|
|
3499
|
-
hasAboutMe: (0,
|
|
3500
|
-
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"),
|
|
3501
3850
|
// Segment by WHICH profile section is missing (profileCompleteness.missing[]),
|
|
3502
3851
|
// rather than only by the overall percentage.
|
|
3503
3852
|
missingSections: tokens("Missing Profile Sections"),
|
|
@@ -3509,8 +3858,8 @@ var UserFilterBranchShape = (0, import_yup32.object)({
|
|
|
3509
3858
|
// data lives in other services' collections. Tri-state: `false` is a real
|
|
3510
3859
|
// filter ("has NO job alert"), which is the audience an alert nudge wants, so
|
|
3511
3860
|
// these are `undefined` when unset rather than defaulting to false.
|
|
3512
|
-
hasJobAlert: (0,
|
|
3513
|
-
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"),
|
|
3514
3863
|
appliedWithinDays: days("Applied Within (days)")
|
|
3515
3864
|
// `search` is NOT here. It is free text over name/email, not a facet: it names
|
|
3516
3865
|
// no field on a user document, user-service treats it as a RESERVED PARAM
|
|
@@ -3523,25 +3872,25 @@ var BRANCH_KEYS = Object.keys(UserFilterBranchShape.fields);
|
|
|
3523
3872
|
var UserFilterBranch = rejectUnknownKeys(UserFilterBranchShape, () => BRANCH_KEYS);
|
|
3524
3873
|
var UserFilterSchema = rejectUnknownKeys(
|
|
3525
3874
|
UserFilterBranchShape.shape({
|
|
3526
|
-
or: (0,
|
|
3875
|
+
or: (0, import_yup33.array)().of(UserFilterBranch).optional().default([]).label("Or Any Of")
|
|
3527
3876
|
}).label("User Filter"),
|
|
3528
3877
|
() => [...BRANCH_KEYS, "or"]
|
|
3529
3878
|
);
|
|
3530
3879
|
|
|
3531
3880
|
// src/marketing/marketing.schema.ts
|
|
3532
3881
|
var MailingListFilterSchema = UserFilterSchema;
|
|
3533
|
-
var MailingListSchema = (0,
|
|
3534
|
-
name: (0,
|
|
3535
|
-
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"),
|
|
3536
3885
|
filter: MailingListFilterSchema.default(
|
|
3537
3886
|
() => MailingListFilterSchema.getDefault()
|
|
3538
3887
|
)
|
|
3539
3888
|
}).label("Mailing List");
|
|
3540
|
-
var CampaignTriggerSchema = (0,
|
|
3541
|
-
kind: (0,
|
|
3889
|
+
var CampaignTriggerSchema = (0, import_yup34.object)({
|
|
3890
|
+
kind: (0, import_yup34.string)().oneOf(SupportedCampaignTriggerKinds).required().default("manual" /* Manual */).label("Trigger"),
|
|
3542
3891
|
// IANA zone, e.g. "Asia/Kolkata". Local wall-clock times are interpreted in it,
|
|
3543
3892
|
// so occurrences land at the intended hour across DST rather than drifting.
|
|
3544
|
-
timezone: (0,
|
|
3893
|
+
timezone: (0, import_yup34.string)().optional().default("UTC").label("Timezone").when("kind", {
|
|
3545
3894
|
is: (k) => k !== "manual" /* Manual */,
|
|
3546
3895
|
then: (s) => s.required()
|
|
3547
3896
|
}),
|
|
@@ -3555,26 +3904,26 @@ var CampaignTriggerSchema = (0, import_yup33.object)({
|
|
|
3555
3904
|
is: "schedule" /* Schedule */,
|
|
3556
3905
|
then: (s) => s.required()
|
|
3557
3906
|
}),
|
|
3558
|
-
interval: (0,
|
|
3559
|
-
every: (0,
|
|
3560
|
-
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")
|
|
3561
3910
|
}).optional().default(void 0).label("Repeats").when("kind", {
|
|
3562
3911
|
is: "schedule" /* Schedule */,
|
|
3563
3912
|
then: (s) => s.required()
|
|
3564
3913
|
}),
|
|
3565
3914
|
/** Local wall-clock send time, "HH:mm" in `timezone`. */
|
|
3566
|
-
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"),
|
|
3567
3916
|
/** For weekly intervals: ISO weekdays, 1 = Monday .. 7 = Sunday. */
|
|
3568
|
-
byWeekday: (0,
|
|
3917
|
+
byWeekday: (0, import_yup34.array)().of((0, import_yup34.number)().integer().min(1).max(7).required()).optional().default([]).label("On Days"),
|
|
3569
3918
|
/**
|
|
3570
3919
|
* For monthly intervals: 1-31, or -1 meaning "last day of the month". A month
|
|
3571
3920
|
* shorter than the chosen day is clamped to its last day, so 31 in February
|
|
3572
3921
|
* fires on the 28th/29th rather than being skipped.
|
|
3573
3922
|
*/
|
|
3574
|
-
byMonthday: (0,
|
|
3575
|
-
end: (0,
|
|
3576
|
-
kind: (0,
|
|
3577
|
-
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", {
|
|
3578
3927
|
is: "afterOccurrences" /* AfterOccurrences */,
|
|
3579
3928
|
then: (s) => s.required()
|
|
3580
3929
|
}),
|
|
@@ -3584,8 +3933,8 @@ var CampaignTriggerSchema = (0, import_yup33.object)({
|
|
|
3584
3933
|
})
|
|
3585
3934
|
}).optional().default(() => ({ kind: "never" /* Never */ })).label("End Condition")
|
|
3586
3935
|
}).label("Trigger");
|
|
3587
|
-
var CampaignDataSourceSchema = (0,
|
|
3588
|
-
id: (0,
|
|
3936
|
+
var CampaignDataSourceSchema = (0, import_yup34.object)({
|
|
3937
|
+
id: (0, import_yup34.string)().required().label("Data Source"),
|
|
3589
3938
|
/**
|
|
3590
3939
|
* Derive this source's filter per recipient from their profile, instead of
|
|
3591
3940
|
* using the admin-entered `params` for everyone.
|
|
@@ -3600,7 +3949,7 @@ var CampaignDataSourceSchema = (0, import_yup33.object)({
|
|
|
3600
3949
|
* un-personalised. Whether a source can honour it at all is declared by the
|
|
3601
3950
|
* source itself (`supportsPersonalisation`), which this package cannot see.
|
|
3602
3951
|
*/
|
|
3603
|
-
personalised: (0,
|
|
3952
|
+
personalised: (0, import_yup34.boolean)().optional().label("Personalised"),
|
|
3604
3953
|
/**
|
|
3605
3954
|
* A free-form bag whose keys are defined by the chosen source's OWN
|
|
3606
3955
|
* `paramsSchema`, which this package cannot see. Same `lazy` treatment as
|
|
@@ -3613,22 +3962,22 @@ var CampaignDataSourceSchema = (0, import_yup33.object)({
|
|
|
3613
3962
|
* them against the real source schema in `checkCampaignConfig`, which is the
|
|
3614
3963
|
* only place that knows what a given source accepts.
|
|
3615
3964
|
*/
|
|
3616
|
-
params: (0,
|
|
3965
|
+
params: (0, import_yup34.lazy)((value) => {
|
|
3617
3966
|
const keys = value && typeof value === "object" ? Object.keys(value) : [];
|
|
3618
|
-
return (0,
|
|
3619
|
-
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()]))
|
|
3620
3969
|
).optional().default(() => ({})).label("Parameters");
|
|
3621
3970
|
})
|
|
3622
3971
|
}).label("Data Source");
|
|
3623
|
-
var TemplateVariableBindingSchema = (0,
|
|
3624
|
-
kind: (0,
|
|
3625
|
-
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")
|
|
3626
3975
|
}).label("Template Variable Binding");
|
|
3627
|
-
var CampaignSchema = (0,
|
|
3628
|
-
name: (0,
|
|
3976
|
+
var CampaignSchema = (0, import_yup34.object)({
|
|
3977
|
+
name: (0, import_yup34.string)().required().min(1).max(200).label("Campaign Name"),
|
|
3629
3978
|
// The template renders its own subject; an override is only needed for the
|
|
3630
3979
|
// inline-HTML path, hence not required when a template is chosen.
|
|
3631
|
-
subject: (0,
|
|
3980
|
+
subject: (0, import_yup34.string)().optional().max(255).label("Subject").when("templateKey", {
|
|
3632
3981
|
is: (v) => !v,
|
|
3633
3982
|
then: (s) => s.required().min(1)
|
|
3634
3983
|
}),
|
|
@@ -3639,12 +3988,12 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3639
3988
|
* one with a compliance-checked footer and a render test,
|
|
3640
3989
|
* and hand-pasted HTML that repeats forever is a mistake that repeats forever.
|
|
3641
3990
|
*/
|
|
3642
|
-
html: (0,
|
|
3991
|
+
html: (0, import_yup34.string)().optional().label("HTML Body").when("templateKey", {
|
|
3643
3992
|
is: (v) => !v,
|
|
3644
3993
|
then: (s) => s.required().min(1)
|
|
3645
3994
|
}),
|
|
3646
|
-
text: (0,
|
|
3647
|
-
listId: (0,
|
|
3995
|
+
text: (0, import_yup34.string)().optional().label("Plain-text Body"),
|
|
3996
|
+
listId: (0, import_yup34.string)().required().label("Mailing List"),
|
|
3648
3997
|
/**
|
|
3649
3998
|
* Where the campaign is in its life. See `CampaignStatus` for the transitions.
|
|
3650
3999
|
*
|
|
@@ -3653,9 +4002,9 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3653
4002
|
* value the enum never contained (`scheduled`) reached production rows and
|
|
3654
4003
|
* rendered in the admin list as though it were real.
|
|
3655
4004
|
*/
|
|
3656
|
-
status: (0,
|
|
4005
|
+
status: (0, import_yup34.string)().oneOf(SupportedCampaignStatuses).optional().default("draft" /* Draft */).label("Status"),
|
|
3657
4006
|
/** Key from email-service's template registry. Mutually exclusive with `html`. */
|
|
3658
|
-
templateKey: (0,
|
|
4007
|
+
templateKey: (0, import_yup34.string)().optional().label("Email Template"),
|
|
3659
4008
|
/**
|
|
3660
4009
|
* One entry per variable the chosen template declares. Validated at save time
|
|
3661
4010
|
* against the template's own `variables`, so a missing required binding is a
|
|
@@ -3670,9 +4019,9 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3670
4019
|
* whose required variables all appear unbound. Shaping each entry also means a
|
|
3671
4020
|
* malformed binding is rejected here rather than at send time.
|
|
3672
4021
|
*/
|
|
3673
|
-
bindings: (0,
|
|
4022
|
+
bindings: (0, import_yup34.lazy)((value) => {
|
|
3674
4023
|
const keys = value && typeof value === "object" ? Object.keys(value) : [];
|
|
3675
|
-
return (0,
|
|
4024
|
+
return (0, import_yup34.object)(
|
|
3676
4025
|
Object.fromEntries(keys.map((k) => [k, TemplateVariableBindingSchema.required()]))
|
|
3677
4026
|
).optional().default(() => ({})).label("Template Data");
|
|
3678
4027
|
}),
|
|
@@ -3684,7 +4033,7 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3684
4033
|
* `groups.groupCount`), so two sources providing the same name cannot
|
|
3685
4034
|
* overwrite each other and a template says which one it means.
|
|
3686
4035
|
*/
|
|
3687
|
-
dataSources: (0,
|
|
4036
|
+
dataSources: (0, import_yup34.array)().of(CampaignDataSourceSchema).optional().default(void 0).label("Data Sources"),
|
|
3688
4037
|
trigger: CampaignTriggerSchema.default(
|
|
3689
4038
|
() => CampaignTriggerSchema.getDefault()
|
|
3690
4039
|
),
|
|
@@ -3699,7 +4048,7 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3699
4048
|
* representable, and the admin list showed exactly that. Activation is a
|
|
3700
4049
|
* state transition, so it belongs in the state.
|
|
3701
4050
|
*/
|
|
3702
|
-
dryRun: (0,
|
|
4051
|
+
dryRun: (0, import_yup34.boolean)().optional().default(true).label("Dry Run"),
|
|
3703
4052
|
/**
|
|
3704
4053
|
* Re-eligibility: when someone this campaign already mailed may get it again.
|
|
3705
4054
|
*
|
|
@@ -3707,23 +4056,23 @@ var CampaignSchema = (0, import_yup33.object)({
|
|
|
3707
4056
|
* person. `N`: again only after N days. Opt-in, because most recurring
|
|
3708
4057
|
* campaigns exist to mail the same people repeatedly.
|
|
3709
4058
|
*/
|
|
3710
|
-
resendAfterDays: (0,
|
|
3711
|
-
maxRecipients: (0,
|
|
3712
|
-
utm: (0,
|
|
3713
|
-
campaign: (0,
|
|
3714
|
-
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")
|
|
3715
4064
|
}).optional().default(void 0).label("Link Tagging")
|
|
3716
4065
|
}).label("Campaign");
|
|
3717
4066
|
|
|
3718
4067
|
// src/pagination/pagination.schema.ts
|
|
3719
|
-
var
|
|
3720
|
-
var PaginationSchema = (0,
|
|
3721
|
-
page: (0,
|
|
3722
|
-
limit: (0,
|
|
3723
|
-
sortBy: (0,
|
|
3724
|
-
nextPage: (0,
|
|
3725
|
-
prevPage: (0,
|
|
3726
|
-
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")
|
|
3727
4076
|
});
|
|
3728
4077
|
|
|
3729
4078
|
// src/pagination/pagination.constant.ts
|
|
@@ -3739,7 +4088,7 @@ var DefaultPaginationOptions = {
|
|
|
3739
4088
|
};
|
|
3740
4089
|
|
|
3741
4090
|
// src/saved-search/saved-search.schema.ts
|
|
3742
|
-
var
|
|
4091
|
+
var import_yup36 = require("yup");
|
|
3743
4092
|
|
|
3744
4093
|
// src/saved-search/saved-search.constant.ts
|
|
3745
4094
|
var SavedSearchStatus = /* @__PURE__ */ ((SavedSearchStatus2) => {
|
|
@@ -3750,21 +4099,21 @@ var SavedSearchStatus = /* @__PURE__ */ ((SavedSearchStatus2) => {
|
|
|
3750
4099
|
var SupportedSavedSearchStatuses = Object.values(SavedSearchStatus);
|
|
3751
4100
|
|
|
3752
4101
|
// src/saved-search/saved-search.schema.ts
|
|
3753
|
-
var SavedSearchSchema = (0,
|
|
4102
|
+
var SavedSearchSchema = (0, import_yup36.object)({
|
|
3754
4103
|
/** Public identifier. Server-assigned. */
|
|
3755
|
-
shortId: (0,
|
|
4104
|
+
shortId: (0, import_yup36.string)().trim().label("Short Id"),
|
|
3756
4105
|
/**
|
|
3757
4106
|
* Owner's Better Auth account id. Server-assigned from the verified token,
|
|
3758
4107
|
* never accepted from a request body.
|
|
3759
4108
|
*/
|
|
3760
|
-
ownerUserId: (0,
|
|
4109
|
+
ownerUserId: (0, import_yup36.string)().trim().label("Owner"),
|
|
3761
4110
|
/** What the user calls this search, e.g. "Remote React roles". */
|
|
3762
|
-
label: (0,
|
|
4111
|
+
label: (0, import_yup36.string)().trim().max(120).required().label("Label"),
|
|
3763
4112
|
/**
|
|
3764
4113
|
* The free-text query. Optional because a search can be filters-only ("all
|
|
3765
4114
|
* remote jobs in Sweden"), which is a legitimate alert to want.
|
|
3766
4115
|
*/
|
|
3767
|
-
search: (0,
|
|
4116
|
+
search: (0, import_yup36.string)().trim().max(500).optional().label("Search Text"),
|
|
3768
4117
|
/**
|
|
3769
4118
|
* Field filters, in the same `{ field: values }` shape the search endpoint
|
|
3770
4119
|
* parses from `filter[field]=a,b`. Held as a free-form object rather than a
|
|
@@ -3772,7 +4121,7 @@ var SavedSearchSchema = (0, import_yup35.object)({
|
|
|
3772
4121
|
* change independently; validating them here would put this package in the
|
|
3773
4122
|
* business of tracking that vocabulary.
|
|
3774
4123
|
*/
|
|
3775
|
-
filter: (0,
|
|
4124
|
+
filter: (0, import_yup36.object)().optional().default({}).label("Filters"),
|
|
3776
4125
|
/**
|
|
3777
4126
|
* How often to mail matches. `off` keeps the search saved but silent, which is
|
|
3778
4127
|
* the difference between "I don't want mail" and "delete my search".
|
|
@@ -3781,26 +4130,26 @@ var SavedSearchSchema = (0, import_yup35.object)({
|
|
|
3781
4130
|
* than defining a second one: two vocabularies for the same concept is how
|
|
3782
4131
|
* they drift.
|
|
3783
4132
|
*/
|
|
3784
|
-
frequency: (0,
|
|
3785
|
-
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"),
|
|
3786
4135
|
/**
|
|
3787
4136
|
* Epoch ms of the last alert sent for this search. The matching sweep reads it
|
|
3788
4137
|
* to decide whether the cadence is due, and writes it only AFTER a successful
|
|
3789
4138
|
* publish, so a failed run retries next tick rather than silently skipping a
|
|
3790
4139
|
* period.
|
|
3791
4140
|
*/
|
|
3792
|
-
lastNotifiedAt: (0,
|
|
4141
|
+
lastNotifiedAt: (0, import_yup36.number)().optional().label("Last Notified At"),
|
|
3793
4142
|
/**
|
|
3794
4143
|
* Epoch ms high-water mark: only jobs created after this are "new" for the
|
|
3795
4144
|
* next alert. Kept separate from `lastNotifiedAt` because a run that finds no
|
|
3796
4145
|
* matches should still advance what counts as new, without implying mail was
|
|
3797
4146
|
* sent.
|
|
3798
4147
|
*/
|
|
3799
|
-
lastMatchedAt: (0,
|
|
4148
|
+
lastMatchedAt: (0, import_yup36.number)().optional().label("Last Matched At")
|
|
3800
4149
|
}).noUnknown().strict();
|
|
3801
4150
|
|
|
3802
4151
|
// src/report/report.schema.ts
|
|
3803
|
-
var
|
|
4152
|
+
var import_yup37 = require("yup");
|
|
3804
4153
|
|
|
3805
4154
|
// src/report/report.constant.ts
|
|
3806
4155
|
var ResourceType = /* @__PURE__ */ ((ResourceType3) => {
|
|
@@ -3824,15 +4173,15 @@ var ReportReason = /* @__PURE__ */ ((ReportReason3) => {
|
|
|
3824
4173
|
var SupportedReportReasons = Object.values(ReportReason);
|
|
3825
4174
|
|
|
3826
4175
|
// src/report/report.schema.ts
|
|
3827
|
-
var ReportSchema = (0,
|
|
3828
|
-
type: (0,
|
|
3829
|
-
resourceId: (0,
|
|
3830
|
-
reason: (0,
|
|
3831
|
-
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")
|
|
3832
4181
|
}).label("Report Schema");
|
|
3833
4182
|
|
|
3834
4183
|
// src/feedback/feedback-filter.schema.ts
|
|
3835
|
-
var
|
|
4184
|
+
var import_yup38 = require("yup");
|
|
3836
4185
|
|
|
3837
4186
|
// src/feedback/feedback.constant.ts
|
|
3838
4187
|
var FeedbackType = /* @__PURE__ */ ((FeedbackType3) => {
|
|
@@ -3855,7 +4204,7 @@ var SupportedFeedbackStatuses = Object.values(FeedbackStatus);
|
|
|
3855
4204
|
var FEEDBACK_MESSAGE_MAX = 4e3;
|
|
3856
4205
|
|
|
3857
4206
|
// src/feedback/feedback-filter.schema.ts
|
|
3858
|
-
var FeedbackFilterShape = (0,
|
|
4207
|
+
var FeedbackFilterShape = (0, import_yup38.object)({
|
|
3859
4208
|
type: enumFacet(SupportedFeedbackTypes, "Type"),
|
|
3860
4209
|
status: enumFacet(SupportedFeedbackStatuses, "Status")
|
|
3861
4210
|
}).label("Feedback Filter");
|
|
@@ -3865,18 +4214,18 @@ var FeedbackFilterSchema = rejectUnknownKeys(
|
|
|
3865
4214
|
);
|
|
3866
4215
|
|
|
3867
4216
|
// src/feedback/feedback.schema.ts
|
|
3868
|
-
var
|
|
3869
|
-
var FeedbackSchema = (0,
|
|
3870
|
-
type: (0,
|
|
3871
|
-
message: (0,
|
|
3872
|
-
email: (0,
|
|
3873
|
-
pageUrl: (0,
|
|
3874
|
-
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")
|
|
3875
4224
|
}).label("Feedback Schema");
|
|
3876
4225
|
|
|
3877
4226
|
// src/skill/skill-filter.schema.ts
|
|
3878
|
-
var
|
|
3879
|
-
var SkillFilterShape = (0,
|
|
4227
|
+
var import_yup40 = require("yup");
|
|
4228
|
+
var SkillFilterShape = (0, import_yup40.object)({
|
|
3880
4229
|
/** Display names, matched exactly. Free-text matching is `?search=`. */
|
|
3881
4230
|
names: tokens("Names"),
|
|
3882
4231
|
/**
|
|
@@ -3894,7 +4243,7 @@ var SkillFilterSchema = rejectUnknownKeys(
|
|
|
3894
4243
|
);
|
|
3895
4244
|
|
|
3896
4245
|
// src/billing/billing.schema.ts
|
|
3897
|
-
var
|
|
4246
|
+
var import_yup41 = require("yup");
|
|
3898
4247
|
|
|
3899
4248
|
// src/billing/billing.constant.ts
|
|
3900
4249
|
var PlanKind = /* @__PURE__ */ ((PlanKind2) => {
|
|
@@ -3997,60 +4346,60 @@ var GRANT_MAX_LIMIT = 1e5;
|
|
|
3997
4346
|
var CONSUME_MAX_UNITS = 1e3;
|
|
3998
4347
|
|
|
3999
4348
|
// src/billing/billing.schema.ts
|
|
4000
|
-
var MoneySchema = (0,
|
|
4001
|
-
amountMinor: (0,
|
|
4349
|
+
var MoneySchema = (0, import_yup41.object)({
|
|
4350
|
+
amountMinor: (0, import_yup41.number)().integer().min(0).required().label("Amount (minor units)"),
|
|
4002
4351
|
/**
|
|
4003
4352
|
* ISO-4217, as returned by Paddle. Deliberately NOT constrained to
|
|
4004
4353
|
* `SupportedSalaryCurrencies`: that list is the job-salary vocabulary, and
|
|
4005
4354
|
* Paddle bills in currencies it does not contain. Constraining it here would
|
|
4006
4355
|
* reject real payments.
|
|
4007
4356
|
*/
|
|
4008
|
-
currencyCode: (0,
|
|
4357
|
+
currencyCode: (0, import_yup41.string)().trim().uppercase().required().label("Currency")
|
|
4009
4358
|
}).label("Money");
|
|
4010
|
-
var PlanGrantSchema = (0,
|
|
4359
|
+
var PlanGrantSchema = (0, import_yup41.object)({
|
|
4011
4360
|
/**
|
|
4012
4361
|
* The gated capability, e.g. `job.post`. A free string on purpose: see the
|
|
4013
4362
|
* note on `FeatureKey` in `billing.constant.ts`. Adding a feature to the
|
|
4014
4363
|
* paywall must not require releasing this package.
|
|
4015
4364
|
*/
|
|
4016
|
-
feature: (0,
|
|
4017
|
-
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"),
|
|
4018
4367
|
/** Uses per period. Required for `quota`, meaningless otherwise. */
|
|
4019
|
-
limit: (0,
|
|
4368
|
+
limit: (0, import_yup41.number)().integer().min(1).max(GRANT_MAX_LIMIT).optional().label("Limit").when("type", {
|
|
4020
4369
|
is: "quota" /* Quota */,
|
|
4021
4370
|
then: (s) => s.required("A quota grant needs a limit")
|
|
4022
4371
|
}),
|
|
4023
|
-
period: (0,
|
|
4372
|
+
period: (0, import_yup41.string)().oneOf(SupportedQuotaPeriods).optional().default("month" /* Month */).label("Period").when("type", {
|
|
4024
4373
|
is: "quota" /* Quota */,
|
|
4025
4374
|
then: (s) => s.required("A quota grant needs a period")
|
|
4026
4375
|
}),
|
|
4027
4376
|
/** Non-expiring uses granted per purchase. Required for `credit`. */
|
|
4028
|
-
amount: (0,
|
|
4377
|
+
amount: (0, import_yup41.number)().integer().min(1).max(GRANT_MAX_LIMIT).optional().label("Amount").when("type", {
|
|
4029
4378
|
is: "credit" /* Credit */,
|
|
4030
4379
|
then: (s) => s.required("A credit grant needs an amount")
|
|
4031
4380
|
})
|
|
4032
4381
|
}).label("Plan Grant");
|
|
4033
|
-
var PaddlePriceIdsSchema = (0,
|
|
4034
|
-
sandbox: (0,
|
|
4035
|
-
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")
|
|
4036
4385
|
}).label("Paddle Price IDs");
|
|
4037
|
-
var PlanSchema = (0,
|
|
4386
|
+
var PlanSchema = (0, import_yup41.object)({
|
|
4038
4387
|
/** Stable slug, e.g. `employer-pro`. The identifier everything else references. */
|
|
4039
|
-
key: (0,
|
|
4040
|
-
name: (0,
|
|
4041
|
-
description: (0,
|
|
4042
|
-
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"),
|
|
4043
4392
|
/**
|
|
4044
4393
|
* The line this plan belongs to; a user holds one live subscription per line.
|
|
4045
4394
|
* Optional on purpose: absent is the default line, so existing plans need no
|
|
4046
4395
|
* migration and together still read as "one plan at a time".
|
|
4047
4396
|
*/
|
|
4048
|
-
audience: (0,
|
|
4049
|
-
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"),
|
|
4050
4399
|
paddlePriceIds: PaddlePriceIdsSchema.default(
|
|
4051
4400
|
() => PaddlePriceIdsSchema.getDefault()
|
|
4052
4401
|
),
|
|
4053
|
-
grants: (0,
|
|
4402
|
+
grants: (0, import_yup41.array)().of(PlanGrantSchema.required()).required().min(1, "A plan must grant at least one feature").label("Grants"),
|
|
4054
4403
|
/** Display price for the pricing page. Billing is always Paddle's own figure. */
|
|
4055
4404
|
price: MoneySchema.optional().default(void 0).label("Price"),
|
|
4056
4405
|
/**
|
|
@@ -4063,416 +4412,84 @@ var PlanSchema = (0, import_yup40.object)({
|
|
|
4063
4412
|
* a subscription as "monthly" at the use site rather than defaulting it here,
|
|
4064
4413
|
* so an unset value stays visible as unset.
|
|
4065
4414
|
*/
|
|
4066
|
-
billingPeriod: (0,
|
|
4415
|
+
billingPeriod: (0, import_yup41.string)().oneOf(SupportedBillingPeriods).optional().label("Billing Period"),
|
|
4067
4416
|
/** Ordering on the pricing page, ascending. */
|
|
4068
|
-
sortOrder: (0,
|
|
4069
|
-
createdAt: (0,
|
|
4070
|
-
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")
|
|
4071
4420
|
}).label("Plan");
|
|
4072
|
-
var BillingSubscriptionSchema = (0,
|
|
4073
|
-
userId: (0,
|
|
4074
|
-
paddleSubscriptionId: (0,
|
|
4075
|
-
paddleCustomerId: (0,
|
|
4076
|
-
planKey: (0,
|
|
4077
|
-
priceIds: (0,
|
|
4078
|
-
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"),
|
|
4079
4428
|
/** Start of the period the quota is anchored to. */
|
|
4080
|
-
currentPeriodStart: (0,
|
|
4081
|
-
currentPeriodEnd: (0,
|
|
4429
|
+
currentPeriodStart: (0, import_yup41.number)().optional().label("Current Period Start"),
|
|
4430
|
+
currentPeriodEnd: (0, import_yup41.number)().optional().label("Current Period End"),
|
|
4082
4431
|
/** Set when a cancellation is scheduled; access continues until the period ends. */
|
|
4083
|
-
canceledAt: (0,
|
|
4432
|
+
canceledAt: (0, import_yup41.number)().optional().label("Canceled At"),
|
|
4084
4433
|
/**
|
|
4085
4434
|
* A downgrade booked for the end of the current period: the plan key it moves
|
|
4086
4435
|
* to at renewal. Upgrades never set this; they apply immediately. Mirrored
|
|
4087
4436
|
* from the Paddle subscription's own `customData`, so Paddle stays the source
|
|
4088
4437
|
* of truth.
|
|
4089
4438
|
*/
|
|
4090
|
-
pendingPlanKey: (0,
|
|
4439
|
+
pendingPlanKey: (0, import_yup41.string)().optional().label("Pending Plan Key"),
|
|
4091
4440
|
/** `occurred_at` of the newest Paddle event applied. Guards out-of-order writes. */
|
|
4092
|
-
lastEventAt: (0,
|
|
4093
|
-
createdAt: (0,
|
|
4094
|
-
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")
|
|
4095
4444
|
}).label("Billing Subscription");
|
|
4096
|
-
var BillingTransactionSchema = (0,
|
|
4097
|
-
userId: (0,
|
|
4098
|
-
paddleTransactionId: (0,
|
|
4099
|
-
paddleCustomerId: (0,
|
|
4100
|
-
paddleSubscriptionId: (0,
|
|
4101
|
-
planKey: (0,
|
|
4102
|
-
priceIds: (0,
|
|
4103
|
-
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"),
|
|
4104
4453
|
total: MoneySchema.optional().default(void 0).label("Total"),
|
|
4105
|
-
billedAt: (0,
|
|
4106
|
-
lastEventAt: (0,
|
|
4107
|
-
createdAt: (0,
|
|
4108
|
-
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")
|
|
4109
4458
|
}).label("Billing Transaction");
|
|
4110
|
-
var FeatureEntitlementSchema = (0,
|
|
4111
|
-
feature: (0,
|
|
4112
|
-
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"),
|
|
4113
4462
|
/** Whether the feature may be used AT ALL right now. */
|
|
4114
|
-
allowed: (0,
|
|
4463
|
+
allowed: (0, import_yup41.boolean)().required().default(false).label("Allowed"),
|
|
4115
4464
|
/** Quota ceiling for the period. Absent for boolean grants. */
|
|
4116
|
-
limit: (0,
|
|
4117
|
-
used: (0,
|
|
4465
|
+
limit: (0, import_yup41.number)().integer().optional().label("Limit"),
|
|
4466
|
+
used: (0, import_yup41.number)().integer().optional().label("Used"),
|
|
4118
4467
|
/** Quota remaining plus any credit balance. Absent for boolean grants. */
|
|
4119
|
-
remaining: (0,
|
|
4468
|
+
remaining: (0, import_yup41.number)().integer().optional().label("Remaining"),
|
|
4120
4469
|
/** Non-expiring balance from one-off purchases. */
|
|
4121
|
-
credits: (0,
|
|
4470
|
+
credits: (0, import_yup41.number)().integer().optional().label("Credits"),
|
|
4122
4471
|
/** When the quota next refreshes. */
|
|
4123
|
-
resetsAt: (0,
|
|
4472
|
+
resetsAt: (0, import_yup41.number)().optional().label("Resets At")
|
|
4124
4473
|
}).label("Feature Entitlement");
|
|
4125
|
-
var EntitlementDenialSchema = (0,
|
|
4126
|
-
feature: (0,
|
|
4127
|
-
reason: (0,
|
|
4128
|
-
limit: (0,
|
|
4129
|
-
used: (0,
|
|
4130
|
-
resetsAt: (0,
|
|
4131
|
-
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")
|
|
4132
4481
|
}).label("Entitlement Denial");
|
|
4133
|
-
var EntitlementConsumeSchema = (0,
|
|
4134
|
-
userId: (0,
|
|
4135
|
-
feature: (0,
|
|
4136
|
-
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"),
|
|
4137
4486
|
/**
|
|
4138
4487
|
* Caller-supplied de-duplication key. Makes a spend exactly-once across the
|
|
4139
4488
|
* retries that at-least-once delivery and ordinary network failures produce.
|
|
4140
4489
|
*/
|
|
4141
|
-
idempotencyKey: (0,
|
|
4490
|
+
idempotencyKey: (0, import_yup41.string)().trim().required().min(8).max(128).label("Idempotency Key")
|
|
4142
4491
|
}).label("Entitlement Consume");
|
|
4143
4492
|
|
|
4144
|
-
// src/taxonomy/taxonomy.schema.ts
|
|
4145
|
-
var import_yup41 = require("yup");
|
|
4146
|
-
|
|
4147
|
-
// src/taxonomy/taxonomy.constant.ts
|
|
4148
|
-
var SupportedConceptSources = ["seed", "manual", "import"];
|
|
4149
|
-
var SupportedTaxonomySources = ["seed", "manual"];
|
|
4150
|
-
var SupportedTaxonomyNodeKinds = ["category", "subcategory", "group"];
|
|
4151
|
-
var SupportedPrefilterRules = [
|
|
4152
|
-
"spoken_language",
|
|
4153
|
-
"no_letters",
|
|
4154
|
-
"url_or_email",
|
|
4155
|
-
"fragment"
|
|
4156
|
-
];
|
|
4157
|
-
var SupportedUnmatchedResolutions = ["pending", "added", "rejected"];
|
|
4158
|
-
var SupportedUnmatchedReasons = ["ambiguous"];
|
|
4159
|
-
var SupportedProposalKinds = ["concept", "alias", "placement"];
|
|
4160
|
-
var SupportedProposalFilters = [...SupportedProposalKinds, "uncategorized"];
|
|
4161
|
-
var SupportedProposalStatuses = ["draft", "approved", "discarded"];
|
|
4162
|
-
var SupportedProposalMessageRoles = ["operator", "model"];
|
|
4163
|
-
var SupportedResolverVerdicts = [
|
|
4164
|
-
"same",
|
|
4165
|
-
"narrower",
|
|
4166
|
-
"broader",
|
|
4167
|
-
"related",
|
|
4168
|
-
"new_concept",
|
|
4169
|
-
"out_of_scope"
|
|
4170
|
-
];
|
|
4171
|
-
var SupportedAuditStatuses = ["pending", "correct", "wrong"];
|
|
4172
|
-
var SupportedReleaseKinds = ["seed", "manual", "review", "auto"];
|
|
4173
|
-
var SupportedReleaseStatuses = ["open", "rolled_back"];
|
|
4174
|
-
var SupportedMatchTypes = ["exact", "canonical", "fuzzy", "none"];
|
|
4175
|
-
var SupportedTaxonomyJobKinds = [
|
|
4176
|
-
"describe-concepts",
|
|
4177
|
-
"retype-concepts",
|
|
4178
|
-
"generate-aliases",
|
|
4179
|
-
"alias-backfill",
|
|
4180
|
-
"close-gaps",
|
|
4181
|
-
"propose-placements",
|
|
4182
|
-
"place-unplaced",
|
|
4183
|
-
"calibrate-placement",
|
|
4184
|
-
"reseed",
|
|
4185
|
-
"reindex",
|
|
4186
|
-
"calibrate-resolver",
|
|
4187
|
-
"golden",
|
|
4188
|
-
"resolve-backlog"
|
|
4189
|
-
];
|
|
4190
|
-
var SupportedTaxonomyJobStates = ["running", "succeeded", "failed", "cancelled"];
|
|
4191
|
-
var CONCEPT_ID_PATTERN = /^[a-z][a-z0-9-]*_[a-z0-9-]+$/;
|
|
4192
|
-
var VOCABULARY_ID_PATTERN = /^[a-z][a-z0-9-]{0,31}$/;
|
|
4193
|
-
var TAXONOMY_NODE_ID_PATTERN = /^[A-Za-z0-9_]{1,64}$/;
|
|
4194
|
-
var CONCEPT_TYPE_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;
|
|
4195
|
-
var SCHEDULE_MIN_HOURS = 1;
|
|
4196
|
-
var SCHEDULE_MAX_HOURS = 24 * 30;
|
|
4197
|
-
|
|
4198
|
-
// src/taxonomy/taxonomy.schema.ts
|
|
4199
|
-
var conceptId = () => (0, import_yup41.string)().matches(CONCEPT_ID_PATTERN, "conceptId must look like <vocabulary>_<slug>");
|
|
4200
|
-
var vocabularyId = () => (0, import_yup41.string)().matches(VOCABULARY_ID_PATTERN, "vocabulary must match [a-z][a-z0-9-]{0,31}");
|
|
4201
|
-
var nodeId = () => (0, import_yup41.string)().matches(TAXONOMY_NODE_ID_PATTERN, "node ids look like CAT_01_TECH");
|
|
4202
|
-
var strings = () => (0, import_yup41.array)((0, import_yup41.string)().trim().min(1).required());
|
|
4203
|
-
var VocabularyTypeSchema = (0, import_yup41.object)({
|
|
4204
|
-
id: (0, import_yup41.string)().matches(CONCEPT_TYPE_PATTERN, "type ids match [a-z][a-z0-9_]*").required().label("Type ID"),
|
|
4205
|
-
/** Shown to the model when it classifies a concept; include examples. */
|
|
4206
|
-
description: (0, import_yup41.string)().defined().label("Description")
|
|
4207
|
-
}).label("Vocabulary Type");
|
|
4208
|
-
var VocabularySchema = (0, import_yup41.object)({
|
|
4209
|
-
vocabularyId: vocabularyId().required().label("Vocabulary ID"),
|
|
4210
|
-
name: (0, import_yup41.string)().trim().min(1).required().label("Name"),
|
|
4211
|
-
/** What one concept is called in prompts and messages: "skill", "role". */
|
|
4212
|
-
noun: (0, import_yup41.string)().trim().min(1).required().label("Noun"),
|
|
4213
|
-
nounPlural: (0, import_yup41.string)().trim().min(1).required().label("Noun (plural)"),
|
|
4214
|
-
/** What belongs in this vocabulary, for prompts. */
|
|
4215
|
-
description: (0, import_yup41.string)().trim().min(1).required().label("Description"),
|
|
4216
|
-
/** Where its terms are written, for the "swap it in" test: "a job posting". */
|
|
4217
|
-
appearsIn: (0, import_yup41.string)().trim().min(1).required().label("Appears In"),
|
|
4218
|
-
/** Things that are NOT concepts of this vocabulary, for prompts. */
|
|
4219
|
-
outOfScope: (0, import_yup41.string)().trim().min(1).required().label("Out of Scope"),
|
|
4220
|
-
types: (0, import_yup41.array)(VocabularyTypeSchema.required()).min(1).required().test(
|
|
4221
|
-
"unique-type-ids",
|
|
4222
|
-
"type ids must be unique",
|
|
4223
|
-
(types) => !types || new Set(types.map((t) => t.id)).size === types.length
|
|
4224
|
-
).label("Types"),
|
|
4225
|
-
/** The type a concept gets when nothing more specific is known. One of `types`. */
|
|
4226
|
-
defaultType: (0, import_yup41.string)().required().test("default-type-listed", "defaultType must be one of the type ids", function(value) {
|
|
4227
|
-
const types = this.parent.types ?? [];
|
|
4228
|
-
return types.some((t) => t.id === value);
|
|
4229
|
-
}).label("Default Type"),
|
|
4230
|
-
prefilter: (0, import_yup41.array)((0, import_yup41.string)().oneOf(SupportedPrefilterRules).required()).default([]).label("Prefilter"),
|
|
4231
|
-
/**
|
|
4232
|
-
* Words that qualify a term without changing what it names ("fluent",
|
|
4233
|
-
* "native"), dropped from its canonical lookup form in THIS vocabulary only.
|
|
4234
|
-
*/
|
|
4235
|
-
qualifiers: strings().optional().label("Qualifiers"),
|
|
4236
|
-
/** Extra instructions per model task; each is optional. */
|
|
4237
|
-
guidance: (0, import_yup41.object)({
|
|
4238
|
-
describe: (0, import_yup41.string)().optional(),
|
|
4239
|
-
classify: (0, import_yup41.string)().optional(),
|
|
4240
|
-
aliases: (0, import_yup41.string)().optional(),
|
|
4241
|
-
verify: (0, import_yup41.string)().optional(),
|
|
4242
|
-
place: (0, import_yup41.string)().optional()
|
|
4243
|
-
}).label("Guidance"),
|
|
4244
|
-
source: (0, import_yup41.string)().oneOf(SupportedTaxonomySources).required().label("Source"),
|
|
4245
|
-
createdAt: (0, import_yup41.number)().required().label("Created At"),
|
|
4246
|
-
updatedAt: (0, import_yup41.number)().required().label("Updated At")
|
|
4247
|
-
}).label("Vocabulary");
|
|
4248
|
-
var TaxonomyNodeSchema = (0, import_yup41.object)({
|
|
4249
|
-
nodeId: nodeId().required().label("Node ID"),
|
|
4250
|
-
vocabulary: vocabularyId().required().label("Vocabulary"),
|
|
4251
|
-
kind: (0, import_yup41.string)().oneOf(SupportedTaxonomyNodeKinds).required().label("Kind"),
|
|
4252
|
-
name: (0, import_yup41.string)().trim().min(1).required().label("Name"),
|
|
4253
|
-
/** Groups carry a description; categories and subcategories usually do not. */
|
|
4254
|
-
description: (0, import_yup41.string)().optional().label("Description"),
|
|
4255
|
-
aliases: strings().default([]).label("Aliases"),
|
|
4256
|
-
/** null for categories (the roots). */
|
|
4257
|
-
parentId: (0, import_yup41.string)().nullable().defined().label("Parent ID"),
|
|
4258
|
-
/** Ancestor ids from the root down to and including this node. */
|
|
4259
|
-
path: (0, import_yup41.array)((0, import_yup41.string)().required()).default([]).label("Path"),
|
|
4260
|
-
source: (0, import_yup41.string)().oneOf(SupportedTaxonomySources).optional().label("Source"),
|
|
4261
|
-
createdAt: (0, import_yup41.number)().required().label("Created At"),
|
|
4262
|
-
updatedAt: (0, import_yup41.number)().required().label("Updated At")
|
|
4263
|
-
}).label("Taxonomy Node");
|
|
4264
|
-
var ConceptMembershipSchema = (0, import_yup41.object)({
|
|
4265
|
-
categoryId: (0, import_yup41.string)().required().label("Category ID"),
|
|
4266
|
-
categoryName: (0, import_yup41.string)().required().label("Category Name"),
|
|
4267
|
-
subcategoryId: (0, import_yup41.string)().required().label("Subcategory ID"),
|
|
4268
|
-
subcategoryName: (0, import_yup41.string)().required().label("Subcategory Name"),
|
|
4269
|
-
groupId: (0, import_yup41.string)().required().label("Group ID"),
|
|
4270
|
-
groupName: (0, import_yup41.string)().required().label("Group Name"),
|
|
4271
|
-
/** The source record this membership came from; '' when written by hand. */
|
|
4272
|
-
sourceId: (0, import_yup41.string)().default("").label("Source ID")
|
|
4273
|
-
}).label("Concept Membership");
|
|
4274
|
-
var ConceptSchema = (0, import_yup41.object)({
|
|
4275
|
-
/** `<vocabulary>_<slug>`, e.g. `skills_power-bi`. Primary key. */
|
|
4276
|
-
conceptId: conceptId().required().label("Concept ID"),
|
|
4277
|
-
vocabulary: vocabularyId().required().label("Vocabulary"),
|
|
4278
|
-
name: (0, import_yup41.string)().trim().min(1).max(200).required().label("Name"),
|
|
4279
|
-
/** One of the vocabulary's type ids; checked against the vocabulary by the service. */
|
|
4280
|
-
type: (0, import_yup41.string)().trim().matches(CONCEPT_TYPE_PATTERN, "type must be a type id").required().label("Type"),
|
|
4281
|
-
description: (0, import_yup41.string)().trim().max(2e3).default("").label("Description"),
|
|
4282
|
-
aliases: strings().default([]).label("Aliases"),
|
|
4283
|
-
memberships: (0, import_yup41.array)(ConceptMembershipSchema.required()).default([]).label("Memberships"),
|
|
4284
|
-
/** Always concepts of the same vocabulary. */
|
|
4285
|
-
relatedConceptIds: strings().default([]).label("Related Concepts"),
|
|
4286
|
-
source: (0, import_yup41.string)().oneOf(SupportedConceptSources).required().label("Source"),
|
|
4287
|
-
createdAt: (0, import_yup41.number)().required().label("Created At"),
|
|
4288
|
-
updatedAt: (0, import_yup41.number)().required().label("Updated At"),
|
|
4289
|
-
/** Resume marker of `retype-concepts`: set once the type was examined. */
|
|
4290
|
-
retypedAt: (0, import_yup41.number)().optional().label("Retyped At"),
|
|
4291
|
-
/** Resume marker of `generate-aliases`: set even when no alias was added. */
|
|
4292
|
-
aliasedAt: (0, import_yup41.number)().optional().label("Aliased At"),
|
|
4293
|
-
/** Set while `description` is a stand-in; removed once a real one is written. */
|
|
4294
|
-
descriptionPending: (0, import_yup41.boolean)().isTrue().optional().label("Description Pending")
|
|
4295
|
-
}).label("Concept");
|
|
4296
|
-
var UnmatchedTermSchema = (0, import_yup41.object)({
|
|
4297
|
-
vocabulary: vocabularyId().required().label("Vocabulary"),
|
|
4298
|
-
/** The raw input as first received. */
|
|
4299
|
-
term: (0, import_yup41.string)().required().label("Term"),
|
|
4300
|
-
/** The dedupe key, so "React JS" and "react.js" share a row. */
|
|
4301
|
-
normalizedTerm: (0, import_yup41.string)().required().label("Normalized Term"),
|
|
4302
|
-
count: (0, import_yup41.number)().integer().min(0).required().label("Count"),
|
|
4303
|
-
firstSeenAt: (0, import_yup41.number)().required().label("First Seen At"),
|
|
4304
|
-
lastSeenAt: (0, import_yup41.number)().required().label("Last Seen At"),
|
|
4305
|
-
/** Which callers sent it, capped. */
|
|
4306
|
-
sources: (0, import_yup41.array)(
|
|
4307
|
-
(0, import_yup41.object)({
|
|
4308
|
-
service: (0, import_yup41.string)().required(),
|
|
4309
|
-
context: (0, import_yup41.string)().optional()
|
|
4310
|
-
}).required()
|
|
4311
|
-
).default([]).label("Sources"),
|
|
4312
|
-
resolution: (0, import_yup41.string)().oneOf(SupportedUnmatchedResolutions).required().label("Resolution"),
|
|
4313
|
-
resolvedConceptId: (0, import_yup41.string)().optional().label("Resolved Concept"),
|
|
4314
|
-
/** `ambiguous`: the concept exists; the caller gave no context that picked one. */
|
|
4315
|
-
reason: (0, import_yup41.string)().oneOf(SupportedUnmatchedReasons).optional().label("Reason"),
|
|
4316
|
-
/** The concepts an ambiguous term could mean. */
|
|
4317
|
-
candidates: (0, import_yup41.array)((0, import_yup41.string)().required()).optional().label("Candidates"),
|
|
4318
|
-
/** Who rejected it when it was not a human: `prefilter:<rule>` or `model`. */
|
|
4319
|
-
rejectedBy: (0, import_yup41.string)().optional().label("Rejected By")
|
|
4320
|
-
}).label("Unmatched Term");
|
|
4321
|
-
var ProposalCandidateSchema = (0, import_yup41.object)({
|
|
4322
|
-
groupId: (0, import_yup41.string)().required(),
|
|
4323
|
-
groupName: (0, import_yup41.string)().required(),
|
|
4324
|
-
subcategoryId: (0, import_yup41.string)().required(),
|
|
4325
|
-
subcategoryName: (0, import_yup41.string)().required(),
|
|
4326
|
-
categoryId: (0, import_yup41.string)().required(),
|
|
4327
|
-
categoryName: (0, import_yup41.string)().required(),
|
|
4328
|
-
score: (0, import_yup41.number)().required(),
|
|
4329
|
-
nearestMembers: (0, import_yup41.array)((0, import_yup41.string)().required()).default([])
|
|
4330
|
-
}).label("Proposal Candidate");
|
|
4331
|
-
var ProposalMessageSchema = (0, import_yup41.object)({
|
|
4332
|
-
role: (0, import_yup41.string)().oneOf(SupportedProposalMessageRoles).required(),
|
|
4333
|
-
/** The operator's instruction, or the model's note on what it changed and why. */
|
|
4334
|
-
content: (0, import_yup41.string)().defined(),
|
|
4335
|
-
/** Which model answered. Absent on operator turns. */
|
|
4336
|
-
model: (0, import_yup41.string)().optional(),
|
|
4337
|
-
at: (0, import_yup41.number)().required()
|
|
4338
|
-
}).label("Proposal Message");
|
|
4339
|
-
var SuggestedHomeSchema = (0, import_yup41.object)({
|
|
4340
|
-
categoryName: (0, import_yup41.string)().defined(),
|
|
4341
|
-
subcategoryName: (0, import_yup41.string)().defined(),
|
|
4342
|
-
groupName: (0, import_yup41.string)().defined()
|
|
4343
|
-
}).label("Suggested Home");
|
|
4344
|
-
var ResolverVerificationSchema = (0, import_yup41.object)({
|
|
4345
|
-
verdict: (0, import_yup41.string)().oneOf(SupportedResolverVerdicts).required(),
|
|
4346
|
-
/** The shown concept the verdict is about; null for `new_concept` / `out_of_scope`. */
|
|
4347
|
-
conceptId: (0, import_yup41.string)().nullable().defined(),
|
|
4348
|
-
evidence: (0, import_yup41.string)().defined(),
|
|
4349
|
-
/** What the judge took the term to mean, abbreviations expanded. */
|
|
4350
|
-
means: (0, import_yup41.string)().optional(),
|
|
4351
|
-
/** For `same`: did the independent confirm step agree? */
|
|
4352
|
-
consistent: (0, import_yup41.boolean)().optional(),
|
|
4353
|
-
confirm: (0, import_yup41.object)({
|
|
4354
|
-
answer: (0, import_yup41.string)().oneOf(["yes", "no"]).required(),
|
|
4355
|
-
evidence: (0, import_yup41.string)().defined()
|
|
4356
|
-
}).optional().default(void 0)
|
|
4357
|
-
}).label("Resolver Verification");
|
|
4358
|
-
var ConceptProposalSchema = (0, import_yup41.object)({
|
|
4359
|
-
proposalId: (0, import_yup41.string)().required().label("Proposal ID"),
|
|
4360
|
-
vocabulary: vocabularyId().required().label("Vocabulary"),
|
|
4361
|
-
/** The miss this closes; `normalizedTerm` links back to its unmatched row. */
|
|
4362
|
-
term: (0, import_yup41.string)().required().label("Term"),
|
|
4363
|
-
normalizedTerm: (0, import_yup41.string)().required().label("Normalized Term"),
|
|
4364
|
-
/** Demand at proposal time, so the queue ranks without a join. */
|
|
4365
|
-
count: (0, import_yup41.number)().integer().min(0).required().label("Count"),
|
|
4366
|
-
/** Other misses folded into this draft because they name the same new concept. */
|
|
4367
|
-
mergedTerms: (0, import_yup41.array)(
|
|
4368
|
-
(0, import_yup41.object)({
|
|
4369
|
-
term: (0, import_yup41.string)().required(),
|
|
4370
|
-
normalizedTerm: (0, import_yup41.string)().required(),
|
|
4371
|
-
count: (0, import_yup41.number)().integer().min(0).required()
|
|
4372
|
-
}).required()
|
|
4373
|
-
).optional().label("Merged Terms"),
|
|
4374
|
-
/** Absent on drafts that predate the field: read as `concept`. */
|
|
4375
|
-
kind: (0, import_yup41.string)().oneOf(SupportedProposalKinds).optional().label("Kind"),
|
|
4376
|
-
/** For `alias`: the concept the term names. For `placement`: the concept to place. */
|
|
4377
|
-
targetConceptId: (0, import_yup41.string)().optional().label("Target Concept"),
|
|
4378
|
-
targetName: (0, import_yup41.string)().optional().label("Target Name"),
|
|
4379
|
-
// The draft concept, editable until approved. Empty strings are valid here:
|
|
4380
|
-
// an alias draft carries no draft concept of its own.
|
|
4381
|
-
name: (0, import_yup41.string)().defined().label("Name"),
|
|
4382
|
-
type: (0, import_yup41.string)().defined().label("Type"),
|
|
4383
|
-
description: (0, import_yup41.string)().defined().label("Description"),
|
|
4384
|
-
aliases: (0, import_yup41.array)((0, import_yup41.string)().required()).default([]).label("Aliases"),
|
|
4385
|
-
/** Empty when no group fits: approved that way, the concept goes live uncategorized. */
|
|
4386
|
-
memberships: (0, import_yup41.array)(ConceptMembershipSchema.required()).default([]).label("Memberships"),
|
|
4387
|
-
suggestedHome: SuggestedHomeSchema.nullable().optional().default(void 0).label("Suggested Home"),
|
|
4388
|
-
/** Resolved to concepts that exist; names that matched nothing are dropped. */
|
|
4389
|
-
relatedConceptIds: (0, import_yup41.array)((0, import_yup41.string)().required()).default([]).label("Related Concepts"),
|
|
4390
|
-
/** Every placement candidate considered, best first. */
|
|
4391
|
-
candidates: (0, import_yup41.array)(ProposalCandidateSchema.required()).default([]).label("Candidates"),
|
|
4392
|
-
needsReview: (0, import_yup41.boolean)().required().label("Needs Review"),
|
|
4393
|
-
reason: (0, import_yup41.string)().optional().label("Reason"),
|
|
4394
|
-
verification: ResolverVerificationSchema.optional().default(void 0).label("Verification"),
|
|
4395
|
-
/** What the auto-accept gate decided for an alias verdict. */
|
|
4396
|
-
autoAccept: (0, import_yup41.object)({
|
|
4397
|
-
accepted: (0, import_yup41.boolean)().required(),
|
|
4398
|
-
reason: (0, import_yup41.string)().optional(),
|
|
4399
|
-
tier: (0, import_yup41.string)().optional(),
|
|
4400
|
-
calibrationId: (0, import_yup41.string)().optional(),
|
|
4401
|
-
releaseId: (0, import_yup41.string)().optional()
|
|
4402
|
-
}).optional().default(void 0).label("Auto Accept"),
|
|
4403
|
-
/** Which model drafted it. */
|
|
4404
|
-
model: (0, import_yup41.string)().defined().label("Model"),
|
|
4405
|
-
/** The refinement conversation, oldest first. */
|
|
4406
|
-
messages: (0, import_yup41.array)(ProposalMessageSchema.required()).default([]).label("Messages"),
|
|
4407
|
-
status: (0, import_yup41.string)().oneOf(SupportedProposalStatuses).required().label("Status"),
|
|
4408
|
-
/** Set when approved: the concept this became. */
|
|
4409
|
-
resolvedConceptId: (0, import_yup41.string)().optional().label("Resolved Concept"),
|
|
4410
|
-
createdAt: (0, import_yup41.number)().required().label("Created At"),
|
|
4411
|
-
updatedAt: (0, import_yup41.number)().required().label("Updated At")
|
|
4412
|
-
}).label("Concept Proposal");
|
|
4413
|
-
var ReleaseSchema = (0, import_yup41.object)({
|
|
4414
|
-
releaseId: (0, import_yup41.string)().required().label("Release ID"),
|
|
4415
|
-
kind: (0, import_yup41.string)().oneOf(SupportedReleaseKinds).required().label("Kind"),
|
|
4416
|
-
status: (0, import_yup41.string)().oneOf(SupportedReleaseStatuses).required().label("Status"),
|
|
4417
|
-
createdBy: (0, import_yup41.string)().required().label("Created By"),
|
|
4418
|
-
createdAt: (0, import_yup41.number)().required().label("Created At"),
|
|
4419
|
-
note: (0, import_yup41.string)().optional().label("Note"),
|
|
4420
|
-
rolledBackAt: (0, import_yup41.number)().optional().label("Rolled Back At"),
|
|
4421
|
-
rolledBackBy: (0, import_yup41.string)().optional().label("Rolled Back By")
|
|
4422
|
-
}).label("Release");
|
|
4423
|
-
var AuditSchema = (0, import_yup41.object)({
|
|
4424
|
-
auditId: (0, import_yup41.string)().required().label("Audit ID"),
|
|
4425
|
-
releaseId: (0, import_yup41.string)().required().label("Release ID"),
|
|
4426
|
-
key: (0, import_yup41.string)().required().label("Key"),
|
|
4427
|
-
term: (0, import_yup41.string)().required().label("Term"),
|
|
4428
|
-
conceptId: (0, import_yup41.string)().required().label("Concept ID"),
|
|
4429
|
-
tier: (0, import_yup41.string)().optional().label("Tier"),
|
|
4430
|
-
status: (0, import_yup41.string)().oneOf(SupportedAuditStatuses).required().label("Status"),
|
|
4431
|
-
createdAt: (0, import_yup41.number)().required().label("Created At"),
|
|
4432
|
-
resolvedAt: (0, import_yup41.number)().optional().label("Resolved At"),
|
|
4433
|
-
resolvedBy: (0, import_yup41.string)().optional().label("Resolved By")
|
|
4434
|
-
}).label("Audit");
|
|
4435
|
-
var ResolverSettingsSchema = (0, import_yup41.object)({
|
|
4436
|
-
autoAccept: (0, import_yup41.object)({
|
|
4437
|
-
/** Stop switch for WRITING auto keys. Off until a calibration passes. */
|
|
4438
|
-
enabled: (0, import_yup41.boolean)().required(),
|
|
4439
|
-
/** Minimum calibrated precision (Wilson 95% lower bound) for a tier to auto-accept. */
|
|
4440
|
-
target: (0, import_yup41.number)().min(0.5).lessThan(1).required(),
|
|
4441
|
-
maxPerRun: (0, import_yup41.number)().integer().min(0).required(),
|
|
4442
|
-
maxPerDay: (0, import_yup41.number)().integer().min(0).required(),
|
|
4443
|
-
/** Share of each auto release sampled into the audit queue (0..1). */
|
|
4444
|
-
auditRate: (0, import_yup41.number)().min(0).max(1).required()
|
|
4445
|
-
}).label("Auto Accept"),
|
|
4446
|
-
/** Stop switch for SERVING auto keys: false hides them from lookups at once. */
|
|
4447
|
-
serveAutoKeys: (0, import_yup41.boolean)().required().label("Serve Auto Keys"),
|
|
4448
|
-
/** Minimum Meilisearch ranking score (0..1) for a fuzzy hit to be considered. */
|
|
4449
|
-
fuzzyMinScore: (0, import_yup41.number)().min(0).max(1).required().label("Fuzzy Min Score"),
|
|
4450
|
-
/** Per-client limit on public search, per minute per replica. 0 disables it. */
|
|
4451
|
-
searchRateLimitPerMin: (0, import_yup41.number)().integer().min(0).required().label("Search Rate Limit"),
|
|
4452
|
-
/** Master switch for scheduled maintenance jobs. */
|
|
4453
|
-
scheduledJobs: (0, import_yup41.boolean)().required().label("Scheduled Jobs"),
|
|
4454
|
-
updatedAt: (0, import_yup41.number)().optional().label("Updated At"),
|
|
4455
|
-
updatedBy: (0, import_yup41.string)().optional().label("Updated By"),
|
|
4456
|
-
/** Why auto-accept was last switched off automatically. */
|
|
4457
|
-
trippedReason: (0, import_yup41.string)().optional().label("Tripped Reason")
|
|
4458
|
-
}).label("Resolver Settings");
|
|
4459
|
-
var TaxonomyScheduleSchema = (0, import_yup41.object)({
|
|
4460
|
-
kind: (0, import_yup41.string)().oneOf(SupportedTaxonomyJobKinds).required().label("Job"),
|
|
4461
|
-
enabled: (0, import_yup41.boolean)().required().label("Enabled"),
|
|
4462
|
-
everyHours: (0, import_yup41.number)().min(SCHEDULE_MIN_HOURS).max(SCHEDULE_MAX_HOURS).required().label("Every (hours)"),
|
|
4463
|
-
/** Last time the scheduler fired this job. */
|
|
4464
|
-
lastRunAt: (0, import_yup41.number)().optional().label("Last Run At"),
|
|
4465
|
-
updatedAt: (0, import_yup41.number)().required().label("Updated At")
|
|
4466
|
-
}).label("Taxonomy Schedule");
|
|
4467
|
-
var NormalizeContextSchema = (0, import_yup41.object)({
|
|
4468
|
-
/** The title of the record the terms come from. */
|
|
4469
|
-
title: (0, import_yup41.string)().max(200).optional(),
|
|
4470
|
-
/** Backbone node ids (category, subcategory or group). */
|
|
4471
|
-
categoryIds: (0, import_yup41.array)(nodeId().required()).max(10).optional(),
|
|
4472
|
-
/** Other terms from the same record, in the same vocabulary. */
|
|
4473
|
-
siblings: (0, import_yup41.array)((0, import_yup41.string)().max(200).required()).max(50).optional()
|
|
4474
|
-
}).label("Normalize Context");
|
|
4475
|
-
|
|
4476
4493
|
// src/taxonomy/taxonomy-filter.schema.ts
|
|
4477
4494
|
var import_yup42 = require("yup");
|
|
4478
4495
|
var ConceptFilterShape = (0, import_yup42.object)({
|