@cavuno/board 4.47.0 → 4.48.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 (60) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/{_spec-DHa5r3B0.d.mts → _spec-Fw9b79TI.d.mts} +45 -3
  3. package/dist/{_spec-DHa5r3B0.d.ts → _spec-Fw9b79TI.d.ts} +45 -3
  4. package/dist/bin.mjs +1 -0
  5. package/dist/{blog-wxhB8zAH.d.ts → blog-DldIXX6n.d.ts} +1 -1
  6. package/dist/{blog-DylAbc0L.d.mts → blog-Dlyky5Eo.d.mts} +1 -1
  7. package/dist/{board-DHsd92Gy.d.ts → board-B1Ueww2w.d.ts} +2 -2
  8. package/dist/{board-Bpze3b50.d.mts → board-DkwbMZdt.d.mts} +2 -2
  9. package/dist/{breadcrumbs-B6yhrHJV.d.mts → breadcrumbs-Bj8SieZi.d.mts} +5 -3
  10. package/dist/{breadcrumbs-15j5xvmN.d.ts → breadcrumbs-CzFiddAt.d.ts} +5 -3
  11. package/dist/browser/cavuno-board.global.min.js +1 -1
  12. package/dist/{chunk-5KCWHENV.mjs → chunk-2KD2CWFL.mjs} +1 -1
  13. package/dist/{chunk-XXQCESMU.mjs → chunk-JFDWTTOQ.mjs} +5 -0
  14. package/dist/{chunk-KDFKVWTZ.mjs → chunk-JTFUOGWE.mjs} +3 -3
  15. package/dist/doctor.js +1 -0
  16. package/dist/doctor.mjs +1 -0
  17. package/dist/filters.d.mts +2 -2
  18. package/dist/filters.d.ts +2 -2
  19. package/dist/format.d.mts +4 -4
  20. package/dist/format.d.ts +4 -4
  21. package/dist/format.js +3 -2
  22. package/dist/format.mjs +2 -2
  23. package/dist/go.js +1 -0
  24. package/dist/go.mjs +1 -1
  25. package/dist/index.d.mts +71 -13
  26. package/dist/index.d.ts +71 -13
  27. package/dist/index.js +1 -1
  28. package/dist/index.mjs +1 -1
  29. package/dist/{jobs-CMK-DZg3.d.mts → jobs-oSTStcbC.d.mts} +1 -1
  30. package/dist/{jobs-CIrTcMjw.d.ts → jobs-rnatMRvm.d.ts} +1 -1
  31. package/dist/paths.d.mts +7 -1
  32. package/dist/paths.d.ts +7 -1
  33. package/dist/paths.js +5 -0
  34. package/dist/paths.mjs +3 -1
  35. package/dist/route-contract.js +1 -0
  36. package/dist/route-contract.mjs +2 -2
  37. package/dist/{search-666oDd7H.d.ts → search-CKvtGE6t.d.ts} +1 -1
  38. package/dist/{search-DBQApXN1.d.mts → search-uiAE7AFt.d.mts} +1 -1
  39. package/dist/{seo-ynqiQmby.d.ts → seo-C2WvBFEi.d.ts} +1 -1
  40. package/dist/{seo-gY8y9RMw.d.mts → seo-Cz0544dX.d.mts} +1 -1
  41. package/dist/seo-files.d.mts +2 -2
  42. package/dist/seo-files.d.ts +2 -2
  43. package/dist/seo.d.mts +6 -6
  44. package/dist/seo.d.ts +6 -6
  45. package/dist/seo.js +3 -2
  46. package/dist/seo.mjs +2 -2
  47. package/dist/server.d.mts +6 -6
  48. package/dist/server.d.ts +6 -6
  49. package/dist/sitemap.d.mts +6 -6
  50. package/dist/sitemap.d.ts +6 -6
  51. package/dist/sitemap.js +1 -0
  52. package/dist/sitemap.mjs +1 -1
  53. package/dist/suggest.d.mts +2 -2
  54. package/dist/suggest.d.ts +2 -2
  55. package/dist/well-known.js +1 -0
  56. package/dist/well-known.mjs +2 -2
  57. package/package.json +1 -1
  58. package/skills/cavuno-board-job-alerts/SKILL.md +27 -1
  59. package/skills/cavuno-board-talent-access/SKILL.md +2 -0
  60. package/skills/manifest.json +1 -1
