@cavuno/board 4.56.1 → 4.56.2

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 (68) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/{_spec-DS4-nx__.d.mts → _spec-CDYDY0hB.d.mts} +310 -0
  3. package/dist/{_spec-DS4-nx__.d.ts → _spec-CDYDY0hB.d.ts} +310 -0
  4. package/dist/bin.mjs +26 -4
  5. package/dist/{blog-By6dc-Ce.d.ts → blog-DNGOmaKI.d.ts} +1 -1
  6. package/dist/{blog-BcjUrzqE.d.mts → blog-WupXypHv.d.mts} +1 -1
  7. package/dist/{board-B7104o4G.d.ts → board-CmQox8FZ.d.ts} +2 -2
  8. package/dist/{board-BboonvQM.d.mts → board-DbBBz7Pv.d.mts} +2 -2
  9. package/dist/{breadcrumbs-CfRlf9_7.d.ts → breadcrumbs-DpXiAo9j.d.ts} +2 -2
  10. package/dist/{breadcrumbs-DmnLLDr9.d.mts → breadcrumbs-mQTz0vZo.d.mts} +2 -2
  11. package/dist/browser/cavuno-board.global.min.js +1 -1
  12. package/dist/{chunk-VERFP5OF.mjs → chunk-GUXSUQCP.mjs} +18 -4
  13. package/dist/{chunk-DZD3DAEY.mjs → chunk-M4CX64RC.mjs} +25 -1
  14. package/dist/{chunk-ENQ4ZIO2.mjs → chunk-MSY7ERBY.mjs} +13 -1
  15. package/dist/{chunk-EWD4PIOM.mjs → chunk-R3QB3WM6.mjs} +1 -1
  16. package/dist/doctor.js +26 -4
  17. package/dist/doctor.mjs +26 -4
  18. package/dist/filters.d.mts +2 -2
  19. package/dist/filters.d.ts +2 -2
  20. package/dist/format.d.mts +4 -4
  21. package/dist/format.d.ts +4 -4
  22. package/dist/format.js +5 -1
  23. package/dist/format.mjs +2 -2
  24. package/dist/go.js +5 -1
  25. package/dist/go.mjs +1 -1
  26. package/dist/index.d.mts +241 -13
  27. package/dist/index.d.ts +241 -13
  28. package/dist/index.js +226 -2
  29. package/dist/index.mjs +202 -2
  30. package/dist/{jobs-DkDmvx2n.d.ts → jobs-B-NPmaV0.d.ts} +1 -1
  31. package/dist/{jobs-D70pujRc.d.mts → jobs-CgmHLS8j.d.mts} +1 -1
  32. package/dist/paths.d.mts +16 -1
  33. package/dist/paths.d.ts +16 -1
  34. package/dist/paths.js +13 -1
  35. package/dist/paths.mjs +5 -1
  36. package/dist/{roles-Bh3WNF9u.d.mts → roles-B_d0igKI.d.mts} +5 -1
  37. package/dist/{roles-Bh3WNF9u.d.ts → roles-B_d0igKI.d.ts} +5 -1
  38. package/dist/route-contract.d.mts +2 -2
  39. package/dist/route-contract.d.ts +2 -2
  40. package/dist/route-contract.js +26 -4
  41. package/dist/route-contract.mjs +2 -2
  42. package/dist/{search-DCNHOZQK.d.mts → search--bO1b3RJ.d.mts} +1 -1
  43. package/dist/{search-DAwVPHKk.d.ts → search-BvhQ92ZO.d.ts} +1 -1
  44. package/dist/{seo-Duj1plPG.d.mts → seo-C7HjUu_z.d.mts} +1 -1
  45. package/dist/{seo-BH3Ryx7D.d.ts → seo-CBRBS8Mc.d.ts} +1 -1
  46. package/dist/seo-files.d.mts +2 -2
  47. package/dist/seo-files.d.ts +2 -2
  48. package/dist/seo-files.js +5 -0
  49. package/dist/seo-files.mjs +5 -0
  50. package/dist/seo.d.mts +6 -6
  51. package/dist/seo.d.ts +6 -6
  52. package/dist/seo.js +5 -1
  53. package/dist/seo.mjs +2 -2
  54. package/dist/server.d.mts +6 -6
  55. package/dist/server.d.ts +6 -6
  56. package/dist/server.mjs +1 -1
  57. package/dist/sitemap.d.mts +6 -6
  58. package/dist/sitemap.d.ts +6 -6
  59. package/dist/sitemap.js +5 -1
  60. package/dist/sitemap.mjs +2 -2
  61. package/dist/suggest.d.mts +2 -2
  62. package/dist/suggest.d.ts +2 -2
  63. package/dist/well-known.d.mts +1 -1
  64. package/dist/well-known.d.ts +1 -1
  65. package/dist/well-known.js +26 -4
  66. package/dist/well-known.mjs +2 -2
  67. package/package.json +1 -1
  68. package/skills/manifest.json +1 -1
