@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thejob/schema",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -13,6 +13,7 @@ import { DurationSchema } from "../duration/duration.schema.js";
13
13
  import { LocationSchema } from "../location/location.schema.js";
14
14
  import { PageSchema } from "../page/page.schema.js";
15
15
  import { SkillSchema } from "../skill/skill.schema.js";
16
+ import { ConceptSchema } from "../taxonomy/taxonomy.schema.js";
16
17
  import { QuestionType } from "../question/index.js";
17
18
  import type {
18
19
  TChoiceQuestionSchema,
@@ -70,14 +71,27 @@ export const JobSchema = object({
70
71
  workMode: string().required().label("Work mode"),
71
72
 
72
73
  /**
73
- * `conceptId`/`conceptName` carry the taxonomy-service normalization. They are
74
- * picked here (not just `name`/`logo`) because SkillSchema is `.noUnknown()`:
75
- * an unpicked field that is actually PRESENT fails validation, so omitting them
76
- * would reject every normalized job.
74
+ * `name` is the skill exactly as posted. `concept` is what thejob-taxonomy-service
75
+ * resolved it to (`vocabulary: skills`), written by jobs-service, never by the
76
+ * poster: enough of the concept to filter by id and display the canonical name
77
+ * without a lookup. A copy, so it can go stale after a taxonomy release; see
78
+ * `taxonomyVersion`.
79
+ *
80
+ * Additive, never authoritative: the raw `name` is always kept, so a wrong
81
+ * match, a taxonomy release or an outage is recoverable by re-normalizing.
82
+ * `concept` is absent when the term did not resolve (a normal outcome, logged
83
+ * as a miss on the taxonomy side) or the job predates normalization, so read
84
+ * `concept?.name ?? name`.
77
85
  */
78
86
  skills: array()
79
87
  .of(
80
- SkillSchema.pick(["name", "logo", "conceptId", "conceptName"])
88
+ SkillSchema.pick(["name", "logo"])
89
+ .shape({
90
+ concept: ConceptSchema.pick(["conceptId", "vocabulary", "name", "type"])
91
+ .nullable()
92
+ .optional()
93
+ .default(undefined),
94
+ })
81
95
  .required()
82
96
  .label("Skill"),
83
97
  )
@@ -283,6 +297,15 @@ export const JobSchema = object({
283
297
  .optional()
284
298
  .label("Sub Categories"),
285
299
 
300
+ /**
301
+ * The taxonomy state `skills[].concept` was resolved against (the service's
302
+ * `taxonomyVersion`, bumped by every release and rollback); behind the current
303
+ * version means the concepts may be stale. Written by jobs-service with every
304
+ * skills write: `null` when that write could not be normalized (taxonomy down
305
+ * or unconfigured), absent on jobs that predate normalization.
306
+ */
307
+ taxonomyVersion: number().integer().min(0).nullable().optional().label("Taxonomy Version"),
308
+
286
309
  termsAccepted: boolean()
287
310
  .oneOf([true], "Accept terms before proceeding")
288
311
  .required("Accept terms before proceeding")