package/dist/seo.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-wxhB8zAH.js';
2
- import { e as JsonLdObject } from './breadcrumbs-15j5xvmN.js';
3
- export { A as ALL_COUNTRY_CODES, B as BreadcrumbItemInput, g as FaqItem, J as JobBreadcrumb, h as JsonLdBoard, N as NumberNotation, i as SENIORITY_ORDER, j as SalaryFaqEntry, k as SalaryJsonLdOptions, l as SalaryOccupationListOptions, b as buildJobBreadcrumbs, m as buildSalaryFaq, o as companyCategorySalaryJsonLd, p as companySalaryJsonLd, q as createBreadcrumbJsonLd, r as createJobPostingJsonLd, s as crossAxisSalaryJsonLd, t as faqJsonLd, c as formatSalaryStat, d as formatSalaryStatRange, u as itemListJsonLd, v as locationSalaryJsonLd, n as normalizeWebsiteUrl, w as skillSalaryJsonLd, x as sortBySeniority, y as titleSalaryJsonLd } from './breadcrumbs-15j5xvmN.js';
4
- import './_spec-DHa5r3B0.js';
5
- import './board-DHsd92Gy.js';
6
- import './jobs-CIrTcMjw.js';
1
+ import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-DldIXX6n.js';
2
+ import { e as JsonLdObject } from './breadcrumbs-CzFiddAt.js';
3
+ export { A as ALL_COUNTRY_CODES, B as BreadcrumbItemInput, g as FaqItem, J as JobBreadcrumb, h as JsonLdBoard, N as NumberNotation, i as SENIORITY_ORDER, j as SalaryFaqEntry, k as SalaryJsonLdOptions, l as SalaryOccupationListOptions, b as buildJobBreadcrumbs, m as buildSalaryFaq, o as companyCategorySalaryJsonLd, p as companySalaryJsonLd, q as createBreadcrumbJsonLd, r as createJobPostingJsonLd, s as crossAxisSalaryJsonLd, t as faqJsonLd, c as formatSalaryStat, d as formatSalaryStatRange, u as itemListJsonLd, v as locationSalaryJsonLd, n as normalizeWebsiteUrl, w as skillSalaryJsonLd, x as sortBySeniority, y as titleSalaryJsonLd } from './breadcrumbs-CzFiddAt.js';
4
+ import './_spec-Fw9b79TI.js';
5
+ import './board-B1Ueww2w.js';
6
+ import './jobs-rnatMRvm.js';
7
7
 