package/dist/index.mjs CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  isSsoRequired,
26
26
  isUnauthorized,
27
27
  isValidationError
28
- } from "./chunk-DZD3DAEY.mjs";
28
+ } from "./chunk-M4CX64RC.mjs";
29
29
 
30
30
  // src/query.ts
31
31
  function toSearchParams(query) {
@@ -46,7 +46,7 @@ function toSearchParams(query) {
46
46
  }
47
47
 
48
48
  // src/version.ts
49
- var SDK_VERSION = "4.56.1";
49
+ var SDK_VERSION = "4.56.2";
50
50
 
51
51
  // src/client.ts
52
52
  function isRawBody(body) {
@@ -3408,6 +3408,84 @@ function plansNamespace(client) {
3408
3408
  };
3409
3409
  }
3410
3410
 
3411
+ // src/namespaces/products.ts
3412
+ var productBase = (slug) => `/products/${encodeURIComponent(slug)}`;
3413
+ function productsNamespace(client) {
3414
+ return {
3415
+ /**
3416
+ * List the board's listed digital products. Filter with `price`,
3417
+ * search with `q`, sort with `sort`, page with `cursor`.
3418
+ *
3419
+ * @example
3420
+ * const { data, nextCursor } = await board.products.list({ price: 'free' });
3421
+ */
3422
+ list(query, options) {
3423
+ return client.fetch("/products", {
3424
+ ...options,
3425
+ query
3426
+ });
3427
+ },
3428
+ /**
3429
+ * A product page by slug. Unlisted products answer by their exact slug
3430
+ * with `isListed: false`: keep those out of listings and sitemaps.
3431
+ *
3432
+ * @example
3433
+ * const product = await board.products.get('salary-guide');
3434
+ */
3435
+ get(slug, options) {
3436
+ return client.fetch(productBase(slug), options);
3437
+ },
3438
+ /**
3439
+ * A product's visible reviews, newest first. Empty when ratings are off.
3440
+ *
3441
+ * @example
3442
+ * const { data } = await board.products.reviews('salary-guide');
3443
+ */
3444
+ reviews(slug, query, options) {
3445
+ return client.fetch(
3446
+ `${productBase(slug)}/reviews`,
3447
+ { ...options, query }
3448
+ );
3449
+ },
3450
+ /**
3451
+ * Buy or claim a product. A free product returns `status: 'complete'`
3452
+ * with the download page path in `downloadUrl`; a paid one returns
3453
+ * `status: 'open'` with an embedded Stripe Checkout mount kit (it
3454
+ * expires after 30 minutes). Signed in, the purchase also lands in
3455
+ * `purchases.mine()`.
3456
+ *
3457
+ * @example
3458
+ * const result = await board.products.checkout('salary-guide', {
3459
+ * email: 'ada@example.com',
3460
+ * answers: [],
3461
+ * });
3462
+ * if (result.status === 'complete') redirect(result.downloadUrl!);
3463
+ */
3464
+ checkout(slug, body, options) {
3465
+ return client.fetch(`${productBase(slug)}/checkout`, {
3466
+ ...options,
3467
+ method: "POST",
3468
+ body
3469
+ });
3470
+ },
3471
+ /**
3472
+ * After Stripe returns the buyer (`session_id` on the return URL):
3473
+ * `awaiting_payment` until the payment lands, then `paid` with
3474
+ * `downloadUrl`. Poll briefly.
3475
+ *
3476
+ * @example
3477
+ * const s = await board.products.getCheckout('salary-guide', sessionId);
3478
+ * if (s.downloadUrl) redirect(s.downloadUrl);
3479
+ */
3480
+ getCheckout(slug, sessionId, options) {
3481
+ return client.fetch(
3482
+ `${productBase(slug)}/checkout/${encodeURIComponent(sessionId)}`,
3483
+ options
3484
+ );
3485
+ }
3486
+ };
3487
+ }
3488
+
3411
3489
  // src/namespaces/profile-fields.ts
3412
3490
  function profileFieldsNamespace(client) {
3413
3491
  return {
@@ -3428,6 +3506,125 @@ function profileFieldsNamespace(client) {
3428
3506
  };
3429
3507
  }
3430
3508
 
3509
+ // src/namespaces/purchases.ts
3510
+ var PURCHASE_CONFIRMATION_HEADER = "x-cavuno-purchase-confirmation";
3511
+ var purchaseBase = (token) => `/purchases/${encodeURIComponent(token)}`;
3512
+ function withConfirmation(options) {
3513
+ if (!options) return {};
3514
+ const { confirmationToken, ...rest } = options;
3515
+ if (!confirmationToken) return rest;
3516
+ const headers = new Headers(rest.headers);
3517
+ headers.set(PURCHASE_CONFIRMATION_HEADER, confirmationToken);
3518
+ return { ...rest, headers };
3519
+ }
3520
+ function purchasesNamespace(client) {
3521
+ return {
3522
+ /**
3523
+ * Open a purchase's download page by its token. A shared link asks for
3524
+ * the purchase email (`purchase_email_confirmation_required`, 403): call
3525
+ * `confirmEmail`, keep the `confirmationToken` it returns, and pass it
3526
+ * back on later calls.
3527
+ *
3528
+ * @example
3529
+ * const purchase = await board.purchases.get(token, { confirmationToken });
3530
+ */
3531
+ get(token, options) {
3532
+ return client.fetch(
3533
+ purchaseBase(token),
3534
+ withConfirmation(options)
3535
+ );
3536
+ },
3537
+ /**
3538
+ * Confirm the purchase email on a shared link. Returns the
3539
+ * `confirmationToken` to pass on later calls for this purchase.
3540
+ *
3541
+ * @example
3542
+ * const { confirmationToken } = await board.purchases.confirmEmail(token, {
3543
+ * email: 'ada@example.com',
3544
+ * });
3545
+ */
3546
+ confirmEmail(token, body, options) {
3547
+ return client.fetch(
3548
+ `${purchaseBase(token)}/confirm`,
3549
+ { ...options, method: "POST", body }
3550
+ );
3551
+ },
3552
+ /**
3553
+ * Count one download of a file and get a signed, short-lived link.
3554
+ * `purchase_file_preparing` (409) while the buyer's stamped copy is made
3555
+ * (they are emailed when it is ready); `purchase_download_limit_reached`
3556
+ * (409) when no downloads are left (only the board can reset it).
3557
+ *
3558
+ * @example
3559
+ * const { url } = await board.purchases.download(token, fileId);
3560
+ */
3561
+ download(token, fileId, options) {
3562
+ return client.fetch(
3563
+ `${purchaseBase(token)}/files/${encodeURIComponent(fileId)}/download`,
3564
+ { ...withConfirmation(options), method: "POST" }
3565
+ );
3566
+ },
3567
+ /**
3568
+ * Count every ready file and get a short-lived link to one streamed ZIP.
3569
+ * Offer it only while the page's `downloadAllAvailable` is true: files
3570
+ * totalling more than 500 MB are refused, with nothing counted, as
3571
+ * `409 purchase_download_all_unavailable` (download them one by one).
3572
+ *
3573
+ * @example
3574
+ * const { url } = await board.purchases.downloadAll(token);
3575
+ */
3576
+ downloadAll(token, options) {
3577
+ return client.fetch(
3578
+ `${purchaseBase(token)}/download-all`,
3579
+ { ...withConfirmation(options), method: "POST" }
3580
+ );
3581
+ },
3582
+ /**
3583
+ * Write or replace the buyer's review (1 to 5 stars).
3584
+ *
3585
+ * @example
3586
+ * await board.purchases.review(token, { stars: 5, comment: 'Useful' });
3587
+ */
3588
+ review(token, body, options) {
3589
+ return client.fetch(
3590
+ `${purchaseBase(token)}/review`,
3591
+ {
3592
+ ...withConfirmation(options),
3593
+ method: "PUT",
3594
+ body
3595
+ }
3596
+ );
3597
+ },
3598
+ /**
3599
+ * "Email me this link again". Always accepted, whether or not the email
3600
+ * holds a purchase.
3601
+ *
3602
+ * @example
3603
+ * await board.purchases.resend({ email: 'ada@example.com' });
3604
+ */
3605
+ resend(body, options) {
3606
+ return client.fetch("/purchases/resend", {
3607
+ ...options,
3608
+ method: "POST",
3609
+ body
3610
+ });
3611
+ },
3612
+ /**
3613
+ * The signed-in user's purchases (by account and verified email), each
3614
+ * with its download page path. Requires a board user session.
3615
+ *
3616
+ * @example
3617
+ * const { data } = await board.purchases.mine();
3618
+ */
3619
+ mine(options) {
3620
+ return client.fetch(
3621
+ "/me/purchases",
3622
+ options
3623
+ );
3624
+ }
3625
+ };
3626
+ }
3627
+
3431
3628
  // src/namespaces/redirects.ts
3432
3629
  function redirectsNamespace(client) {
3433
3630
  return {
@@ -3862,6 +4059,8 @@ function createBoardClient(options) {
3862
4059
  profileFields: profileFieldsNamespace(client),
3863
4060
  plans: plansNamespace(client),
3864
4061
  paywall: paywallNamespace(client),
4062
+ products: productsNamespace(client),
4063
+ purchases: purchasesNamespace(client),
3865
4064
  sitemap: sitemapNamespace(client)
3866
4065
  };
3867
4066
  }
@@ -3871,6 +4070,7 @@ export {
3871
4070
  BOARD_API_ERROR_CODES,
3872
4071
  BoardApiError,
3873
4072
  BoardClient,
4073
+ PURCHASE_CONFIRMATION_HEADER,
3874
4074
  REFRESH_TOKEN_KEY,
3875
4075
  SDK_VERSION,
3876
4076
  SIGN_IN_REDIRECT_ERROR_CODES,
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-DS4-nx__.js';
1
+ import { S as Schemas } from './_spec-CDYDY0hB.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-DS4-nx__.mjs';
1
+ import { S as Schemas } from './_spec-CDYDY0hB.mjs';
2
2
 
3
3
  /**
4
4
  * Optional pagination metadata returned by Board API list operations.
package/dist/paths.d.mts CHANGED
@@ -141,6 +141,17 @@ declare function talentProfilePath(handle: string): string;
141
141
  * in a place. Pass the place's `canonicalSlug` from the talent place list.
142
142
  */
143
143
  declare function talentLocationPath(placeSlug: string): string;
144
+ /**
145
+ * A digital product's page (`/products/<slug>`). Unlisted products are
146
+ * reachable here by their exact slug.
147
+ */
148
+ declare function productPath(productSlug: string): string;
149
+ /**
150
+ * A purchase's download page (`/purchases/<token>`). The token is the
151
+ * buyer's secret: never put this path in a sitemap, analytics or a
152
+ * shared-cache key.
153
+ */
154
+ declare function purchasePath(purchaseToken: string): string;
144
155
  /**
145
156
  * Static top-level board paths (indexed marketing + index surfaces). Kept
146
157
  * here so the sitemap and consumers share one definition of the chrome
@@ -171,6 +182,10 @@ declare const BOARD_PATHS: {
171
182
  */
172
183
  readonly alertsManage: "/alerts/manage";
173
184
  readonly alertsConfirm: "/alerts/confirm";
185
+ /** The digital product catalogue. */
186
+ readonly products: "/products";
187
+ /** A signed-in board user's purchased products. */
188
+ readonly mePurchases: "/me/purchases";
174
189
  };
175
190
  /**
176
191
  * Email `/go` indirection paths. Pure builders so
@@ -196,4 +211,4 @@ declare function goAlertsConfirmPath(): string;
196
211
  */
197
212
  declare function boardUrl(origin: string, path: string): string;
198
213
 
199
- export { BOARD_PATHS, type SuggestionPathInput, type SuggestionPathOptions, type SuggestionPathScope, blogAuthorPath, blogPostPath, blogTagPath, boardUrl, companyMarketPath, companyPath, companySalaryPath, encodePathSegment, goAlertsConfirmPath, goAlertsManagePath, goJobPath, jobDetailPath, jobsCategoryPath, jobsLocationCategoryPath, jobsLocationPath, jobsLocationSkillPath, jobsSkillPath, salaryLocationPath, salarySkillPath, salaryTitlePath, suggestionPath, talentLocationPath, talentProfilePath };
214
+ export { BOARD_PATHS, type SuggestionPathInput, type SuggestionPathOptions, type SuggestionPathScope, blogAuthorPath, blogPostPath, blogTagPath, boardUrl, companyMarketPath, companyPath, companySalaryPath, encodePathSegment, goAlertsConfirmPath, goAlertsManagePath, goJobPath, jobDetailPath, jobsCategoryPath, jobsLocationCategoryPath, jobsLocationPath, jobsLocationSkillPath, jobsSkillPath, productPath, purchasePath, salaryLocationPath, salarySkillPath, salaryTitlePath, suggestionPath, talentLocationPath, talentProfilePath };
package/dist/paths.d.ts CHANGED
@@ -141,6 +141,17 @@ declare function talentProfilePath(handle: string): string;
141
141
  * in a place. Pass the place's `canonicalSlug` from the talent place list.
142
142
  */
143
143
  declare function talentLocationPath(placeSlug: string): string;
144
+ /**
145
+ * A digital product's page (`/products/<slug>`). Unlisted products are
146
+ * reachable here by their exact slug.
147
+ */
148
+ declare function productPath(productSlug: string): string;
149
+ /**
150
+ * A purchase's download page (`/purchases/<token>`). The token is the
151
+ * buyer's secret: never put this path in a sitemap, analytics or a
152
+ * shared-cache key.
153
+ */
154
+ declare function purchasePath(purchaseToken: string): string;
144
155
  /**
145
156
  * Static top-level board paths (indexed marketing + index surfaces). Kept
146
157
  * here so the sitemap and consumers share one definition of the chrome
@@ -171,6 +182,10 @@ declare const BOARD_PATHS: {
171
182
  */
172
183
  readonly alertsManage: "/alerts/manage";
173
184
  readonly alertsConfirm: "/alerts/confirm";
185
+ /** The digital product catalogue. */
186
+ readonly products: "/products";
187
+ /** A signed-in board user's purchased products. */
188
+ readonly mePurchases: "/me/purchases";
174
189
  };
175
190
  /**
176
191
  * Email `/go` indirection paths. Pure builders so
@@ -196,4 +211,4 @@ declare function goAlertsConfirmPath(): string;
196
211
  */
197
212
  declare function boardUrl(origin: string, path: string): string;
198
213
 
199
- export { BOARD_PATHS, type SuggestionPathInput, type SuggestionPathOptions, type SuggestionPathScope, blogAuthorPath, blogPostPath, blogTagPath, boardUrl, companyMarketPath, companyPath, companySalaryPath, encodePathSegment, goAlertsConfirmPath, goAlertsManagePath, goJobPath, jobDetailPath, jobsCategoryPath, jobsLocationCategoryPath, jobsLocationPath, jobsLocationSkillPath, jobsSkillPath, salaryLocationPath, salarySkillPath, salaryTitlePath, suggestionPath, talentLocationPath, talentProfilePath };
214
+ export { BOARD_PATHS, type SuggestionPathInput, type SuggestionPathOptions, type SuggestionPathScope, blogAuthorPath, blogPostPath, blogTagPath, boardUrl, companyMarketPath, companyPath, companySalaryPath, encodePathSegment, goAlertsConfirmPath, goAlertsManagePath, goJobPath, jobDetailPath, jobsCategoryPath, jobsLocationCategoryPath, jobsLocationPath, jobsLocationSkillPath, jobsSkillPath, productPath, purchasePath, salaryLocationPath, salarySkillPath, salaryTitlePath, suggestionPath, talentLocationPath, talentProfilePath };
package/dist/paths.js CHANGED
@@ -38,6 +38,8 @@ __export(paths_exports, {
38
38
  jobsLocationPath: () => jobsLocationPath,
39
39
  jobsLocationSkillPath: () => jobsLocationSkillPath,
40
40
  jobsSkillPath: () => jobsSkillPath,
41
+ productPath: () => productPath,
42
+ purchasePath: () => purchasePath,
41
43
  salaryLocationPath: () => salaryLocationPath,
42
44
  salarySkillPath: () => salarySkillPath,
43
45
  salaryTitlePath: () => salaryTitlePath,
@@ -135,6 +137,12 @@ function talentProfilePath(handle) {
135
137
  function talentLocationPath(placeSlug) {
136
138
  return `/talent/locations/${encodePathSegment(placeSlug)}`;
137
139
  }
140
+ function productPath(productSlug) {
141
+ return `/products/${encodePathSegment(productSlug)}`;
142
+ }
143
+ function purchasePath(purchaseToken) {
144
+ return `/purchases/${encodePathSegment(purchaseToken)}`;
145
+ }
138
146
  var BOARD_PATHS = {
139
147
  home: "/",
140
148
  jobs: "/jobs",
@@ -159,7 +167,11 @@ var BOARD_PATHS = {
159
167
  * one definition.
160
168
  */
161
169
  alertsManage: "/alerts/manage",
162
- alertsConfirm: "/alerts/confirm"
170
+ alertsConfirm: "/alerts/confirm",
171
+ /** The digital product catalogue. */
172
+ products: "/products",
173
+ /** A signed-in board user's purchased products. */
174
+ mePurchases: "/me/purchases"
163
175
  };
164
176
  function goJobPath(jobId) {
165
177
  return `/go/job/${jobId}`;
package/dist/paths.mjs CHANGED
@@ -17,13 +17,15 @@ import {
17
17
  jobsLocationPath,
18
18
  jobsLocationSkillPath,
19
19
  jobsSkillPath,
20
+ productPath,
21
+ purchasePath,
20
22
  salaryLocationPath,
21
23
  salarySkillPath,
22
24
  salaryTitlePath,
23
25
  suggestionPath,
24
26
  talentLocationPath,
25
27
  talentProfilePath
26
- } from "./chunk-ENQ4ZIO2.mjs";
28
+ } from "./chunk-MSY7ERBY.mjs";
27
29
  export {
28
30
  BOARD_PATHS,
29
31
  blogAuthorPath,
@@ -43,6 +45,8 @@ export {
43
45
  jobsLocationPath,
44
46
  jobsLocationSkillPath,
45
47
  jobsSkillPath,
48
+ productPath,
49
+ purchasePath,
46
50
  salaryLocationPath,
47
51
  salarySkillPath,
48
52
  salaryTitlePath,
@@ -63,7 +63,11 @@ type ValidateManifestResult = {
63
63
  /** Every role the compiler can assign. */
64
64
  type RouteRole = 'jobDetail' | 'jobsCategory' | 'jobsSkill' | 'jobsLocation' | 'company' | 'companyMarket' | 'companySalary' | 'salaryTitle' | 'salarySkill' | 'salaryLocation' | 'blogPost' | 'blogTag' | 'blogAuthor'
65
65
  /** One candidate's public profile; optional, never required. */
66
- | 'talentProfile' | 'home' | 'jobs' | 'companies' | 'salaries' | 'salaryCompanies' | 'salaryTitles' | 'salarySkills' | 'salaryLocations' | 'blog' | 'about' | 'privacyPolicy' | 'termsOfService' | 'cookiePolicy' | 'impressum' | 'talent' | 'employers' | 'alertsManage' | 'alertsConfirm';
66
+ | 'talentProfile'
67
+ /** A digital product's page. */
68
+ | 'product'
69
+ /** A purchase's download page (emails link here). */
70
+ | 'purchase' | 'home' | 'jobs' | 'companies' | 'salaries' | 'salaryCompanies' | 'salaryTitles' | 'salarySkills' | 'salaryLocations' | 'blog' | 'about' | 'privacyPolicy' | 'termsOfService' | 'cookiePolicy' | 'impressum' | 'talent' | 'employers' | 'alertsManage' | 'alertsConfirm' | 'products' | 'mePurchases';
67
71
  /**
68
72
  * Exact param-name set per role, derived from each helper's signature.
69
73
  * Empty arrays = static / zero-param roles (never inferred by signature).
@@ -63,7 +63,11 @@ type ValidateManifestResult = {
63
63
  /** Every role the compiler can assign. */
64
64
  type RouteRole = 'jobDetail' | 'jobsCategory' | 'jobsSkill' | 'jobsLocation' | 'company' | 'companyMarket' | 'companySalary' | 'salaryTitle' | 'salarySkill' | 'salaryLocation' | 'blogPost' | 'blogTag' | 'blogAuthor'
65
65
  /** One candidate's public profile; optional, never required. */
66
- | 'talentProfile' | 'home' | 'jobs' | 'companies' | 'salaries' | 'salaryCompanies' | 'salaryTitles' | 'salarySkills' | 'salaryLocations' | 'blog' | 'about' | 'privacyPolicy' | 'termsOfService' | 'cookiePolicy' | 'impressum' | 'talent' | 'employers' | 'alertsManage' | 'alertsConfirm';
66
+ | 'talentProfile'
67
+ /** A digital product's page. */
68
+ | 'product'
69
+ /** A purchase's download page (emails link here). */
70
+ | 'purchase' | 'home' | 'jobs' | 'companies' | 'salaries' | 'salaryCompanies' | 'salaryTitles' | 'salarySkills' | 'salaryLocations' | 'blog' | 'about' | 'privacyPolicy' | 'termsOfService' | 'cookiePolicy' | 'impressum' | 'talent' | 'employers' | 'alertsManage' | 'alertsConfirm' | 'products' | 'mePurchases';
67
71
  /**
68
72
  * Exact param-name set per role, derived from each helper's signature.
69
73
  * Empty arrays = static / zero-param roles (never inferred by signature).
@@ -1,5 +1,5 @@
1
- import { R as RouteEntry, a as RouteRole, C as ClassifyResult, b as CompileResult, V as ValidateManifestError, c as ValidateManifestResult, M as ManifestV1 } from './roles-Bh3WNF9u.mjs';
2
- export { A as ALL_ROLES, d as Ambiguity, e as CANONICAL_MANIFEST, f as REQUIRED_ROLES, g as ROLE_PARAM_REGISTRY, i as isRouteRole } from './roles-Bh3WNF9u.mjs';
1
+ import { R as RouteEntry, a as RouteRole, C as ClassifyResult, b as CompileResult, V as ValidateManifestError, c as ValidateManifestResult, M as ManifestV1 } from './roles-B_d0igKI.mjs';
2
+ export { A as ALL_ROLES, d as Ambiguity, e as CANONICAL_MANIFEST, f as REQUIRED_ROLES, g as ROLE_PARAM_REGISTRY, i as isRouteRole } from './roles-B_d0igKI.mjs';
3
3
 
4
4
  /**
5
5
  * Classify routes into role assignments. Markers (keyed by `sourcePath`)
@@ -1,5 +1,5 @@
1
- import { R as RouteEntry, a as RouteRole, C as ClassifyResult, b as CompileResult, V as ValidateManifestError, c as ValidateManifestResult, M as ManifestV1 } from './roles-Bh3WNF9u.js';
2
- export { A as ALL_ROLES, d as Ambiguity, e as CANONICAL_MANIFEST, f as REQUIRED_ROLES, g as ROLE_PARAM_REGISTRY, i as isRouteRole } from './roles-Bh3WNF9u.js';
1
+ import { R as RouteEntry, a as RouteRole, C as ClassifyResult, b as CompileResult, V as ValidateManifestError, c as ValidateManifestResult, M as ManifestV1 } from './roles-B_d0igKI.js';
2
+ export { A as ALL_ROLES, d as Ambiguity, e as CANONICAL_MANIFEST, f as REQUIRED_ROLES, g as ROLE_PARAM_REGISTRY, i as isRouteRole } from './roles-B_d0igKI.js';
3
3
 
4
4
  /**
5
5
  * Classify routes into role assignments. Markers (keyed by `sourcePath`)
@@ -103,6 +103,12 @@ function blogAuthorPath(authorSlug) {
103
103
  function talentProfilePath(handle) {
104
104
  return `/p/${encodePathSegment(handle)}`;
105
105
  }
106
+ function productPath(productSlug) {
107
+ return `/products/${encodePathSegment(productSlug)}`;
108
+ }
109
+ function purchasePath(purchaseToken) {
110
+ return `/purchases/${encodePathSegment(purchaseToken)}`;
111
+ }
106
112
  var BOARD_PATHS = {
107
113
  home: "/",
108
114
  jobs: "/jobs",
@@ -127,7 +133,11 @@ var BOARD_PATHS = {
127
133
  * one definition.
128
134
  */
129
135
  alertsManage: "/alerts/manage",
130
- alertsConfirm: "/alerts/confirm"
136
+ alertsConfirm: "/alerts/confirm",
137
+ /** The digital product catalogue. */
138
+ products: "/products",
139
+ /** A signed-in board user's purchased products. */
140
+ mePurchases: "/me/purchases"
131
141
  };
132
142
 
133
143
  // src/route-contract/roles.ts
@@ -146,6 +156,8 @@ var ROLE_PARAM_REGISTRY = {
146
156
  blogTag: ["tagSlug"],
147
157
  blogAuthor: ["authorSlug"],
148
158
  talentProfile: ["handle"],
159
+ product: ["productSlug"],
160
+ purchase: ["purchaseToken"],
149
161
  home: [],
150
162
  jobs: [],
151
163
  companies: [],
@@ -163,7 +175,9 @@ var ROLE_PARAM_REGISTRY = {
163
175
  talent: [],
164
176
  employers: [],
165
177
  alertsManage: [],
166
- alertsConfirm: []
178
+ alertsConfirm: [],
179
+ products: [],
180
+ mePurchases: []
167
181
  };
168
182
  var REQUIRED_ROLES = [
169
183
  "jobDetail",
@@ -194,6 +208,8 @@ var CANONICAL_MANIFEST = {
194
208
  blogTag: blogTagPath(":tagSlug"),
195
209
  blogAuthor: blogAuthorPath(":authorSlug"),
196
210
  talentProfile: talentProfilePath(":handle"),
211
+ product: productPath(":productSlug"),
212
+ purchase: purchasePath(":purchaseToken"),
197
213
  home: BOARD_PATHS.home,
198
214
  jobs: BOARD_PATHS.jobs,
199
215
  companies: BOARD_PATHS.companies,
@@ -211,7 +227,9 @@ var CANONICAL_MANIFEST = {
211
227
  talent: BOARD_PATHS.talent,
212
228
  employers: BOARD_PATHS.employers,
213
229
  alertsManage: "/alerts/manage",
214
- alertsConfirm: "/alerts/confirm"
230
+ alertsConfirm: "/alerts/confirm",
231
+ products: BOARD_PATHS.products,
232
+ mePurchases: BOARD_PATHS.mePurchases
215
233
  }
216
234
  };
217
235
 
@@ -1133,7 +1151,11 @@ var ROLE_INDEX_PATHS = {
1133
1151
  talent: BOARD_PATHS.talent,
1134
1152
  employers: BOARD_PATHS.employers,
1135
1153
  alertsManage: BOARD_PATHS.home,
1136
- alertsConfirm: BOARD_PATHS.home
1154
+ alertsConfirm: BOARD_PATHS.home,
1155
+ product: BOARD_PATHS.products,
1156
+ purchase: BOARD_PATHS.home,
1157
+ products: BOARD_PATHS.products,
1158
+ mePurchases: BOARD_PATHS.home
1137
1159
  };
1138
1160
  function splitSegments(path) {
1139
1161
  const withoutLeading = path.startsWith("/") ? path.slice(1) : path;
@@ -26,8 +26,8 @@ import {
26
26
  parseTanStackRoutes,
27
27
  sameParamSet,
28
28
  validateManifest
29
- } from "./chunk-VERFP5OF.mjs";
30
- import "./chunk-ENQ4ZIO2.mjs";
29
+ } from "./chunk-GUXSUQCP.mjs";
30
+ import "./chunk-MSY7ERBY.mjs";
31
31
  export {
32
32
  ALL_ROLES,
33
33
  CANONICAL_MANIFEST,
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-DS4-nx__.mjs';
1
+ import { S as Schemas } from './_spec-CDYDY0hB.mjs';
2
2
 
3
3
  type Awaitable<T> = T | Promise<T>;
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-DS4-nx__.js';
1
+ import { S as Schemas } from './_spec-CDYDY0hB.js';
2
2
 
3
3
  type Awaitable<T> = T | Promise<T>;
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { S as Schemas } from './_spec-DS4-nx__.mjs';
1
+ import { S as Schemas } from './_spec-CDYDY0hB.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-DS4-nx__.js';
1
+ import { S as Schemas } from './_spec-CDYDY0hB.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-Duj1plPG.mjs';
2
- import './_spec-DS4-nx__.mjs';
1
+ import { B as BoardSeo } from './seo-C7HjUu_z.mjs';
2
+ import './_spec-CDYDY0hB.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-BH3Ryx7D.js';
2
- import './_spec-DS4-nx__.js';
1
+ import { B as BoardSeo } from './seo-CBRBS8Mc.js';
2
+ import './_spec-CDYDY0hB.js';
3
3
 
4
4
  /**
5
5
  * `@cavuno/board/seo-files` — platform-owned crawler/identity file bodies
package/dist/seo-files.js CHANGED
@@ -81,6 +81,11 @@ function robotsBody(input) {
81
81
  "Allow: /",
82
82
  "Disallow: /go/",
83
83
  "Disallow: /t/",
84
+ // Board API responses carry `url` fields that are Board API paths
85
+ // (`/v1/boards/<key>/...`). Crawlers pick them out of the page's embedded
86
+ // data and request them on the board's own host, where nothing is served
87
+ // under `/v1/`. Keep them out of the crawl instead of collecting 404s.
88
+ "Disallow: /v1/",
84
89
  ...baseRoots.flatMap(paginationRules),
85
90
  ...localeRoots.flatMap(paginationRules),
86
91
  "",
@@ -49,6 +49,11 @@ function robotsBody(input) {
49
49
  "Allow: /",
50
50
  "Disallow: /go/",
51
51
  "Disallow: /t/",
52
+ // Board API responses carry `url` fields that are Board API paths
53
+ // (`/v1/boards/<key>/...`). Crawlers pick them out of the page's embedded
54
+ // data and request them on the board's own host, where nothing is served
55
+ // under `/v1/`. Keep them out of the crawl instead of collecting 404s.
56
+ "Disallow: /v1/",
52
57
  ...baseRoots.flatMap(paginationRules),
53
58
  ...localeRoots.flatMap(paginationRules),
54
59
  "",
package/dist/seo.d.mts CHANGED
@@ -1,9 +1,9 @@
1
- import { P as PublicBlogPostSummary, B as BlogAuthorEmbed } from './blog-BcjUrzqE.mjs';
2
- import { e as JsonLdObject } from './breadcrumbs-DmnLLDr9.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-DmnLLDr9.mjs';
4
- import './_spec-DS4-nx__.mjs';
5
- import './board-BboonvQM.mjs';
6
- import './jobs-D70pujRc.mjs';
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';
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-By6dc-Ce.js';
2
- import { e as JsonLdObject } from './breadcrumbs-CfRlf9_7.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-CfRlf9_7.js';
4
- import './_spec-DS4-nx__.js';
5
- import './board-B7104o4G.js';
6
- import './jobs-DkDmvx2n.js';
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';
7
7
 
8
8
  /**
9
9
  * Blog structured data on the `@cavuno/board` wire types, transcribed from
package/dist/seo.js CHANGED
@@ -207,7 +207,11 @@ var BOARD_PATHS = {
207
207
  * one definition.
208
208
  */
209
209
  alertsManage: "/alerts/manage",
210
- alertsConfirm: "/alerts/confirm"
210
+ alertsConfirm: "/alerts/confirm",
211
+ /** The digital product catalogue. */
212
+ products: "/products",
213
+ /** A signed-in board user's purchased products. */
214
+ mePurchases: "/me/purchases"
211
215
  };
212
216
  function boardUrl(origin, path) {
213
217
  return `${origin.replace(/\/+$/, "")}${path}`;