@cavuno/board 4.57.0 → 4.58.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 +11 -0
  2. package/dist/{_spec-CDYDY0hB.d.mts → _spec-DIzdOWz7.d.mts} +4 -0
  3. package/dist/{_spec-CDYDY0hB.d.ts → _spec-DIzdOWz7.d.ts} +4 -0
  4. package/dist/{blog-DNGOmaKI.d.ts → blog-CyvB9C6W.d.ts} +1 -1
  5. package/dist/{blog-WupXypHv.d.mts → blog-DgbGOmzW.d.mts} +1 -1
  6. package/dist/{board-DbBBz7Pv.d.mts → board-D3ByAGAb.d.mts} +2 -2
  7. package/dist/{board-CmQox8FZ.d.ts → board-leXc6_BM.d.ts} +2 -2
  8. package/dist/{breadcrumbs-DpXiAo9j.d.ts → breadcrumbs-aCKRBNWX.d.ts} +2 -2
  9. package/dist/{breadcrumbs-mQTz0vZo.d.mts → breadcrumbs-zYG4xzpC.d.mts} +2 -2
  10. package/dist/browser/cavuno-board.global.min.js +1 -1
  11. package/dist/filters.d.mts +2 -2
  12. package/dist/filters.d.ts +2 -2
  13. package/dist/format.d.mts +4 -4
  14. package/dist/format.d.ts +4 -4
  15. package/dist/index.d.mts +11 -11
  16. package/dist/index.d.ts +11 -11
  17. package/dist/index.js +6 -3
  18. package/dist/index.mjs +6 -3
  19. package/dist/{jobs-B-NPmaV0.d.ts → jobs-DodvFXH2.d.ts} +1 -1
  20. package/dist/{jobs-CgmHLS8j.d.mts → jobs-nA2K33Nu.d.mts} +1 -1
  21. package/dist/{search--bO1b3RJ.d.mts → search-8kX6OW03.d.mts} +1 -1
  22. package/dist/{search-BvhQ92ZO.d.ts → search-C1XNGSm6.d.ts} +1 -1
  23. package/dist/{seo-C7HjUu_z.d.mts → seo-Bn5gQY8t.d.mts} +1 -1
  24. package/dist/{seo-CBRBS8Mc.d.ts → seo-DFAwxGej.d.ts} +1 -1
  25. package/dist/seo-files.d.mts +2 -2
  26. package/dist/seo-files.d.ts +2 -2
  27. package/dist/seo.d.mts +6 -6
  28. package/dist/seo.d.ts +6 -6
  29. package/dist/server.d.mts +6 -6
  30. package/dist/server.d.ts +6 -6
  31. package/dist/sitemap.d.mts +20 -9
  32. package/dist/sitemap.d.ts +20 -9
  33. package/dist/sitemap.js +12 -3
  34. package/dist/sitemap.mjs +12 -3
  35. package/dist/suggest.d.mts +2 -2
  36. package/dist/suggest.d.ts +2 -2
  37. package/package.json +1 -1
  38. package/skills/cavuno-board-products/SKILL.md +135 -0
  39. package/skills/cavuno-board-setup/SKILL.md +1 -0
  40. package/skills/cavuno-board-sitemap/SKILL.md +6 -2
  41. package/skills/manifest.json +8 -1
