@burdenoff/website-sdk 2026.1027.1 → 2026.1028.1

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/index.mjs CHANGED
@@ -16598,6 +16598,10 @@ function BlogPostPage(props) {
16598
16598
  ] });
16599
16599
  }
16600
16600
  var CASE_STUDY_TAG = "case-study";
16601
+ function hasCustomerSignOff(page) {
16602
+ const signedAt = page.customerSignOff?.signedAt;
16603
+ return typeof signedAt === "string" && !Number.isNaN(new Date(signedAt).getTime());
16604
+ }
16601
16605
  var ANIMATION_STYLES = `
16602
16606
  @keyframes csFadeUp { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }
16603
16607
  @keyframes csFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }
@@ -16627,6 +16631,9 @@ var CASE_STUDIES_QUERY = `
16627
16631
  readingTime
16628
16632
  featured
16629
16633
  category
16634
+ customerSignOff {
16635
+ signedAt
16636
+ }
16630
16637
  }
16631
16638
  total
16632
16639
  hasMore
@@ -16653,6 +16660,9 @@ var CASE_STUDY_QUERY = `
16653
16660
  readingTime
16654
16661
  featured
16655
16662
  category
16663
+ customerSignOff {
16664
+ signedAt
16665
+ }
16656
16666
  }
16657
16667
  }
16658
16668
  `;
@@ -17023,11 +17033,15 @@ function CaseStudiesListPage(props) {
17023
17033
  setPosts([]);
17024
17034
  return;
17025
17035
  }
17026
- const caseStudies = (result.data?.publicContentPages?.items || []).filter(
17027
- (p) => p.tags?.includes(CASE_STUDY_TAG)
17036
+ const items = result.data?.publicContentPages?.items || [];
17037
+ const caseStudies = items.filter(
17038
+ (p) => p.tags?.includes(CASE_STUDY_TAG) && hasCustomerSignOff(p)
17028
17039
  );
17029
17040
  setPosts(caseStudies);
17030
- setTotal(result.data?.publicContentPages?.total || 0);
17041
+ const dropped = items.length - caseStudies.length;
17042
+ setTotal(
17043
+ Math.max(0, (result.data?.publicContentPages?.total || 0) - dropped)
17044
+ );
17031
17045
  setError(null);
17032
17046
  } catch {
17033
17047
  setError("load-failed");
@@ -17209,7 +17223,8 @@ function CaseStudyPage(props) {
17209
17223
  setError(result.errors[0]?.message ?? "Failed to load case study");
17210
17224
  return;
17211
17225
  }
17212
- setPost(result.data?.publicContentPage ?? null);
17226
+ const page = result.data?.publicContentPage ?? null;
17227
+ setPost(page && hasCustomerSignOff(page) ? page : null);
17213
17228
  setError(null);
17214
17229
  } catch {
17215
17230
  setError("Failed to load case study");
@@ -17278,6 +17293,7 @@ function CaseStudyPage(props) {
17278
17293
  ] }) });
17279
17294
  }
17280
17295
  const formattedDate = formatDate(post.publishedAt || post.lastUpdated);
17296
+ const approvedDate = formatDate(post.customerSignOff?.signedAt);
17281
17297
  return /* @__PURE__ */ jsxs("div", { className: `w-full ${className}`, children: [
17282
17298
  /* @__PURE__ */ jsx(ProseStyles, {}),
17283
17299
  /* @__PURE__ */ jsx(
@@ -17315,6 +17331,17 @@ function CaseStudyPage(props) {
17315
17331
  ] })
17316
17332
  ] }) : null
17317
17333
  ] }),
