@cavuno/board 4.16.0 → 4.19.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 (41) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/dist/{_spec-DdWB8z1Z.d.mts → _spec-DyTPJbIZ.d.mts} +41 -7
  3. package/dist/{_spec-DdWB8z1Z.d.ts → _spec-DyTPJbIZ.d.ts} +41 -7
  4. package/dist/{blog-DopIQsKV.d.mts → blog-Cdw6_ocq.d.mts} +1 -1
  5. package/dist/{blog-B7xorPBw.d.ts → blog-vDgRPBAK.d.ts} +1 -1
  6. package/dist/{board-CkgTW4cC.d.mts → board-CLDHd9N_.d.mts} +10 -3
  7. package/dist/{board-Bpnqn4Rg.d.ts → board-DpDCNMJD.d.ts} +10 -3
  8. package/dist/{breadcrumbs-CAppxMoS.d.mts → breadcrumbs-CKtVWTOB.d.mts} +2 -2
  9. package/dist/{breadcrumbs-DelEqbSz.d.ts → breadcrumbs-CYT3HxfO.d.ts} +2 -2
  10. package/dist/browser/cavuno-board.global.min.js +1 -1
  11. package/dist/{chunk-W73BOGOQ.mjs → chunk-XNO4NOPW.mjs} +2 -100
  12. package/dist/chunk-Z4ALWIGS.mjs +101 -0
  13. package/dist/filters.d.mts +2 -2
  14. package/dist/filters.d.ts +2 -2
  15. package/dist/format.d.mts +4 -4
  16. package/dist/format.d.ts +4 -4
  17. package/dist/index.d.mts +42 -13
  18. package/dist/index.d.ts +42 -13
  19. package/dist/index.js +23 -3
  20. package/dist/index.mjs +33 -12
  21. package/dist/{jobs-Dq0TTcRf.d.mts → jobs-Bnx1B6at.d.mts} +1 -1
  22. package/dist/{jobs-CExc4QdI.d.ts → jobs-Bwl7pKKg.d.ts} +1 -1
  23. package/dist/{search-CZOec95V.d.ts → search-CQZ-ibOl.d.ts} +1 -1
  24. package/dist/{search-D6hau3d4.d.mts → search-DlxLGmDk.d.mts} +1 -1
  25. package/dist/{seo-C1hFa0-v.d.ts → seo-BfEBr4pW.d.ts} +1 -1
  26. package/dist/seo-files.d.mts +2 -2
  27. package/dist/seo-files.d.ts +2 -2
  28. package/dist/{seo-CJSwd_ss.d.mts → seo-zYWVcaj1.d.mts} +1 -1
  29. package/dist/seo.d.mts +6 -6
  30. package/dist/seo.d.ts +6 -6
  31. package/dist/server.d.mts +6 -6
  32. package/dist/server.d.ts +6 -6
  33. package/dist/server.mjs +4 -2
  34. package/dist/sitemap.d.mts +15 -7
  35. package/dist/sitemap.d.ts +15 -7
  36. package/dist/sitemap.js +49 -4
  37. package/dist/sitemap.mjs +44 -4
  38. package/dist/suggest.d.mts +2 -2
  39. package/dist/suggest.d.ts +2 -2
  40. package/package.json +1 -1
  41. package/skills/manifest.json +1 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,40 @@
3
3
  This changelog records changes that affect Board API compatibility, exported
4
4
  types, runtime behavior, or supported integration patterns.
5
5
 
6
+ ## 4.19.0 — 2026-09-02
7
+
8
+ - **`board.sitemap()` / `board.sitemap.entries(bucket, { limit, cursor })`**:
9
+ new namespace over `GET /sitemap` and `GET /sitemap/{bucket}`. The board
10
+ publishes its complete sitemap — every bucket with an entry count, and each
11
+ bucket's board-relative `path` + `lastModified` entries, cursor-paged up to
12
+ 1000 per page — so a headless frontend reproduces the hosted sitemap exactly
13
+ (cross-axis salary pages, jobs place × category / skill pages, markets)
14
+ without enumerating the catalog itself.
15
+ - **`@cavuno/board/sitemap` walker**: `listedBuckets` and `buildBucketUrls`
16
+ now read the published sitemap first and fall back to the previous
17
+ per-family enumeration only when the API answers 404. A sitemap build drops
18
+ from ~25 catalog reads to a handful of cached reads. All existing exports
19
+ are unchanged.
20
+ - **`board.companies.markets({ cursor })`**: the unsearched market list is
21
+ now paginated (`hasMore` / `nextCursor` are real; use `paginate()`). With
22
+ `search` it remains a top-N preview. `CompanyMarketsListQuery` gains `cursor`.
23
+
24
+ ## 4.18.0 — 2026-09-02
25
+
26
+ - **`board.auth.requestMagicLink({ intent: 'sign_in' })`**: new optional
27
+ `intent` on `POST /auth/magic-link`. Pass `'sign_in'` from a sign-in form so
28
+ an unknown email is refused with 404 `board_auth_account_not_found` instead
29
+ of silently minting a candidate sign-up token. Omit it to keep the previous
30
+ sign-in-or-sign-up behaviour. Any other value is a 400.
31
+ - **`BOARD_API_ERROR_CODES`**: adds `board_auth_account_not_found`.
32
+
33
+ ## 4.17.0 — 2026-08-31
34
+
35
+ - **`EmployerPipelineStage.systemStage`**: a closed set of pipeline literals —
36
+ `shortlisted`, `contacted`, `replied`, `review`, `offer`, `hired`,
37
+ `rejected`, or `null` — instead of an open string. `applied` remains a
38
+ list-query alias for `review`, not a `systemStage` value.
39
+
6
40
  ## 4.16.0 — 2026-08-31
