@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/format.js CHANGED
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var format_exports = {};
22
22
  __export(format_exports, {
23
23
  cardLocationLabel: () => cardLocationLabel,
24
+ companyIntro: () => companyIntro,
24
25
  fieldLabel: () => fieldLabel,
25
26
  formatDate: () => formatDate,
26
27
  formatMonthYear: () => formatMonthYear,
@@ -28,7 +29,8 @@ __export(format_exports, {
28
29
  formatSalaryRange: () => formatSalaryRange,
29
30
  fullJobToCard: () => fullJobToCard,
30
31
  getSalaryLexicon: () => getSalaryLexicon,
31
- locationLabel: () => locationLabel
32
+ locationLabel: () => locationLabel,
33
+ resolveCustomFieldDisplay: () => resolveCustomFieldDisplay
32
34
  });
33
35
  module.exports = __toCommonJS(format_exports);
34
36
 
@@ -451,3 +453,76 @@ function formatSalaryRange(language, min, max, timeframe, currency = null, timef
451
453
  timeframeLabel
452
454
  );
453
455
  }
456
+
457
+ // src/format/company-intro.ts
458
+ var NAMED_ENTITIES = {
459
+ amp: "&",
460
+ lt: "<",
461
+ gt: ">",
462
+ quot: '"',
463
+ apos: "'",
464
+ nbsp: " "
465
+ };
466
+ function decodeEntities(input) {
467
+ return input.replace(/&(#\d+|#x[0-9a-f]+|[a-z]+);/gi, (match, body) => {
468
+ const token = String(body);
469
+ if (token[0] === "#") {
470
+ const code = token[1] === "x" || token[1] === "X" ? parseInt(token.slice(2), 16) : parseInt(token.slice(1), 10);
471
+ if (!Number.isInteger(code) || code < 0 || code > 1114111) return match;
472
+ return String.fromCodePoint(code);
473
+ }
474
+ return NAMED_ENTITIES[token.toLowerCase()] ?? match;
475
+ });
476
+ }
477
+ function companyIntro(summary, description) {
478
+ const trimmedSummary = summary?.trim();
479
+ if (trimmedSummary) return trimmedSummary;
480
+ if (!description) return null;
481
+ const text = decodeEntities(
482
+ description.replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<br\s*\/?>/gi, " ").replace(/<\/(p|div|li|h[1-6])>/gi, " ").replace(/<[^>]*>/g, "")
483
+ ).replace(/\s+/g, " ").trim();
484
+ if (!text) return null;
485
+ const [first] = text.split(/(?<=[.!?])\s+/);
486
+ return first ?? text;
487
+ }
488
+
489
+ // src/format/custom-fields.ts
490
+ function renderTextValue(def, raw) {
491
+ switch (def.type) {
492
+ case "number":
493
+ return typeof raw === "number" ? String(raw) : null;
494
+ case "single_select": {
495
+ if (typeof raw !== "string") return null;
496
+ return def.options?.find((o) => o.key === raw)?.label ?? null;
497
+ }
498
+ case "multi_select": {
499
+ if (!Array.isArray(raw) || raw.length === 0) return null;
500
+ const labels = raw.map((key) => def.options?.find((o) => o.key === key)?.label).filter((label) => Boolean(label));
501
+ return labels.length > 0 ? labels.join(", ") : null;
502
+ }
503
+ default:
504
+ return typeof raw === "string" && raw.trim() !== "" ? raw : null;
505
+ }
506
+ }
507
+ function resolveCustomFieldDisplay(definitions, values) {
508
+ const entries = [];
509
+ for (const def of definitions ?? []) {
510
+ const raw = values?.[def.key];
511
+ if (def.type === "boolean") {
512
+ if (typeof raw === "boolean") {
513
+ entries.push({
514
+ key: def.key,
515
+ label: def.label,
516
+ kind: "boolean",
517
+ value: raw
518
+ });
519
+ }
520
+ continue;
521
+ }
522
+ const value = renderTextValue(def, raw);
523
+ if (value !== null) {
524
+ entries.push({ key: def.key, label: def.label, kind: "text", value });
525
+ }
526
+ }
527
+ return entries;
528
+ }
package/dist/format.mjs CHANGED
@@ -417,8 +417,82 @@ function formatSalaryRange(language, min, max, timeframe, currency = null, timef
417
417
  timeframeLabel
418
418
  );
419
419
  }