package/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
- import { S as Schemas, c as components } from './_spec-CDYDY0hB.js';
2
- import { F as FetchOptions, S as StorageMode, B as BoardRequest, A as Awaitable, L as Logger, a as BoardClient, b as SearchSuggestQuery } from './search-BvhQ92ZO.js';
3
- export { c as ACCESS_TOKEN_KEY, d as BOARD_ACCESS_GRANT_KEY, C as CompanySuggestion, e as CustomStorage, M as MarketSuggestion, R as REFRESH_TOKEN_KEY, f as SearchSuggestType, g as SuggestResult, h as SuggestionItem, T as TermSuggestion } from './search-BvhQ92ZO.js';
4
- import { L as ListEnvelope, R as RemoteOption, E as EmploymentType, S as Seniority, a as JobCapability, b as CustomFieldFilter, O as ObjectReferenceFilter, c as JobCollectionChoiceQuery, d as JobsListQuery, e as JobCardListEnvelope, f as JobRetrieveQuery, g as JobsSearchBody, h as JobCardSearchEnvelope, i as JobsSimilarQuery, j as SearchEnvelope } from './jobs-B-NPmaV0.js';
5
- export { k as CustomFieldValue, C as CustomFieldValues, l as CustomFilterValue, m as EducationRequirement, n as JobCatalogPagination, o as JobCollectionChoiceList, p as JobCollectionFieldDefinition, q as JobCompany, r as JobCustomEmploymentType, J as JobSort, s as OfficeLocation, t as OffsetPagination, P as PublicJob, u as PublicJobCard, v as RelatedSearch, w as RemotePermit, x as RemoteTimezone, y as ResolvedJobCollectionField, z as StorefrontPagination } from './jobs-B-NPmaV0.js';
6
- import { c as CompaniesListQuery, d as CompanyListEnvelope, e as CompaniesSearchBody, f as CompanyJobsListQuery, g as CompanySimilarQuery, h as CompanyMarketsListQuery, i as SalaryDetailQuery, b as CompanySalary } from './board-CmQox8FZ.js';
7
- export { B as BoardCustomEmploymentType, j as BoardFormBuiltinField, k as BoardFormField, l as BoardFormLayout, m as BoardFormLockReason, n as BoardJobFormField, o as BoardProfileFormField, p as BoardRoleSignIn, q as BoardSignInSsoConnection, a as CompanyCategorySalary, r as CompanyMarket, s as CompanyMarketRef, t as CompanySalarySummary, C as CustomFieldDefinition, u as CustomFieldOption, v as CustomFieldType, L as LocationSalaryDetail, w as LocationSkillsIndex, x as LocationTitlesIndex, P as PublicBoard, y as PublicBoardAds, z as PublicBoardAnalytics, A as PublicBoardFeatures, D as PublicBoardJobForm, E as PublicBoardSignIn, F as PublicCompany, G as PublicCompanyDetail, H as PublicCompanyMembership, I as SalaryCompany, J as SalaryLocation, K as SalarySkill, M as SalaryTitle, N as SkillLocationSalary, O as SkillLocationsIndex, S as SkillSalaryDetail, Q as TitleLocationSalary, R as TitleLocationsIndex, T as TitleSalaryDetail } from './board-CmQox8FZ.js';
8
- export { B as BoardSeo } from './seo-CBRBS8Mc.js';
9
- import { a as BlogPostsListQuery, b as BlogSimilarQuery, c as BlogSearchBody } from './blog-DNGOmaKI.js';
10
- export { B as BlogAuthorEmbed, d as BlogTagEmbed, e as PublicBlogAdjacentPosts, f as PublicBlogAuthor, g as PublicBlogPost, P as PublicBlogPostSummary, h as PublicBlogTag } from './blog-DNGOmaKI.js';
1
+ import { S as Schemas, c as components } from './_spec-DIzdOWz7.js';
2
+ import { F as FetchOptions, S as StorageMode, B as BoardRequest, A as Awaitable, L as Logger, a as BoardClient, b as SearchSuggestQuery } from './search-C1XNGSm6.js';
3
+ export { c as ACCESS_TOKEN_KEY, d as BOARD_ACCESS_GRANT_KEY, C as CompanySuggestion, e as CustomStorage, M as MarketSuggestion, R as REFRESH_TOKEN_KEY, f as SearchSuggestType, g as SuggestResult, h as SuggestionItem, T as TermSuggestion } from './search-C1XNGSm6.js';
4
+ import { L as ListEnvelope, R as RemoteOption, E as EmploymentType, S as Seniority, a as JobCapability, b as CustomFieldFilter, O as ObjectReferenceFilter, c as JobCollectionChoiceQuery, d as JobsListQuery, e as JobCardListEnvelope, f as JobRetrieveQuery, g as JobsSearchBody, h as JobCardSearchEnvelope, i as JobsSimilarQuery, j as SearchEnvelope } from './jobs-DodvFXH2.js';
5
+ export { k as CustomFieldValue, C as CustomFieldValues, l as CustomFilterValue, m as EducationRequirement, n as JobCatalogPagination, o as JobCollectionChoiceList, p as JobCollectionFieldDefinition, q as JobCompany, r as JobCustomEmploymentType, J as JobSort, s as OfficeLocation, t as OffsetPagination, P as PublicJob, u as PublicJobCard, v as RelatedSearch, w as RemotePermit, x as RemoteTimezone, y as ResolvedJobCollectionField, z as StorefrontPagination } from './jobs-DodvFXH2.js';
6
+ import { c as CompaniesListQuery, d as CompanyListEnvelope, e as CompaniesSearchBody, f as CompanyJobsListQuery, g as CompanySimilarQuery, h as CompanyMarketsListQuery, i as SalaryDetailQuery, b as CompanySalary } from './board-leXc6_BM.js';
7
+ export { B as BoardCustomEmploymentType, j as BoardFormBuiltinField, k as BoardFormField, l as BoardFormLayout, m as BoardFormLockReason, n as BoardJobFormField, o as BoardProfileFormField, p as BoardRoleSignIn, q as BoardSignInSsoConnection, a as CompanyCategorySalary, r as CompanyMarket, s as CompanyMarketRef, t as CompanySalarySummary, C as CustomFieldDefinition, u as CustomFieldOption, v as CustomFieldType, L as LocationSalaryDetail, w as LocationSkillsIndex, x as LocationTitlesIndex, P as PublicBoard, y as PublicBoardAds, z as PublicBoardAnalytics, A as PublicBoardFeatures, D as PublicBoardJobForm, E as PublicBoardSignIn, F as PublicCompany, G as PublicCompanyDetail, H as PublicCompanyMembership, I as SalaryCompany, J as SalaryLocation, K as SalarySkill, M as SalaryTitle, N as SkillLocationSalary, O as SkillLocationsIndex, S as SkillSalaryDetail, Q as TitleLocationSalary, R as TitleLocationsIndex, T as TitleSalaryDetail } from './board-leXc6_BM.js';
8
+ export { B as BoardSeo } from './seo-DFAwxGej.js';
9
+ import { a as BlogPostsListQuery, b as BlogSimilarQuery, c as BlogSearchBody } from './blog-CyvB9C6W.js';
10
+ export { B as BlogAuthorEmbed, d as BlogTagEmbed, e as PublicBlogAdjacentPosts, f as PublicBlogAuthor, g as PublicBlogPost, P as PublicBlogPostSummary, h as PublicBlogTag } from './blog-CyvB9C6W.js';
11
11
 
