@cavuno/board 4.27.0 → 4.28.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/CHANGELOG.md +45 -0
- package/dist/{_spec-B_pBNVUd.d.mts → _spec-DQvmsp5o.d.mts} +102 -20
- package/dist/{_spec-B_pBNVUd.d.ts → _spec-DQvmsp5o.d.ts} +102 -20
- package/dist/{blog-DzGRUsj5.d.ts → blog-CUkvhn3c.d.ts} +1 -1
- package/dist/{blog-fhXRik6k.d.mts → blog-CvuObn9O.d.mts} +1 -1
- package/dist/{board-fVAXZ8T5.d.ts → board-CCG1pO6r.d.ts} +2 -2
- package/dist/{board-DEiEHcpe.d.mts → board-D6xOidUX.d.mts} +2 -2
- package/dist/{breadcrumbs-qE3CD--N.d.mts → breadcrumbs-BBvJ5gq-.d.mts} +2 -2
- package/dist/{breadcrumbs-DNaaP3xa.d.ts → breadcrumbs-D2Cwrju4.d.ts} +2 -2
- package/dist/browser/cavuno-board.global.min.js +1 -1
- package/dist/{chunk-DUTQOLOF.mjs → chunk-EHSB2VAJ.mjs} +4 -0
- package/dist/filters.d.mts +2 -2
- package/dist/filters.d.ts +2 -2
- package/dist/format.d.mts +4 -4
- package/dist/format.d.ts +4 -4
- package/dist/index.d.mts +91 -14
- package/dist/index.d.ts +91 -14
- package/dist/index.js +44 -4
- package/dist/index.mjs +41 -5
- package/dist/{jobs-R-h3A3kl.d.mts → jobs-CEIuahbz.d.ts} +9 -7
- package/dist/{jobs-BRysn2m0.d.ts → jobs-DjMcghv6.d.mts} +9 -7
- package/dist/{search-BlB690ma.d.mts → search-C0LiPXVb.d.mts} +1 -1
- package/dist/{search-BK_zHHNQ.d.ts → search-D-EjtZH3.d.ts} +1 -1
- package/dist/{seo-C7gMl6Y7.d.ts → seo-CjNGqZZH.d.ts} +1 -1
- package/dist/{seo-0mbZ7M_E.d.mts → seo-DCQp8V1c.d.mts} +1 -1
- package/dist/seo-files.d.mts +2 -2
- package/dist/seo-files.d.ts +2 -2
- package/dist/seo.d.mts +6 -6
- package/dist/seo.d.ts +6 -6
- package/dist/server.d.mts +6 -6
- package/dist/server.d.ts +6 -6
- package/dist/server.mjs +1 -1
- package/dist/sitemap.d.mts +6 -6
- package/dist/sitemap.d.ts +6 -6
- package/dist/sitemap.mjs +1 -1
- package/dist/suggest.d.mts +2 -2
- package/dist/suggest.d.ts +2 -2
- package/package.json +1 -1
- package/skills/cavuno-board-account/SKILL.md +27 -0
- package/skills/cavuno-board-errors/SKILL.md +1 -1
- package/skills/cavuno-board-filters/SKILL.md +90 -1
- package/skills/cavuno-board-format/SKILL.md +52 -0
- package/skills/cavuno-board-post-a-job/SKILL.md +24 -0
- package/skills/cavuno-board-salaries/SKILL.md +7 -0
- package/skills/manifest.json +2 -2
|
@@ -96,6 +96,55 @@ the same card view-model as listings — do not convert a full job client-side.
|
|
|
96
96
|
const card = toJobCardVM(saved.job, { language, /* … */ });
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
+
## Badges on job cards
|
|
100
|
+
|
|
101
|
+
Every job card (listings, search, company jobs, similar, recommended, and
|
|
102
|
+
saved jobs) carries `customFieldValues` for the job and
|
|
103
|
+
`company.customFieldValues` for its company. Both hold only select, boolean,
|
|
104
|
+
and number values keyed by field key; select values are option keys. Text
|
|
105
|
+
fields stay on the full job and company, and private company fields never
|
|
106
|
+
appear. Both are `{}` when empty, so a card needs no extra request to show a
|
|
107
|
+
badge.
|
|
108
|
+
|
|
109
|
+
```ts snippet
|
|
110
|
+
import { resolveCustomFieldDisplay } from '@cavuno/board/format';
|
|
111
|
+
|
|
112
|
+
const context = await board.context();
|
|
113
|
+
const companyFields = await board.profileFields.retrieve('company');
|
|
114
|
+
|
|
115
|
+
// Badge only the fields the operator wants on cards (an app-config list).
|
|
116
|
+
const JOB_BADGE_KEYS = ['work_type'];
|
|
117
|
+
const jobBadges = resolveCustomFieldDisplay(
|
|
118
|
+
context.language,
|
|
119
|
+
context.customFields.job.filter((field) => JOB_BADGE_KEYS.includes(field.key)),
|
|
120
|
+
card.customFieldValues).flatMap((entry) => {
|
|
121
|
+
switch (entry.kind) {
|
|
122
|
+
case 'text': // a single_select resolves to its option label
|
|
123
|
+
return [entry.value];
|
|
124
|
+
case 'multi_select':
|
|
125
|
+
return entry.values;
|
|
126
|
+
case 'boolean':
|
|
127
|
+
return entry.value ? [entry.label] : [];
|
|
128
|
+
case 'number':
|
|
129
|
+
return [`${entry.label}: ${entry.value}`];
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// Company badge: resolve the stored option key to its public label.
|
|
134
|
+
const employerField = companyFields.definitions.find(
|
|
135
|
+
(field) => field.key === 'employer_category');
|
|
136
|
+
const employerKey = card.company?.customFieldValues.employer_category;
|
|
137
|
+
const employerBadge =
|
|
138
|
+
typeof employerKey === 'string'
|
|
139
|
+
? (employerField?.options?.find((option) => option.key === employerKey)
|
|
140
|
+
?.label ?? null)
|
|
141
|
+
: null;
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Load the definitions once per page (both are cacheable board metadata), not
|
|
145
|
+
once per card. A key with no current definition or option resolves to nothing:
|
|
146
|
+
drop the badge rather than printing the raw key.
|
|
147
|
+
|
|
99
148
|
## Completion gate
|
|
100
149
|
|
|
101
150
|
Finish only after every applicable check passes:
|
|
@@ -107,6 +156,9 @@ Finish only after every applicable check passes:
|
|
|
107
156
|
- Open ranges return `bound: 'from' | 'upTo'`; the application adds open-range
|
|
108
157
|
chrome and composes order itself.
|
|
109
158
|
- Saved jobs arrive as cards; no `fullJobToCard` conversion.
|
|
159
|
+
- Card badges read `card.customFieldValues` / `card.company.customFieldValues`
|
|
160
|
+
and resolve option keys to labels through the definitions; no raw key is
|
|
161
|
+
shown and no card triggers a per-job detail fetch.
|
|
110
162
|
- Salary-stat formatters receive the detail's `currency` (never invent USD).
|
|
111
163
|
- Formatting changes neither salary amounts nor invents chrome words.
|
|
112
164
|
|
|
@@ -87,6 +87,30 @@ The list replaces the job's wording: omit it on `update` to keep what is stored,
|
|
|
87
87
|
|
|
88
88
|
Validate `required` client-side from these entries before submitting, so the poster sees a missing field before the request.
|
|
89
89
|
|
|
90
|
+
## Pick office locations
|
|
91
|
+
|
|
92
|
+
Back the `location` field with `board.locations.search`, a worldwide search over countries, regions, cities, and localities. `session` is required: generate one per location-field interaction, reuse it across keystrokes and the pick-time `board.locations.resolve` call, then generate a new one for the next interaction. Renew it before 50 search requests or after 180 seconds. Pass `jobForm.location.allowedCountries` as `country` to narrow suggestions to the board's allowed countries.
|
|
93
|
+
|
|
94
|
+
```ts snippet
|
|
95
|
+
const session = crypto.randomUUID();
|
|
96
|
+
const { data: locations } = await board.locations.search({
|
|
97
|
+
q: 'berl',
|
|
98
|
+
session,
|
|
99
|
+
country: jobForm.location.allowedCountries?.join(','),
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const picked = locations[0];
|
|
103
|
+
if (picked) {
|
|
104
|
+
const location = await board.locations.resolve({
|
|
105
|
+
locationId: picked.id,
|
|
106
|
+
session,
|
|
107
|
+
});
|
|
108
|
+
submission.officeLocations.push({ locationId: location.id });
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Show `fullName` in the input once picked and `contextLabel` as the secondary line in the result list. Resolve the picked `id` with the same session before committing the selection, then send the resolved `id` as `locationId` in the later job submission. `board.taxonomy.places.list({ q })` ids are accepted as `locationId` too. An id the server does not recognise throws `locations_invalid_id`, and `locations_unavailable` means the search is temporarily down, so let the poster retry.
|
|
113
|
+
|
|
90
114
|
## Resolve a logo
|
|
91
115
|
|
|
92
116
|
Both logo paths return a stored `publicUrl` for `create`. The SDK owns multipart encoding.
|
|
@@ -37,6 +37,13 @@ const companies = await board.salaries.companies.list();
|
|
|
37
37
|
region, and city nesting from each `SalaryLocation.parentSlug`; top-level rows
|
|
38
38
|
have `parentSlug: null`.
|
|
39
39
|
|
|
40
|
+
Every place row in a salary response (location index nodes, `topLocations`,
|
|
41
|
+
child, sibling, and other locations) carries `placeName` and `placeLabel`.
|
|
42
|
+
Render `placeLabel` wherever places are listed: it tells a city from the
|
|
43
|
+
region it shares a name with ("New York, NY" under "New York", "Washington,
|
|
44
|
+
DC" beside "Washington"). Keep `placeName` for data you pass on, such as
|
|
45
|
+
JSON-LD.
|
|
46
|
+
|
|
40
47
|
## Retrieve detail and canonicalize slugs
|
|
41
48
|
|
|
42
49
|
Every axis `retrieve(slug)` accepts an inbound English or board-language slug.
|
package/skills/manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "4.
|
|
2
|
+
"version": "4.28.0",
|
|
3
3
|
"skills": [
|
|
4
4
|
{
|
|
5
5
|
"name": "cavuno-board-account",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
61
|
"name": "cavuno-board-filters",
|
|
62
|
-
"description": "Listing-filter contracts with @cavuno/board. Use for job filter controls, profile-field filters, collection choices, sort controls, listing URL validation, or taxonomy-backed filter options.",
|
|
62
|
+
"description": "Listing-filter contracts with @cavuno/board. Use for job filter controls, job and company custom-field filters, profile-field filters, collection choices, sort controls, listing URL validation, or taxonomy-backed filter options.",
|
|
63
63
|
"path": "skills/cavuno-board-filters/SKILL.md",
|
|
64
64
|
"framework": null,
|
|
65
65
|
"category": "core"
|