8
8
  /**
9
9
  * Blog structured data on the `@cavuno/board` wire types, transcribed from
package/dist/seo.js CHANGED
@@ -199,6 +199,7 @@ var BOARD_PATHS = {
199
199
  cookiePolicy: "/cookie-policy",
200
200
  impressum: "/impressum",
201
201
  talent: "/talent",
202
+ talentLocations: "/talent/locations",
202
203
  employers: "/employers",
203
204
  /**
204
205
  * Alert-email surfaces. Promoted out of raw literals in
@@ -262,11 +263,11 @@ function buildJobBreadcrumbs(job) {
262
263
  ];
263
264
  let lastPlaceSlug = null;
264
265
  for (const place of job.placeHierarchy) {
265
- lastPlaceSlug = place.slug;
266
+ lastPlaceSlug = place.canonicalSlug;
266
267
  crumbs.push({
267
268
  kind: "place",
268
269
  name: place.name,
269
- path: jobsLocationPath(place.slug)
270
+ path: jobsLocationPath(place.canonicalSlug)
270
271
  });
271
272
  }
272
273
  const primaryCategory = job.categories[0];
package/dist/seo.mjs CHANGED
@@ -17,11 +17,11 @@ import {
17
17
  skillSalaryJsonLd,
18
18
  sortBySeniority,
19
19
  titleSalaryJsonLd
20
- } from "./chunk-KDFKVWTZ.mjs";
20
+ } from "./chunk-JTFUOGWE.mjs";
21
21
  import {
22
22
  boardUrl,
23
23
  jobDetailPath
24
- } from "./chunk-XXQCESMU.mjs";
24
+ } from "./chunk-JFDWTTOQ.mjs";
25
25
 
26
26
  // src/seo/blog.ts
27
27
  function createBlogArticleJsonLd({
package/dist/server.d.mts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { BoardSdk } from './index.mjs';
2
- import './_spec-DHa5r3B0.mjs';
3
- import './search-DBQApXN1.mjs';
4
- import './jobs-CMK-DZg3.mjs';
5
- import './board-Bpze3b50.mjs';
6
- import './seo-gY8y9RMw.mjs';
7
- import './blog-DylAbc0L.mjs';
2
+ import './_spec-Fw9b79TI.mjs';
3
+ import './search-uiAE7AFt.mjs';
4
+ import './jobs-oSTStcbC.mjs';
5
+ import './board-DkwbMZdt.mjs';
6
+ import './seo-Cz0544dX.mjs';
7
+ import './blog-Dlyky5Eo.mjs';
8
8
 
9
9
  /**
10
10
  * Session cookie codec — pure (no framework imports, no node imports) so it
package/dist/server.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { BoardSdk } from './index.js';
2
- import './_spec-DHa5r3B0.js';
3
- import './search-666oDd7H.js';
4
- import './jobs-CIrTcMjw.js';
5
- import './board-DHsd92Gy.js';
6
- import './seo-ynqiQmby.js';
7
- import './blog-wxhB8zAH.js';
2
+ import './_spec-Fw9b79TI.js';
3
+ import './search-CKvtGE6t.js';
4
+ import './jobs-rnatMRvm.js';
5
+ import './board-B1Ueww2w.js';
6
+ import './seo-C2WvBFEi.js';
7
+ import './blog-DldIXX6n.js';
8
8
 
9
9
  /**
10
10
  * Session cookie codec — pure (no framework imports, no node imports) so it
@@ -1,10 +1,10 @@
1
1
  import { BoardSdk } from './index.mjs';
2
- import './_spec-DHa5r3B0.mjs';
3
- import './search-DBQApXN1.mjs';
4
- import './jobs-CMK-DZg3.mjs';
5
- import './board-Bpze3b50.mjs';
6
- import './seo-gY8y9RMw.mjs';
7
- import './blog-DylAbc0L.mjs';
2
+ import './_spec-Fw9b79TI.mjs';
3
+ import './search-uiAE7AFt.mjs';
4
+ import './jobs-oSTStcbC.mjs';
5
+ import './board-DkwbMZdt.mjs';
6
+ import './seo-Cz0544dX.mjs';
7
+ import './blog-Dlyky5Eo.mjs';
8
8
 
9
9
  /**
10
10
  * Sitemap primitives — the pure XML + bucket-filename logic behind a board
package/dist/sitemap.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { BoardSdk } from './index.js';
2
- import './_spec-DHa5r3B0.js';
3
- import './search-666oDd7H.js';
4
- import './jobs-CIrTcMjw.js';
5
- import './board-DHsd92Gy.js';
6
- import './seo-ynqiQmby.js';
7
- import './blog-wxhB8zAH.js';
2
+ import './_spec-Fw9b79TI.js';
3
+ import './search-CKvtGE6t.js';
4
+ import './jobs-rnatMRvm.js';
5
+ import './board-B1Ueww2w.js';
6
+ import './seo-C2WvBFEi.js';
7
+ import './blog-DldIXX6n.js';
8
8
 
9
9
  /**
10
10
  * Sitemap primitives — the pure XML + bucket-filename logic behind a board
package/dist/sitemap.js CHANGED
@@ -240,6 +240,7 @@ var BOARD_PATHS = {
240
240
  cookiePolicy: "/cookie-policy",
241
241
  impressum: "/impressum",
242
242
  talent: "/talent",
243
+ talentLocations: "/talent/locations",
243
244
  employers: "/employers",
244
245
  /**
245
246
  * Alert-email surfaces. Promoted out of raw literals in
package/dist/sitemap.mjs CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  salaryLocationPath,
20
20
  salarySkillPath,
21
21
  salaryTitlePath
22
- } from "./chunk-XXQCESMU.mjs";
22
+ } from "./chunk-JFDWTTOQ.mjs";
23
23
 
24
24
  // src/sitemap/xml.ts
25
25
  var SITEMAP_BUCKETS = [
@@ -1,5 +1,5 @@
1
- import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-DBQApXN1.mjs';
2
- import './_spec-DHa5r3B0.mjs';
1
+ import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-uiAE7AFt.mjs';
2
+ import './_spec-Fw9b79TI.mjs';
3
3
 
4
4
  /**
5
5
  * `@cavuno/board/suggest` — framework-agnostic headless search-suggest
package/dist/suggest.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-666oDd7H.js';
2
- import './_spec-DHa5r3B0.js';
1
+ import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-CKvtGE6t.js';
2
+ import './_spec-Fw9b79TI.js';
3
3
 
4
4
  /**
5
5
  * `@cavuno/board/suggest` — framework-agnostic headless search-suggest
@@ -100,6 +100,7 @@ var BOARD_PATHS = {
100
100
  cookiePolicy: "/cookie-policy",
101
101
  impressum: "/impressum",
102
102
  talent: "/talent",
103
+ talentLocations: "/talent/locations",
103
104
  employers: "/employers",
104
105
  /**
105
106
  * Alert-email surfaces. Promoted out of raw literals in
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  compileManifest
3
- } from "./chunk-5KCWHENV.mjs";
4
- import "./chunk-XXQCESMU.mjs";
3
+ } from "./chunk-2KD2CWFL.mjs";
4
+ import "./chunk-JFDWTTOQ.mjs";
5
5
 
6
6
  // src/well-known/handler.ts
7
7
  var WELL_KNOWN_CACHE_CONTROL = "public, max-age=300";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cavuno/board",
3
- "version": "4.47.0",
3
+ "version": "4.48.0",
4
4
  "description": "Build custom job boards and careers pages with Cavuno’s TypeScript SDK.",
5
5
  "keywords": [
6
6
  "api-client",
@@ -44,6 +44,29 @@ Only `jobFunctions`, `placeSlugs`, and `remoteOptions` filter digest delivery. S
44
44
 
45
45
  `jobFunctions` are category and skill slugs (the `slug` of a category or skill, such as `engineering` or `media-and-communication`). A digest matches a job when any entry equals one of the job's category or skill slugs. Prefer sending slugs. If you send display names or free-text keywords instead, the server slugifies each one when the alert is saved and matches it against the board's category and skill slugs, their aliases, and their board-language slugs. A display name that does not slugify to one of those (for example, a renamed category) is stored slugified and will not match, so send slugs whenever you have them. Alerts read back from the API therefore always carry slugs, so compare and display them as slugs.
46
46
 
47
+ ## Alert kinds, keywords, and anchor jobs
48
+
49
+ Every alert read back from either lane carries a read-only `kind`:
50
+
51
+ - `similar_job`: jobs similar to the job the visitor subscribed from. Subscribe from a job page with `context: { source: 'job_detail', jobId }` (or `job_apply_dialog`). `anchorJob` is that job as `{ id, slug, title }`, kept after the job closes. It is `null` for other kinds, and for an older similar-job alert whose job has not been captured yet.
52
+ - `search`: a board search for the alert's keywords, in `filters.query`. An older search alert can report `kind: 'search'` with `filters.query` `null`: its keyword is the single `jobFunctions` entry. When `query` is `null`, show the job functions as the alert's search instead.
53
+ - `filters`: jobs matching the stored filters exactly.
54
+
55
+ Send the query a search page ran as `filters.query` (on `board.me.alerts`, the top-level `query`), at most 200 characters after trimming. Keep sending the location and other filters alongside it.
56
+
57
+ ```ts snippet
58
+ await board.jobAlerts.subscribe({
59
+ email: 'ada@example.com',
60
+ consent: true,
61
+ filters: { query: 'Python developer', placeSlugs: ['berlin'] },
62
+ context: { source: 'jobs_list' },
63
+ });
64
+ ```
65
+
66
+ A sent `query` is stored as given (trimmed), so `front-end` reads back as `front-end`. A job-page `context` without a `jobId` cannot anchor a similar-job alert; with a `query` it makes a `search` alert. A client that predates `query` and sends the search keyword as its single `jobFunctions` entry, with a search-page `context.source`, still works: the server keeps that keyword as the alert's `query`.
67
+
68
+ On an update, `null` clears `query`, and omitting it keeps the stored keywords as long as `jobFunctions` are unchanged. An update never changes `kind`, except that giving a `filters` alert a `query` makes it a `search` alert. A `similar_job` alert takes no `query`: sending one, on subscribe with a job-page `context` or on an update, fails with `validation_bad_request` (400). To follow keywords instead, remove the similar-job alert and create a search alert. In alert lists, show the kind and, for similar-job alerts, link the anchor job.
69
+
47
70
  ## Anonymous lane: manage-token transport
48
71
 
49
72
  The read and write transports intentionally use different keys:
@@ -94,16 +117,19 @@ const { data: alerts } = await board.me.alerts.list();
94
117
  alerts[0]?.isActive;
95
118
  alerts[0]?.lastSentAt;
96
119
  alerts[0]?.filters;
120
+ alerts[0]?.kind;
121
+ alerts[0]?.anchorJob;
97
122
 
98
123
  const alert = await board.me.alerts.create({
99
124
  frequency: 'weekly',
100
- jobFunctions: ['engineering'],
125
+ query: 'Platform engineer',
101
126
  remoteOptions: ['remote'],
102
127
  });
103
128
 
104
129
  const current = await board.me.alerts.retrieve(alert.id);
105
130
  await board.me.alerts.update(alert.id, {
106
131
  frequency: 'weekly',
132
+ query: current.filters.query,
107
133
  jobFunctions: current.filters.jobFunctions,
108
134
  seniorityLevels: current.filters.seniorityLevels,
109
135
  remoteOptions: current.filters.remoteOptions,
@@ -130,6 +130,8 @@ await board.me.conversations.start({
130
130
 
131
131
  Named `/p/{handle}` is the share bypass and always shows a full `public` profile. Opaque `/p/{id}` is the unlock-gated route. When `accessModel === 'paid_unlocks_and_messaging'`, directory cards redact for viewers who are not unlimited.
132
132
 
133
+ `lastActive` on directory cards and profiles is a coarse bucket (`today`, `this_week`, `this_month`, `last_3_months`, `over_3_months`) for a signed-in employer looking at a candidate who is actively looking or open to offers, and `null` otherwise. It stays on redacted cards. Render it as a short label such as "Active this week" and hide it when `null`.
134
+
133
135
  ```ts snippet
134
136
  const named = await board.talent.retrieve('jane-doe');
135
137
  const opaque = await board.talent.retrieve('bu_candidate');
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.47.0",
2
+ "version": "4.48.0",
3
3
  "skills": [
4
4
  {
5
5
  "name": "cavuno-board-account",