12
12
  /**
13
13
  * Well-known `<domain>_<snake_reason>` codes the Board API sends, grouped by
@@ -202,7 +202,7 @@ declare function paginate<Q extends Record<string, unknown>, P extends PageShape
202
202
  * constant because the package is platform-neutral and cannot read
203
203
  * package.json at runtime.
204
204
  */
205
- declare const SDK_VERSION = "4.57.0";
205
+ declare const SDK_VERSION = "4.58.0";
206
206
 
207
207
  type SavedJob = Schemas['SavedJob'];
208
208
  type SavedJobsListQuery = {
package/dist/index.js CHANGED
@@ -430,7 +430,7 @@ async function clearSession(storage) {
430
430
  }
431
431
 
432
432
  // src/version.ts
433
- var SDK_VERSION = "4.57.0";
433
+ var SDK_VERSION = "4.58.0";
434
434
 
435
435
  // src/client.ts
436
436
  function isRawBody(body) {
@@ -1613,8 +1613,11 @@ function meNamespace(client) {
1613
1613
  return client.fetch("/me", { ...options, query });
1614
1614
  },
1615
1615
  /**
1616
- * Permanently delete my account and all dependent data (profile,
1617
- * collections, saved jobs, alerts, avatar/resume files). Synchronous and
1616
+ * Permanently delete my account and all dependent data on this board:
1617
+ * profile, profile field values and files, avatar and resume files,
1618
+ * collections, saved jobs and alerts; job applications with their
1619
+ * resumes, notes and activity; conversations and messages, including the
1620
+ * employer side; and shortlist and pipeline entries. Synchronous and
1618
1621
  * irreversible — resolves void once the cascade completes (204).
1619
1622
  *
1620
1623
  * @example
package/dist/index.mjs CHANGED
@@ -46,7 +46,7 @@ function toSearchParams(query) {
46
46
  }
47
47
 
48
48
  // src/version.ts
49
- var SDK_VERSION = "4.57.0";
49
+ var SDK_VERSION = "4.58.0";
50
50
 
51
51
  // src/client.ts
52
52
  function isRawBody(body) {
@@ -1229,8 +1229,11 @@ function meNamespace(client) {
1229
1229
  return client.fetch("/me", { ...options, query });
1230
1230
  },
1231
1231
  /**
1232
- * Permanently delete my account and all dependent data (profile,
1233
- * collections, saved jobs, alerts, avatar/resume files). Synchronous and
1232
+ * Permanently delete my account and all dependent data on this board:
1233
+ * profile, profile field values and files, avatar and resume files,
1234
+ * collections, saved jobs and alerts; job applications with their
1235
+ * resumes, notes and activity; conversations and messages, including the
1236
+ * employer side; and shortlist and pipeline entries. Synchronous and
1234
1237
  * irreversible — resolves void once the cascade completes (204).
1235
1238
  *
1236
1239
  * @example
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-CDYDY0hB.js';
1
+ import { S as Schemas } from './_spec-DIzdOWz7.js';
2
2
 
3
3
  /**
4
4
  * Optional pagination metadata returned by Board API list operations.
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-CDYDY0hB.mjs';
1
+ import { S as Schemas } from './_spec-DIzdOWz7.mjs';
2
2
 
3
3
  /**
4
4
  * Optional pagination metadata returned by Board API list operations.
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-CDYDY0hB.mjs';
1
+ import { S as Schemas } from './_spec-DIzdOWz7.mjs';
2
2
 
3
3
  type Awaitable<T> = T | Promise<T>;
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-CDYDY0hB.js';
1
+ import { S as Schemas } from './_spec-DIzdOWz7.js';
2
2
 
3
3
  type Awaitable<T> = T | Promise<T>;
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-CDYDY0hB.mjs';
1
+ import { S as Schemas } from './_spec-DIzdOWz7.mjs';
2
2
 
3
3
  /**
4
4
  * The public SEO-infra payload (`board.seo()`) — platform infrastructure a
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-CDYDY0hB.js';
1
+ import { S as Schemas } from './_spec-DIzdOWz7.js';
2
2
 
3
3
  /**
4
4
  * The public SEO-infra payload (`board.seo()`) — platform infrastructure a
@@ -1,5 +1,5 @@
1
- import { B as BoardSeo } from './seo-C7HjUu_z.mjs';
2
- import './_spec-CDYDY0hB.mjs';
1
+ import { B as BoardSeo } from './seo-Bn5gQY8t.mjs';
2
+ import './_spec-DIzdOWz7.mjs';
3
3
 
4
4
  /**
5
5
  * `@cavuno/board/seo-files` — platform-owned crawler/identity file bodies
@@ -1,5 +1,5 @@
1
- import { B as BoardSeo } from './seo-CBRBS8Mc.js';
2
- import './_spec-CDYDY0hB.js';
1
+ import { B as BoardSeo } from './seo-DFAwxGej.js';
2
+ import './_spec-DIzdOWz7.js';
3
3
 
4
4
  /**
5
5
  * `@cavuno/board/seo-files` — platform-owned crawler/identity file bodies
package/dist/seo.d.mts CHANGED
@@ -1,9 +1,9 @@
1
- import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-WupXypHv.mjs';
2
- import { e as JsonLdObject } from './breadcrumbs-mQTz0vZo.mjs';
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-mQTz0vZo.mjs';
4
- import './_spec-CDYDY0hB.mjs';
5
- import './board-DbBBz7Pv.mjs';
6
- import './jobs-CgmHLS8j.mjs';
1
+ import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-DgbGOmzW.mjs';
2
+ import { e as JsonLdObject } from './breadcrumbs-zYG4xzpC.mjs';
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-zYG4xzpC.mjs';
4
+ import './_spec-DIzdOWz7.mjs';
5
+ import './board-D3ByAGAb.mjs';
6
+ import './jobs-nA2K33Nu.mjs';
7
7
 
8
8
  /**
9
9
  * Blog structured data on the `@cavuno/board` wire types, transcribed from
package/dist/seo.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-DNGOmaKI.js';
2
- import { e as JsonLdObject } from './breadcrumbs-DpXiAo9j.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-DpXiAo9j.js';
4
- import './_spec-CDYDY0hB.js';
5
- import './board-CmQox8FZ.js';
6
- import './jobs-B-NPmaV0.js';
1
+ import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-CyvB9C6W.js';
2
+ import { e as JsonLdObject } from './breadcrumbs-aCKRBNWX.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-aCKRBNWX.js';
4
+ import './_spec-DIzdOWz7.js';
5
+ import './board-leXc6_BM.js';
6
+ import './jobs-DodvFXH2.js';
7
7
 
8
8
  /**
9
9
  * Blog structured data on the `@cavuno/board` wire types, transcribed from
package/dist/server.d.mts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { BoardSdk } from './index.mjs';
2
- import './_spec-CDYDY0hB.mjs';
3
- import './search--bO1b3RJ.mjs';
4
- import './jobs-CgmHLS8j.mjs';
5
- import './board-DbBBz7Pv.mjs';
6
- import './seo-C7HjUu_z.mjs';
7
- import './blog-WupXypHv.mjs';
2
+ import './_spec-DIzdOWz7.mjs';
3
+ import './search-8kX6OW03.mjs';
4
+ import './jobs-nA2K33Nu.mjs';
5
+ import './board-D3ByAGAb.mjs';
6
+ import './seo-Bn5gQY8t.mjs';
7
+ import './blog-DgbGOmzW.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-CDYDY0hB.js';
3
- import './search-BvhQ92ZO.js';
4
- import './jobs-B-NPmaV0.js';
5
- import './board-CmQox8FZ.js';
6
- import './seo-CBRBS8Mc.js';
7
- import './blog-DNGOmaKI.js';
2
+ import './_spec-DIzdOWz7.js';
3
+ import './search-C1XNGSm6.js';
4
+ import './jobs-DodvFXH2.js';
5
+ import './board-leXc6_BM.js';
6
+ import './seo-DFAwxGej.js';
7
+ import './blog-CyvB9C6W.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-CDYDY0hB.mjs';
3
- import './search--bO1b3RJ.mjs';
4
- import './jobs-CgmHLS8j.mjs';
5
- import './board-DbBBz7Pv.mjs';
6
- import './seo-C7HjUu_z.mjs';
7
- import './blog-WupXypHv.mjs';
2
+ import './_spec-DIzdOWz7.mjs';
3
+ import './search-8kX6OW03.mjs';
4
+ import './jobs-nA2K33Nu.mjs';
5
+ import './board-D3ByAGAb.mjs';
6
+ import './seo-Bn5gQY8t.mjs';
7
+ import './blog-DgbGOmzW.mjs';
8
8
 
9
9
  /**
10
10
  * Sitemap primitives — the pure XML + bucket-filename logic behind a board
@@ -89,7 +89,18 @@ interface ListedSitemapBucket {
89
89
  * freshness stamp survives.
90
90
  */
91
91
  declare function listedBucketEntries(board: BoardSdk): Promise<ListedSitemapBucket[]>;
92
- declare function buildBucketUrls(board: BoardSdk, origin: string, bucket: SitemapBucket): Promise<string[]>;
92
+ /** Options for `buildBucketUrls` and `buildBucketEntries`. */
93
+ interface BuildBucketOptions {
94
+ /**
95
+ * Whether your site publishes `/impressum`, usually because it has
96
+ * Impressum content of its own. When set, the marketing bucket lists
97
+ * `/impressum` exactly when this is `true`, whatever the board's published
98
+ * sitemap or the deprecated `features.impressum` says. Leave it unset to
99
+ * keep following the board.
100
+ */
101
+ impressum?: boolean;
102
+ }
103
+ declare function buildBucketUrls(board: BoardSdk, origin: string, bucket: SitemapBucket, options?: BuildBucketOptions): Promise<string[]>;
93
104
  /**
94
105
  * Like `buildBucketUrls`, but keeps each URL's `lastModified` where the board
95
106
  * publishes one. The result feeds `renderUrlset` directly, so every `<url>`
@@ -100,6 +111,6 @@ declare function buildBucketUrls(board: BoardSdk, origin: string, bucket: Sitema
100
111
  * so entries come back as `{ url }` only — identical output to
101
112
  * `buildBucketUrls`, just in the wider shape.
102
113
  */
103
- declare function buildBucketEntries(board: BoardSdk, origin: string, bucket: SitemapBucket): Promise<SitemapUrlEntry[]>;
114
+ declare function buildBucketEntries(board: BoardSdk, origin: string, bucket: SitemapBucket, options?: BuildBucketOptions): Promise<SitemapUrlEntry[]>;
104
115
 
105
- export { type ListedSitemapBucket, MIN_JOBS_PER_INDEXED_PAGE, SITEMAP_BUCKETS, SITEMAP_CHUNK_SIZE, type SitemapBucket, type SitemapIndexEntry, type SitemapUrlEntry, bucketFilename, buildBucketEntries, buildBucketUrls, chunk, listedBucketEntries, listedBuckets, parseBucketFilename, renderSitemapIndex, renderUrlset, xmlEscape };
116
+ export { type BuildBucketOptions, type ListedSitemapBucket, MIN_JOBS_PER_INDEXED_PAGE, SITEMAP_BUCKETS, SITEMAP_CHUNK_SIZE, type SitemapBucket, type SitemapIndexEntry, type SitemapUrlEntry, bucketFilename, buildBucketEntries, buildBucketUrls, chunk, listedBucketEntries, listedBuckets, parseBucketFilename, renderSitemapIndex, renderUrlset, xmlEscape };
package/dist/sitemap.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { BoardSdk } from './index.js';
2
- import './_spec-CDYDY0hB.js';
3
- import './search-BvhQ92ZO.js';
4
- import './jobs-B-NPmaV0.js';
5
- import './board-CmQox8FZ.js';
6
- import './seo-CBRBS8Mc.js';
7
- import './blog-DNGOmaKI.js';
2
+ import './_spec-DIzdOWz7.js';
3
+ import './search-C1XNGSm6.js';
4
+ import './jobs-DodvFXH2.js';
5
+ import './board-leXc6_BM.js';
6
+ import './seo-DFAwxGej.js';
7
+ import './blog-CyvB9C6W.js';
8
8
 
9
9
  /**
10
10
  * Sitemap primitives — the pure XML + bucket-filename logic behind a board
@@ -89,7 +89,18 @@ interface ListedSitemapBucket {
89
89
  * freshness stamp survives.
90
90
  */
91
91
  declare function listedBucketEntries(board: BoardSdk): Promise<ListedSitemapBucket[]>;
92
- declare function buildBucketUrls(board: BoardSdk, origin: string, bucket: SitemapBucket): Promise<string[]>;
92
+ /** Options for `buildBucketUrls` and `buildBucketEntries`. */
93
+ interface BuildBucketOptions {
94
+ /**
95
+ * Whether your site publishes `/impressum`, usually because it has
96
+ * Impressum content of its own. When set, the marketing bucket lists
97
+ * `/impressum` exactly when this is `true`, whatever the board's published
98
+ * sitemap or the deprecated `features.impressum` says. Leave it unset to
99
+ * keep following the board.
100
+ */
101
+ impressum?: boolean;
102
+ }
103
+ declare function buildBucketUrls(board: BoardSdk, origin: string, bucket: SitemapBucket, options?: BuildBucketOptions): Promise<string[]>;
93
104
  /**
94
105
  * Like `buildBucketUrls`, but keeps each URL's `lastModified` where the board
95
106
  * publishes one. The result feeds `renderUrlset` directly, so every `<url>`
@@ -100,6 +111,6 @@ declare function buildBucketUrls(board: BoardSdk, origin: string, bucket: Sitema
100
111
  * so entries come back as `{ url }` only — identical output to
101
112
  * `buildBucketUrls`, just in the wider shape.
102
113
  */
103
- declare function buildBucketEntries(board: BoardSdk, origin: string, bucket: SitemapBucket): Promise<SitemapUrlEntry[]>;
114
+ declare function buildBucketEntries(board: BoardSdk, origin: string, bucket: SitemapBucket, options?: BuildBucketOptions): Promise<SitemapUrlEntry[]>;
104
115
 
105
- export { type ListedSitemapBucket, MIN_JOBS_PER_INDEXED_PAGE, SITEMAP_BUCKETS, SITEMAP_CHUNK_SIZE, type SitemapBucket, type SitemapIndexEntry, type SitemapUrlEntry, bucketFilename, buildBucketEntries, buildBucketUrls, chunk, listedBucketEntries, listedBuckets, parseBucketFilename, renderSitemapIndex, renderUrlset, xmlEscape };
116
+ export { type BuildBucketOptions, type ListedSitemapBucket, MIN_JOBS_PER_INDEXED_PAGE, SITEMAP_BUCKETS, SITEMAP_CHUNK_SIZE, type SitemapBucket, type SitemapIndexEntry, type SitemapUrlEntry, bucketFilename, buildBucketEntries, buildBucketUrls, chunk, listedBucketEntries, listedBuckets, parseBucketFilename, renderSitemapIndex, renderUrlset, xmlEscape };
package/dist/sitemap.js CHANGED
@@ -335,11 +335,20 @@ async function listedBucketEntries(board) {
335
335
  );
336
336
  }
337
337
  }
