@cavuno/board 3.2.0 → 4.1.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +433 -0
  2. package/README.md +6 -2
  3. package/dist/{_spec-nkWAraS0.d.mts → _spec-BZDv2dc5.d.mts} +100 -68
  4. package/dist/{_spec-nkWAraS0.d.ts → _spec-BZDv2dc5.d.ts} +100 -68
  5. package/dist/bin.mjs +7 -2
  6. package/dist/{blog-iV9XEIGf.d.ts → blog-BHx6iH3Z.d.ts} +1 -1
  7. package/dist/{blog-DGBHmExV.d.mts → blog-DyDvyQrI.d.mts} +1 -1
  8. package/dist/{board-JhdUWIoq.d.ts → board-BF3Qao6J.d.mts} +7 -6
  9. package/dist/{board-BJbXd_9_.d.mts → board-BTEZ0uiI.d.ts} +7 -6
  10. package/dist/breadcrumbs-SGaWth6C.d.ts +372 -0
  11. package/dist/breadcrumbs-icxRVydh.d.mts +372 -0
  12. package/dist/chunk-BGKNXG4H.mjs +146 -0
  13. package/dist/{chunk-NXY3OWGF.mjs → chunk-T2KC6XGV.mjs} +1 -1
  14. package/dist/{chunk-STE77MAT.mjs → chunk-YEAQ3JEI.mjs} +143 -134
  15. package/dist/doctor.js +1 -1
  16. package/dist/doctor.mjs +1 -1
  17. package/dist/filters.d.mts +25 -20
  18. package/dist/filters.d.ts +25 -20
  19. package/dist/filters.js +3 -692
  20. package/dist/filters.mjs +3 -29
  21. package/dist/format.d.mts +57 -231
  22. package/dist/format.d.ts +57 -231
  23. package/dist/format.js +327 -968
  24. package/dist/format.mjs +207 -264
  25. package/dist/go.js +11 -1
  26. package/dist/go.mjs +1 -1
  27. package/dist/index.d.mts +67 -76
  28. package/dist/index.d.ts +67 -76
  29. package/dist/index.js +45 -36
  30. package/dist/index.mjs +45 -36
  31. package/dist/{jobs-BiEvL9d7.d.ts → jobs-BX6d_sdd.d.mts} +4 -4
  32. package/dist/{jobs-lVvKCBCU.d.mts → jobs-BbLJfz1z.d.ts} +4 -4
  33. package/dist/paths.d.mts +89 -1
  34. package/dist/paths.d.ts +89 -1
  35. package/dist/paths.js +62 -14
  36. package/dist/paths.mjs +11 -3
  37. package/dist/route-contract.js +23 -13
  38. package/dist/route-contract.mjs +2 -2
  39. package/dist/{search-CCyFWPi3.d.mts → search-7B-mVRNA.d.ts} +14 -3
  40. package/dist/{search-CyRvVMUp.d.ts → search-OKrdAHv8.d.mts} +14 -3
  41. package/dist/seo.d.mts +30 -29
  42. package/dist/seo.d.ts +30 -29
  43. package/dist/seo.js +197 -718
  44. package/dist/seo.mjs +26 -24
  45. package/dist/server.d.mts +5 -5
  46. package/dist/server.d.ts +5 -5
  47. package/dist/sitemap.d.mts +5 -5
  48. package/dist/sitemap.d.ts +5 -5
  49. package/dist/sitemap.js +25 -14
  50. package/dist/sitemap.mjs +3 -2
  51. package/dist/skills.js +1 -1
  52. package/dist/skills.mjs +1 -1
  53. package/dist/suggest.d.mts +2 -2
  54. package/dist/suggest.d.ts +2 -2
  55. package/dist/suggest.js +17 -3
  56. package/dist/suggest.mjs +17 -3
  57. package/dist/well-known.js +23 -13
  58. package/dist/well-known.mjs +2 -2
  59. package/package.json +2 -4
  60. package/skills/cavuno-board-api-client/SKILL.md +42 -0
  61. package/skills/cavuno-board-applications/SKILL.md +4 -1
  62. package/skills/cavuno-board-filters/SKILL.md +11 -12
  63. package/skills/cavuno-board-format/SKILL.md +68 -56
  64. package/skills/cavuno-board-i18n/SKILL.md +102 -21
  65. package/skills/cavuno-board-search-suggestions/SKILL.md +8 -3
  66. package/skills/cavuno-board-seo/BLOG.md +4 -1
  67. package/skills/cavuno-board-seo/JOB_AND_BREADCRUMBS.md +5 -2
  68. package/skills/cavuno-board-seo/LISTING.md +35 -12
  69. package/skills/cavuno-board-seo/SALARY.md +83 -18
  70. package/skills/cavuno-board-seo/SKILL.md +3 -2
  71. package/skills/manifest.json +3 -3
  72. package/dist/breadcrumbs-1hMjcsqA.d.mts +0 -171
  73. package/dist/breadcrumbs-DexU07TT.d.ts +0 -171
  74. package/dist/chunk-IJCJ26SQ.mjs +0 -596
  75. package/dist/chunk-L7ZOYWHW.mjs +0 -98
  76. package/dist/chunk-LUGJWOT7.mjs +0 -96
  77. package/dist/ui-copy-CCkz6CVF.d.mts +0 -230
  78. package/dist/ui-copy-CCkz6CVF.d.ts +0 -230
