@cavuno/board 1.29.0 → 1.31.0-preview.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/seo.d.ts CHANGED
@@ -1,5 +1,6 @@
1
- import { P as PublicBoard, a as PublicBlogPostSummary, B as BlogAuthorEmbed, C as CompanyCategorySalary, b as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './salaries-CXt6Vkrp.js';
2
- import { P as PublicJob } from './jobs-DK5mPBgq.js';
1
+ import { P as PublicBlogPostSummary, B as BlogAuthorEmbed, C as CompanyCategorySalary, a as CompanySalary, L as LocationSalaryDetail, S as SkillSalaryDetail, T as TitleSalaryDetail } from './salaries-CrtQBy81.js';
2
+ import { P as PublicBoard } from './board--nLjpneU.js';
3
+ import { P as PublicJob } from './jobs-Dmz8uexp.js';
3
4
 
4
5
  /**
5
6
  * Google for Jobs `JobPosting` structured data on the `@cavuno/board` wire
@@ -132,6 +133,18 @@ interface BreadcrumbItemInput {
132
133
  declare function createBreadcrumbJsonLd(items: BreadcrumbItemInput[], options?: {
133
134
  origin?: string | null;
134
135
  }): JsonLdObject | null;
136
+ /**
137
+ * Home › Jobs › [country › region › city] › primaryCategory › Title.
138
+ * The place crumbs link into the listing routes (`/jobs/locations/:slug`);
139
+ * the category crumb nests under the most-specific place when present
140
+ * (`/jobs/locations/:place/:category`), else `/jobs/:category`. The last
141
+ * crumb (the job title) carries no `path` — the current page. Mirrors
142
+ * page.tsx:336-367.
143
+ */
144
+ declare function buildJobBreadcrumbs(job: PublicJob): Array<{
145
+ name: string;
146
+ path?: string;
147
+ }>;
135
148
 
136
149
  /**
137
150
  * Framework-neutral `<head>` + structural JSON-LD builders for jobs-listing
@@ -285,4 +298,4 @@ declare function companySalaryJsonLd(locale: string, d: CompanySalary): JsonLdOb
285
298
  /** `Occupation` for one job category at a company (the hosted category page). */
286
299
  declare function companyCategorySalaryJsonLd(locale: string, d: CompanyCategorySalary): JsonLdObject | null;
287
300
 
288
- export { ALL_COUNTRY_CODES, type ArticleJsonLdPost, type BreadcrumbItemInput, type FaqItem, type JsonLdBoard, type JsonLdObject, type ListingHeadOptions, SENIORITY_ORDER, buildSalaryFaq, companyCategorySalaryJsonLd, companySalaryJsonLd, createAuthorProfileJsonLd, createBlogArticleJsonLd, createBreadcrumbJsonLd, createJobPostingJsonLd, crossAxisSalaryJsonLd, faqJsonLd, formatRange, formatSeniority, formatUsd, itemListJsonLd, listingHead, listingJsonLd, locationSalaryJsonLd, normalizeWebsiteUrl, skillSalaryJsonLd, sortBySeniority, titleSalaryJsonLd };
301
+ export { ALL_COUNTRY_CODES, type ArticleJsonLdPost, type BreadcrumbItemInput, type FaqItem, type JsonLdBoard, type JsonLdObject, type ListingHeadOptions, SENIORITY_ORDER, buildJobBreadcrumbs, buildSalaryFaq, companyCategorySalaryJsonLd, companySalaryJsonLd, createAuthorProfileJsonLd, createBlogArticleJsonLd, createBreadcrumbJsonLd, createJobPostingJsonLd, crossAxisSalaryJsonLd, faqJsonLd, formatRange, formatSeniority, formatUsd, itemListJsonLd, listingHead, listingJsonLd, locationSalaryJsonLd, normalizeWebsiteUrl, skillSalaryJsonLd, sortBySeniority, titleSalaryJsonLd };
package/dist/seo.js CHANGED
@@ -22,6 +22,7 @@ var seo_exports = {};
22
22
  __export(seo_exports, {
23
23
  ALL_COUNTRY_CODES: () => ALL_COUNTRY_CODES,
24
24
  SENIORITY_ORDER: () => SENIORITY_ORDER,
25
+ buildJobBreadcrumbs: () => buildJobBreadcrumbs,
25
26
  buildSalaryFaq: () => buildSalaryFaq,
26
27
  companyCategorySalaryJsonLd: () => companyCategorySalaryJsonLd,
27
28
  companySalaryJsonLd: () => companySalaryJsonLd,
@@ -203,6 +204,26 @@ function resolveBreadcrumbHref(href, origin) {
203
204
  function isAbsoluteUrl(href) {
204
205
  return /^https?:\/\//i.test(href);
205
206
  }
207
+ function buildJobBreadcrumbs(job) {
208
+ const crumbs = [
209
+ { name: "Home", path: "/" },
210
+ { name: "Jobs", path: "/jobs" }
211
+ ];
212
+ let lastPlaceSlug = null;
213
+ for (const place of job.placeHierarchy) {
214
+ lastPlaceSlug = place.slug;
215
+ crumbs.push({ name: place.name, path: `/jobs/locations/${place.slug}` });
216
+ }
217
+ const primaryCategory = job.categories[0];
218
+ if (primaryCategory) {
219
+ crumbs.push({
220
+ name: primaryCategory.name,
221
+ path: lastPlaceSlug ? `/jobs/locations/${lastPlaceSlug}/${primaryCategory.slug}` : `/jobs/${primaryCategory.slug}`
222
+ });
223
+ }
224
+ crumbs.push({ name: job.title });
225
+ return crumbs;
226
+ }
206
227
 
207
228
  // src/seo/job-posting.ts
208
229
  var EDUCATION_TO_CREDENTIAL = {
package/dist/seo.mjs CHANGED
@@ -156,6 +156,26 @@ function resolveBreadcrumbHref(href, origin) {
156
156
  function isAbsoluteUrl(href) {
157
157
  return /^https?:\/\//i.test(href);
158
158
  }
159
+ function buildJobBreadcrumbs(job) {
160
+ const crumbs = [
161
+ { name: "Home", path: "/" },
162
+ { name: "Jobs", path: "/jobs" }
163
+ ];
164
+ let lastPlaceSlug = null;
165
+ for (const place of job.placeHierarchy) {
166
+ lastPlaceSlug = place.slug;
167
+ crumbs.push({ name: place.name, path: `/jobs/locations/${place.slug}` });
168
+ }
169
+ const primaryCategory = job.categories[0];
170
+ if (primaryCategory) {
171
+ crumbs.push({
172
+ name: primaryCategory.name,
173
+ path: lastPlaceSlug ? `/jobs/locations/${lastPlaceSlug}/${primaryCategory.slug}` : `/jobs/${primaryCategory.slug}`
174
+ });
175
+ }
176
+ crumbs.push({ name: job.title });
177
+ return crumbs;
178
+ }
159
179
 
160
180
  // src/seo/job-posting.ts
161
181
  var EDUCATION_TO_CREDENTIAL = {
@@ -1056,6 +1076,7 @@ function companyCategorySalaryJsonLd(locale, d) {
1056
1076
  export {
1057
1077
  ALL_COUNTRY_CODES,
1058
1078
  SENIORITY_ORDER,
1079
+ buildJobBreadcrumbs,
1059
1080
  buildSalaryFaq,
1060
1081
  companyCategorySalaryJsonLd,
1061
1082
  companySalaryJsonLd,
package/dist/server.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { BoardSdk } from './index.mjs';
2
- import './jobs-DK5mPBgq.mjs';
3
- import './salaries-CrJsaZe6.mjs';
2
+ import './jobs-Dmz8uexp.mjs';
3
+ import './board-BS8Ax7hz.mjs';
4
+ import './salaries-QXFAyysR.mjs';
4
5
 
5
6
  /**
6
7
  * Session cookie codec — pure (no framework imports, no node imports) so it
package/dist/server.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { BoardSdk } from './index.js';
2
- import './jobs-DK5mPBgq.js';
3
- import './salaries-CXt6Vkrp.js';
2
+ import './jobs-Dmz8uexp.js';
3
+ import './board--nLjpneU.js';
4
+ import './salaries-CrtQBy81.js';
4
5
 
5
6
  /**
6
7
  * Session cookie codec — pure (no framework imports, no node imports) so it
@@ -1,6 +1,7 @@
1
1
  import { BoardSdk } from './index.mjs';
2
- import './jobs-DK5mPBgq.mjs';
3
- import './salaries-CrJsaZe6.mjs';
2
+ import './jobs-Dmz8uexp.mjs';
3
+ import './board-BS8Ax7hz.mjs';
4
+ import './salaries-QXFAyysR.mjs';
4
5
 
5
6
  /**
6
7
  * Sitemap primitives — the pure XML + bucket-filename logic behind a board
package/dist/sitemap.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { BoardSdk } from './index.js';
2
- import './jobs-DK5mPBgq.js';
3
- import './salaries-CXt6Vkrp.js';
2
+ import './jobs-Dmz8uexp.js';
3
+ import './board--nLjpneU.js';
4
+ import './salaries-CrtQBy81.js';
4
5
 
5
6
  /**
6
7
  * Sitemap primitives — the pure XML + bucket-filename logic behind a board
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cavuno/board",
3
- "version": "1.29.0",
3
+ "version": "1.31.0-preview.0",
4
4
  "description": "Typed isomorphic client for the Cavuno Board API",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -29,6 +29,20 @@ named in its summary and still needs the manual checks below. Use the
29
29
  rest of this skill for the behavioral checks doctor does not automate
30
30
  (auth flows, gating semantics, production build).
31
31
 
32
+ Add `--sandbox` to also run the write probes (register → login → apply →
33
+ alert-signup). They are refused unless the board the `pk_` resolves is
34
+ THE platform sandbox (`sandbox: true` in the board context — set only by
35
+ the platform's sandbox seed and stripped from any client settings write)
36
+ — never point them at a real tenant. The
37
+ email-delivery check additionally needs `RESEND_API_KEY` (a platform
38
+ operator credential) and SKIPs loudly without it.
39
+
40
+ Rate limits are real on the sandbox: the auth endpoints share a
41
+ 10-requests/min bucket and register allows 5 signups per 15 minutes per
42
+ IP, and one probe run consumes 4 requests + 1 signup. Rapid reruns will
43
+ start failing with HTTP 429 — that's the limiter working, not a broken
44
+ board; wait a few minutes.
45
+
32
46
  ## 1 — Probe the API directly (before blaming app code)
33
47
 
34
48
  Use the real env values the app reads (`PUBLIC_CAVUNO_API_URL`,
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.29.0",
2
+ "version": "1.31.0-preview.0",
3
3
  "skills": [
4
4
  {
5
5
  "name": "cavuno-board-account",