420
+
421
+ // src/format/company-intro.ts
422
+ var NAMED_ENTITIES = {
423
+ amp: "&",
424
+ lt: "<",
425
+ gt: ">",
426
+ quot: '"',
427
+ apos: "'",
428
+ nbsp: " "
429
+ };
430
+ function decodeEntities(input) {
431
+ return input.replace(/&(#\d+|#x[0-9a-f]+|[a-z]+);/gi, (match, body) => {
432
+ const token = String(body);
433
+ if (token[0] === "#") {
434
+ const code = token[1] === "x" || token[1] === "X" ? parseInt(token.slice(2), 16) : parseInt(token.slice(1), 10);
435
+ if (!Number.isInteger(code) || code < 0 || code > 1114111) return match;
436
+ return String.fromCodePoint(code);
437
+ }
438
+ return NAMED_ENTITIES[token.toLowerCase()] ?? match;
439
+ });
440
+ }
441
+ function companyIntro(summary, description) {
442
+ const trimmedSummary = summary?.trim();
443
+ if (trimmedSummary) return trimmedSummary;
444
+ if (!description) return null;
445
+ const text = decodeEntities(
446
+ description.replace(/<script[\s\S]*?<\/script>/gi, " ").replace(/<style[\s\S]*?<\/style>/gi, " ").replace(/<br\s*\/?>/gi, " ").replace(/<\/(p|div|li|h[1-6])>/gi, " ").replace(/<[^>]*>/g, "")
447
+ ).replace(/\s+/g, " ").trim();
448
+ if (!text) return null;
449
+ const [first] = text.split(/(?<=[.!?])\s+/);
450
+ return first ?? text;
451
+ }
452
+
453
+ // src/format/custom-fields.ts
454
+ function renderTextValue(def, raw) {
455
+ switch (def.type) {
456
+ case "number":
457
+ return typeof raw === "number" ? String(raw) : null;
458
+ case "single_select": {
459
+ if (typeof raw !== "string") return null;
460
+ return def.options?.find((o) => o.key === raw)?.label ?? null;
461
+ }
462
+ case "multi_select": {
463
+ if (!Array.isArray(raw) || raw.length === 0) return null;
464
+ const labels = raw.map((key) => def.options?.find((o) => o.key === key)?.label).filter((label) => Boolean(label));
465
+ return labels.length > 0 ? labels.join(", ") : null;
466
+ }
467
+ default:
468
+ return typeof raw === "string" && raw.trim() !== "" ? raw : null;
469
+ }
470
+ }
471
+ function resolveCustomFieldDisplay(definitions, values) {
472
+ const entries = [];
473
+ for (const def of definitions ?? []) {
474
+ const raw = values?.[def.key];
475
+ if (def.type === "boolean") {
476
+ if (typeof raw === "boolean") {
477
+ entries.push({
478
+ key: def.key,
479
+ label: def.label,
480
+ kind: "boolean",
481
+ value: raw
482
+ });
483
+ }
484
+ continue;
485
+ }
486
+ const value = renderTextValue(def, raw);
487
+ if (value !== null) {
488
+ entries.push({ key: def.key, label: def.label, kind: "text", value });
489
+ }
490
+ }
491
+ return entries;
492
+ }
420
493
  export {
421
494
  cardLocationLabel,
495
+ companyIntro,
422
496
  fieldLabel,
423
497
  formatDate,
424
498
  formatMonthYear,
@@ -426,5 +500,6 @@ export {
426
500
  formatSalaryRange,
427
501
  fullJobToCard,
428
502
  getSalaryLexicon,
429
- locationLabel
503
+ locationLabel,
504
+ resolveCustomFieldDisplay
430
505
  };
package/dist/index.d.mts CHANGED
@@ -1,7 +1,8 @@
1
- import { b as Schemas, R as RemoteOption, E as EmploymentType, S as Seniority, L as ListEnvelope, c as components, d as JobsListQuery, e as JobCardListEnvelope, f as JobsSearchBody, g as JobCardSearchEnvelope, h as JobsSimilarQuery, i as SearchEnvelope } from './jobs-DK5mPBgq.mjs';
2
- export { C as CustomFieldValue, j as CustomFieldValues, k as EducationRequirement, l as JobCompany, J as JobSort, O as OfficeLocation, P as PublicJob, a as PublicJobCard, m as RelatedSearch, n as RemotePermit, o as RemoteTimezone, p as StorefrontPagination } from './jobs-DK5mPBgq.mjs';
3
- import { c as CompaniesListQuery, d as CompanyListEnvelope, e as CompaniesSearchBody, f as CompanyJobsListQuery, g as CompanySimilarQuery, h as CompanyMarketsListQuery, i as SalaryDetailQuery, j as BlogPostsListQuery, k as BlogSimilarQuery, l as BlogSearchBody } from './salaries-CrJsaZe6.mjs';
4
- export { B as BlogAuthorEmbed, m as BlogTagEmbed, C as CompanyCategorySalary, n as CompanyMarket, o as CompanyMarketRef, b as CompanySalary, p as CustomFieldDefinition, q as CustomFieldOption, r as CustomFieldType, L as LocationSalaryDetail, s as LocationSkillsIndex, t as LocationTitlesIndex, u as PublicBlogAdjacentPosts, v as PublicBlogAuthor, w as PublicBlogPost, a as PublicBlogPostSummary, x as PublicBlogTag, P as PublicBoard, y as PublicBoardAnalytics, z as PublicBoardFeatures, A as PublicBoardTheme, D as PublicCompany, E as PublicCompanyDetail, F as SalaryCompany, G as SalaryLocation, H as SalarySkill, I as SalaryTitle, J as SkillLocationSalary, K as SkillLocationsIndex, S as SkillSalaryDetail, M as TitleLocationSalary, N as TitleLocationsIndex, T as TitleSalaryDetail } from './salaries-CrJsaZe6.mjs';
1
+ import { b as Schemas, R as RemoteOption, E as EmploymentType, S as Seniority, L as ListEnvelope, c as components, d as JobsListQuery, e as JobCardListEnvelope, f as JobsSearchBody, g as JobCardSearchEnvelope, h as JobsSimilarQuery, i as SearchEnvelope } from './jobs-Dmz8uexp.mjs';
2
+ export { j as CustomFieldValue, C as CustomFieldValues, k as EducationRequirement, l as JobCompany, J as JobSort, O as OfficeLocation, P as PublicJob, a as PublicJobCard, m as RelatedSearch, n as RemotePermit, o as RemoteTimezone, p as StorefrontPagination } from './jobs-Dmz8uexp.mjs';
3
+ export { C as CustomFieldDefinition, a as CustomFieldOption, b as CustomFieldType, P as PublicBoard, c as PublicBoardAnalytics, d as PublicBoardFeatures, e as PublicBoardTheme } from './board-BS8Ax7hz.mjs';
4
+ import { b as CompaniesListQuery, c as CompanyListEnvelope, d as CompaniesSearchBody, e as CompanyJobsListQuery, f as CompanySimilarQuery, g as CompanyMarketsListQuery, h as SalaryDetailQuery, i as BlogPostsListQuery, j as BlogSimilarQuery, k as BlogSearchBody } from './salaries-QXFAyysR.mjs';
5
+ export { B as BlogAuthorEmbed, l as BlogTagEmbed, C as CompanyCategorySalary, m as CompanyMarket, n as CompanyMarketRef, a as CompanySalary, L as LocationSalaryDetail, o as LocationSkillsIndex, p as LocationTitlesIndex, q as PublicBlogAdjacentPosts, r as PublicBlogAuthor, s as PublicBlogPost, P as PublicBlogPostSummary, t as PublicBlogTag, u as PublicCompany, v as PublicCompanyDetail, w as SalaryCompany, x as SalaryLocation, y as SalarySkill, z as SalaryTitle, A as SkillLocationSalary, D as SkillLocationsIndex, S as SkillSalaryDetail, E as TitleLocationSalary, F as TitleLocationsIndex, T as TitleSalaryDetail } from './salaries-QXFAyysR.mjs';
5
6
 
6
7
  type Awaitable<T> = T | Promise<T>;
7
8
  /**
@@ -203,7 +204,7 @@ declare function paginate<Q extends Record<string, unknown>, P extends PageShape
203
204
  * constant because the package is platform-neutral and cannot read
204
205
  * package.json at runtime.
205
206
  */
206
- declare const SDK_VERSION = "1.29.0";
207
+ declare const SDK_VERSION = "1.31.0-preview.0";
207
208
 
208
209
  type SavedJob = Schemas['SavedJob'];
209
210
  type SavedJobsListQuery = {
@@ -382,6 +383,47 @@ declare function isColdRule(messages: Message[], counterpartyId: string): boolea
382
383
  /** The id of the viewer's most recent message (the only one that shows "Seen"). */
383
384
  declare function lastOwnMessageId(messages: Message[], counterpartyId: string): string | null;
384
385
 
386
+ /**
387
+ * The apply-decision ladder (ADR-0054) as a pure function — a core-entry
388
+ * derive export like `messaging-derive`, so security/logic fixes ship via
389
+ * the versioned package instead of re-copied registry files. Unit-testable
390
+ * independent of React. Mirrors the hosted board's rule: an external
391
+ * `applicationUrl`, when present, is the apply path for EVERYONE — it is
392
+ * never gated behind auth or verification, so a signed-in-but-unverified
393
+ * candidate is never worse off than an anonymous visitor.
394
+ */
395
+ type ApplyAction = {
396
+ kind: 'external';
397
+ url: string;
398
+ } | {
399
+ kind: 'sign-in';
400
+ } | {
401
+ kind: 'verify-email';
402
+ } | {
403
+ kind: 'native';
404
+ jobSlug: string;
405
+ } | {
406
+ kind: 'applied';
407
+ } | {
408
+ kind: 'none';
409
+ };
410
+ /**
411
+ * A job's `applicationUrl` is operator/submitter-controlled and reaches
412
+ * this component through the public API, so it can carry a dangerous
413
+ * scheme (`javascript:`, `data:`, `vbscript:`) that would execute when
414
+ * rendered as an `<a href>`. Only http(s) and mailto are safe apply
415
+ * targets; anything else is treated as no external URL at all.
416
+ */
417
+ declare function isSafeApplicationUrl(url: string): boolean;
418
+ declare function resolveApplyAction(state: {
419
+ jobSlug: string | null;
420
+ applicationUrl: string | null;
421
+ viewer: {
422
+ emailVerified: boolean;
423
+ } | null;
424
+ applied: boolean;
425
+ }): ApplyAction;
426
+
385
427
  type BoardUser = Schemas['BoardUser'];
386
428
  type BoardAuthSession = Schemas['BoardAuthSession'];
387
429
  type RegisterBody = Schemas['BoardAuthRegisterBody'];
@@ -654,6 +696,7 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
654
696
  logoUrl: string | null;
655
697
  primaryDomain: string | null;
656
698
  showCavunoBranding: boolean;
699
+ sandbox: boolean;
657
700
  features: {
658
701
  jobAlerts: boolean;
659
702
  candidates: boolean;
@@ -2892,4 +2935,4 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
2892
2935
  };
2893
2936
  type BoardSdk = ReturnType<typeof createBoardClient>;
2894
2937
 
2895
- export { ACCESS_TOKEN_KEY, type AccessCheckoutBody, type AccessCheckoutSession, type AccessCheckoutSessionState, type AccessGrant, type AccessPortalBody, type AccessPortalSession, type AddApplicantNoteBody, type Alert, type AlertBody, type Application, type ApplicationsListQuery, type ApplyBody, type Awaitable, BOARD_ACCESS_GRANT_KEY, BOARD_API_ERROR_CODES, type Block, type BlockStatus, type BlockUserBody, type BlockedUser, BlogPostsListQuery, BlogSearchBody, BlogSimilarQuery, type BoardAccessGrant, BoardApiError, type BoardApiErrorCode, type BoardAuthSession, BoardClient, type BoardRequest, type BoardSdk, type BoardSeo, type BoardUser, type BulkMoveApplicantsBody, type BulkRejectApplicantsBody, type CandidateAvatar, type CandidateEducation, type CandidateExperience, type CandidateLanguage, type CandidateProfile, type CandidateSkill, type ClaimableCompany, CompaniesListQuery, CompaniesSearchBody, CompanyJobsListQuery, CompanyListEnvelope, CompanyMarketsListQuery, type CompanyMembership, CompanySimilarQuery, type ConfirmWorkEmailBody, type ConsumeMagicLinkBody, type Conversation, type ConversationArchive, type ConversationDetail, type ConversationRef, type ConversationsListQuery, type CreateBoardClientOptions, type CreateCompanyBody, type CreateEducationBody, type CreateEmployerJobBody, type CreateExperienceBody, type CreateJobPostingInput, type CreatePipelineStageBody, type CustomStorage, type EditMessageBody, type EmbedJobsQuery, type EmployerApplicant, type EmployerBillingOption, type EmployerCheckout, type EmployerCheckoutBody, type EmployerCompany, type EmployerCompanySearchQuery, type EmployerJob, type EmployerJobSummary, type EmployerJobsListQuery, type EmployerPipeline, type EmployerPipelineQuery, type EmployerPipelineStage, EmploymentType, type FetchOptions, type FindExistingConversationQuery, type ForgotPasswordBody, type HandleAvailability, type JobAlertConfirmation, type JobAlertDeletePreferenceInput, type JobAlertFiltersInput, type JobAlertFrequency, type JobAlertManageQuery, type JobAlertManageResult, type JobAlertManageState, type JobAlertManageTokenInput, type JobAlertPreference, type JobAlertRemoteOption, type JobAlertResendResult, type JobAlertStoredFilters, type JobAlertSubscribeInput, type JobAlertSubscription, type JobAlertUpdatePreferenceInput, JobCardListEnvelope, JobCardSearchEnvelope, type JobPostingBillingCheck, type JobPostingBillingOptions, type JobPostingBillingVerification, type JobPostingLogoResult, type JobPostingPlan, type JobPostingResult, type JobPostingSubscriptionEntitlements, JobsListQuery, JobsSearchBody, JobsSimilarQuery, type LegalEntity, type LegalPageType, ListEnvelope, type Logger, type LoginBody, type LogoutBody, type Message, type ModerationReport, type MoveApplicantStageBody, type NotificationPreference, type OAuthAuthorizationQuery, type OAuthAuthorizationUrl, type OAuthExchangeBody, type OAuthProvider, type Paginator, type PaywallOffer, type PaywallOfferListEnvelope, type PlacesListQuery, type Plan, type PlanListEnvelope, type PlansListQuery, type PublicLegalPage, type PublicPlace, REFRESH_TOKEN_KEY, type ReadReceipt, type RedirectResolution, type RefreshBody, type RegisterBody, RemoteOption, type ReorderPipelineStagesBody, type ReplyBody, type ReportBody, type RequestMagicLinkBody, type ResetPasswordBody, type Resume, type ResumeUploadOptions, SDK_VERSION, SalaryDetailQuery, type SalesLedPlan, type SalesLedPlanListEnvelope, type SaveJobBody, type SavedJob, type SavedJobsListQuery, SearchEnvelope, type SendWorkEmailBody, Seniority, type StartAboutApplicationBody, type StartConversationBody, type StorageMode, type TalentDirectoryEntry, type TalentDirectoryListEnvelope, type TalentDirectoryQuery, type TalentProfile, type TaxonomyGeo, type TaxonomyResolution, type ThreadMessagesQuery, type UnreadCount, type UnsubscribeBody, type UpdateApplicationFactsBody, type UpdateCandidateProfileBody, type UpdateEducationBody, type UpdateEmployerCompanyBody, type UpdateEmployerJobBody, type UpdateExperienceBody, type UpdateLanguagesBody, type UpdateNotificationPreferenceBody, type UpdatePipelineStageBody, type UpdateSkillsBody, type VerifyEmailBody, createBoardClient, isBoardApiError, isBoardPasswordRequired, isColdRule, isConflict, isForbidden, isNotFound, isOwnMessage, isRateLimited, isUnauthorized, isValidationError, lastOwnMessageId, paginate };
2938
+ export { ACCESS_TOKEN_KEY, type AccessCheckoutBody, type AccessCheckoutSession, type AccessCheckoutSessionState, type AccessGrant, type AccessPortalBody, type AccessPortalSession, type AddApplicantNoteBody, type Alert, type AlertBody, type Application, type ApplicationsListQuery, type ApplyAction, type ApplyBody, type Awaitable, BOARD_ACCESS_GRANT_KEY, BOARD_API_ERROR_CODES, type Block, type BlockStatus, type BlockUserBody, type BlockedUser, BlogPostsListQuery, BlogSearchBody, BlogSimilarQuery, type BoardAccessGrant, BoardApiError, type BoardApiErrorCode, type BoardAuthSession, BoardClient, type BoardRequest, type BoardSdk, type BoardSeo, type BoardUser, type BulkMoveApplicantsBody, type BulkRejectApplicantsBody, type CandidateAvatar, type CandidateEducation, type CandidateExperience, type CandidateLanguage, type CandidateProfile, type CandidateSkill, type ClaimableCompany, CompaniesListQuery, CompaniesSearchBody, CompanyJobsListQuery, CompanyListEnvelope, CompanyMarketsListQuery, type CompanyMembership, CompanySimilarQuery, type ConfirmWorkEmailBody, type ConsumeMagicLinkBody, type Conversation, type ConversationArchive, type ConversationDetail, type ConversationRef, type ConversationsListQuery, type CreateBoardClientOptions, type CreateCompanyBody, type CreateEducationBody, type CreateEmployerJobBody, type CreateExperienceBody, type CreateJobPostingInput, type CreatePipelineStageBody, type CustomStorage, type EditMessageBody, type EmbedJobsQuery, type EmployerApplicant, type EmployerBillingOption, type EmployerCheckout, type EmployerCheckoutBody, type EmployerCompany, type EmployerCompanySearchQuery, type EmployerJob, type EmployerJobSummary, type EmployerJobsListQuery, type EmployerPipeline, type EmployerPipelineQuery, type EmployerPipelineStage, EmploymentType, type FetchOptions, type FindExistingConversationQuery, type ForgotPasswordBody, type HandleAvailability, type JobAlertConfirmation, type JobAlertDeletePreferenceInput, type JobAlertFiltersInput, type JobAlertFrequency, type JobAlertManageQuery, type JobAlertManageResult, type JobAlertManageState, type JobAlertManageTokenInput, type JobAlertPreference, type JobAlertRemoteOption, type JobAlertResendResult, type JobAlertStoredFilters, type JobAlertSubscribeInput, type JobAlertSubscription, type JobAlertUpdatePreferenceInput, JobCardListEnvelope, JobCardSearchEnvelope, type JobPostingBillingCheck, type JobPostingBillingOptions, type JobPostingBillingVerification, type JobPostingLogoResult, type JobPostingPlan, type JobPostingResult, type JobPostingSubscriptionEntitlements, JobsListQuery, JobsSearchBody, JobsSimilarQuery, type LegalEntity, type LegalPageType, ListEnvelope, type Logger, type LoginBody, type LogoutBody, type Message, type ModerationReport, type MoveApplicantStageBody, type NotificationPreference, type OAuthAuthorizationQuery, type OAuthAuthorizationUrl, type OAuthExchangeBody, type OAuthProvider, type Paginator, type PaywallOffer, type PaywallOfferListEnvelope, type PlacesListQuery, type Plan, type PlanListEnvelope, type PlansListQuery, type PublicLegalPage, type PublicPlace, REFRESH_TOKEN_KEY, type ReadReceipt, type RedirectResolution, type RefreshBody, type RegisterBody, RemoteOption, type ReorderPipelineStagesBody, type ReplyBody, type ReportBody, type RequestMagicLinkBody, type ResetPasswordBody, type Resume, type ResumeUploadOptions, SDK_VERSION, SalaryDetailQuery, type SalesLedPlan, type SalesLedPlanListEnvelope, type SaveJobBody, type SavedJob, type SavedJobsListQuery, SearchEnvelope, type SendWorkEmailBody, Seniority, type StartAboutApplicationBody, type StartConversationBody, type StorageMode, type TalentDirectoryEntry, type TalentDirectoryListEnvelope, type TalentDirectoryQuery, type TalentProfile, type TaxonomyGeo, type TaxonomyResolution, type ThreadMessagesQuery, type UnreadCount, type UnsubscribeBody, type UpdateApplicationFactsBody, type UpdateCandidateProfileBody, type UpdateEducationBody, type UpdateEmployerCompanyBody, type UpdateEmployerJobBody, type UpdateExperienceBody, type UpdateLanguagesBody, type UpdateNotificationPreferenceBody, type UpdatePipelineStageBody, type UpdateSkillsBody, type VerifyEmailBody, createBoardClient, isBoardApiError, isBoardPasswordRequired, isColdRule, isConflict, isForbidden, isNotFound, isOwnMessage, isRateLimited, isSafeApplicationUrl, isUnauthorized, isValidationError, lastOwnMessageId, paginate, resolveApplyAction };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { b as Schemas, R as RemoteOption, E as EmploymentType, S as Seniority, L as ListEnvelope, c as components, d as JobsListQuery, e as JobCardListEnvelope, f as JobsSearchBody, g as JobCardSearchEnvelope, h as JobsSimilarQuery, i as SearchEnvelope } from './jobs-DK5mPBgq.js';
2
- export { C as CustomFieldValue, j as CustomFieldValues, k as EducationRequirement, l as JobCompany, J as JobSort, O as OfficeLocation, P as PublicJob, a as PublicJobCard, m as RelatedSearch, n as RemotePermit, o as RemoteTimezone, p as StorefrontPagination } from './jobs-DK5mPBgq.js';
3
- import { c as CompaniesListQuery, d as CompanyListEnvelope, e as CompaniesSearchBody, f as CompanyJobsListQuery, g as CompanySimilarQuery, h as CompanyMarketsListQuery, i as SalaryDetailQuery, j as BlogPostsListQuery, k as BlogSimilarQuery, l as BlogSearchBody } from './salaries-CXt6Vkrp.js';
4
- export { B as BlogAuthorEmbed, m as BlogTagEmbed, C as CompanyCategorySalary, n as CompanyMarket, o as CompanyMarketRef, b as CompanySalary, p as CustomFieldDefinition, q as CustomFieldOption, r as CustomFieldType, L as LocationSalaryDetail, s as LocationSkillsIndex, t as LocationTitlesIndex, u as PublicBlogAdjacentPosts, v as PublicBlogAuthor, w as PublicBlogPost, a as PublicBlogPostSummary, x as PublicBlogTag, P as PublicBoard, y as PublicBoardAnalytics, z as PublicBoardFeatures, A as PublicBoardTheme, D as PublicCompany, E as PublicCompanyDetail, F as SalaryCompany, G as SalaryLocation, H as SalarySkill, I as SalaryTitle, J as SkillLocationSalary, K as SkillLocationsIndex, S as SkillSalaryDetail, M as TitleLocationSalary, N as TitleLocationsIndex, T as TitleSalaryDetail } from './salaries-CXt6Vkrp.js';
1
+ import { b as Schemas, R as RemoteOption, E as EmploymentType, S as Seniority, L as ListEnvelope, c as components, d as JobsListQuery, e as JobCardListEnvelope, f as JobsSearchBody, g as JobCardSearchEnvelope, h as JobsSimilarQuery, i as SearchEnvelope } from './jobs-Dmz8uexp.js';
2
+ export { j as CustomFieldValue, C as CustomFieldValues, k as EducationRequirement, l as JobCompany, J as JobSort, O as OfficeLocation, P as PublicJob, a as PublicJobCard, m as RelatedSearch, n as RemotePermit, o as RemoteTimezone, p as StorefrontPagination } from './jobs-Dmz8uexp.js';
3
+ export { C as CustomFieldDefinition, a as CustomFieldOption, b as CustomFieldType, P as PublicBoard, c as PublicBoardAnalytics, d as PublicBoardFeatures, e as PublicBoardTheme } from './board--nLjpneU.js';
4
+ import { b as CompaniesListQuery, c as CompanyListEnvelope, d as CompaniesSearchBody, e as CompanyJobsListQuery, f as CompanySimilarQuery, g as CompanyMarketsListQuery, h as SalaryDetailQuery, i as BlogPostsListQuery, j as BlogSimilarQuery, k as BlogSearchBody } from './salaries-CrtQBy81.js';
5
+ export { B as BlogAuthorEmbed, l as BlogTagEmbed, C as CompanyCategorySalary, m as CompanyMarket, n as CompanyMarketRef, a as CompanySalary, L as LocationSalaryDetail, o as LocationSkillsIndex, p as LocationTitlesIndex, q as PublicBlogAdjacentPosts, r as PublicBlogAuthor, s as PublicBlogPost, P as PublicBlogPostSummary, t as PublicBlogTag, u as PublicCompany, v as PublicCompanyDetail, w as SalaryCompany, x as SalaryLocation, y as SalarySkill, z as SalaryTitle, A as SkillLocationSalary, D as SkillLocationsIndex, S as SkillSalaryDetail, E as TitleLocationSalary, F as TitleLocationsIndex, T as TitleSalaryDetail } from './salaries-CrtQBy81.js';
5
6
 
6
7
  type Awaitable<T> = T | Promise<T>;
7
8
  /**
@@ -203,7 +204,7 @@ declare function paginate<Q extends Record<string, unknown>, P extends PageShape
203
204
  * constant because the package is platform-neutral and cannot read
204
205
  * package.json at runtime.
205
206
  */
206
- declare const SDK_VERSION = "1.29.0";
207
+ declare const SDK_VERSION = "1.31.0-preview.0";
207
208
 
208
209
  type SavedJob = Schemas['SavedJob'];
209
210
  type SavedJobsListQuery = {
@@ -382,6 +383,47 @@ declare function isColdRule(messages: Message[], counterpartyId: string): boolea
382
383
  /** The id of the viewer's most recent message (the only one that shows "Seen"). */
383
384
  declare function lastOwnMessageId(messages: Message[], counterpartyId: string): string | null;
384
385
 
386
+ /**
387
+ * The apply-decision ladder (ADR-0054) as a pure function — a core-entry
388
+ * derive export like `messaging-derive`, so security/logic fixes ship via
389
+ * the versioned package instead of re-copied registry files. Unit-testable
390
+ * independent of React. Mirrors the hosted board's rule: an external
391
+ * `applicationUrl`, when present, is the apply path for EVERYONE — it is
392
+ * never gated behind auth or verification, so a signed-in-but-unverified
393
+ * candidate is never worse off than an anonymous visitor.
394
+ */
395
+ type ApplyAction = {
396
+ kind: 'external';
397
+ url: string;
398
+ } | {
399
+ kind: 'sign-in';
400
+ } | {
401
+ kind: 'verify-email';
402
+ } | {
403
+ kind: 'native';
404
+ jobSlug: string;
405
+ } | {
406
+ kind: 'applied';
407
+ } | {
408
+ kind: 'none';
409
+ };
410
+ /**
411
+ * A job's `applicationUrl` is operator/submitter-controlled and reaches
412
+ * this component through the public API, so it can carry a dangerous
413
+ * scheme (`javascript:`, `data:`, `vbscript:`) that would execute when
414
+ * rendered as an `<a href>`. Only http(s) and mailto are safe apply
415
+ * targets; anything else is treated as no external URL at all.
416
+ */
417
+ declare function isSafeApplicationUrl(url: string): boolean;
418
+ declare function resolveApplyAction(state: {
419
+ jobSlug: string | null;
420
+ applicationUrl: string | null;
421
+ viewer: {
422
+ emailVerified: boolean;
423
+ } | null;
424
+ applied: boolean;
425
+ }): ApplyAction;
426
+
385
427
  type BoardUser = Schemas['BoardUser'];
386
428
  type BoardAuthSession = Schemas['BoardAuthSession'];
387
429
  type RegisterBody = Schemas['BoardAuthRegisterBody'];
@@ -654,6 +696,7 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
654
696
  logoUrl: string | null;
655
697
  primaryDomain: string | null;
656
698
  showCavunoBranding: boolean;
699
+ sandbox: boolean;
657
700
  features: {
658
701
  jobAlerts: boolean;
659
702
  candidates: boolean;
@@ -2892,4 +2935,4 @@ declare function createBoardClient(options: CreateBoardClientOptions): {
2892
2935
  };
2893
2936
  type BoardSdk = ReturnType<typeof createBoardClient>;
2894
2937
 
2895
- export { ACCESS_TOKEN_KEY, type AccessCheckoutBody, type AccessCheckoutSession, type AccessCheckoutSessionState, type AccessGrant, type AccessPortalBody, type AccessPortalSession, type AddApplicantNoteBody, type Alert, type AlertBody, type Application, type ApplicationsListQuery, type ApplyBody, type Awaitable, BOARD_ACCESS_GRANT_KEY, BOARD_API_ERROR_CODES, type Block, type BlockStatus, type BlockUserBody, type BlockedUser, BlogPostsListQuery, BlogSearchBody, BlogSimilarQuery, type BoardAccessGrant, BoardApiError, type BoardApiErrorCode, type BoardAuthSession, BoardClient, type BoardRequest, type BoardSdk, type BoardSeo, type BoardUser, type BulkMoveApplicantsBody, type BulkRejectApplicantsBody, type CandidateAvatar, type CandidateEducation, type CandidateExperience, type CandidateLanguage, type CandidateProfile, type CandidateSkill, type ClaimableCompany, CompaniesListQuery, CompaniesSearchBody, CompanyJobsListQuery, CompanyListEnvelope, CompanyMarketsListQuery, type CompanyMembership, CompanySimilarQuery, type ConfirmWorkEmailBody, type ConsumeMagicLinkBody, type Conversation, type ConversationArchive, type ConversationDetail, type ConversationRef, type ConversationsListQuery, type CreateBoardClientOptions, type CreateCompanyBody, type CreateEducationBody, type CreateEmployerJobBody, type CreateExperienceBody, type CreateJobPostingInput, type CreatePipelineStageBody, type CustomStorage, type EditMessageBody, type EmbedJobsQuery, type EmployerApplicant, type EmployerBillingOption, type EmployerCheckout, type EmployerCheckoutBody, type EmployerCompany, type EmployerCompanySearchQuery, type EmployerJob, type EmployerJobSummary, type EmployerJobsListQuery, type EmployerPipeline, type EmployerPipelineQuery, type EmployerPipelineStage, EmploymentType, type FetchOptions, type FindExistingConversationQuery, type ForgotPasswordBody, type HandleAvailability, type JobAlertConfirmation, type JobAlertDeletePreferenceInput, type JobAlertFiltersInput, type JobAlertFrequency, type JobAlertManageQuery, type JobAlertManageResult, type JobAlertManageState, type JobAlertManageTokenInput, type JobAlertPreference, type JobAlertRemoteOption, type JobAlertResendResult, type JobAlertStoredFilters, type JobAlertSubscribeInput, type JobAlertSubscription, type JobAlertUpdatePreferenceInput, JobCardListEnvelope, JobCardSearchEnvelope, type JobPostingBillingCheck, type JobPostingBillingOptions, type JobPostingBillingVerification, type JobPostingLogoResult, type JobPostingPlan, type JobPostingResult, type JobPostingSubscriptionEntitlements, JobsListQuery, JobsSearchBody, JobsSimilarQuery, type LegalEntity, type LegalPageType, ListEnvelope, type Logger, type LoginBody, type LogoutBody, type Message, type ModerationReport, type MoveApplicantStageBody, type NotificationPreference, type OAuthAuthorizationQuery, type OAuthAuthorizationUrl, type OAuthExchangeBody, type OAuthProvider, type Paginator, type PaywallOffer, type PaywallOfferListEnvelope, type PlacesListQuery, type Plan, type PlanListEnvelope, type PlansListQuery, type PublicLegalPage, type PublicPlace, REFRESH_TOKEN_KEY, type ReadReceipt, type RedirectResolution, type RefreshBody, type RegisterBody, RemoteOption, type ReorderPipelineStagesBody, type ReplyBody, type ReportBody, type RequestMagicLinkBody, type ResetPasswordBody, type Resume, type ResumeUploadOptions, SDK_VERSION, SalaryDetailQuery, type SalesLedPlan, type SalesLedPlanListEnvelope, type SaveJobBody, type SavedJob, type SavedJobsListQuery, SearchEnvelope, type SendWorkEmailBody, Seniority, type StartAboutApplicationBody, type StartConversationBody, type StorageMode, type TalentDirectoryEntry, type TalentDirectoryListEnvelope, type TalentDirectoryQuery, type TalentProfile, type TaxonomyGeo, type TaxonomyResolution, type ThreadMessagesQuery, type UnreadCount, type UnsubscribeBody, type UpdateApplicationFactsBody, type UpdateCandidateProfileBody, type UpdateEducationBody, type UpdateEmployerCompanyBody, type UpdateEmployerJobBody, type UpdateExperienceBody, type UpdateLanguagesBody, type UpdateNotificationPreferenceBody, type UpdatePipelineStageBody, type UpdateSkillsBody, type VerifyEmailBody, createBoardClient, isBoardApiError, isBoardPasswordRequired, isColdRule, isConflict, isForbidden, isNotFound, isOwnMessage, isRateLimited, isUnauthorized, isValidationError, lastOwnMessageId, paginate };
2938
+ export { ACCESS_TOKEN_KEY, type AccessCheckoutBody, type AccessCheckoutSession, type AccessCheckoutSessionState, type AccessGrant, type AccessPortalBody, type AccessPortalSession, type AddApplicantNoteBody, type Alert, type AlertBody, type Application, type ApplicationsListQuery, type ApplyAction, type ApplyBody, type Awaitable, BOARD_ACCESS_GRANT_KEY, BOARD_API_ERROR_CODES, type Block, type BlockStatus, type BlockUserBody, type BlockedUser, BlogPostsListQuery, BlogSearchBody, BlogSimilarQuery, type BoardAccessGrant, BoardApiError, type BoardApiErrorCode, type BoardAuthSession, BoardClient, type BoardRequest, type BoardSdk, type BoardSeo, type BoardUser, type BulkMoveApplicantsBody, type BulkRejectApplicantsBody, type CandidateAvatar, type CandidateEducation, type CandidateExperience, type CandidateLanguage, type CandidateProfile, type CandidateSkill, type ClaimableCompany, CompaniesListQuery, CompaniesSearchBody, CompanyJobsListQuery, CompanyListEnvelope, CompanyMarketsListQuery, type CompanyMembership, CompanySimilarQuery, type ConfirmWorkEmailBody, type ConsumeMagicLinkBody, type Conversation, type ConversationArchive, type ConversationDetail, type ConversationRef, type ConversationsListQuery, type CreateBoardClientOptions, type CreateCompanyBody, type CreateEducationBody, type CreateEmployerJobBody, type CreateExperienceBody, type CreateJobPostingInput, type CreatePipelineStageBody, type CustomStorage, type EditMessageBody, type EmbedJobsQuery, type EmployerApplicant, type EmployerBillingOption, type EmployerCheckout, type EmployerCheckoutBody, type EmployerCompany, type EmployerCompanySearchQuery, type EmployerJob, type EmployerJobSummary, type EmployerJobsListQuery, type EmployerPipeline, type EmployerPipelineQuery, type EmployerPipelineStage, EmploymentType, type FetchOptions, type FindExistingConversationQuery, type ForgotPasswordBody, type HandleAvailability, type JobAlertConfirmation, type JobAlertDeletePreferenceInput, type JobAlertFiltersInput, type JobAlertFrequency, type JobAlertManageQuery, type JobAlertManageResult, type JobAlertManageState, type JobAlertManageTokenInput, type JobAlertPreference, type JobAlertRemoteOption, type JobAlertResendResult, type JobAlertStoredFilters, type JobAlertSubscribeInput, type JobAlertSubscription, type JobAlertUpdatePreferenceInput, JobCardListEnvelope, JobCardSearchEnvelope, type JobPostingBillingCheck, type JobPostingBillingOptions, type JobPostingBillingVerification, type JobPostingLogoResult, type JobPostingPlan, type JobPostingResult, type JobPostingSubscriptionEntitlements, JobsListQuery, JobsSearchBody, JobsSimilarQuery, type LegalEntity, type LegalPageType, ListEnvelope, type Logger, type LoginBody, type LogoutBody, type Message, type ModerationReport, type MoveApplicantStageBody, type NotificationPreference, type OAuthAuthorizationQuery, type OAuthAuthorizationUrl, type OAuthExchangeBody, type OAuthProvider, type Paginator, type PaywallOffer, type PaywallOfferListEnvelope, type PlacesListQuery, type Plan, type PlanListEnvelope, type PlansListQuery, type PublicLegalPage, type PublicPlace, REFRESH_TOKEN_KEY, type ReadReceipt, type RedirectResolution, type RefreshBody, type RegisterBody, RemoteOption, type ReorderPipelineStagesBody, type ReplyBody, type ReportBody, type RequestMagicLinkBody, type ResetPasswordBody, type Resume, type ResumeUploadOptions, SDK_VERSION, SalaryDetailQuery, type SalesLedPlan, type SalesLedPlanListEnvelope, type SaveJobBody, type SavedJob, type SavedJobsListQuery, SearchEnvelope, type SendWorkEmailBody, Seniority, type StartAboutApplicationBody, type StartConversationBody, type StorageMode, type TalentDirectoryEntry, type TalentDirectoryListEnvelope, type TalentDirectoryQuery, type TalentProfile, type TaxonomyGeo, type TaxonomyResolution, type ThreadMessagesQuery, type UnreadCount, type UnsubscribeBody, type UpdateApplicationFactsBody, type UpdateCandidateProfileBody, type UpdateEducationBody, type UpdateEmployerCompanyBody, type UpdateEmployerJobBody, type UpdateExperienceBody, type UpdateLanguagesBody, type UpdateNotificationPreferenceBody, type UpdatePipelineStageBody, type UpdateSkillsBody, type VerifyEmailBody, createBoardClient, isBoardApiError, isBoardPasswordRequired, isColdRule, isConflict, isForbidden, isNotFound, isOwnMessage, isRateLimited, isSafeApplicationUrl, isUnauthorized, isValidationError, lastOwnMessageId, paginate, resolveApplyAction };
package/dist/index.js CHANGED
@@ -36,10 +36,12 @@ __export(src_exports, {
36
36
  isNotFound: () => isNotFound,
37
37
  isOwnMessage: () => isOwnMessage,
38
38
  isRateLimited: () => isRateLimited,
39
+ isSafeApplicationUrl: () => isSafeApplicationUrl,
39
40
  isUnauthorized: () => isUnauthorized,
40
41
  isValidationError: () => isValidationError,
41
42
  lastOwnMessageId: () => lastOwnMessageId,
42
- paginate: () => paginate
43
+ paginate: () => paginate,
44
+ resolveApplyAction: () => resolveApplyAction
43
45
  });
44
46
  module.exports = __toCommonJS(src_exports);
45
47
 
@@ -310,7 +312,7 @@ async function clearSession(storage) {
310
312
  }
311
313
 
312
314
  // src/version.ts
313
- var SDK_VERSION = "1.29.0";
315
+ var SDK_VERSION = "1.31.0-preview.0";
314
316
 
315
317
  // src/client.ts
316
318
  function isRawBody(body) {
@@ -2610,6 +2612,24 @@ function lastOwnMessageId(messages, counterpartyId) {
2610
2612
  return null;
2611
2613
  }
2612
2614
 
2615
+ // src/apply-derive.ts
2616
+ function isSafeApplicationUrl(url) {
2617
+ const cleaned = url.replace(/^[\u0000-\u0020]+|[\u0000-\u0020]+$/g, "").replace(/[\t\n\r]/g, "");
2618
+ const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(cleaned)?.[1]?.toLowerCase();
2619
+ if (scheme === void 0) return true;
2620
+ return scheme === "http" || scheme === "https" || scheme === "mailto";
2621
+ }
2622
+ function resolveApplyAction(state) {
2623
+ if (state.applicationUrl && isSafeApplicationUrl(state.applicationUrl)) {
2624
+ return { kind: "external", url: state.applicationUrl };
2625
+ }
2626
+ if (!state.jobSlug) return { kind: "none" };
2627
+ if (!state.viewer) return { kind: "sign-in" };
2628
+ if (!state.viewer.emailVerified) return { kind: "verify-email" };
2629
+ if (state.applied) return { kind: "applied" };
2630
+ return { kind: "native", jobSlug: state.jobSlug };
2631
+ }
2632
+
2613
2633
  // src/index.ts
2614
2634
  function createBoardClient(options) {
2615
2635
  const client = new BoardClient({
package/dist/index.mjs CHANGED
@@ -265,7 +265,7 @@ async function clearSession(storage) {
265
265
  }
266
266
 
267
267
  // src/version.ts
268
- var SDK_VERSION = "1.29.0";
268
+ var SDK_VERSION = "1.31.0-preview.0";
269
269
 
270
270
  // src/client.ts
271
271
  function isRawBody(body) {
@@ -2565,6 +2565,24 @@ function lastOwnMessageId(messages, counterpartyId) {
2565
2565
  return null;
2566
2566
  }
2567
2567
 
2568
+ // src/apply-derive.ts
2569
+ function isSafeApplicationUrl(url) {
2570
+ const cleaned = url.replace(/^[\u0000-\u0020]+|[\u0000-\u0020]+$/g, "").replace(/[\t\n\r]/g, "");
2571
+ const scheme = /^([a-z][a-z0-9+.-]*):/i.exec(cleaned)?.[1]?.toLowerCase();
2572
+ if (scheme === void 0) return true;
2573
+ return scheme === "http" || scheme === "https" || scheme === "mailto";
2574
+ }
2575
+ function resolveApplyAction(state) {
2576
+ if (state.applicationUrl && isSafeApplicationUrl(state.applicationUrl)) {
2577
+ return { kind: "external", url: state.applicationUrl };
2578
+ }
2579
+ if (!state.jobSlug) return { kind: "none" };
2580
+ if (!state.viewer) return { kind: "sign-in" };
2581
+ if (!state.viewer.emailVerified) return { kind: "verify-email" };
2582
+ if (state.applied) return { kind: "applied" };
2583
+ return { kind: "native", jobSlug: state.jobSlug };
2584
+ }
2585
+
2568
2586
  // src/index.ts
2569
2587
  function createBoardClient(options) {
2570
2588
  const client = new BoardClient({
@@ -2638,8 +2656,10 @@ export {
2638
2656
  isNotFound,
2639
2657
  isOwnMessage,
2640
2658
  isRateLimited,
2659
+ isSafeApplicationUrl,
2641
2660
  isUnauthorized,
2642
2661
  isValidationError,
2643
2662
  lastOwnMessageId,
2644
- paginate
2663
+ paginate,
2664
+ resolveApplyAction
2645
2665
  };
@@ -2382,6 +2382,8 @@ interface components {
2382
2382
  primaryDomain: string | null;
2383
2383
  /** @description Whitelabel toggle (default `true`). Render the "Powered by Cavuno" badge unless `false`. */
2384
2384
  showCavunoBranding: boolean;
2385
+ /** @description True ONLY for the platform sandbox fixture tenant — the safe target for write probes (doctor tier 3); data is reset nightly. Every real tenant board is `false`. */
2386
+ sandbox: boolean;
2385
2387
  features: {
2386
2388
  jobAlerts: boolean;
2387
2389
  candidates: boolean;
@@ -3833,4 +3835,4 @@ type JobsSimilarQuery = {
3833
3835
  };
3834
3836
  type JobsSearchBody = Schemas['PublicSearchJobsBody'];
3835
3837
 
3836
- export type { CustomFieldValue as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S, PublicJobCard as a, Schemas as b, components as c, JobsListQuery as d, JobCardListEnvelope as e, JobsSearchBody as f, JobCardSearchEnvelope as g, JobsSimilarQuery as h, SearchEnvelope as i, CustomFieldValues as j, EducationRequirement as k, JobCompany as l, RelatedSearch as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
3838
+ export type { CustomFieldValues as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S, PublicJobCard as a, Schemas as b, components as c, JobsListQuery as d, JobCardListEnvelope as e, JobsSearchBody as f, JobCardSearchEnvelope as g, JobsSimilarQuery as h, SearchEnvelope as i, CustomFieldValue as j, EducationRequirement as k, JobCompany as l, RelatedSearch as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
@@ -2382,6 +2382,8 @@ interface components {
2382
2382
  primaryDomain: string | null;
2383
2383
  /** @description Whitelabel toggle (default `true`). Render the "Powered by Cavuno" badge unless `false`. */
2384
2384
  showCavunoBranding: boolean;
2385
+ /** @description True ONLY for the platform sandbox fixture tenant — the safe target for write probes (doctor tier 3); data is reset nightly. Every real tenant board is `false`. */
2386
+ sandbox: boolean;
2385
2387
  features: {
2386
2388
  jobAlerts: boolean;
2387
2389
  candidates: boolean;
@@ -3833,4 +3835,4 @@ type JobsSimilarQuery = {
3833
3835
  };
3834
3836
  type JobsSearchBody = Schemas['PublicSearchJobsBody'];
3835
3837
 
3836
- export type { CustomFieldValue as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S, PublicJobCard as a, Schemas as b, components as c, JobsListQuery as d, JobCardListEnvelope as e, JobsSearchBody as f, JobCardSearchEnvelope as g, JobsSimilarQuery as h, SearchEnvelope as i, CustomFieldValues as j, EducationRequirement as k, JobCompany as l, RelatedSearch as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
3838
+ export type { CustomFieldValues as C, EmploymentType as E, JobSort as J, ListEnvelope as L, OfficeLocation as O, PublicJob as P, RemoteOption as R, Seniority as S, PublicJobCard as a, Schemas as b, components as c, JobsListQuery as d, JobCardListEnvelope as e, JobsSearchBody as f, JobCardSearchEnvelope as g, JobsSimilarQuery as h, SearchEnvelope as i, CustomFieldValue as j, EducationRequirement as k, JobCompany as l, RelatedSearch as m, RemotePermit as n, RemoteTimezone as o, StorefrontPagination as p };
@@ -1,18 +1,4 @@
1
- import { b as Schemas, L as ListEnvelope, m as RelatedSearch } from './jobs-DK5mPBgq.js';
2
-
3
- type PublicBoard = Schemas['PublicBoardContext'];
4
- type PublicBoardFeatures = PublicBoard['features'];
5
- type PublicBoardAnalytics = PublicBoard['analytics'];
6
- type PublicBoardTheme = NonNullable<PublicBoard['theme']>;
7
- /**
8
- * An operator-defined custom job-field definition (CAV-294). Board-wide;
9
- * use it to render and localize a job's opaque `customFieldValues` (resolve
10
- * option `key`s → labels, honour field `type` and display order). Shared with
11
- * the Operator API's custom-field surface (one canonical schema).
12
- */
13
- type CustomFieldDefinition = Schemas['CustomFieldDefinition'];
14
- type CustomFieldType = CustomFieldDefinition['type'];
15
- type CustomFieldOption = Schemas['CustomFieldOption'];
1
+ import { b as Schemas, L as ListEnvelope, m as RelatedSearch } from './jobs-Dmz8uexp.js';
16
2
 
17
3
  /** Author shape embedded on posts (no `object` discriminator). */
18
4
  type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
@@ -127,4 +113,4 @@ type SalaryDetailQuery = {
127
113
  locale?: string;
128
114
  };
129
115
 
130
- export type { PublicBoardTheme as A, BlogAuthorEmbed as B, CompanyCategorySalary as C, PublicCompany as D, PublicCompanyDetail as E, SalaryCompany as F, SalaryLocation as G, SalarySkill as H, SalaryTitle as I, SkillLocationSalary as J, SkillLocationsIndex as K, LocationSalaryDetail as L, TitleLocationSalary as M, TitleLocationsIndex as N, PublicBoard as P, SkillSalaryDetail as S, TitleSalaryDetail as T, PublicBlogPostSummary as a, CompanySalary as b, CompaniesListQuery as c, CompanyListEnvelope as d, CompaniesSearchBody as e, CompanyJobsListQuery as f, CompanySimilarQuery as g, CompanyMarketsListQuery as h, SalaryDetailQuery as i, BlogPostsListQuery as j, BlogSimilarQuery as k, BlogSearchBody as l, BlogTagEmbed as m, CompanyMarket as n, CompanyMarketRef as o, CustomFieldDefinition as p, CustomFieldOption as q, CustomFieldType as r, LocationSkillsIndex as s, LocationTitlesIndex as t, PublicBlogAdjacentPosts as u, PublicBlogAuthor as v, PublicBlogPost as w, PublicBlogTag as x, PublicBoardAnalytics as y, PublicBoardFeatures as z };
116
+ export type { SkillLocationSalary as A, BlogAuthorEmbed as B, CompanyCategorySalary as C, SkillLocationsIndex as D, TitleLocationSalary as E, TitleLocationsIndex as F, LocationSalaryDetail as L, PublicBlogPostSummary as P, SkillSalaryDetail as S, TitleSalaryDetail as T, CompanySalary as a, CompaniesListQuery as b, CompanyListEnvelope as c, CompaniesSearchBody as d, CompanyJobsListQuery as e, CompanySimilarQuery as f, CompanyMarketsListQuery as g, SalaryDetailQuery as h, BlogPostsListQuery as i, BlogSimilarQuery as j, BlogSearchBody as k, BlogTagEmbed as l, CompanyMarket as m, CompanyMarketRef as n, LocationSkillsIndex as o, LocationTitlesIndex as p, PublicBlogAdjacentPosts as q, PublicBlogAuthor as r, PublicBlogPost as s, PublicBlogTag as t, PublicCompany as u, PublicCompanyDetail as v, SalaryCompany as w, SalaryLocation as x, SalarySkill as y, SalaryTitle as z };
@@ -1,18 +1,4 @@
1
- import { b as Schemas, L as ListEnvelope, m as RelatedSearch } from './jobs-DK5mPBgq.mjs';
2
-
3
- type PublicBoard = Schemas['PublicBoardContext'];
4
- type PublicBoardFeatures = PublicBoard['features'];
5
- type PublicBoardAnalytics = PublicBoard['analytics'];
6
- type PublicBoardTheme = NonNullable<PublicBoard['theme']>;
7
- /**
8
- * An operator-defined custom job-field definition (CAV-294). Board-wide;
9
- * use it to render and localize a job's opaque `customFieldValues` (resolve
10
- * option `key`s → labels, honour field `type` and display order). Shared with
11
- * the Operator API's custom-field surface (one canonical schema).
12
- */
13
- type CustomFieldDefinition = Schemas['CustomFieldDefinition'];
14
- type CustomFieldType = CustomFieldDefinition['type'];
15
- type CustomFieldOption = Schemas['CustomFieldOption'];
1
+ import { b as Schemas, L as ListEnvelope, m as RelatedSearch } from './jobs-Dmz8uexp.mjs';
16
2
 
17
3
  /** Author shape embedded on posts (no `object` discriminator). */
18
4
  type BlogAuthorEmbed = Schemas['PublicBlogAuthorEmbed'];
@@ -127,4 +113,4 @@ type SalaryDetailQuery = {
127
113
  locale?: string;
128
114
  };
129
115
 
130
- export type { PublicBoardTheme as A, BlogAuthorEmbed as B, CompanyCategorySalary as C, PublicCompany as D, PublicCompanyDetail as E, SalaryCompany as F, SalaryLocation as G, SalarySkill as H, SalaryTitle as I, SkillLocationSalary as J, SkillLocationsIndex as K, LocationSalaryDetail as L, TitleLocationSalary as M, TitleLocationsIndex as N, PublicBoard as P, SkillSalaryDetail as S, TitleSalaryDetail as T, PublicBlogPostSummary as a, CompanySalary as b, CompaniesListQuery as c, CompanyListEnvelope as d, CompaniesSearchBody as e, CompanyJobsListQuery as f, CompanySimilarQuery as g, CompanyMarketsListQuery as h, SalaryDetailQuery as i, BlogPostsListQuery as j, BlogSimilarQuery as k, BlogSearchBody as l, BlogTagEmbed as m, CompanyMarket as n, CompanyMarketRef as o, CustomFieldDefinition as p, CustomFieldOption as q, CustomFieldType as r, LocationSkillsIndex as s, LocationTitlesIndex as t, PublicBlogAdjacentPosts as u, PublicBlogAuthor as v, PublicBlogPost as w, PublicBlogTag as x, PublicBoardAnalytics as y, PublicBoardFeatures as z };
116
+ export type { SkillLocationSalary as A, BlogAuthorEmbed as B, CompanyCategorySalary as C, SkillLocationsIndex as D, TitleLocationSalary as E, TitleLocationsIndex as F, LocationSalaryDetail as L, PublicBlogPostSummary as P, SkillSalaryDetail as S, TitleSalaryDetail as T, CompanySalary as a, CompaniesListQuery as b, CompanyListEnvelope as c, CompaniesSearchBody as d, CompanyJobsListQuery as e, CompanySimilarQuery as f, CompanyMarketsListQuery as g, SalaryDetailQuery as h, BlogPostsListQuery as i, BlogSimilarQuery as j, BlogSearchBody as k, BlogTagEmbed as l, CompanyMarket as m, CompanyMarketRef as n, LocationSkillsIndex as o, LocationTitlesIndex as p, PublicBlogAdjacentPosts as q, PublicBlogAuthor as r, PublicBlogPost as s, PublicBlogTag as t, PublicCompany as u, PublicCompanyDetail as v, SalaryCompany as w, SalaryLocation as x, SalarySkill as y, SalaryTitle as z };
package/dist/seo.d.mts 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-CrJsaZe6.mjs';
2
- import { P as PublicJob } from './jobs-DK5mPBgq.mjs';
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-QXFAyysR.mjs';
2
+ import { P as PublicBoard } from './board-BS8Ax7hz.mjs';
3
+ import { P as PublicJob } from './jobs-Dmz8uexp.mjs';
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 };