338
- async function buildBucketUrls(board, origin, bucket) {
339
- const entries = await buildBucketEntries(board, origin, bucket);
338
+ async function buildBucketUrls(board, origin, bucket, options) {
339
+ const entries = await buildBucketEntries(board, origin, bucket, options);
340
340
  return entries.map((entry) => entry.url);
341
341
  }
342
- async function buildBucketEntries(board, origin, bucket) {
342
+ async function buildBucketEntries(board, origin, bucket, options) {
343
+ const entries = await boardBucketEntries(board, origin, bucket);
344
+ if (bucket !== "marketing" || options?.impressum === void 0) {
345
+ return entries;
346
+ }
347
+ const impressumUrl = `${origin}${BOARD_PATHS.impressum}`;
348
+ const listed = entries.filter((entry) => entry.url !== impressumUrl);
349
+ return options.impressum ? [...listed, { url: impressumUrl }] : listed;
350
+ }
351
+ async function boardBucketEntries(board, origin, bucket) {
343
352
  try {
344
353
  return await mirrorBucketEntries(board, origin, bucket);
345
354
  } catch (error) {
package/dist/sitemap.mjs CHANGED
@@ -201,11 +201,20 @@ async function listedBucketEntries(board) {
201
201
  );
202
202
  }
203
203
  }
204
- async function buildBucketUrls(board, origin, bucket) {
205
- const entries = await buildBucketEntries(board, origin, bucket);
204
+ async function buildBucketUrls(board, origin, bucket, options) {
205
+ const entries = await buildBucketEntries(board, origin, bucket, options);
206
206
  return entries.map((entry) => entry.url);
207
207
  }
208
- async function buildBucketEntries(board, origin, bucket) {
208
+ async function buildBucketEntries(board, origin, bucket, options) {
209
+ const entries = await boardBucketEntries(board, origin, bucket);
210
+ if (bucket !== "marketing" || options?.impressum === void 0) {
211
+ return entries;
212
+ }
213
+ const impressumUrl = `${origin}${BOARD_PATHS.impressum}`;
214
+ const listed = entries.filter((entry) => entry.url !== impressumUrl);
215
+ return options.impressum ? [...listed, { url: impressumUrl }] : listed;
216
+ }
217
+ async function boardBucketEntries(board, origin, bucket) {
209
218
  try {
210
219
  return await mirrorBucketEntries(board, origin, bucket);
211
220
  } catch (error) {
@@ -1,5 +1,5 @@
1
- import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search--bO1b3RJ.mjs';
2
- import './_spec-CDYDY0hB.mjs';
1
+ import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-8kX6OW03.mjs';
2
+ import './_spec-DIzdOWz7.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-BvhQ92ZO.js';
2
- import './_spec-CDYDY0hB.js';
1
+ import { h as SuggestionItem, b as SearchSuggestQuery, F as FetchOptions, g as SuggestResult } from './search-C1XNGSm6.js';
2
+ import './_spec-DIzdOWz7.js';
3
3
 
4
4
  /**
5
5
  * `@cavuno/board/suggest` — framework-agnostic headless search-suggest
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cavuno/board",
3
- "version": "4.57.0",
3
+ "version": "4.58.0",
4
4
  "description": "Build custom job boards and careers pages with Cavuno’s TypeScript SDK.",
5
5
  "keywords": [
6
6
  "api-client",
@@ -0,0 +1,135 @@
1
+ ---
2
+ name: cavuno-board-products
3
+ description: Digital product storefront with @cavuno/board. Use for product lists and pages, reviews, free claims, embedded paid checkout, the purchase download page with its email confirmation, downloads, buyer reviews, resending the link, or the signed-in buyer's purchases.
4
+ ---
5
+
6
+ # Digital product storefront
7
+
8
+ Operators create products in the Cavuno dashboard or the Operator API. The frontend lists them, sells them and serves the buyer's download page. `board.products` covers the catalogue and checkout; `board.purchases` covers everything after the purchase, keyed by the purchase token in the buyer's download link.
9
+
10
+ Routes: `BOARD_PATHS.products` (`/products`), `productPath(slug)`, the download page at `purchasePath(token)`, and `BOARD_PATHS.mePurchases` (`/me/purchases`), all from `@cavuno/board/paths`. Link to the `downloadUrl` the API returns instead of building the download path: it follows the board's route manifest.
11
+
12
+ ## List and render products
13
+
14
+ ```ts snippet
15
+ const { data: products, nextCursor } = await board.products.list({
16
+ sort: 'featured', // 'newest' | 'rating' | 'price_asc'
17
+ price: 'paid', // or 'free'; omit for both
18
+ limit: 24,
19
+ });
20
+
21
+ const product = await board.products.get('salary-guide');
22
+ if (product.ratingsEnabled) {
23
+ const { data: reviews } = await board.products.reviews('salary-guide');
24
+ }
25
+ ```
26
+
27
+ Only listed products appear in `list`; show a Products nav item only when it returns any. `get` also answers for an unlisted product by its exact slug: render it, but keep `isListed: false` pages out of lists, sitemaps and search indexes. An unknown, archived or undeliverable product is `products_not_found` (404). `price.kind` is `free`, `fixed` or `pay_what_you_want` (`amountCents` is the minimum, `suggestedCents` the prefill). `details` rows are `kind: 'text'` (`label`, `value`) or `kind: 'check'` (`label`, `checked`): render a check row as a tick or a cross with "Yes"/"No" as its accessible text, not as a word. Catalogue reads are public and cacheable.
28
+
29
+ ## Checkout: free and paid
30
+
31
+ Collect the email and the answers to `product.questions` (text → string, checkbox → boolean, dropdown → one of `options`) in your own form, then call `checkout` from the server.
32
+
33
+ ```ts snippet
34
+ const result = await board.products.checkout('salary-guide', {
35
+ email: 'ada@example.com',
36
+ answers: [{ questionId: 'waiver', value: true }],
37
+ jobAlertOptIn: false, // free products only; render unticked
38
+ returnPath: '/products/salary-guide',
39
+ website: '', // honeypot: render hidden, send empty
40
+ });
41
+
42
+ if (result.status === 'complete') {
43
+ redirect(result.downloadUrl); // free claim recorded and emailed
44
+ } else {
45
+ mountEmbeddedCheckout(result); // paid: Stripe mount kit
46
+ }
47
+ ```
48
+
49
+ `status: 'open'` returns `publishableKey`, `stripeAccountId`, `clientSecret` and `sessionId`. Mount with `loadStripe(publishableKey, { stripeAccount: stripeAccountId })` and `initEmbeddedCheckout({ clientSecret })`. The session expires after 30 minutes. For pay what you want, send `amountCents` (at least the minimum) or omit it to let the buyer choose on Stripe's page; `amountCents: 0` on a $0+ product is a free claim.
50
+
51
+ After Stripe returns with `session_id`, poll briefly:
52
+
53
+ ```ts snippet
54
+ const status = await board.products.getCheckout('salary-guide', sessionId, {
55
+ cache: 'no-store',
56
+ });
57
+ if (status.status === 'paid') redirect(status.downloadUrl);
58
+ // still 'awaiting_payment' after ~10 s: "We have emailed your download link"
59
+ ```
60
+
61
+ Checkout errors: `product_sold_out` (409), `product_email_invalid` (400), `product_email_blocked` (403), `product_amount_below_minimum` (400, `details.minimumCents`), `product_amount_invalid` (400), `product_answers_invalid` (400, `details.questionId`), `stripe_not_connected` (409), `rate_limited` (429), `rate_limit_unavailable` (503); `getCheckout` with an unknown session is `product_checkout_not_found`.
62
+
63
+ ## Download page and the shared-link check
64
+
65
+ The token is the buyer's credential: `no-store`, `noindex`, and never in analytics, sitemaps or cache keys. The buyer's first open and a signed-in buyer pass; a forwarded link gets `purchase_email_confirmation_required` (403). A server-side frontend never forwards the API's confirmation cookie, so keep the returned `confirmationToken` in your own per-purchase cookie and pass it back as the `confirmationToken` option (sent as `PURCHASE_CONFIRMATION_HEADER`).
66
+
67
+ ```ts snippet
68
+ import { isBoardApiError } from '@cavuno/board';
69
+
70
+ try {
71
+ const purchase = await board.purchases.get(token, {
72
+ confirmationToken,
73
+ cache: 'no-store',
74
+ });
75
+ if (purchase.confirmationToken) saveConfirmation(purchase.confirmationToken);
76
+ } catch (error) {
77
+ if (
78
+ isBoardApiError(error) &&
79
+ error.code === 'purchase_email_confirmation_required'
80
+ ) {
81
+ renderEmailPrompt(); // then:
82
+ const confirmation = await board.purchases.confirmEmail(token, {
83
+ email: typedEmail,
84
+ }); // purchase_email_mismatch (403) on a wrong email
85
+ saveConfirmation(confirmation.confirmationToken);
86
+ } else throw error;
87
+ }
88
+ ```
89
+
90
+ `purchase.files` holds files (`state`: `ready`, `preparing`, `limit_reached`; `downloadsLeft`, `sizeBytes`, `pageCount`, `stamped`) and links (`url`, opened directly). Also `downloadCap`, `stamping`, `receiptUrl` (null for free), `refundPolicy`, `ratingsEnabled` and the buyer's own `review`.
91
+
92
+ ## Downloads
93
+
94
+ Each call counts a download, so trigger it from a button, then redirect to the short-lived signed `url` at once.
95
+
96
+ ```ts snippet
97
+ const { url } = await board.purchases.download(token, fileId, {
98
+ confirmationToken,
99
+ });
100
+ const zip = await board.purchases.downloadAll(token, { confirmationToken });
101
+ // zip.preparing / zip.limitReached: file ids left out of the ZIP
102
+ ```
103
+
104
+ `purchase_file_preparing` (409): the stamped PDF is being made, nothing counted, the buyer is emailed when ready. `purchase_download_limit_reached` (409): permanent until the board resets it; never retry it as a rate limit. `purchase_download_all_unavailable` (503): offer single files. Also `purchase_awaiting_payment` (409), `purchase_access_removed` (410), `purchase_unavailable` (410), `purchase_file_not_found` and `purchases_not_found` (404). Purchase-token routes ignore the board password and plan gates.
105
+
106
+ ## Reviews, resend and the library
107
+
108
+ ```ts snippet
109
+ await board.purchases.review(
110
+ token,
111
+ { stars: 5, comment: 'Exactly what I needed' }, // displayName optional
112
+ { confirmationToken });
113
+
114
+ await board.purchases.resend({
115
+ email: 'ada@example.com',
116
+ productSlug: 'salary-guide',
117
+ website: '',
118
+ }); // always 202: never reveals whether a purchase exists
119
+
120
+ const { data: mine } = await board.purchases.mine({ cache: 'no-store' });
121
+ ```
122
+
123
+ `review` replaces the buyer's earlier review; `product_reviews_disabled` (404) when ratings are off, `purchase_refunded` (409), `purchase_review_invalid` (400). `mine` needs a board user session and lists purchases made while signed in plus those made with the user's verified email, each with `downloadUrl`.
124
+
125
+ ## Completion gate
126
+
127
+ - The list shows listed products only; a link-only product page renders with `noindex`.
128
+ - A free claim redirects to `downloadUrl`; a paid test checkout mounts, returns with `session_id`, and `getCheckout` reaches `paid`.
129
+ - A forwarded download link asks for the email, and the confirmation survives a reload through your own cookie.
130
+ - Downloads start from a button; `purchase_download_limit_reached` disables the button instead of retrying.
131
+ - Download pages, checkout status and `mine()` are `no-store`; purchase paths never reach analytics or the sitemap.
132
+
133
+ ## Cavuno SDK reference
134
+
135
+ For setup and API details beyond this workflow, use the [Cavuno Board SDK documentation](https://cavuno.com/docs/sdk/build-your-board/digital-products).
@@ -64,6 +64,7 @@ Route each enabled capability to its focused skill:
64
64
  | Saved jobs and applications | `cavuno-board-applications` |
65
65
  | Messaging | `cavuno-board-messaging` |
66
66
  | Candidate paywall | `cavuno-board-paywall` |
67
+ | Digital products | `cavuno-board-products` |
67
68
  | Employer talent access | `cavuno-board-talent-access` |
68
69
  | Public job posting | `cavuno-board-post-a-job` |
69
70
  | Localized chrome | `cavuno-board-i18n` |
@@ -132,8 +132,12 @@ it):
132
132
 
133
133
  - Taxonomy and location pages enter the sitemap at five distinct jobs,
134
134
  `MIN_JOBS_PER_INDEXED_PAGE`.
135
- - Marketing URLs follow context feature flags for impressum, talent directory,
136
- and employers. Blog is listed only when `features.blog` is enabled.
135
+ - Marketing URLs follow context feature flags for talent directory and
136
+ employers. Blog is listed only when `features.blog` is enabled.
137
+ - `/impressum` follows the board unless you pass the `impressum` option
138
+ (`buildBucketEntries(board, origin, bucket, { impressum })`). Pass it when
139
+ your site owns its Impressum content, so the sitemap lists `/impressum`
140
+ exactly when the page exists. `features.impressum` is deprecated.
137
141
  - Salary index reads use `context().language`, producing board-language
138
142
  canonical salary slugs. Job, company, market, and blog slugs arrive
139
143
  canonical on the wire.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.57.0",
2
+ "version": "4.58.0",
3
3
  "skills": [
4
4
  {
5
5
  "name": "cavuno-board-account",
@@ -113,6 +113,13 @@
113
113
  "framework": null,
114
114
  "category": "core"
115
115
  },
116
+ {
117
+ "name": "cavuno-board-products",
118
+ "description": "Digital product storefront with @cavuno/board. Use for product lists and pages, reviews, free claims, embedded paid checkout, the purchase download page with its email confirmation, downloads, buyer reviews, resending the link, or the signed-in buyer's purchases.",
119
+ "path": "skills/cavuno-board-products/SKILL.md",
120
+ "framework": null,
121
+ "category": "core"
122
+ },
116
123
  {
117
124
  "name": "cavuno-board-salaries",
118
125
  "description": "Salary read models with @cavuno/board. Use for title, skill, or location salary indexes and detail, cross-axis pages, or the salary companies hub.",