7
41
 
8
42
  - **`@cavuno/board/analytics`**: new subpath with `install({ publishableKey })`
@@ -249,6 +249,11 @@ interface components {
249
249
  email: string;
250
250
  /** @description Optional same-origin path to carry through the email link. */
251
251
  returnTo?: string;
252
+ /**
253
+ * @description Pass `sign_in` from a sign-in form: an unknown email returns 404 `board_auth_account_not_found` and nothing is minted or sent; existing users are unchanged. Omit it for today’s behaviour (existing users get a sign-in token; unknown emails get a candidate sign-up token when candidate registration is enabled).
254
+ * @enum {string}
255
+ */
256
+ intent?: "sign_in";
252
257
  };
253
258
  BoardAuthResetPasswordBody: {
254
259
  token: string;
@@ -290,6 +295,20 @@ interface components {
290
295
  name: string;
291
296
  };
292
297
  };
298
+ BoardSitemap: {
299
+ /** @enum {string} */
300
+ object: "board_sitemap";
301
+ /** @description The buckets the board publishes, in the canonical bucket order. Empty buckets are omitted — exactly the set the hosted `/sitemap.xml` index lists. */
302
+ buckets: components["schemas"]["BoardSitemapBucketSummary"][];
303
+ };
304
+ BoardSitemapBucketSummary: {
305
+ /** @description Bucket name — pass it to `GET /boards/:identifier/sitemap/{bucket}` to read its entries. */
306
+ bucket: string;
307
+ /** @description Number of entries in the bucket. */
308
+ count: number;
309
+ /** @description ISO 8601 timestamp of the newest content in the bucket, when the board tracks one. */
310
+ lastModified?: string;
311
+ };
293
312
  BoardUser: {
294
313
  /** @description Board user ID. */
295
314
  id: string;
@@ -1054,7 +1073,7 @@ interface components {
1054
1073
  inOfficePeriod?: "per_week" | "per_month" | "per_year";
1055
1074
  /** @description How often the candidate must be in-office over `inOfficePeriod`. */
1056
1075
  inOfficeFrequency?: number;
1057
- /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1076
+ /** @description Physical office locations associated with the job. Prefer `{query: "City, Country"}` for free-form input; `{city, country, region?, locality?}` is also accepted when you already have structured fields. Each entry is resolved server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1058
1077
  officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
1059
1078
  /** @description The job title. */
1060
1079
  title: string;
@@ -1211,8 +1230,11 @@ interface components {
1211
1230
  object: "employer_pipeline_stage";
1212
1231
  jobId: string;
1213
1232
  label: string;
1214
- /** @description The stable system meaning (`review`/`offer`/`hired`/`rejected`), or `null` for a custom employer stage. */
1215
- systemStage: string | null;
1233
+ /**
1234
+ * @description The stable system meaning, or `null` for a custom employer stage.
1235
+ * @enum {string|null}
1236
+ */
1237
+ systemStage: "shortlisted" | "contacted" | "replied" | "review" | "offer" | "hired" | "rejected" | null;
1216
1238
  isProtected: boolean;
1217
1239
  hidden: boolean;
1218
1240
  position: number;
@@ -1299,7 +1321,7 @@ interface components {
1299
1321
  inOfficePeriod?: "per_week" | "per_month" | "per_year";
1300
1322
  /** @description How often the candidate must be in-office over `inOfficePeriod`. */
1301
1323
  inOfficeFrequency?: number;
1302
- /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1324
+ /** @description Physical office locations associated with the job. Prefer `{query: "City, Country"}` for free-form input; `{city, country, region?, locality?}` is also accepted when you already have structured fields. Each entry is resolved server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1303
1325
  officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
1304
1326
  /** @description The job title. */
1305
1327
  title?: string;
@@ -1355,6 +1377,9 @@ interface components {
1355
1377
  displayName: string | null;
1356
1378
  };
1357
1379
  JobOfficeLocationInput: {
1380
+ /** @description Free-form location string (e.g. `"Berlin, Germany"`, `"Utrecht, Netherlands"`, `"Mountain View, California, USA"`). Resolved server-side; rejected when no high-confidence match is found. */
1381
+ query: string;
1382
+ } | {
1358
1383
  /** @description Neighborhood or sub-locality. */
1359
1384
  locality?: string;
1360
1385
  /** @description City. */
@@ -1363,9 +1388,6 @@ interface components {
1363
1388
  region?: string;
1364
1389
  /** @description ISO 3166-1 alpha-2 country code OR recognized country name/alias. Aliases are normalized to canonical alpha-2 server-side (e.g. `US`, `USA`, `United States` → `US`; `UK`, `GB`, `United Kingdom` → `GB`). */
1365
1390
  country: string;
1366
- } | {
1367
- /** @description Free-form location string (e.g. `"Berlin, Germany"`, `"Mountain View, California, USA"`). Mapbox parses + ranks candidates server-side; rejects on low confidence. */
1368
- query: string;
1369
1391
  };
1370
1392
  JobPostingBillingOptions: {
1371
1393
  /** @enum {string} */
@@ -2443,6 +2465,14 @@ interface components {
2443
2465
  /** Format: email */
2444
2466
  workEmail: string;
2445
2467
  };
2468
+ SitemapEntry: {
2469
+ /** @enum {string} */
2470
+ object: "sitemap_entry";
2471
+ /** @description Board-relative path, always starting with `/`. Prefix it with your own origin to build the absolute URL — the API never returns the hosted origin. */
2472
+ path: string;
2473
+ /** @description ISO 8601 timestamp of the entry, when one is known. */
2474
+ lastModified?: string;
2475
+ };
2446
2476
  SkillLocationSalary: {
2447
2477
  /** @enum {string} */
2448
2478
  object: "skill_location_salary";
@@ -2597,9 +2627,13 @@ interface components {
2597
2627
  StartConversationBody: {
2598
2628
  candidateBoardUserId: string;
2599
2629
  body: string;
2630
+ /** @description Optional job id. When set, this send is from that job pipeline and may auto-advance Shortlisted to Contacted. */
2631
+ job?: string;
2600
2632
  } | {
2601
2633
  candidateHandle: string;
2602
2634
  body: string;
2635
+ /** @description Optional job id. When set, this send is from that job pipeline and may auto-advance Shortlisted to Contacted. */
2636
+ job?: string;
2603
2637
  };
2604
2638
  SuggestResult: {
2605
2639
  /** @enum {string} */
@@ -249,6 +249,11 @@ interface components {
249
249
  email: string;
250
250
  /** @description Optional same-origin path to carry through the email link. */
251
251
  returnTo?: string;
252
+ /**
253
+ * @description Pass `sign_in` from a sign-in form: an unknown email returns 404 `board_auth_account_not_found` and nothing is minted or sent; existing users are unchanged. Omit it for today’s behaviour (existing users get a sign-in token; unknown emails get a candidate sign-up token when candidate registration is enabled).
254
+ * @enum {string}
255
+ */
256
+ intent?: "sign_in";
252
257
  };
253
258
  BoardAuthResetPasswordBody: {
254
259
  token: string;
@@ -290,6 +295,20 @@ interface components {
290
295
  name: string;
291
296
  };
292
297
  };
298
+ BoardSitemap: {
299
+ /** @enum {string} */
300
+ object: "board_sitemap";
301
+ /** @description The buckets the board publishes, in the canonical bucket order. Empty buckets are omitted — exactly the set the hosted `/sitemap.xml` index lists. */
302
+ buckets: components["schemas"]["BoardSitemapBucketSummary"][];
303
+ };
304
+ BoardSitemapBucketSummary: {
305
+ /** @description Bucket name — pass it to `GET /boards/:identifier/sitemap/{bucket}` to read its entries. */
306
+ bucket: string;
307
+ /** @description Number of entries in the bucket. */
308
+ count: number;
309
+ /** @description ISO 8601 timestamp of the newest content in the bucket, when the board tracks one. */
310
+ lastModified?: string;
311
+ };
293
312
  BoardUser: {
294
313
  /** @description Board user ID. */
295
314
  id: string;
@@ -1054,7 +1073,7 @@ interface components {
1054
1073
  inOfficePeriod?: "per_week" | "per_month" | "per_year";
1055
1074
  /** @description How often the candidate must be in-office over `inOfficePeriod`. */
1056
1075
  inOfficeFrequency?: number;
1057
- /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1076
+ /** @description Physical office locations associated with the job. Prefer `{query: "City, Country"}` for free-form input; `{city, country, region?, locality?}` is also accepted when you already have structured fields. Each entry is resolved server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1058
1077
  officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
1059
1078
  /** @description The job title. */
1060
1079
  title: string;
@@ -1211,8 +1230,11 @@ interface components {
1211
1230
  object: "employer_pipeline_stage";
1212
1231
  jobId: string;
1213
1232
  label: string;
1214
- /** @description The stable system meaning (`review`/`offer`/`hired`/`rejected`), or `null` for a custom employer stage. */
1215
- systemStage: string | null;
1233
+ /**
1234
+ * @description The stable system meaning, or `null` for a custom employer stage.
1235
+ * @enum {string|null}
1236
+ */
1237
+ systemStage: "shortlisted" | "contacted" | "replied" | "review" | "offer" | "hired" | "rejected" | null;
1216
1238
  isProtected: boolean;
1217
1239
  hidden: boolean;
1218
1240
  position: number;
@@ -1299,7 +1321,7 @@ interface components {
1299
1321
  inOfficePeriod?: "per_week" | "per_month" | "per_year";
1300
1322
  /** @description How often the candidate must be in-office over `inOfficePeriod`. */
1301
1323
  inOfficeFrequency?: number;
1302
- /** @description Physical office locations associated with the job. Each entry is forward-geocoded server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1324
+ /** @description Physical office locations associated with the job. Prefer `{query: "City, Country"}` for free-form input; `{city, country, region?, locality?}` is also accepted when you already have structured fields. Each entry is resolved server-side; a country mismatch returns `400 jobs_unresolvable_location`. */
1303
1325
  officeLocations?: components["schemas"]["JobOfficeLocationInput"][];
1304
1326
  /** @description The job title. */
1305
1327
  title?: string;
@@ -1355,6 +1377,9 @@ interface components {
1355
1377
  displayName: string | null;
1356
1378
  };
1357
1379
  JobOfficeLocationInput: {
1380
+ /** @description Free-form location string (e.g. `"Berlin, Germany"`, `"Utrecht, Netherlands"`, `"Mountain View, California, USA"`). Resolved server-side; rejected when no high-confidence match is found. */
1381
+ query: string;
1382
+ } | {
1358
1383
  /** @description Neighborhood or sub-locality. */
1359
1384
  locality?: string;
1360
1385
  /** @description City. */
@@ -1363,9 +1388,6 @@ interface components {
1363
1388
  region?: string;
1364
1389
  /** @description ISO 3166-1 alpha-2 country code OR recognized country name/alias. Aliases are normalized to canonical alpha-2 server-side (e.g. `US`, `USA`, `United States` → `US`; `UK`, `GB`, `United Kingdom` → `GB`). */
1365
1390
  country: string;
1366
- } | {
1367
- /** @description Free-form location string (e.g. `"Berlin, Germany"`, `"Mountain View, California, USA"`). Mapbox parses + ranks candidates server-side; rejects on low confidence. */
1368
- query: string;
1369
1391
  };
1370
1392
  JobPostingBillingOptions: {
1371
1393
  /** @enum {string} */
@@ -2443,6 +2465,14 @@ interface components {
2443
2465
  /** Format: email */
2444
2466
  workEmail: string;
2445
2467
  };
2468
+ SitemapEntry: {
2469
+ /** @enum {string} */
2470
+ object: "sitemap_entry";
2471
+ /** @description Board-relative path, always starting with `/`. Prefix it with your own origin to build the absolute URL — the API never returns the hosted origin. */
2472
+ path: string;
2473
+ /** @description ISO 8601 timestamp of the entry, when one is known. */
2474
+ lastModified?: string;
2475
+ };
2446
2476
  SkillLocationSalary: {
2447
2477
  /** @enum {string} */
2448
2478
  object: "skill_location_salary";
@@ -2597,9 +2627,13 @@ interface components {
2597
2627
  StartConversationBody: {
2598
2628
  candidateBoardUserId: string;
2599
2629
  body: string;
2630
+ /** @description Optional job id. When set, this send is from that job pipeline and may auto-advance Shortlisted to Contacted. */
2631
+ job?: string;
2600
2632
  } | {
2601
2633
  candidateHandle: string;
2602
2634
  body: string;
2635
+ /** @description Optional job id. When set, this send is from that job pipeline and may auto-advance Shortlisted to Contacted. */
2636
+ job?: string;
2603
2637
  };
2604
2638
  SuggestResult: {
2605
2639
  /** @enum {string} */
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-DdWB8z1Z.mjs';
1
+ import { S as Schemas } from './_spec-DyTPJbIZ.mjs';
2
2
 
3
3
  /** Author shape embedded on posts (no `object` discriminator). */
4
4
  type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-DdWB8z1Z.js';
1
+ import { S as Schemas } from './_spec-DyTPJbIZ.js';
2
2
 
3
3
  /** Author shape embedded on posts (no `object` discriminator). */
4
4
  type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
@@ -1,5 +1,5 @@
1
- import { S as Schemas } from './_spec-DdWB8z1Z.mjs';
2
- import { L as ListEnvelope, m as RelatedSearch } from './jobs-Dq0TTcRf.mjs';
1
+ import { S as Schemas } from './_spec-DyTPJbIZ.mjs';
2
+ import { L as ListEnvelope, m as RelatedSearch } from './jobs-Bnx1B6at.mjs';
3
3
 
4
4
  type PublicCompany = Schemas['CompanyPublic'];
5
5
  /** A market (sector) a company operates in — name + its source slug. */
@@ -52,8 +52,15 @@ type CompanySimilarQuery = {
52
52
  };
53
53
  type CompanyMarket = Schemas['CompanyMarket'];
54
54
  type CompanyMarketsListQuery = {
55
- /** 1–200, default 100 (a top-by-company-count preview). */
55
+ /** Page size, 1–200 (default 100). */
56
56
  limit?: number;
57
+ /**
58
+ * Opaque forward cursor from a previous response's `nextCursor`. The
59
+ * unsearched list is fully paginated (walk it with `paginate` to enumerate
60
+ * every market); a `search` call returns one preview page with
61
+ * `hasMore: false`, so the cursor does not apply there.
62
+ */
63
+ cursor?: string;
57
64
  search?: string;
58
65
  };
59
66
  type CompaniesSearchBody = Schemas['PublicCompaniesSearchBody'];
@@ -1,5 +1,5 @@
1
- import { S as Schemas } from './_spec-DdWB8z1Z.js';
2
- import { L as ListEnvelope, m as RelatedSearch } from './jobs-CExc4QdI.js';
1
+ import { S as Schemas } from './_spec-DyTPJbIZ.js';
2
+ import { L as ListEnvelope, m as RelatedSearch } from './jobs-Bwl7pKKg.js';
3
3
 
4
4
  type PublicCompany = Schemas['CompanyPublic'];
5
5
  /** A market (sector) a company operates in — name + its source slug. */
@@ -52,8 +52,15 @@ type CompanySimilarQuery = {
52
52
  };
53
53
  type CompanyMarket = Schemas['CompanyMarket'];
54
54
  type CompanyMarketsListQuery = {
55
- /** 1–200, default 100 (a top-by-company-count preview). */
55
+ /** Page size, 1–200 (default 100). */
56
56
  limit?: number;
57
+ /**
58
+ * Opaque forward cursor from a previous response's `nextCursor`. The
59
+ * unsearched list is fully paginated (walk it with `paginate` to enumerate
60
+ * every market); a `search` call returns one preview page with
61
+ * `hasMore: false`, so the cursor does not apply there.
62
+ */
63
+ cursor?: string;
57
64
  search?: string;
58
65
  };
59
66
  type CompaniesSearchBody = Schemas['PublicCompaniesSearchBody'];
@@ -1,5 +1,5 @@
1
- import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-CkgTW4cC.mjs';
2
- import { P as PublicJob } from './jobs-Dq0TTcRf.mjs';
1
+ import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-CLDHd9N_.mjs';
2
+ import { P as PublicJob } from './jobs-Bnx1B6at.mjs';
3
3
 
4
4
  /**
5
5
  * Wire enum for `salaryTimeframe`. Defined here (not re-exported from any
@@ -1,5 +1,5 @@
1
- import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-Bpnqn4Rg.js';
2
- import { P as PublicJob } from './jobs-CExc4QdI.js';
1
+ import { P as PublicBoard, a as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './board-DpDCNMJD.js';
2
+ import { P as PublicJob } from './jobs-Bwl7pKKg.js';
3
3
 
4
4
  /**
5
5
  * Wire enum for `salaryTimeframe`. Defined here (not re-exported from any