17334
+ approvedDate && /* @__PURE__ */ jsxs(
17335
+ "p",
17336
+ {
17337
+ className: "-mt-4 mb-8 text-xs text-muted-foreground",
17338
+ "data-cs": "customer-signoff",
17339
+ children: [
17340
+ "Approved for publication by the customer on ",
17341
+ approvedDate
17342
+ ]
17343
+ }
17344
+ ),
17318
17345
  post.thumbnail && /* @__PURE__ */ jsx("div", { className: "mb-10 aspect-[16/9] overflow-hidden rounded-xl", children: /* @__PURE__ */ jsx(
17319
17346
  "img",
17320
17347
  {
@@ -20607,6 +20634,112 @@ function shouldRenderSiteFooter(pathname) {
20607
20634
  return !isFooterlessPath(pathname);
20608
20635
  }
20609
20636
 
20610
- export { ANSWERS_PATH, ANSWER_HEADING_SHIFT, ANSWER_PATH_PREFIX, AnswerDetailPage, AnswersPage, BlogListPage, BlogPostPage, Button, CONCEPTS_PATH, CONCEPT_ILLUSTRATION_NOTICE, CONCEPT_PATH_PREFIX, CONCEPT_WORKFLOW_NOTICE, CareersApplyForm, CareersSubmissionForm, CaseStudiesListPage, CaseStudyPage, ChangelogPage, ConceptDetailPage, ConceptsPage, ContactPage, ContentRenderer, ContractsPage, DEFAULT_CONTACT_CATEGORIES, DEFAULT_EXPLORE_EXAMPLE_PROMPTS, DOMAINS_URL, ECOSYSTEM_PRODUCTS, ESCALATE_EXPLORE_CONVERSATION_MUTATION, EXPLORE_CATALOG_QUERY, EXPLORE_CATALOG_QUERY_WITHOUT_HIGHLIGHTS, EXPLORE_ESCALATION_NOTE_SOFT_MAX, EXPLORE_LOCALES, EXPLORE_MESSAGE_QUERY, EXPLORE_PREFILL_MAX_LENGTH, EXPLORE_RECAPTCHA_ACTION, ElectronDownloadLink, ExploreAnswerBody, ExploreAnswerStyles, ExploreChatProvider, ExploreCta, ExplorePage, ExplorePanel, FALLBACK_EXPLORE_LIMITS, FOOTERLESS_ROUTES, Input, LEGAL_DOCUMENTS, LEGAL_DOCUMENT_KEYS, Label, LaunchCountdown, LegalPage, Markdown, NewsletterForm, NewsletterPage, PRODUCT_SLUG_ALIASES, PRODUCT_SLUG_EMIT, PRODUCT_SLUG_RENAMES, PUBLISHED_ANSWER_FIELDS, PageHead, PartnersPage, PressKitPage, PricingPage, PricingProductKeyError, PricingSection, ProblemsSolvedSection, ProductCard, ProductProvider, ResourceLinks, RybbitAnalytics, SEND_EXPLORE_MESSAGE_MUTATION, Select, SocialLinks, StarRating, StoreBrowsePage, StoreHomePage, StoreProductDetailPage, Textarea, TypeBadge, UnsubscribePage, WaitlistForm, WaitlistPage, WebSDKClient, WebSDKProvider, WebsiteSwitcher, answerPath, answerPlainText, answerSourceHost, answerSpeechText, answerStrings, availablePlanCurrencies, buttonVariants, classifyExploreError, cleanPlanDisplayName, cn, conceptPath, detectElectronPlatform, emitProductSlug, exploreQuestionHref, fetchLegalContent, fetchLegalContentPage, fetchPublicJobPosting, fetchPublicJobPostings, fetchPublicJobPostingsForSubmission, fetchPublicProduct, findLegalDocument, formatAnswerDate, formatDownloads, formatLegalDate, formatPrice2 as formatPrice, getAnswerBySlug, getConceptBySlug, getRecaptchaV3Token, inlineImageOrigins, isFooterlessPath, isInlineImageAllowed, isInlineVideoAllowed, isPublishedSourceUrl, isSameProductSlug, isUuidLike, isValidUrl, legacyProductSlug, loadRecaptchaV3, looksLikeDeliverableEmail, normalizeProductSlug, normalizeRoutePath, planPriceIn, productSlugVariants, productSlugsByOrigin, resolvePricingProductKey, shouldRenderSiteFooter, speechLocaleOf, splitLeadingHeading, stopSpeaking, useContentPage, useContentPages, useExploreChat, useExploreConversation, useProduct, useProductConfig, useProgressiveReveal, usePublicJobPosting, usePublicJobPostings, usePublicJobPostingsForSubmission, useSpeechOutput, useWebSDK, useWebSDKConfig };
20637
+ // src/comparison/index.ts
20638
+ var DEFAULT_COMPARISON_MAX_AGE_DAYS = 180;
20639
+ var DAY_MS = 24 * 60 * 60 * 1e3;
20640
+ var ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
20641
+ function parseVerifiedAt(value) {
20642
+ if (typeof value !== "string" || !ISO_DATE.test(value)) return null;
20643
+ const date = /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
20644
+ if (Number.isNaN(date.getTime())) return null;
20645
+ return date.toISOString().slice(0, 10) === value ? date : null;
20646
+ }
20647
+ function isHttpUrl(value) {
20648
+ try {
20649
+ const url = new URL(value);
20650
+ return url.protocol === "https:" || url.protocol === "http:";
20651
+ } catch {
20652
+ return false;
20653
+ }
20654
+ }
20655
+ function checkComparisonFreshness(claims, options = {}) {
20656
+ const maxAgeDays = options.maxAgeDays ?? DEFAULT_COMPARISON_MAX_AGE_DAYS;
20657
+ const now2 = options.now ?? /* @__PURE__ */ new Date();
20658
+ const issues = [];
20659
+ for (const claim of claims) {
20660
+ const sources = claim.sources ?? [];
20661
+ if (sources.length === 0) {
20662
+ issues.push({
20663
+ path: claim.path,
20664
+ problem: "missing-source",
20665
+ detail: "no source: add { url, verifiedAt } for the vendor page this claim was checked against"
20666
+ });
20667
+ continue;
20668
+ }
20669
+ let newest = null;
20670
+ for (const source of sources) {
20671
+ if (!isHttpUrl(source.url)) {
20672
+ issues.push({
20673
+ path: claim.path,
20674
+ problem: "invalid-url",
20675
+ detail: `source URL is not an http(s) URL: ${JSON.stringify(source.url)}`
20676
+ });
20677
+ }
20678
+ const verified = parseVerifiedAt(source.verifiedAt);
20679
+ if (!verified) {
20680
+ issues.push({
20681
+ path: claim.path,
20682
+ problem: "invalid-date",
20683
+ detail: `verifiedAt must be YYYY-MM-DD, got ${JSON.stringify(source.verifiedAt)}`
20684
+ });
20685
+ continue;
20686
+ }
20687
+ if (verified.getTime() > now2.getTime() + DAY_MS) {
20688
+ issues.push({
20689
+ path: claim.path,
20690
+ problem: "future-date",
20691
+ detail: `verifiedAt ${source.verifiedAt} is in the future`
20692
+ });
20693
+ continue;
20694
+ }
20695
+ if (!newest || verified.getTime() > newest.getTime()) newest = verified;
20696
+ }
20697
+ if (newest) {
20698
+ const ageDays = Math.floor((now2.getTime() - newest.getTime()) / DAY_MS);
20699
+ if (ageDays > maxAgeDays) {
20700
+ issues.push({
20701
+ path: claim.path,
20702
+ problem: "stale",
20703
+ detail: `last verified ${newest.toISOString().slice(0, 10)} (${ageDays} days ago, limit ${maxAgeDays}): re-read the vendor page and update verifiedAt or the claim`
20704
+ });
20705
+ }
20706
+ }
20707
+ }
20708
+ return issues;
20709
+ }
20710
+ function latestVerification(claims) {
20711
+ let latest = null;
20712
+ for (const claim of claims) {
20713
+ for (const source of claim.sources ?? []) {
20714
+ if (parseVerifiedAt(source.verifiedAt) && (!latest || source.verifiedAt > latest)) {
20715
+ latest = source.verifiedAt;
20716
+ }
20717
+ }
20718
+ }
20719
+ return latest;
20720
+ }
20721
+ function oldestVerification(claims) {
20722
+ let oldest = null;
20723
+ for (const claim of claims) {
20724
+ for (const source of claim.sources ?? []) {
20725
+ if (parseVerifiedAt(source.verifiedAt) && (!oldest || source.verifiedAt < oldest)) {
20726
+ oldest = source.verifiedAt;
20727
+ }
20728
+ }
20729
+ }
20730
+ return oldest;
20731
+ }
20732
+ function formatFreshnessReport(issues) {
20733
+ if (issues.length === 0)
20734
+ return "Comparison sources: all claims sourced and fresh.";
20735
+ const lines = issues.map((i) => ` - [${i.problem}] ${i.path}: ${i.detail}`);
20736
+ return [
20737
+ `Comparison sources: ${issues.length} problem(s) found.`,
20738
+ ...lines,
20739
+ "Re-check each claim against the vendor's current page, then update the claim and its verifiedAt."
20740
+ ].join("\n");
20741
+ }
20742
+
20743
+ export { ANSWERS_PATH, ANSWER_HEADING_SHIFT, ANSWER_PATH_PREFIX, AnswerDetailPage, AnswersPage, BlogListPage, BlogPostPage, Button, CONCEPTS_PATH, CONCEPT_ILLUSTRATION_NOTICE, CONCEPT_PATH_PREFIX, CONCEPT_WORKFLOW_NOTICE, CareersApplyForm, CareersSubmissionForm, CaseStudiesListPage, CaseStudyPage, ChangelogPage, ConceptDetailPage, ConceptsPage, ContactPage, ContentRenderer, ContractsPage, DEFAULT_COMPARISON_MAX_AGE_DAYS, DEFAULT_CONTACT_CATEGORIES, DEFAULT_EXPLORE_EXAMPLE_PROMPTS, DOMAINS_URL, ECOSYSTEM_PRODUCTS, ESCALATE_EXPLORE_CONVERSATION_MUTATION, EXPLORE_CATALOG_QUERY, EXPLORE_CATALOG_QUERY_WITHOUT_HIGHLIGHTS, EXPLORE_ESCALATION_NOTE_SOFT_MAX, EXPLORE_LOCALES, EXPLORE_MESSAGE_QUERY, EXPLORE_PREFILL_MAX_LENGTH, EXPLORE_RECAPTCHA_ACTION, ElectronDownloadLink, ExploreAnswerBody, ExploreAnswerStyles, ExploreChatProvider, ExploreCta, ExplorePage, ExplorePanel, FALLBACK_EXPLORE_LIMITS, FOOTERLESS_ROUTES, Input, LEGAL_DOCUMENTS, LEGAL_DOCUMENT_KEYS, Label, LaunchCountdown, LegalPage, Markdown, NewsletterForm, NewsletterPage, PRODUCT_SLUG_ALIASES, PRODUCT_SLUG_EMIT, PRODUCT_SLUG_RENAMES, PUBLISHED_ANSWER_FIELDS, PageHead, PartnersPage, PressKitPage, PricingPage, PricingProductKeyError, PricingSection, ProblemsSolvedSection, ProductCard, ProductProvider, ResourceLinks, RybbitAnalytics, SEND_EXPLORE_MESSAGE_MUTATION, Select, SocialLinks, StarRating, StoreBrowsePage, StoreHomePage, StoreProductDetailPage, Textarea, TypeBadge, UnsubscribePage, WaitlistForm, WaitlistPage, WebSDKClient, WebSDKProvider, WebsiteSwitcher, answerPath, answerPlainText, answerSourceHost, answerSpeechText, answerStrings, availablePlanCurrencies, buttonVariants, checkComparisonFreshness, classifyExploreError, cleanPlanDisplayName, cn, conceptPath, detectElectronPlatform, emitProductSlug, exploreQuestionHref, fetchLegalContent, fetchLegalContentPage, fetchPublicJobPosting, fetchPublicJobPostings, fetchPublicJobPostingsForSubmission, fetchPublicProduct, findLegalDocument, formatAnswerDate, formatDownloads, formatFreshnessReport, formatLegalDate, formatPrice2 as formatPrice, getAnswerBySlug, getConceptBySlug, getRecaptchaV3Token, hasCustomerSignOff, inlineImageOrigins, isFooterlessPath, isInlineImageAllowed, isInlineVideoAllowed, isPublishedSourceUrl, isSameProductSlug, isUuidLike, isValidUrl, latestVerification, legacyProductSlug, loadRecaptchaV3, looksLikeDeliverableEmail, normalizeProductSlug, normalizeRoutePath, oldestVerification, parseVerifiedAt, planPriceIn, productSlugVariants, productSlugsByOrigin, resolvePricingProductKey, shouldRenderSiteFooter, speechLocaleOf, splitLeadingHeading, stopSpeaking, useContentPage, useContentPages, useExploreChat, useExploreConversation, useProduct, useProductConfig, useProgressiveReveal, usePublicJobPosting, usePublicJobPostings, usePublicJobPostingsForSubmission, useSpeechOutput, useWebSDK, useWebSDKConfig };
20611
20744
  //# sourceMappingURL=index.mjs.map
20612
20745
  //# sourceMappingURL=index.mjs.map