package/dist/filters.mjs CHANGED
@@ -1,11 +1,3 @@
1
- import {
2
- fieldLabel
3
- } from "./chunk-LUGJWOT7.mjs";
4
- import {
5
- getSalaryLexicon,
6
- uiCopy
7
- } from "./chunk-IJCJ26SQ.mjs";
8
-
9
1
  // src/filters/index.ts
10
2
  var REMOTE_OPTIONS = [
11
3
  "on_site",
@@ -35,22 +27,6 @@ var JOB_SORTS = [
35
27
  "salary_high"
36
28
  ];
37
29
  var DEFAULT_SORT = "relevance";
38
- function seniorityLabels(locale, labels) {
39
- if (!labels?.jobCardLabels) return getSalaryLexicon(locale).seniority;
40
- const out = {};
41
- for (const seniority of SENIORITIES) {
42
- out[seniority] = fieldLabel(locale, seniority, labels) ?? seniority;
43
- }
44
- return out;
45
- }
46
- function sortLabels(locale, labels) {
47
- const copy = uiCopy(locale, labels).jobCard;
48
- return {
49
- relevance: copy.aiRankedLabel,
50
- newest: copy.sortNewestLabel,
51
- salary_high: copy.sortSalaryHighLabel
52
- };
53
- }
54
30
  var COMPANY_SLUG_MAX = 10;
55
31
  var SENIORITY_LOOKUP = new Set(SENIORITIES);
56
32
  function parseSeniority(raw) {
@@ -59,7 +35,7 @@ function parseSeniority(raw) {
59
35
  const seen = /* @__PURE__ */ new Set();
60
36
  for (const value of values) {
61
37
  if (typeof value !== "string") continue;
62
- const normalized = value.trim().toLowerCase();
38
+ const normalized = value.trim().toLowerCase().normalize("NFC");
63
39
  if (!normalized || seen.has(normalized)) continue;
64
40
  if (!SENIORITY_LOOKUP.has(normalized)) continue;
65
41
  seen.add(normalized);
@@ -73,7 +49,7 @@ function parseCompany(raw) {
73
49
  const seen = /* @__PURE__ */ new Set();
74
50
  for (const value of values) {
75
51
  if (typeof value !== "string") continue;
76
- const normalized = value.trim().toLowerCase();
52
+ const normalized = value.trim().toLowerCase().normalize("NFC");
77
53
  if (!normalized || seen.has(normalized)) continue;
78
54
  seen.add(normalized);
79
55
  result.push(normalized);
@@ -101,7 +77,5 @@ export {
101
77
  SENIORITIES,
102
78
  parseCompany,
103
79
  parseListingFilters,
104
- parseSeniority,
105
- seniorityLabels,
106
- sortLabels
80
+ parseSeniority
107
81
  };
package/dist/format.d.mts CHANGED
@@ -1,9 +1,7 @@
1
- import { P as PublicJob, a as PublicJobCard, C as CustomFieldValues } from './jobs-lVvKCBCU.mjs';
2
- import { B as BoardLabelOverrides } from './ui-copy-CCkz6CVF.mjs';
3
- export { A as AlertsCopy, a as ApplyCopy, b as BlogCopy, c as BreadcrumbsCopy, C as CopyLinkCopy, E as EntityCopy, F as FooterCopy, J as JobCardCopy, d as JobDetailCopy, e as JobSearchCopy, N as NavCopy, P as PUBLIC_LABEL_GROUPS, f as PaginationCopy, S as SalaryCopy, U as UiCopy, u as uiCopy } from './ui-copy-CCkz6CVF.mjs';
4
- export { b as buildJobBreadcrumbs, f as formatSalaryStatRange, a as formatSalaryStatUsd, n as normalizeWebsiteUrl } from './breadcrumbs-1hMjcsqA.mjs';
5
- import { C as CustomFieldDefinition } from './board-BJbXd_9_.mjs';
6
- import './_spec-nkWAraS0.mjs';
1
+ export { C as CurrencyDisplay, F as FormattedSalaryRange, J as JobBreadcrumb, N as NumberNotation, S as SalaryTimeframeInput, a as SalaryTimeframeValue, b as buildJobBreadcrumbs, f as formatSalaryRange, c as formatSalaryStat, d as formatSalaryStatRange, n as normalizeWebsiteUrl } from './breadcrumbs-icxRVydh.mjs';
2
+ import { C as CustomFieldDefinition } from './board-BF3Qao6J.mjs';
3
+ import { C as CustomFieldValues } from './jobs-BX6d_sdd.mjs';
4
+ import './_spec-BZDv2dc5.mjs';
7
5
 
8
6
  /**
9
7
  * Date display helpers in the board language (required leading parameter,
@@ -11,8 +9,12 @@ import './_spec-nkWAraS0.mjs';
11
9
  * tested against the hosted behavior.
12
10
  *
13
11
  * Job cards and the job-detail header render the RELATIVE form
14
- * (`formatPublishedRelativeDate` — "5d ago"); the absolute medium date
12
+ * (`formatPublishedRelativeDate` — "5 days ago"); the absolute medium date
15
13
  * (`formatDate`) is what hosted uses for blog metadata and detail facts.
14
+ *
15
+ * Invalid locales return `null` rather than English unit abbreviations
16
+ * (`5d` / `5mo`) or a sign-stripped digit string. Past vs future is kept
17
+ * (negative → past) so RTF can own the word.
16
18
  */
17
19
  /**
18
20
  * Absolute medium date in the board language, UTC-pinned — e.g.
@@ -22,229 +24,28 @@ import './_spec-nkWAraS0.mjs';
22
24
  */
23
25
  declare function formatDate(locale: string, value: string | number | null): string | null;
24
26
  /**
25
- * Relative published label — "5d ago" (en) / "vor 5 T." (de) — the form the
26
- * hosted board renders on job cards and the job-detail header. Under one
27
- * minute renders "now". `referenceNowMs` exists for deterministic tests.
27
+ * Relative published label — "5 days ago" (en) / "vor 5 Tagen" (de) — the
28
+ * form the hosted board renders on job cards and the job-detail header.
29
+ * Under one minute uses `Intl.RelativeTimeFormat` with `numeric: 'auto'` so
30
+ * the board language owns "now" / "jetzt" / "maintenant". `referenceNowMs`
31
+ * exists for deterministic tests.
28
32
  */
29
33
  declare function formatPublishedRelativeDate(locale: string, value: string | number | null, referenceNowMs?: number): string | null;
30
34
  /**
31
35
  * Month-year label, e.g. "Jun 2023" — transcribed from the hosted board's
32
- * `formatMonthYear`. The `T00:00:00` suffix
33
- * prevents timezone-related off-by-one-month issues on date-only strings.
34
- */
35
- declare function formatMonthYear(locale: string, dateStr: string): string;
36
-
37
- /**
38
- * Adapt a full `PublicJob` (e.g. an embedded saved job) to the slim
39
- * `PublicJobCard` shape a list card renders — computing the card's
40
- * pre-resolved `locationLabel`/`remoteLocationLabel` from the full job's
41
- * fields. Board language is required because the computed location label is
42
- * display text.
43
- */
44
- declare function fullJobToCard(locale: string, job: PublicJob): PublicJobCard;
45
-
46
- /**
47
- * Display label for a job enum value (`remoteOption`, `employmentType`,
48
- * `seniority`) in the board language, ⊕ the board's stored operator
49
- * overrides when the `labels` bag is passed. Unknown values pass through
50
- * unchanged (enums grow additively within v1); unseeded languages fall back
51
- * to the English source vocabulary.
36
+ * `formatMonthYear`.
52
37
  *
53
- * @example
54
- * fieldLabel('en', 'mid_level'); // "Mid-level"
55
- * fieldLabel('de', 'executive'); // "Führungskraft"
56
- * fieldLabel('de', 'full_time'); // "Vollzeit"
57
- * fieldLabel('de', 'full_time', board.labels); // operator override when set
58
- */
59
- declare function fieldLabel(locale: string, value: string | null, labels?: BoardLabelOverrides): string | null;
60
-
61
- /**
62
- * Location display labels for job cards and detail pages, in the board
63
- * language. The wrapper words
64
- * ("Remote", "(hybrid)", "Worldwide") follow the hosted board's current
65
- * English-only rendering; place names arrive already board-language from the
66
- * wire (the API serves canonical, localized labels).
67
- */
68
- /**
69
- * Location label for the full `PublicJob` (detail pages, embedded saved
70
- * jobs): first office location's display name, remote/hybrid wrapping per
71
- * `remoteOption`.
72
- */
73
- declare function locationLabel(locale: string, job: PublicJob): string;
74
- /**
75
- * Location label for a list CARD. The card read-model pre-computes
76
- * `locationLabel` and (for remote jobs) `remoteLocationLabel` server-side —
77
- * the slim card carries no `officeLocations`/`remoteWorldwide` — so those
78
- * wire fields are used directly, matching what the hosted card renders.
79
- */
80
- declare function cardLocationLabel(locale: string, job: Pick<PublicJobCard, 'remoteOption' | 'remoteLocationLabel' | 'locationLabel'>): string;
81
-
82
- /**
83
- * The closed, board-language salary LEXICON — the fixed salary words:
84
- * timeframe labels + range prefixes, seniority labels, and metadata
85
- * `<title>`/`<description>` sentence FRAMES, keyed by the board language
86
- * (`board.context().language`), NOT by any visitor locale.
87
- *
88
- * Transcribed from the hosted board's `salary-lexicon.ts` and tested against it : the two
89
- * copies cannot drift silently. The `de` strings are native-reviewed.
90
- * Unseeded locales fall back to the English source WORDS while number and
91
- * currency formatting stays locale-correct.
92
- */
93
- /** Wire enum for `salaryTimeframe`. */
94
- type SalaryTimeframeValue = 'per_year' | 'per_month' | 'per_week' | 'per_day' | 'per_hour';
95
- type SeniorityKey = 'entry_level' | 'associate' | 'mid_level' | 'senior' | 'lead' | 'principal' | 'director' | 'executive';
96
- /**
97
- * Board-language builders for the salary-page metadata sentence frames. Each
98
- * receives already-formatted parts (entity name, board-language `range`/amount
99
- * strings, counts) and returns one localized sentence. The numbers are
100
- * formatted upstream (`formatSalaryRange`); the FRAME is the words.
101
- */
102
- interface SalaryFrames {
103
- entitySalariesTitle(a: {
104
- entity: string;
105
- range: string;
106
- }): string;
107
- salariesInPlaceTitle(a: {
108
- place: string;
109
- range: string;
110
- }): string;
111
- salariesInPlaceTitleNoRange(a: {
112
- place: string;
113
- }): string;
114
- entitySalariesInPlaceTitle(a: {
115
- entity: string;
116
- place: string;
117
- range: string;
118
- }): string;
119
- companySalariesTitle(a: {
120
- company: string;
121
- range: string | null;
122
- }): string;
123
- companyCategorySalariesTitle(a: {
124
- company: string;
125
- category: string;
126
- range: string | null;
127
- }): string;
128
- professionalsEarn(a: {
129
- entity: string;
130
- range: string;
131
- count: number;
132
- }): string;
133
- rolesPay(a: {
134
- entity: string;
135
- range: string;
136
- count: number;
137
- }): string;
138
- professionalsInLocationEarn(a: {
139
- entity: string;
140
- place: string;
141
- range: string;
142
- count: number;
143
- }): string;
144
- seniorityRange(a: {
145
- lowLabel: string;
146
- lowAmount: string;
147
- highLabel: string;
148
- highAmount: string;
149
- }): string;
150
- seniorityRangeWhile(a: {
151
- lowLabel: string;
152
- lowAmount: string;
153
- highLabel: string;
154
- highAmount: string;
155
- }): string;
156
- compareAcrossTopPaying(a: {
157
- count: number;
158
- }): string;
159
- compareAcrossTop(a: {
160
- count: number;
161
- }): string;
162
- boardWideAverage(a: {
163
- entity: string;
164
- range: string;
165
- }): string;
166
- averageSalaryInCity(a: {
167
- place: string;
168
- range: string;
169
- count: number;
170
- }): string;
171
- browseLocationsInRegion(a: {
172
- count: number;
173
- place: string;
174
- }): string;
175
- companyPays(a: {
176
- company: string;
177
- range: string;
178
- count: number;
179
- }): string;
180
- breakdownAcrossCategories(a: {
181
- count: number;
182
- }): string;
183
- compareWithSimilar(a: {
184
- count: number;
185
- }): string;
186
- salaryInfoFor(a: {
187
- company: string;
188
- board: string;
189
- }): string;
190
- categoryRolesAtCompanyPay(a: {
191
- category: string;
192
- company: string;
193
- range: string;
194
- count: number;
195
- }): string;
196
- categorySalaryDataFor(a: {
197
- category: string;
198
- company: string;
199
- board: string;
200
- }): string;
201
- }
202
- interface SalaryLexicon {
203
- /** Per-timeframe display word, e.g. `per_year` → "Yearly" / "pro Jahr". */
204
- timeframe: Record<SalaryTimeframeValue, string>;
205
- /** Open-ended range prefixes, e.g. "From" / "ab", "Up to" / "bis zu". */
206
- rangePrefix: {
207
- from: string;
208
- upTo: string;
209
- };
210
- /** Seniority-level labels, e.g. `senior` → "Senior". */
211
- seniority: Record<SeniorityKey, string>;
212
- /** Metadata `<title>`/`<description>` sentence builders. */
213
- frames: SalaryFrames;
214
- }
215
- /**
216
- * Resolve the salary lexicon for a board language; unseeded locales fall back
217
- * to the English source.
218
- */
219
- declare function getSalaryLexicon(locale: string | undefined): SalaryLexicon;
220
-
221
- type SalaryTimeframeInput = SalaryTimeframeValue | string | null | undefined;
222
- /** Owner-customized timeframe words (board settings) — from the board's SEO/labels config. */
223
- interface SalaryTimeframeOverrides {
224
- yearlyLabel?: string;
225
- monthlyLabel?: string;
226
- weeklyLabel?: string;
227
- dailyLabel?: string;
228
- hourlyLabel?: string;
229
- }
230
- /**
231
- * Format a per-job salary range in the BOARD language
232
- * (`board.context().language` — required, never defaulted; see ).
233
- * The fixed words (timeframe, "From"/"Up to") come from
234
- * `getSalaryLexicon(language)` with precedence owner-override > lexicon >
235
- * English source. Currency placement is gated: `en` keeps the legacy manual
236
- * symbol-before form (byte-identical to the hosted board); non-`en` uses
237
- * `Intl` `style:'currency'` so the symbol sits per locale.
238
- *
239
- * @example
240
- * formatSalaryRange('en', 90000, 120000, 'per_year', 'USD');
241
- * // "$90K – $120K Yearly"
242
- * formatSalaryRange('de', 90000, null, 'per_year', 'EUR');
243
- * // "ab 90.000 € pro Jahr"
244
- */
245
- declare function formatSalaryRange(language: string | undefined, min: number | null, max: number | null, timeframe: SalaryTimeframeInput, currency?: string | null, timeframeOverrides?: SalaryTimeframeOverrides): string | null;
246
-
247
- declare function companyIntro(summary: string | null, description: string | null): string | null;
38
+ * - Date-only inputs (`YYYY-MM`, `YYYY-MM-DD`) get a UTC midnight pin
39
+ * (`T00:00:00.000Z`) so the UTC formatter below keeps the same calendar
40
+ * month. Local midnight + `timeZone: 'UTC'` would shift western zones
41
+ * back a day (e.g. Jun 1 AEST → May 31 UTC).
42
+ * - Full ISO timestamps are formatted with `timeZone: 'UTC'` (same pin as
43
+ * `formatDate`) so a UTC midnight never renders as the previous month
44
+ * under America/Los_Angeles.
45
+ * - Missing or unparseable input returns `null`, matching `formatDate` —
46
+ * never the English literal `"Invalid Date"`.
47
+ */
48
+ declare function formatMonthYear(locale: string, dateStr: string | null | undefined): string | null;
248
49
 
249
50
  /**
250
51
  * ISO 3166-1 alpha-2 country lexicon — the `country` slice of the remote-
@@ -265,7 +66,9 @@ interface CountryOption {
265
66
  * The complete country option list, display-named in the BOARD language
266
67
  * and sorted by that language's
267
68
  * collation — the shape a country picker renders. Falls back to the bare
268
- * code when the runtime cannot resolve the language or name a region.
69
+ * code when the runtime cannot name a region. When the board language is
70
+ * invalid or unsupported (`normalizeLocale` → `null`), returns ISO codes
71
+ * as names sorted by code — never host-default English names/collation.
269
72
  */
270
73
  declare function countryOptions(language: string): CountryOption[];
271
74
 
@@ -276,9 +79,22 @@ declare function countryOptions(language: string): CountryOption[];
276
79
  * context) in config order, so display order is operator-controlled, orphan
277
80
  * values (deleted definitions) are never inspected, and empty values drop per
278
81
  * field. Select values resolve their stored option KEY to the current label
279
- * (rename-safe); an option with no current match is dropped. Booleans stay raw
280
- * (a discriminated `kind`) — the render layer authors the "Yes"/"No" chrome
281
- * (English; localized copy is the use-intl future release).
82
+ * (rename-safe); an option with no current match is dropped. Booleans and
83
+ * numbers stay raw (discriminated `kind`) — the render layer formats them
84
+ * with the board locale (`Intl.NumberFormat`, Yes/No chrome). Pre-stringifying
85
+ * numbers would ship `kind: 'text'` and foreclose locale-aware formatting.
86
+ *
87
+ * Multi-select stays an array of resolved labels (`kind: 'multi_select'`).
88
+ * Pre-joining with `Intl.ListFormat` would ship `kind: 'text'` and foreclose
89
+ * locale-aware **list** formatting (short style, disjunction, separate chips)
90
+ * for the same reason numbers must not be pre-stringified. The application
91
+ * joins when it wants a sentence:
92
+ * `new Intl.ListFormat(language, { style: 'long', type: 'conjunction' }).format(values)`.
93
+ *
94
+ * `language` remains the required leading parameter ( call-site
95
+ * pattern / signature stability). It is not read here — multi-select no
96
+ * longer joins in the SDK — but callers already pass `board.context().language`
97
+ * and removing it would be a delete from the published surface.
282
98
  */
283
99
  type CustomFieldDisplayEntry = {
284
100
  key: string;
@@ -290,7 +106,17 @@ type CustomFieldDisplayEntry = {
290
106
  label: string;
291
107
  kind: 'boolean';
292
108
  value: boolean;
109
+ } | {
110
+ key: string;
111
+ label: string;
112
+ kind: 'number';
113
+ value: number;
114
+ } | {
115
+ key: string;
116
+ label: string;
117
+ kind: 'multi_select';
118
+ values: string[];
293
119
  };
294
- declare function resolveCustomFieldDisplay(definitions: CustomFieldDefinition[] | undefined, values: CustomFieldValues | undefined): CustomFieldDisplayEntry[];
120
+ declare function resolveCustomFieldDisplay(language: string, definitions: CustomFieldDefinition[] | undefined, values: CustomFieldValues | undefined): CustomFieldDisplayEntry[];
295
121
 
296
- export { BoardLabelOverrides, COUNTRY_CODES, type CountryOption, type CustomFieldDisplayEntry, type IsoCountryCode, type SalaryFrames, type SalaryLexicon, type SalaryTimeframeInput, type SalaryTimeframeOverrides, type SalaryTimeframeValue, type SeniorityKey, cardLocationLabel, companyIntro, countryOptions, fieldLabel, formatDate, formatMonthYear, formatPublishedRelativeDate, formatSalaryRange, fullJobToCard, getSalaryLexicon, locationLabel, resolveCustomFieldDisplay };
122
+ export { COUNTRY_CODES, type CountryOption, type CustomFieldDisplayEntry, type IsoCountryCode, countryOptions, formatDate, formatMonthYear, formatPublishedRelativeDate, resolveCustomFieldDisplay };