@singi-labs/sifa-sdk 0.19.56 → 0.19.57

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 (35) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.d.cts +3 -3
  3. package/dist/index.d.ts +3 -3
  4. package/dist/index.js +1 -1
  5. package/dist/{network-map-D-XnMy5U.d.ts → network-map-CKF7Yozc.d.ts} +2 -2
  6. package/dist/{network-map-4C9UwVmp.d.cts → network-map-DHOOMSCP.d.cts} +2 -2
  7. package/dist/{org-DTZzfRQs.d.cts → org-Bq3HbpLD.d.cts} +18 -4
  8. package/dist/{org-DtO2TCzd.d.ts → org-CelDIOiN.d.ts} +18 -4
  9. package/dist/{profile-summary-CVFSy7BE.d.cts → profile-summary-CD3-QflX.d.cts} +1 -1
  10. package/dist/{profile-summary-DiONU2n-.d.ts → profile-summary-CyRzFe7f.d.ts} +1 -1
  11. package/dist/query/fetchers/follow.js +13 -4
  12. package/dist/query/fetchers/follow.js.map +1 -1
  13. package/dist/query/fetchers/index.cjs +21 -6
  14. package/dist/query/fetchers/index.cjs.map +1 -1
  15. package/dist/query/fetchers/index.d.cts +5 -5
  16. package/dist/query/fetchers/index.d.ts +5 -5
  17. package/dist/query/fetchers/index.js.map +1 -1
  18. package/dist/query/fetchers/search.js +8 -2
  19. package/dist/query/fetchers/search.js.map +1 -1
  20. package/dist/query/hooks/index.cjs +17 -4
  21. package/dist/query/hooks/index.cjs.map +1 -1
  22. package/dist/query/hooks/index.d.cts +3 -3
  23. package/dist/query/hooks/index.d.ts +3 -3
  24. package/dist/query/hooks/use-follow.js +1 -1
  25. package/dist/query/hooks/use-follow.js.map +1 -1
  26. package/dist/query/index.cjs +22 -7
  27. package/dist/query/index.cjs.map +1 -1
  28. package/dist/query/index.d.cts +8 -8
  29. package/dist/query/index.d.ts +8 -8
  30. package/dist/query/index.js.map +1 -1
  31. package/dist/{types-CYjcuKr4.d.cts → types-BHnGSJ3z.d.cts} +26 -3
  32. package/dist/{types-Bl8KYBSl.d.ts → types-BKEBVobU.d.ts} +26 -3
  33. package/dist/{use-org-notification-emails-D29UFyp2.d.cts → use-org-notification-emails-BTR2Yxq8.d.cts} +7 -6
  34. package/dist/{use-org-notification-emails-C-GftYx5.d.ts → use-org-notification-emails-DDIi6giD.d.ts} +7 -6
  35. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -7171,7 +7171,7 @@ function describeSifaRecord(collection, value) {
7171
7171
  }
7172
7172
 
7173
7173
  // src/index.ts
7174
- var SIFA_SDK_VERSION = "0.19.56";
7174
+ var SIFA_SDK_VERSION = "0.19.57";
7175
7175
 
7176
7176
  exports.ACTIVITY_TIERS = ACTIVITY_TIERS;
7177
7177
  exports.ACTIVITY_VERBS = ACTIVITY_VERBS;
package/dist/index.d.cts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { P as ProfileSkill, a as ProfilePresentationDelivery, L as LocationValue, b as PdsProviderInfo, c as Profile, A as AccountFacetMode, d as ProfilePosition, e as ProfileCertification, f as ProfileEducation, g as ProfileHonor, h as ProfileLanguage, i as ProfileProject, j as ProfilePublication, k as ProfileInvolvement, R as RelatedIdentifier } from './index-BeQbepFn.cjs';
2
2
  export { l as ActiveApp, m as ActorCard, n as AuthorSuggestion, C as CoSpeaker, E as Endorsement, o as EndorsementData, p as ExternalAccount, q as ExternalAccountKeytraceClaim, F as FeedItem, r as LanguageProficiency, O as OrgAddressView, s as OrgFloorVerdict, t as OrgLinkView, u as OrgProfileView, v as PROJECT_ROLES, w as PresentationLinkView, x as ProfileCourse, y as ProfileIndustry, z as ProfileInvestment, B as ProfileInvestmentLink, D as ProfileInvolvementLink, G as ProfileLocation, H as ProfileOverrideSource, I as ProfilePresentation, J as ProfileVolunteering, K as ProjectMemberCard, M as ProjectRole, N as PublicationContributor, Q as RecognizedEntity, S as SkillRef, T as SkillSuggestion, U as TrustStat, V as VerifiedAccount } from './index-BeQbepFn.cjs';
3
- import { S as SearchFilters } from './types-CYjcuKr4.cjs';
4
- export { A as ADULT_CONTENT_LABELS, a as ActiveAppView, b as ActivityLabel, c as AdultContentLabel, d as AtfundLinkView, C as CertificationView, e as CoSpeakerView, f as ContributorView, g as CourseView, D as DurationView, E as EducationView, h as ExternalAccountView, H as HonorView, I as IndustryDomain, i as InvolvementLinkView, j as InvolvementView, L as LanguageView, P as PositionView, k as PresentationDeliveryView, l as PresentationView, m as ProfileLocationView, n as ProfileView, o as ProjectMemberView, p as ProjectView, q as PublicationView, R as RepoCollectionGroup, r as RepoDeleteOutcome, s as RepoDeleteRecordResult, t as RepoDeleteResult, u as RepoGroupDefinition, v as RepoGroupId, w as RepoInventory, x as RepoRecordLabel, y as RepoRecordSummary, z as SIFA_REPO_GROUPS, B as SkillView, V as VolunteeringView, F as describeSifaRecord, G as hasAdultContent, J as repoGroupForCollection } from './types-CYjcuKr4.cjs';
3
+ import { S as SearchFilters } from './types-BHnGSJ3z.cjs';
4
+ export { A as ADULT_CONTENT_LABELS, a as ActiveAppView, b as ActivityLabel, c as AdultContentLabel, d as AtfundLinkView, C as CertificationView, e as CoSpeakerView, f as ContributorView, g as CourseView, D as DurationView, E as EducationView, h as ExternalAccountView, H as HonorView, I as IndustryDomain, i as InvolvementLinkView, j as InvolvementView, L as LanguageView, P as PositionView, k as PresentationDeliveryView, l as PresentationView, m as ProfileLocationView, n as ProfileView, o as ProjectMemberView, p as ProjectView, q as PublicationView, R as RepoCollectionGroup, r as RepoDeleteOutcome, s as RepoDeleteRecordResult, t as RepoDeleteResult, u as RepoGroupDefinition, v as RepoGroupId, w as RepoInventory, x as RepoRecordLabel, y as RepoRecordSummary, z as SIFA_REPO_GROUPS, B as SkillView, V as VolunteeringView, F as describeSifaRecord, G as hasAdultContent, J as repoGroupForCollection } from './types-BHnGSJ3z.cjs';
5
5
  import { A as AgentRef } from './verification-providers-7il3kPQS.cjs';
6
6
  export { a as AccountVerification, V as VERIFICATION_PROVIDERS, b as VerificationProvider, c as VerificationProviderId, d as VerificationSource, e as agentRefSchema, f as atUriSchema, g as cidSchema, h as datetimeSchema, i as didSchema, j as externalRecordRefSchema, k as getVerificationProvider, l as isKnownVerificationProvider, m as languageTagSchema, n as maxGraphemes, p as partialDateSchema, o as primaryVerification, r as resolveVerifierProvider, s as selfLabelsSchema, q as skillRefSchema, t as strongRefSchema, u as uriSchema } from './verification-providers-7il3kPQS.cjs';
7
7
  import { P as PresentationDuration, a as ProfilePresentationDeliveryRecord, b as ProfilePresentationRecord, O as OrgProfileRecord } from './profile-investment-BiHM7C5q.cjs';
8
8
  export { A as ArtifactLink, c as ArtifactLinkSchema, d as AtmosphereFeedItem, e as AtmosphereFeedItemSchema, B as BlobRef, f as BlobRefSchema, E as EndorsementConfirmationRecord, g as EndorsementConfirmationRecordSchema, h as EndorsementRecord, i as EndorsementRecordSchema, F as FeedActor, j as FeedActorSchema, k as FeedCursor, l as FollowFeedItem, m as FollowFeedItemSchema, n as FollowFeedPage, o as FollowFeedPageSchema, G as GraphFollowRecord, p as GraphFollowRecordSchema, I as InvestmentAmountSchema, q as OrgEmploymentAttestationRecord, r as OrgEmploymentAttestationRecordSchema, s as OrgProfileRecordSchema, t as PROFILE_INVESTMENT_NSID, u as PROFILE_INVOLVEMENT_NSID, v as PresentationDurationSchema, w as PresentationLink, x as PresentationLinkSchema, y as ProfileCertificationRecord, z as ProfileCertificationRecordSchema, C as ProfileCourseRecord, D as ProfileCourseRecordSchema, H as ProfileEducationRecord, J as ProfileEducationRecordSchema, K as ProfileExternalAccountRecord, L as ProfileExternalAccountRecordSchema, M as ProfileHonorRecord, N as ProfileHonorRecordSchema, Q as ProfileInvestmentRecordSchema, R as ProfileInvolvementRecord, S as ProfileInvolvementRecordSchema, T as ProfileLanguageRecord, U as ProfileLanguageRecordSchema, V as ProfilePositionRecord, W as ProfilePositionRecordSchema, X as ProfilePresentationDeliveryRecordSchema, Y as ProfilePresentationRecordSchema, Z as ProfileProjectRecord, _ as ProfileProjectRecordSchema, $ as ProfilePublicationRecord, a0 as ProfilePublicationRecordSchema, a1 as ProfileSelfRecord, a2 as ProfileSelfRecordSchema, a3 as ProfileSkillRecord, a4 as ProfileSkillRecordSchema, a5 as ProfileVolunteeringRecord, a6 as ProfileVolunteeringRecordSchema, a7 as PublicationAuthor, a8 as PublicationAuthorSchema, a9 as RelatedIdentifierSchema, aa as SifaFeedItem, ab as SifaFeedItemSchema, ac as decodeFeedCursor, ad as encodeFeedCursor, ae as makeGraphFollowRecordSchema } from './profile-investment-BiHM7C5q.cjs';
9
9
  import { z } from 'zod';
10
- export { P as ProfileSummary, S as SummarizeProfileViewOptions, s as summarizeProfileView } from './profile-summary-CVFSy7BE.cjs';
10
+ export { P as ProfileSummary, S as SummarizeProfileViewOptions, s as summarizeProfileView } from './profile-summary-CD3-QflX.cjs';
11
11
  import { E as EntitySearchResult } from './follow-profile-CQ3DTTak.cjs';
12
12
  export { a as EntityImportSearchResponse, b as EntityImportSearchResponseSchema, c as EntityMintDomainResponse, d as EntityMintDomainResponseSchema, e as EntityResolveDomainRequest, f as EntityResolveDomainRequestSchema, g as EntityResolveDomainResponse, h as EntityResolveDomainResponseSchema, i as EntitySearchResponse, j as EntitySearchResponseSchema, k as EntitySearchResultSchema, l as EntitySelectRequest, m as EntitySelectRequestSchema, n as EntitySelectResponse, o as EntitySelectResponseSchema, F as FEATURE_FLAGS, p as FeatureAllowlistEntry, q as FeatureAllowlistEntrySchema, r as FeatureFlag, s as FollowProfileItem, t as FollowProfilePage, u as FollowProfilePageSchema, v as FollowProfileSchema } from './follow-profile-CQ3DTTak.cjs';
13
13
 
package/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { P as ProfileSkill, a as ProfilePresentationDelivery, L as LocationValue, b as PdsProviderInfo, c as Profile, A as AccountFacetMode, d as ProfilePosition, e as ProfileCertification, f as ProfileEducation, g as ProfileHonor, h as ProfileLanguage, i as ProfileProject, j as ProfilePublication, k as ProfileInvolvement, R as RelatedIdentifier } from './index-CT-A3BEe.js';
2
2
  export { l as ActiveApp, m as ActorCard, n as AuthorSuggestion, C as CoSpeaker, E as Endorsement, o as EndorsementData, p as ExternalAccount, q as ExternalAccountKeytraceClaim, F as FeedItem, r as LanguageProficiency, O as OrgAddressView, s as OrgFloorVerdict, t as OrgLinkView, u as OrgProfileView, v as PROJECT_ROLES, w as PresentationLinkView, x as ProfileCourse, y as ProfileIndustry, z as ProfileInvestment, B as ProfileInvestmentLink, D as ProfileInvolvementLink, G as ProfileLocation, H as ProfileOverrideSource, I as ProfilePresentation, J as ProfileVolunteering, K as ProjectMemberCard, M as ProjectRole, N as PublicationContributor, Q as RecognizedEntity, S as SkillRef, T as SkillSuggestion, U as TrustStat, V as VerifiedAccount } from './index-CT-A3BEe.js';
3
- import { S as SearchFilters } from './types-Bl8KYBSl.js';
4
- export { A as ADULT_CONTENT_LABELS, a as ActiveAppView, b as ActivityLabel, c as AdultContentLabel, d as AtfundLinkView, C as CertificationView, e as CoSpeakerView, f as ContributorView, g as CourseView, D as DurationView, E as EducationView, h as ExternalAccountView, H as HonorView, I as IndustryDomain, i as InvolvementLinkView, j as InvolvementView, L as LanguageView, P as PositionView, k as PresentationDeliveryView, l as PresentationView, m as ProfileLocationView, n as ProfileView, o as ProjectMemberView, p as ProjectView, q as PublicationView, R as RepoCollectionGroup, r as RepoDeleteOutcome, s as RepoDeleteRecordResult, t as RepoDeleteResult, u as RepoGroupDefinition, v as RepoGroupId, w as RepoInventory, x as RepoRecordLabel, y as RepoRecordSummary, z as SIFA_REPO_GROUPS, B as SkillView, V as VolunteeringView, F as describeSifaRecord, G as hasAdultContent, J as repoGroupForCollection } from './types-Bl8KYBSl.js';
3
+ import { S as SearchFilters } from './types-BKEBVobU.js';
4
+ export { A as ADULT_CONTENT_LABELS, a as ActiveAppView, b as ActivityLabel, c as AdultContentLabel, d as AtfundLinkView, C as CertificationView, e as CoSpeakerView, f as ContributorView, g as CourseView, D as DurationView, E as EducationView, h as ExternalAccountView, H as HonorView, I as IndustryDomain, i as InvolvementLinkView, j as InvolvementView, L as LanguageView, P as PositionView, k as PresentationDeliveryView, l as PresentationView, m as ProfileLocationView, n as ProfileView, o as ProjectMemberView, p as ProjectView, q as PublicationView, R as RepoCollectionGroup, r as RepoDeleteOutcome, s as RepoDeleteRecordResult, t as RepoDeleteResult, u as RepoGroupDefinition, v as RepoGroupId, w as RepoInventory, x as RepoRecordLabel, y as RepoRecordSummary, z as SIFA_REPO_GROUPS, B as SkillView, V as VolunteeringView, F as describeSifaRecord, G as hasAdultContent, J as repoGroupForCollection } from './types-BKEBVobU.js';
5
5
  import { A as AgentRef } from './verification-providers-7il3kPQS.js';
6
6
  export { a as AccountVerification, V as VERIFICATION_PROVIDERS, b as VerificationProvider, c as VerificationProviderId, d as VerificationSource, e as agentRefSchema, f as atUriSchema, g as cidSchema, h as datetimeSchema, i as didSchema, j as externalRecordRefSchema, k as getVerificationProvider, l as isKnownVerificationProvider, m as languageTagSchema, n as maxGraphemes, p as partialDateSchema, o as primaryVerification, r as resolveVerifierProvider, s as selfLabelsSchema, q as skillRefSchema, t as strongRefSchema, u as uriSchema } from './verification-providers-7il3kPQS.js';
7
7
  import { P as PresentationDuration, a as ProfilePresentationDeliveryRecord, b as ProfilePresentationRecord, O as OrgProfileRecord } from './profile-investment-BiHM7C5q.js';
8
8
  export { A as ArtifactLink, c as ArtifactLinkSchema, d as AtmosphereFeedItem, e as AtmosphereFeedItemSchema, B as BlobRef, f as BlobRefSchema, E as EndorsementConfirmationRecord, g as EndorsementConfirmationRecordSchema, h as EndorsementRecord, i as EndorsementRecordSchema, F as FeedActor, j as FeedActorSchema, k as FeedCursor, l as FollowFeedItem, m as FollowFeedItemSchema, n as FollowFeedPage, o as FollowFeedPageSchema, G as GraphFollowRecord, p as GraphFollowRecordSchema, I as InvestmentAmountSchema, q as OrgEmploymentAttestationRecord, r as OrgEmploymentAttestationRecordSchema, s as OrgProfileRecordSchema, t as PROFILE_INVESTMENT_NSID, u as PROFILE_INVOLVEMENT_NSID, v as PresentationDurationSchema, w as PresentationLink, x as PresentationLinkSchema, y as ProfileCertificationRecord, z as ProfileCertificationRecordSchema, C as ProfileCourseRecord, D as ProfileCourseRecordSchema, H as ProfileEducationRecord, J as ProfileEducationRecordSchema, K as ProfileExternalAccountRecord, L as ProfileExternalAccountRecordSchema, M as ProfileHonorRecord, N as ProfileHonorRecordSchema, Q as ProfileInvestmentRecordSchema, R as ProfileInvolvementRecord, S as ProfileInvolvementRecordSchema, T as ProfileLanguageRecord, U as ProfileLanguageRecordSchema, V as ProfilePositionRecord, W as ProfilePositionRecordSchema, X as ProfilePresentationDeliveryRecordSchema, Y as ProfilePresentationRecordSchema, Z as ProfileProjectRecord, _ as ProfileProjectRecordSchema, $ as ProfilePublicationRecord, a0 as ProfilePublicationRecordSchema, a1 as ProfileSelfRecord, a2 as ProfileSelfRecordSchema, a3 as ProfileSkillRecord, a4 as ProfileSkillRecordSchema, a5 as ProfileVolunteeringRecord, a6 as ProfileVolunteeringRecordSchema, a7 as PublicationAuthor, a8 as PublicationAuthorSchema, a9 as RelatedIdentifierSchema, aa as SifaFeedItem, ab as SifaFeedItemSchema, ac as decodeFeedCursor, ad as encodeFeedCursor, ae as makeGraphFollowRecordSchema } from './profile-investment-BiHM7C5q.js';
9
9
  import { z } from 'zod';
10
- export { P as ProfileSummary, S as SummarizeProfileViewOptions, s as summarizeProfileView } from './profile-summary-DiONU2n-.js';
10
+ export { P as ProfileSummary, S as SummarizeProfileViewOptions, s as summarizeProfileView } from './profile-summary-CyRzFe7f.js';
11
11
  import { E as EntitySearchResult } from './follow-profile-ceqefXAw.js';
12
12
  export { a as EntityImportSearchResponse, b as EntityImportSearchResponseSchema, c as EntityMintDomainResponse, d as EntityMintDomainResponseSchema, e as EntityResolveDomainRequest, f as EntityResolveDomainRequestSchema, g as EntityResolveDomainResponse, h as EntityResolveDomainResponseSchema, i as EntitySearchResponse, j as EntitySearchResponseSchema, k as EntitySearchResultSchema, l as EntitySelectRequest, m as EntitySelectRequestSchema, n as EntitySelectResponse, o as EntitySelectResponseSchema, F as FEATURE_FLAGS, p as FeatureAllowlistEntry, q as FeatureAllowlistEntrySchema, r as FeatureFlag, s as FollowProfileItem, t as FollowProfilePage, u as FollowProfilePageSchema, v as FollowProfileSchema } from './follow-profile-ceqefXAw.js';
13
13
 
package/dist/index.js CHANGED
@@ -350,7 +350,7 @@ import {
350
350
  roadmapIssueUrl
351
351
  } from "./roadmap/index.js";
352
352
  import { SIFA_REPO_GROUPS, describeSifaRecord, repoGroupForCollection } from "./repo/index.js";
353
- var SIFA_SDK_VERSION = "0.19.56";
353
+ var SIFA_SDK_VERSION = "0.19.57";
354
354
  export {
355
355
  ACTIVITY_TIERS,
356
356
  ACTIVITY_VERBS,
@@ -1,6 +1,6 @@
1
1
  import { c as Profile, d as ProfilePosition, S as SkillRef, w as PresentationLinkView } from './index-CT-A3BEe.js';
2
- import { K as SifaApiConfig, M as ApiFetchOptions, n as ProfileView, N as CreateResult, W as WriteResult } from './types-Bl8KYBSl.js';
3
- import { S as SummarizeProfileViewOptions, P as ProfileSummary } from './profile-summary-DiONU2n-.js';
2
+ import { K as SifaApiConfig, M as ApiFetchOptions, n as ProfileView, N as CreateResult, W as WriteResult } from './types-BKEBVobU.js';
3
+ import { S as SummarizeProfileViewOptions, P as ProfileSummary } from './profile-summary-CyRzFe7f.js';
4
4
  import { i as EntitySearchResponse, E as EntitySearchResult, c as EntityMintDomainResponse, g as EntityResolveDomainResponse, l as EntitySelectRequest, n as EntitySelectResponse } from './follow-profile-ceqefXAw.js';
5
5
  import { z } from 'zod';
6
6
 
@@ -1,6 +1,6 @@
1
1
  import { c as Profile, d as ProfilePosition, S as SkillRef, w as PresentationLinkView } from './index-BeQbepFn.cjs';
2
- import { K as SifaApiConfig, M as ApiFetchOptions, n as ProfileView, N as CreateResult, W as WriteResult } from './types-CYjcuKr4.cjs';
3
- import { S as SummarizeProfileViewOptions, P as ProfileSummary } from './profile-summary-CVFSy7BE.cjs';
2
+ import { K as SifaApiConfig, M as ApiFetchOptions, n as ProfileView, N as CreateResult, W as WriteResult } from './types-BHnGSJ3z.cjs';
3
+ import { S as SummarizeProfileViewOptions, P as ProfileSummary } from './profile-summary-CD3-QflX.cjs';
4
4
  import { i as EntitySearchResponse, E as EntitySearchResult, c as EntityMintDomainResponse, g as EntityResolveDomainResponse, l as EntitySelectRequest, n as EntitySelectResponse } from './follow-profile-CQ3DTTak.cjs';
5
5
  import { z } from 'zod';
6
6
 
@@ -1,4 +1,4 @@
1
- import { W as WriteResult, K as SifaApiConfig, M as ApiFetchOptions, N as CreateResult, b as ActivityLabel, t as RepoDeleteResult, w as RepoInventory } from './types-CYjcuKr4.cjs';
1
+ import { W as WriteResult, K as SifaApiConfig, M as ApiFetchOptions, N as CreateResult, b as ActivityLabel, t as RepoDeleteResult, w as RepoInventory } from './types-BHnGSJ3z.cjs';
2
2
  import { p as ExternalAccount } from './index-BeQbepFn.cjs';
3
3
  import { a as AccountVerification } from './verification-providers-7il3kPQS.cjs';
4
4
  import { s as FollowProfileItem, p as FeatureAllowlistEntry, r as FeatureFlag } from './follow-profile-CQ3DTTak.cjs';
@@ -1096,6 +1096,11 @@ interface FollowingFeedResponse extends ActivityFeedResponse {
1096
1096
  reason?: FollowingFeedEmptyReason;
1097
1097
  /** When this feed was built (ISO 8601). Absent on a `building` answer. */
1098
1098
  builtAt?: string;
1099
+ /**
1100
+ * Fingerprint of the items shown. Equal for a rebuild that found nothing
1101
+ * new, so compare it (with {@link isNewerFollowingFeed}) rather than times.
1102
+ */
1103
+ contentHash?: string;
1099
1104
  /**
1100
1105
  * True when this is an older build, served while a newer one is built in
1101
1106
  * the background. Poll {@link fetchFollowingFeedVersion} to learn when the
@@ -1119,6 +1124,8 @@ declare function fetchFollowingFeed(config: SifaApiConfig, opts?: FetchFollowing
1119
1124
  interface FollowingFeedVersion {
1120
1125
  /** ISO 8601, or null when nothing is cached for this query. */
1121
1126
  builtAt: string | null;
1127
+ /** Fingerprint of the cached feed's items, or null when unknown. */
1128
+ contentHash: string | null;
1122
1129
  }
1123
1130
  /**
1124
1131
  * When the cached following feed for the same query was built. Cheap: it never
@@ -1126,8 +1133,15 @@ interface FollowingFeedVersion {
1126
1133
  * newer one once {@link isNewerFollowingFeed} says so. Returns `null` on error.
1127
1134
  */
1128
1135
  declare function fetchFollowingFeedVersion(config: SifaApiConfig, opts?: FetchFollowingFeedOptions): Promise<FollowingFeedVersion | null>;
1129
- /** True when `latestBuiltAt` is a newer build than the one shown (`shownBuiltAt`). */
1130
- declare function isNewerFollowingFeed(shownBuiltAt: string | null | undefined, latestBuiltAt: string | null | undefined): boolean;
1136
+ /** The parts of a feed build that {@link isNewerFollowingFeed} compares. */
1137
+ type FollowingFeedBuild = Partial<FollowingFeedVersion>;
1138
+ /**
1139
+ * True when `latest` is a newer build than the one shown AND shows different
1140
+ * items. A rebuild that found nothing new has the same fingerprint, and
1141
+ * offering it would show nothing new. Missing data on either side is false:
1142
+ * better to miss an offer than to make an empty one.
1143
+ */
1144
+ declare function isNewerFollowingFeed(shown: FollowingFeedBuild | null | undefined, latest: FollowingFeedBuild | null | undefined): boolean;
1131
1145
 
1132
1146
  /**
1133
1147
  * Options shared by the cursor-paginated follow-graph endpoints introduced in
@@ -1760,4 +1774,4 @@ declare function addOrgNotificationEmail(config: SifaApiConfig, body: OrgNotific
1760
1774
  */
1761
1775
  declare function removeOrgNotificationEmail(config: SifaApiConfig, body: OrgNotificationEmailRequestInput, options?: Omit<ApiFetchOptions, 'method' | 'body'>): Promise<WriteResult<Partial<OrgNotificationEmailRemoveResult>>>;
1762
1776
 
1763
- export { type HeatmapDay as $, type AccountCheckResult as A, type BulkHideProfileItemInput as B, type ConfirmEndorsementInput as C, type DeleteAccountResult as D, type EndorsementInput as E, type FeatureAllowlistResponse as F, type FetchInboxCountsOptions as G, type FetchMyGithubPullRequestsOptions as H, type FetchMyRoadmapVotesOptions as I, type FetchProfileCompletenessOptions as J, type FetchReactionStatusOptions as K, type FetchSuggestionsOptions as L, type FetchUnlinkedPositionsOptions as M, type FollowListPage as N, type FollowProfile as O, type FollowProfilePageResponse as P, type FollowUserResult as Q, type FollowingFeedApp as R, type FollowingFeedEmptyReason as S, type FollowingFeedResponse as T, type FollowingFeedVersion as U, type FollowingResponse as V, type GetAdminReviewQueuesOptions as W, type GithubPullRequest as X, type GivenConfirmation as Y, HIDDEN_ITEM_SOURCES as Z, HIDDEN_ITEM_TYPES as _, type ConfirmEndorsementResult as a, bulkHideProfileItems as a$, type HeatmapResponse as a0, type HiddenActivityItem as a1, type HiddenApp as a2, type HiddenItemSource as a3, type HiddenItemType as a4, type HideActivityItemInput as a5, type HideProfileItemInput as a6, type InboxCounts as a7, type ListFeatureAllowlistOptions as a8, type MyGithubPullRequestsResponse as a9, type ReactionStatus as aA, type RefreshOrcidPublicationsResult as aB, type RefreshPdsResult as aC, type RepoDeleteInput as aD, type ResetProfileResult as aE, type ResolveQuotedPostsOptions as aF, type RoadmapVoteError as aG, type RoadmapVoteResult as aH, type RoadmapVoter as aI, type RoadmapVotesResponse as aJ, type SifaQueryKey as aK, type SimilarProfile as aL, type StatsResponse as aM, type SubCategoryBulkResult as aN, type SuggestionProfile as aO, type SuggestionsResponse as aP, type UnhideActivityItemInput as aQ, type UnlinkedPosition as aR, type UnlinkedPositionsResult as aS, type UpdateProfileOverrideInput as aT, type UpdateProfileSelfInput as aU, type UploadAvatarResult as aV, type UploadPronunciationAudioResult as aW, type VerifyExternalAccountResult as aX, type WipePreview as aY, addFeatureAllowlist as aZ, addOrgNotificationEmail as a_, type OrgClaimBinding as aa, type OrgClaimResult as ab, type OrgDomainChallengeResult as ac, type OrgDomainVerifyResult as ad, type OrgNotificationEmailAddResult as ae, type OrgNotificationEmailRemoveResult as af, type OrgProfileEcho as ag, type OrgProfileUpdateResult as ah, PROFILE_COMPLETENESS_SIGNALS as ai, type PdsWipeOutcome as aj, type PendingConfirmation as ak, type PendingConfirmationsPage as al, type PrimarySection as am, type ProfileCompleteness as an, type ProfileCompletenessSignal as ao, type ProfileIndustryInput as ap, type ProfileLocationAddress as aq, type ProfileLocationInput as ar, type ProfileSelfLocation as as, QUOTED_POSTS_BATCH_MAX as at, type QuotedPostAuthor as au, type QuotedPostImage as av, type QuotedPostResult as aw, type QuotedPostView as ax, type ReactionError as ay, type ReactionResult as az, type AccountSummary as b, refreshPds as b$, bulkHideStandardPublications as b0, bulkUnhideProfileItems as b1, bulkUnhideStandardPublications as b2, castRoadmapVote as b3, checkAppAccount as b4, confirmEndorsement as b5, createConfirmation as b6, createEndorsement as b7, createExternalAccount as b8, createProfileLocation as b9, fetchMyGithubPullRequests as bA, fetchMyRoadmapVotes as bB, fetchPendingConfirmations as bC, fetchProfileCompleteness as bD, fetchReactionStatus as bE, fetchRepoInventory as bF, fetchRoadmapVotes as bG, fetchSimilarProfiles as bH, fetchStats as bI, fetchSuggestionCount as bJ, fetchSuggestions as bK, fetchUnlinkedPositions as bL, fetchWipePreview as bM, followUser as bN, getAdminReviewQueues as bO, getBlueskySuggestions as bP, getFollowers as bQ, getFollowing as bR, getMutuals as bS, hideActivityItem as bT, hideOrcidPublication as bU, hideProfileItem as bV, hideSifaPublication as bW, hideStandardPublication as bX, isNewerFollowingFeed as bY, listFeatureAllowlist as bZ, refreshOrcidPublications as b_, createReaction as ba, createSkill as bb, deleteAccount as bc, deleteAvatarOverride as bd, deleteExternalAccount as be, deleteNamePronunciationAudio as bf, deleteProfileLocation as bg, deleteReaction as bh, deleteRepoRecords as bi, deleteSkill as bj, dismissConfirmation as bk, dismissUnlinkedPosition as bl, fetchAccounts as bm, fetchActivityFeed as bn, fetchActivityTeaser as bo, fetchAppsRegistry as bp, fetchExternalAccounts as bq, fetchFeaturedProfile as br, fetchFollowing as bs, fetchFollowingFeed as bt, fetchFollowingFeedVersion as bu, fetchGivenConfirmations as bv, fetchHeatmapData as bw, fetchHiddenActivityItems as bx, fetchHiddenApps as by, fetchInboxCounts as bz, type ActivityFeedResponse as c, removeFeatureAllowlist as c0, removeOrgNotificationEmail as c1, repoExportUrl as c2, requestOrgDomainChallenge as c3, resetProfile as c4, resolveQuotedPosts as c5, retractRoadmapVote as c6, revokeConfirmation as c7, setExternalAccountPrimary as c8, setSectionPrimary as c9, submitOrgClaim as ca, switchAccount as cb, unfollowUser as cc, unhideActivityItem as cd, unhideOrcidPublication as ce, unhideProfileItem as cf, unhideSifaPublication as cg, unhideStandardPublication as ch, unsetExternalAccountPrimary as ci, unsetSectionPrimary as cj, updateExternalAccount as ck, updateOrgProfile as cl, updateProfileLocation as cm, updateProfileOverride as cn, updateProfileSelf as co, updateSkill as cp, updateSkillSubCategories as cq, uploadAvatar as cr, uploadNamePronunciationAudio as cs, verifyExternalAccount as ct, verifyOrgDomain as cu, type ActivityItem as d, type ActivityItemLinkHealth as e, type ActivityTeaserResponse as f, type AdminReviewQueues as g, type AppRegistryEntry as h, type CastRoadmapVoteResult as i, type CheckAppAccountOptions as j, type ConfirmationInput as k, type ConfirmationSubjectInput as l, type CreateExternalAccountResult as m, type DismissUnlinkedPositionInput as n, type ExternalAccountInput as o, type FeaturedProfile as p, type FetchAccountsOptions as q, type FetchActivityFeedOptions as r, sifaQueryKeys as s, type FetchActivityTeaserOptions as t, type FetchConfirmationsOptions as u, type FetchFollowListOptions as v, type FetchFollowProfilePageOptions as w, type FetchFollowingFeedOptions as x, type FetchHiddenActivityItemsOptions as y, type FetchHiddenAppsOptions as z };
1777
+ export { HIDDEN_ITEM_TYPES as $, type AccountCheckResult as A, type BulkHideProfileItemInput as B, type ConfirmEndorsementInput as C, type DeleteAccountResult as D, type EndorsementInput as E, type FeatureAllowlistResponse as F, type FetchInboxCountsOptions as G, type FetchMyGithubPullRequestsOptions as H, type FetchMyRoadmapVotesOptions as I, type FetchProfileCompletenessOptions as J, type FetchReactionStatusOptions as K, type FetchSuggestionsOptions as L, type FetchUnlinkedPositionsOptions as M, type FollowListPage as N, type FollowProfile as O, type FollowProfilePageResponse as P, type FollowUserResult as Q, type FollowingFeedApp as R, type FollowingFeedBuild as S, type FollowingFeedEmptyReason as T, type FollowingFeedResponse as U, type FollowingFeedVersion as V, type FollowingResponse as W, type GetAdminReviewQueuesOptions as X, type GithubPullRequest as Y, type GivenConfirmation as Z, HIDDEN_ITEM_SOURCES as _, type ConfirmEndorsementResult as a, addOrgNotificationEmail as a$, type HeatmapDay as a0, type HeatmapResponse as a1, type HiddenActivityItem as a2, type HiddenApp as a3, type HiddenItemSource as a4, type HiddenItemType as a5, type HideActivityItemInput as a6, type HideProfileItemInput as a7, type InboxCounts as a8, type ListFeatureAllowlistOptions as a9, type ReactionResult as aA, type ReactionStatus as aB, type RefreshOrcidPublicationsResult as aC, type RefreshPdsResult as aD, type RepoDeleteInput as aE, type ResetProfileResult as aF, type ResolveQuotedPostsOptions as aG, type RoadmapVoteError as aH, type RoadmapVoteResult as aI, type RoadmapVoter as aJ, type RoadmapVotesResponse as aK, type SifaQueryKey as aL, type SimilarProfile as aM, type StatsResponse as aN, type SubCategoryBulkResult as aO, type SuggestionProfile as aP, type SuggestionsResponse as aQ, type UnhideActivityItemInput as aR, type UnlinkedPosition as aS, type UnlinkedPositionsResult as aT, type UpdateProfileOverrideInput as aU, type UpdateProfileSelfInput as aV, type UploadAvatarResult as aW, type UploadPronunciationAudioResult as aX, type VerifyExternalAccountResult as aY, type WipePreview as aZ, addFeatureAllowlist as a_, type MyGithubPullRequestsResponse as aa, type OrgClaimBinding as ab, type OrgClaimResult as ac, type OrgDomainChallengeResult as ad, type OrgDomainVerifyResult as ae, type OrgNotificationEmailAddResult as af, type OrgNotificationEmailRemoveResult as ag, type OrgProfileEcho as ah, type OrgProfileUpdateResult as ai, PROFILE_COMPLETENESS_SIGNALS as aj, type PdsWipeOutcome as ak, type PendingConfirmation as al, type PendingConfirmationsPage as am, type PrimarySection as an, type ProfileCompleteness as ao, type ProfileCompletenessSignal as ap, type ProfileIndustryInput as aq, type ProfileLocationAddress as ar, type ProfileLocationInput as as, type ProfileSelfLocation as at, QUOTED_POSTS_BATCH_MAX as au, type QuotedPostAuthor as av, type QuotedPostImage as aw, type QuotedPostResult as ax, type QuotedPostView as ay, type ReactionError as az, type AccountSummary as b, refreshOrcidPublications as b$, bulkHideProfileItems as b0, bulkHideStandardPublications as b1, bulkUnhideProfileItems as b2, bulkUnhideStandardPublications as b3, castRoadmapVote as b4, checkAppAccount as b5, confirmEndorsement as b6, createConfirmation as b7, createEndorsement as b8, createExternalAccount as b9, fetchInboxCounts as bA, fetchMyGithubPullRequests as bB, fetchMyRoadmapVotes as bC, fetchPendingConfirmations as bD, fetchProfileCompleteness as bE, fetchReactionStatus as bF, fetchRepoInventory as bG, fetchRoadmapVotes as bH, fetchSimilarProfiles as bI, fetchStats as bJ, fetchSuggestionCount as bK, fetchSuggestions as bL, fetchUnlinkedPositions as bM, fetchWipePreview as bN, followUser as bO, getAdminReviewQueues as bP, getBlueskySuggestions as bQ, getFollowers as bR, getFollowing as bS, getMutuals as bT, hideActivityItem as bU, hideOrcidPublication as bV, hideProfileItem as bW, hideSifaPublication as bX, hideStandardPublication as bY, isNewerFollowingFeed as bZ, listFeatureAllowlist as b_, createProfileLocation as ba, createReaction as bb, createSkill as bc, deleteAccount as bd, deleteAvatarOverride as be, deleteExternalAccount as bf, deleteNamePronunciationAudio as bg, deleteProfileLocation as bh, deleteReaction as bi, deleteRepoRecords as bj, deleteSkill as bk, dismissConfirmation as bl, dismissUnlinkedPosition as bm, fetchAccounts as bn, fetchActivityFeed as bo, fetchActivityTeaser as bp, fetchAppsRegistry as bq, fetchExternalAccounts as br, fetchFeaturedProfile as bs, fetchFollowing as bt, fetchFollowingFeed as bu, fetchFollowingFeedVersion as bv, fetchGivenConfirmations as bw, fetchHeatmapData as bx, fetchHiddenActivityItems as by, fetchHiddenApps as bz, type ActivityFeedResponse as c, refreshPds as c0, removeFeatureAllowlist as c1, removeOrgNotificationEmail as c2, repoExportUrl as c3, requestOrgDomainChallenge as c4, resetProfile as c5, resolveQuotedPosts as c6, retractRoadmapVote as c7, revokeConfirmation as c8, setExternalAccountPrimary as c9, setSectionPrimary as ca, submitOrgClaim as cb, switchAccount as cc, unfollowUser as cd, unhideActivityItem as ce, unhideOrcidPublication as cf, unhideProfileItem as cg, unhideSifaPublication as ch, unhideStandardPublication as ci, unsetExternalAccountPrimary as cj, unsetSectionPrimary as ck, updateExternalAccount as cl, updateOrgProfile as cm, updateProfileLocation as cn, updateProfileOverride as co, updateProfileSelf as cp, updateSkill as cq, updateSkillSubCategories as cr, uploadAvatar as cs, uploadNamePronunciationAudio as ct, verifyExternalAccount as cu, verifyOrgDomain as cv, type ActivityItem as d, type ActivityItemLinkHealth as e, type ActivityTeaserResponse as f, type AdminReviewQueues as g, type AppRegistryEntry as h, type CastRoadmapVoteResult as i, type CheckAppAccountOptions as j, type ConfirmationInput as k, type ConfirmationSubjectInput as l, type CreateExternalAccountResult as m, type DismissUnlinkedPositionInput as n, type ExternalAccountInput as o, type FeaturedProfile as p, type FetchAccountsOptions as q, type FetchActivityFeedOptions as r, sifaQueryKeys as s, type FetchActivityTeaserOptions as t, type FetchConfirmationsOptions as u, type FetchFollowListOptions as v, type FetchFollowProfilePageOptions as w, type FetchFollowingFeedOptions as x, type FetchHiddenActivityItemsOptions as y, type FetchHiddenAppsOptions as z };
@@ -1,4 +1,4 @@
1
- import { W as WriteResult, K as SifaApiConfig, M as ApiFetchOptions, N as CreateResult, b as ActivityLabel, t as RepoDeleteResult, w as RepoInventory } from './types-Bl8KYBSl.js';
1
+ import { W as WriteResult, K as SifaApiConfig, M as ApiFetchOptions, N as CreateResult, b as ActivityLabel, t as RepoDeleteResult, w as RepoInventory } from './types-BKEBVobU.js';
2
2
  import { p as ExternalAccount } from './index-CT-A3BEe.js';
3
3
  import { a as AccountVerification } from './verification-providers-7il3kPQS.js';
4
4
  import { s as FollowProfileItem, p as FeatureAllowlistEntry, r as FeatureFlag } from './follow-profile-ceqefXAw.js';
@@ -1096,6 +1096,11 @@ interface FollowingFeedResponse extends ActivityFeedResponse {
1096
1096
  reason?: FollowingFeedEmptyReason;
1097
1097
  /** When this feed was built (ISO 8601). Absent on a `building` answer. */
1098
1098
  builtAt?: string;
1099
+ /**
1100
+ * Fingerprint of the items shown. Equal for a rebuild that found nothing
1101
+ * new, so compare it (with {@link isNewerFollowingFeed}) rather than times.
1102
+ */
1103
+ contentHash?: string;
1099
1104
  /**
1100
1105
  * True when this is an older build, served while a newer one is built in
1101
1106
  * the background. Poll {@link fetchFollowingFeedVersion} to learn when the
@@ -1119,6 +1124,8 @@ declare function fetchFollowingFeed(config: SifaApiConfig, opts?: FetchFollowing
1119
1124
  interface FollowingFeedVersion {
1120
1125
  /** ISO 8601, or null when nothing is cached for this query. */
1121
1126
  builtAt: string | null;
1127
+ /** Fingerprint of the cached feed's items, or null when unknown. */
1128
+ contentHash: string | null;
1122
1129
  }
1123
1130
  /**
1124
1131
  * When the cached following feed for the same query was built. Cheap: it never
@@ -1126,8 +1133,15 @@ interface FollowingFeedVersion {
1126
1133
  * newer one once {@link isNewerFollowingFeed} says so. Returns `null` on error.
1127
1134
  */
1128
1135
  declare function fetchFollowingFeedVersion(config: SifaApiConfig, opts?: FetchFollowingFeedOptions): Promise<FollowingFeedVersion | null>;
1129
- /** True when `latestBuiltAt` is a newer build than the one shown (`shownBuiltAt`). */
1130
- declare function isNewerFollowingFeed(shownBuiltAt: string | null | undefined, latestBuiltAt: string | null | undefined): boolean;
1136
+ /** The parts of a feed build that {@link isNewerFollowingFeed} compares. */
1137
+ type FollowingFeedBuild = Partial<FollowingFeedVersion>;
1138
+ /**
1139
+ * True when `latest` is a newer build than the one shown AND shows different
1140
+ * items. A rebuild that found nothing new has the same fingerprint, and
1141
+ * offering it would show nothing new. Missing data on either side is false:
1142
+ * better to miss an offer than to make an empty one.
1143
+ */
1144
+ declare function isNewerFollowingFeed(shown: FollowingFeedBuild | null | undefined, latest: FollowingFeedBuild | null | undefined): boolean;
1131
1145
 
1132
1146
  /**
1133
1147
  * Options shared by the cursor-paginated follow-graph endpoints introduced in
@@ -1760,4 +1774,4 @@ declare function addOrgNotificationEmail(config: SifaApiConfig, body: OrgNotific
1760
1774
  */
1761
1775
  declare function removeOrgNotificationEmail(config: SifaApiConfig, body: OrgNotificationEmailRequestInput, options?: Omit<ApiFetchOptions, 'method' | 'body'>): Promise<WriteResult<Partial<OrgNotificationEmailRemoveResult>>>;
1762
1776
 
1763
- export { type HeatmapDay as $, type AccountCheckResult as A, type BulkHideProfileItemInput as B, type ConfirmEndorsementInput as C, type DeleteAccountResult as D, type EndorsementInput as E, type FeatureAllowlistResponse as F, type FetchInboxCountsOptions as G, type FetchMyGithubPullRequestsOptions as H, type FetchMyRoadmapVotesOptions as I, type FetchProfileCompletenessOptions as J, type FetchReactionStatusOptions as K, type FetchSuggestionsOptions as L, type FetchUnlinkedPositionsOptions as M, type FollowListPage as N, type FollowProfile as O, type FollowProfilePageResponse as P, type FollowUserResult as Q, type FollowingFeedApp as R, type FollowingFeedEmptyReason as S, type FollowingFeedResponse as T, type FollowingFeedVersion as U, type FollowingResponse as V, type GetAdminReviewQueuesOptions as W, type GithubPullRequest as X, type GivenConfirmation as Y, HIDDEN_ITEM_SOURCES as Z, HIDDEN_ITEM_TYPES as _, type ConfirmEndorsementResult as a, bulkHideProfileItems as a$, type HeatmapResponse as a0, type HiddenActivityItem as a1, type HiddenApp as a2, type HiddenItemSource as a3, type HiddenItemType as a4, type HideActivityItemInput as a5, type HideProfileItemInput as a6, type InboxCounts as a7, type ListFeatureAllowlistOptions as a8, type MyGithubPullRequestsResponse as a9, type ReactionStatus as aA, type RefreshOrcidPublicationsResult as aB, type RefreshPdsResult as aC, type RepoDeleteInput as aD, type ResetProfileResult as aE, type ResolveQuotedPostsOptions as aF, type RoadmapVoteError as aG, type RoadmapVoteResult as aH, type RoadmapVoter as aI, type RoadmapVotesResponse as aJ, type SifaQueryKey as aK, type SimilarProfile as aL, type StatsResponse as aM, type SubCategoryBulkResult as aN, type SuggestionProfile as aO, type SuggestionsResponse as aP, type UnhideActivityItemInput as aQ, type UnlinkedPosition as aR, type UnlinkedPositionsResult as aS, type UpdateProfileOverrideInput as aT, type UpdateProfileSelfInput as aU, type UploadAvatarResult as aV, type UploadPronunciationAudioResult as aW, type VerifyExternalAccountResult as aX, type WipePreview as aY, addFeatureAllowlist as aZ, addOrgNotificationEmail as a_, type OrgClaimBinding as aa, type OrgClaimResult as ab, type OrgDomainChallengeResult as ac, type OrgDomainVerifyResult as ad, type OrgNotificationEmailAddResult as ae, type OrgNotificationEmailRemoveResult as af, type OrgProfileEcho as ag, type OrgProfileUpdateResult as ah, PROFILE_COMPLETENESS_SIGNALS as ai, type PdsWipeOutcome as aj, type PendingConfirmation as ak, type PendingConfirmationsPage as al, type PrimarySection as am, type ProfileCompleteness as an, type ProfileCompletenessSignal as ao, type ProfileIndustryInput as ap, type ProfileLocationAddress as aq, type ProfileLocationInput as ar, type ProfileSelfLocation as as, QUOTED_POSTS_BATCH_MAX as at, type QuotedPostAuthor as au, type QuotedPostImage as av, type QuotedPostResult as aw, type QuotedPostView as ax, type ReactionError as ay, type ReactionResult as az, type AccountSummary as b, refreshPds as b$, bulkHideStandardPublications as b0, bulkUnhideProfileItems as b1, bulkUnhideStandardPublications as b2, castRoadmapVote as b3, checkAppAccount as b4, confirmEndorsement as b5, createConfirmation as b6, createEndorsement as b7, createExternalAccount as b8, createProfileLocation as b9, fetchMyGithubPullRequests as bA, fetchMyRoadmapVotes as bB, fetchPendingConfirmations as bC, fetchProfileCompleteness as bD, fetchReactionStatus as bE, fetchRepoInventory as bF, fetchRoadmapVotes as bG, fetchSimilarProfiles as bH, fetchStats as bI, fetchSuggestionCount as bJ, fetchSuggestions as bK, fetchUnlinkedPositions as bL, fetchWipePreview as bM, followUser as bN, getAdminReviewQueues as bO, getBlueskySuggestions as bP, getFollowers as bQ, getFollowing as bR, getMutuals as bS, hideActivityItem as bT, hideOrcidPublication as bU, hideProfileItem as bV, hideSifaPublication as bW, hideStandardPublication as bX, isNewerFollowingFeed as bY, listFeatureAllowlist as bZ, refreshOrcidPublications as b_, createReaction as ba, createSkill as bb, deleteAccount as bc, deleteAvatarOverride as bd, deleteExternalAccount as be, deleteNamePronunciationAudio as bf, deleteProfileLocation as bg, deleteReaction as bh, deleteRepoRecords as bi, deleteSkill as bj, dismissConfirmation as bk, dismissUnlinkedPosition as bl, fetchAccounts as bm, fetchActivityFeed as bn, fetchActivityTeaser as bo, fetchAppsRegistry as bp, fetchExternalAccounts as bq, fetchFeaturedProfile as br, fetchFollowing as bs, fetchFollowingFeed as bt, fetchFollowingFeedVersion as bu, fetchGivenConfirmations as bv, fetchHeatmapData as bw, fetchHiddenActivityItems as bx, fetchHiddenApps as by, fetchInboxCounts as bz, type ActivityFeedResponse as c, removeFeatureAllowlist as c0, removeOrgNotificationEmail as c1, repoExportUrl as c2, requestOrgDomainChallenge as c3, resetProfile as c4, resolveQuotedPosts as c5, retractRoadmapVote as c6, revokeConfirmation as c7, setExternalAccountPrimary as c8, setSectionPrimary as c9, submitOrgClaim as ca, switchAccount as cb, unfollowUser as cc, unhideActivityItem as cd, unhideOrcidPublication as ce, unhideProfileItem as cf, unhideSifaPublication as cg, unhideStandardPublication as ch, unsetExternalAccountPrimary as ci, unsetSectionPrimary as cj, updateExternalAccount as ck, updateOrgProfile as cl, updateProfileLocation as cm, updateProfileOverride as cn, updateProfileSelf as co, updateSkill as cp, updateSkillSubCategories as cq, uploadAvatar as cr, uploadNamePronunciationAudio as cs, verifyExternalAccount as ct, verifyOrgDomain as cu, type ActivityItem as d, type ActivityItemLinkHealth as e, type ActivityTeaserResponse as f, type AdminReviewQueues as g, type AppRegistryEntry as h, type CastRoadmapVoteResult as i, type CheckAppAccountOptions as j, type ConfirmationInput as k, type ConfirmationSubjectInput as l, type CreateExternalAccountResult as m, type DismissUnlinkedPositionInput as n, type ExternalAccountInput as o, type FeaturedProfile as p, type FetchAccountsOptions as q, type FetchActivityFeedOptions as r, sifaQueryKeys as s, type FetchActivityTeaserOptions as t, type FetchConfirmationsOptions as u, type FetchFollowListOptions as v, type FetchFollowProfilePageOptions as w, type FetchFollowingFeedOptions as x, type FetchHiddenActivityItemsOptions as y, type FetchHiddenAppsOptions as z };
1777
+ export { HIDDEN_ITEM_TYPES as $, type AccountCheckResult as A, type BulkHideProfileItemInput as B, type ConfirmEndorsementInput as C, type DeleteAccountResult as D, type EndorsementInput as E, type FeatureAllowlistResponse as F, type FetchInboxCountsOptions as G, type FetchMyGithubPullRequestsOptions as H, type FetchMyRoadmapVotesOptions as I, type FetchProfileCompletenessOptions as J, type FetchReactionStatusOptions as K, type FetchSuggestionsOptions as L, type FetchUnlinkedPositionsOptions as M, type FollowListPage as N, type FollowProfile as O, type FollowProfilePageResponse as P, type FollowUserResult as Q, type FollowingFeedApp as R, type FollowingFeedBuild as S, type FollowingFeedEmptyReason as T, type FollowingFeedResponse as U, type FollowingFeedVersion as V, type FollowingResponse as W, type GetAdminReviewQueuesOptions as X, type GithubPullRequest as Y, type GivenConfirmation as Z, HIDDEN_ITEM_SOURCES as _, type ConfirmEndorsementResult as a, addOrgNotificationEmail as a$, type HeatmapDay as a0, type HeatmapResponse as a1, type HiddenActivityItem as a2, type HiddenApp as a3, type HiddenItemSource as a4, type HiddenItemType as a5, type HideActivityItemInput as a6, type HideProfileItemInput as a7, type InboxCounts as a8, type ListFeatureAllowlistOptions as a9, type ReactionResult as aA, type ReactionStatus as aB, type RefreshOrcidPublicationsResult as aC, type RefreshPdsResult as aD, type RepoDeleteInput as aE, type ResetProfileResult as aF, type ResolveQuotedPostsOptions as aG, type RoadmapVoteError as aH, type RoadmapVoteResult as aI, type RoadmapVoter as aJ, type RoadmapVotesResponse as aK, type SifaQueryKey as aL, type SimilarProfile as aM, type StatsResponse as aN, type SubCategoryBulkResult as aO, type SuggestionProfile as aP, type SuggestionsResponse as aQ, type UnhideActivityItemInput as aR, type UnlinkedPosition as aS, type UnlinkedPositionsResult as aT, type UpdateProfileOverrideInput as aU, type UpdateProfileSelfInput as aV, type UploadAvatarResult as aW, type UploadPronunciationAudioResult as aX, type VerifyExternalAccountResult as aY, type WipePreview as aZ, addFeatureAllowlist as a_, type MyGithubPullRequestsResponse as aa, type OrgClaimBinding as ab, type OrgClaimResult as ac, type OrgDomainChallengeResult as ad, type OrgDomainVerifyResult as ae, type OrgNotificationEmailAddResult as af, type OrgNotificationEmailRemoveResult as ag, type OrgProfileEcho as ah, type OrgProfileUpdateResult as ai, PROFILE_COMPLETENESS_SIGNALS as aj, type PdsWipeOutcome as ak, type PendingConfirmation as al, type PendingConfirmationsPage as am, type PrimarySection as an, type ProfileCompleteness as ao, type ProfileCompletenessSignal as ap, type ProfileIndustryInput as aq, type ProfileLocationAddress as ar, type ProfileLocationInput as as, type ProfileSelfLocation as at, QUOTED_POSTS_BATCH_MAX as au, type QuotedPostAuthor as av, type QuotedPostImage as aw, type QuotedPostResult as ax, type QuotedPostView as ay, type ReactionError as az, type AccountSummary as b, refreshOrcidPublications as b$, bulkHideProfileItems as b0, bulkHideStandardPublications as b1, bulkUnhideProfileItems as b2, bulkUnhideStandardPublications as b3, castRoadmapVote as b4, checkAppAccount as b5, confirmEndorsement as b6, createConfirmation as b7, createEndorsement as b8, createExternalAccount as b9, fetchInboxCounts as bA, fetchMyGithubPullRequests as bB, fetchMyRoadmapVotes as bC, fetchPendingConfirmations as bD, fetchProfileCompleteness as bE, fetchReactionStatus as bF, fetchRepoInventory as bG, fetchRoadmapVotes as bH, fetchSimilarProfiles as bI, fetchStats as bJ, fetchSuggestionCount as bK, fetchSuggestions as bL, fetchUnlinkedPositions as bM, fetchWipePreview as bN, followUser as bO, getAdminReviewQueues as bP, getBlueskySuggestions as bQ, getFollowers as bR, getFollowing as bS, getMutuals as bT, hideActivityItem as bU, hideOrcidPublication as bV, hideProfileItem as bW, hideSifaPublication as bX, hideStandardPublication as bY, isNewerFollowingFeed as bZ, listFeatureAllowlist as b_, createProfileLocation as ba, createReaction as bb, createSkill as bc, deleteAccount as bd, deleteAvatarOverride as be, deleteExternalAccount as bf, deleteNamePronunciationAudio as bg, deleteProfileLocation as bh, deleteReaction as bi, deleteRepoRecords as bj, deleteSkill as bk, dismissConfirmation as bl, dismissUnlinkedPosition as bm, fetchAccounts as bn, fetchActivityFeed as bo, fetchActivityTeaser as bp, fetchAppsRegistry as bq, fetchExternalAccounts as br, fetchFeaturedProfile as bs, fetchFollowing as bt, fetchFollowingFeed as bu, fetchFollowingFeedVersion as bv, fetchGivenConfirmations as bw, fetchHeatmapData as bx, fetchHiddenActivityItems as by, fetchHiddenApps as bz, type ActivityFeedResponse as c, refreshPds as c0, removeFeatureAllowlist as c1, removeOrgNotificationEmail as c2, repoExportUrl as c3, requestOrgDomainChallenge as c4, resetProfile as c5, resolveQuotedPosts as c6, retractRoadmapVote as c7, revokeConfirmation as c8, setExternalAccountPrimary as c9, setSectionPrimary as ca, submitOrgClaim as cb, switchAccount as cc, unfollowUser as cd, unhideActivityItem as ce, unhideOrcidPublication as cf, unhideProfileItem as cg, unhideSifaPublication as ch, unhideStandardPublication as ci, unsetExternalAccountPrimary as cj, unsetSectionPrimary as ck, updateExternalAccount as cl, updateOrgProfile as cm, updateProfileLocation as cn, updateProfileOverride as co, updateProfileSelf as cp, updateSkill as cq, updateSkillSubCategories as cr, uploadAvatar as cs, uploadNamePronunciationAudio as ct, verifyExternalAccount as cu, verifyOrgDomain as cv, type ActivityItem as d, type ActivityItemLinkHealth as e, type ActivityTeaserResponse as f, type AdminReviewQueues as g, type AppRegistryEntry as h, type CastRoadmapVoteResult as i, type CheckAppAccountOptions as j, type ConfirmationInput as k, type ConfirmationSubjectInput as l, type CreateExternalAccountResult as m, type DismissUnlinkedPositionInput as n, type ExternalAccountInput as o, type FeaturedProfile as p, type FetchAccountsOptions as q, type FetchActivityFeedOptions as r, sifaQueryKeys as s, type FetchActivityTeaserOptions as t, type FetchConfirmationsOptions as u, type FetchFollowListOptions as v, type FetchFollowProfilePageOptions as w, type FetchFollowingFeedOptions as x, type FetchHiddenActivityItemsOptions as y, type FetchHiddenAppsOptions as z };
@@ -1,4 +1,4 @@
1
- import { n as ProfileView } from './types-CYjcuKr4.cjs';
1
+ import { n as ProfileView } from './types-BHnGSJ3z.cjs';
2
2
 
3
3
  /**
4
4
  * Compact professional summary derived from a {@link ProfileView}.
@@ -1,4 +1,4 @@
1
- import { n as ProfileView } from './types-Bl8KYBSl.js';
1
+ import { n as ProfileView } from './types-BKEBVobU.js';
2
2
 
3
3
  /**
4
4
  * Compact professional summary derived from a {@link ProfileView}.
@@ -101,19 +101,28 @@ async function fetchFollowingFeed(config, opts = {}) {
101
101
  async function fetchFollowingFeedVersion(config, opts = {}) {
102
102
  const { query, headers } = await followingFeedRequest(config, opts);
103
103
  try {
104
- return await apiFetch(config, `/api/following/feed/version${query}`, {
104
+ const body = await apiFetch(config, `/api/following/feed/version${query}`, {
105
105
  credentials: "include",
106
106
  cache: "no-store",
107
107
  ...opts,
108
108
  headers
109
109
  });
110
+ return isFollowingFeedVersion(body) ? body : null;
110
111
  } catch {
111
112
  return null;
112
113
  }
113
114
  }
114
- function isNewerFollowingFeed(shownBuiltAt, latestBuiltAt) {
115
- if (!shownBuiltAt || !latestBuiltAt) return false;
116
- return Date.parse(latestBuiltAt) > Date.parse(shownBuiltAt);
115
+ function isFollowingFeedVersion(value) {
116
+ if (typeof value !== "object" || value === null) return false;
117
+ const { builtAt, contentHash } = value;
118
+ const stringOrNull = (v) => v === null || typeof v === "string";
119
+ return stringOrNull(builtAt) && stringOrNull(contentHash) && (builtAt === null || !Number.isNaN(Date.parse(builtAt)));
120
+ }
121
+ function isNewerFollowingFeed(shown, latest) {
122
+ if (shown?.builtAt == null || latest?.builtAt == null || shown.contentHash == null || latest.contentHash == null) {
123
+ return false;
124
+ }
125
+ return Date.parse(latest.builtAt) > Date.parse(shown.builtAt) && latest.contentHash !== shown.contentHash;
117
126
  }
118
127
  export {
119
128
  FOLLOWING_FEED_LXM,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/query/fetchers/follow.ts"],"sourcesContent":["import {\n apiFetch,\n encodeIdentifier,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\nimport type { AccountVerification } from '../../taxonomy/verification-providers.js';\nimport type { ActivityFeedResponse } from './activity.js';\n\nexport interface FollowProfile {\n did: string;\n handle: string;\n displayName?: string;\n headline?: string;\n avatarUrl?: string;\n source: string;\n claimed: boolean;\n followedAt: string;\n blueskyVerified?: boolean;\n blueskyVerifiedAt?: string | null;\n /**\n * Every verification the account holds, across all recognized providers\n * (Bluesky and firehose-sourced ones like mu). Supersedes the Bluesky-only\n * `blueskyVerified` pair for badge rendering. Absent on older API responses.\n */\n verificationBadges?: AccountVerification[];\n}\n\nexport interface FollowingResponse {\n follows: FollowProfile[];\n cursor?: string;\n}\n\n/** People the authenticated user follows. Empty on error. */\nexport async function fetchFollowing(\n config: SifaApiConfig,\n opts: { source?: string; cursor?: string; limit?: number } & ApiFetchOptions = {},\n): Promise<FollowingResponse> {\n const params = new URLSearchParams();\n if (opts.source) params.set('source', opts.source);\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n\n try {\n return await apiFetch<FollowingResponse>(config, `/api/following${qs ? `?${qs}` : ''}`, {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n });\n } catch {\n return { follows: [] };\n }\n}\n\n/**\n * Result of {@link followUser}. Extends {@link WriteResult} with the\n * follow `rkey` returned by sifa-api on success. Self-follow + invalid\n * handle surface as `success: false` with the server-provided message;\n * dup-follow is idempotent (sifa-api E7) and resolves as `success: true`.\n */\nexport type FollowUserResult = WriteResult<{\n rkey?: string;\n /** DID of the followed subject (server-resolved from the handle). */\n subjectDid?: string;\n}>;\n\n/**\n * Create an `id.sifa.graph.follow` record on the caller's PDS via the\n * AppView. Idempotent on duplicate (server catches the unique-violation\n * and returns 200, per sifa-api#673 E7).\n */\nexport function followUser(\n config: SifaApiConfig,\n handle: string,\n opts: { note?: string } & Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<FollowUserResult> {\n const { note, ...rest } = opts;\n return apiWrite<{ rkey?: string; subjectDid?: string }>(\n config,\n `/api/follow/${encodeIdentifier(handle)}`,\n 'POST',\n {\n body: note !== undefined ? { note } : undefined,\n ...rest,\n },\n );\n}\n\n/** Delete the authenticated viewer's `id.sifa.graph.follow` for `handle`. */\nexport function unfollowUser(\n config: SifaApiConfig,\n handle: string,\n opts: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/follow/${encodeIdentifier(handle)}`, 'DELETE', opts);\n}\n\nexport interface FollowListPage {\n follows: FollowProfile[];\n cursor: string | null;\n}\n\nexport interface FetchFollowListOptions extends ApiFetchOptions {\n cursor?: string;\n limit?: number;\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls\n * (mirrors {@link FetchActivityFeedOptions}; required for authenticated\n * server fetches because `credentials: 'include'` does not propagate\n * cookies from RSC).\n */\n cookieHeader?: string;\n}\n\nfunction buildListPath(prefix: string, opts: FetchFollowListOptions): string {\n const params = new URLSearchParams();\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n return `${prefix}${qs ? `?${qs}` : ''}`;\n}\n\n/**\n * Paginated list of `handle`'s followers. Returns an empty page on error\n * so the UI can render a graceful \"no followers yet\" state.\n */\nexport async function getFollowers(\n config: SifaApiConfig,\n handle: string,\n opts: FetchFollowListOptions = {},\n): Promise<FollowListPage> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ follows: FollowProfile[]; cursor?: string | null }>(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handle)}/followers`, opts),\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { follows: res.follows, cursor: res.cursor ?? null };\n } catch {\n return { follows: [], cursor: null };\n }\n}\n\n/** Paginated list of who `handle` follows. */\nexport async function getFollowing(\n config: SifaApiConfig,\n handle: string,\n opts: FetchFollowListOptions = {},\n): Promise<FollowListPage> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ follows: FollowProfile[]; cursor?: string | null }>(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handle)}/following`, opts),\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { follows: res.follows, cursor: res.cursor ?? null };\n } catch {\n return { follows: [], cursor: null };\n }\n}\n\n/** The method binding for the following-feed service-auth token; MUST match the\n * sifa-api endpoint's `lxm`. */\nexport const FOLLOWING_FEED_LXM = 'id.sifa.feed.getFollowingFeed';\n\n/** One app the viewer's network is active on, for the feed's source tabs. */\nexport interface FollowingFeedApp {\n /** Registry app id, e.g. `tangled`. Pass back as {@link FetchFollowingFeedOptions.app}. */\n id: string;\n name: string;\n /** Summed recent activity across the network; the tab ordering. */\n count: number;\n}\n\n/**\n * Why a following-feed page came back empty. Lets a client say something true\n * per case instead of one catch-all sentence, and point at the right next step.\n */\nexport type FollowingFeedEmptyReason =\n | 'no_follows'\n | 'no_visible_follows'\n | 'no_cross_app_activity'\n | 'no_recent_records'\n | 'all_hidden'\n | 'nothing_renderable'\n | 'hydration_failed'\n /** The feed is still being built. Nothing is wrong: ask again shortly. */\n | 'building';\n\n/** Options for {@link fetchFollowingFeed}. */\nexport interface FetchFollowingFeedOptions extends ApiFetchOptions {\n limit?: number;\n /**\n * Opt in to the viewer's Bluesky activity too. Off by default: the point of\n * the feed is what connections do on OTHER apps.\n *\n * Ignored when {@link app} is set, since a source tab selects one app.\n */\n includeBluesky?: boolean;\n /**\n * Restrict the page to one app (a registry id from the response's `apps`).\n * This is what a source tab selects. `app: 'bluesky'` selects Bluesky even\n * though it is excluded from the default mixed view.\n */\n app?: string;\n /** Forward a `Cookie` header on Next.js RSC server-side calls (web). */\n cookieHeader?: string;\n}\n\n/** The following feed's response: an activity feed plus its tab metadata. */\nexport interface FollowingFeedResponse extends ActivityFeedResponse {\n /**\n * Apps the viewer's network is actually active on, most active first.\n * Present on empty pages too, so a client's tabs survive a quiet tab.\n */\n apps?: FollowingFeedApp[];\n /** Set only when `items` is empty. */\n reason?: FollowingFeedEmptyReason;\n /** When this feed was built (ISO 8601). Absent on a `building` answer. */\n builtAt?: string;\n /**\n * True when this is an older build, served while a newer one is built in\n * the background. Poll {@link fetchFollowingFeedVersion} to learn when the\n * newer one is ready.\n */\n stale?: boolean;\n}\n\n/** Query string and auth headers shared by the feed and its version check. */\nasync function followingFeedRequest(config: SifaApiConfig, opts: FetchFollowingFeedOptions) {\n const params = new URLSearchParams();\n if (opts.limit) params.set('limit', String(opts.limit));\n // A selected tab decides Bluesky on its own, so the flag is not also sent.\n if (opts.app) params.set('app', opts.app);\n else if (opts.includeBluesky) params.set('includeBluesky', 'true');\n const qs = params.toString();\n\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n if (config.getAuthToken) {\n const token = await config.getAuthToken(FOLLOWING_FEED_LXM);\n if (token) headers.Authorization = `Bearer ${token}`;\n }\n return { query: qs ? `?${qs}` : '', headers };\n}\n\n/**\n * The viewer's cross-app following feed: what OTHER apps their connections use\n * (Tangled, WhiteWind, Smoke Signal, ...) — Bluesky is excluded server-side by\n * default, as it is the least interesting part and other apps already surface\n * it. Pass `includeBluesky: true` to bring it back in.\n *\n * Auth is identity-only server-side, so the NATIVE app supplies\n * `config.getAuthToken` to mint a service-auth Bearer, while WEB relies on its\n * session cookie (`credentials: 'include'`). Returns `null` on error. v1 is a\n * finite first page (no cursor yet).\n */\nexport async function fetchFollowingFeed(\n config: SifaApiConfig,\n opts: FetchFollowingFeedOptions = {},\n): Promise<FollowingFeedResponse | null> {\n const { query, headers } = await followingFeedRequest(config, opts);\n try {\n return await apiFetch<FollowingFeedResponse>(config, `/api/following/feed${query}`, {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n headers,\n });\n } catch {\n return null;\n }\n}\n\n/** When the cached following feed for a query was built. */\nexport interface FollowingFeedVersion {\n /** ISO 8601, or null when nothing is cached for this query. */\n builtAt: string | null;\n}\n\n/**\n * When the cached following feed for the same query was built. Cheap: it never\n * builds a feed. A client showing a `stale` feed polls this and offers the\n * newer one once {@link isNewerFollowingFeed} says so. Returns `null` on error.\n */\nexport async function fetchFollowingFeedVersion(\n config: SifaApiConfig,\n opts: FetchFollowingFeedOptions = {},\n): Promise<FollowingFeedVersion | null> {\n const { query, headers } = await followingFeedRequest(config, opts);\n try {\n return await apiFetch<FollowingFeedVersion>(config, `/api/following/feed/version${query}`, {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n headers,\n });\n } catch {\n return null;\n }\n}\n\n/** True when `latestBuiltAt` is a newer build than the one shown (`shownBuiltAt`). */\nexport function isNewerFollowingFeed(\n shownBuiltAt: string | null | undefined,\n latestBuiltAt: string | null | undefined,\n): boolean {\n if (!shownBuiltAt || !latestBuiltAt) return false;\n return Date.parse(latestBuiltAt) > Date.parse(shownBuiltAt);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/query/fetchers/follow.ts"],"sourcesContent":["import {\n apiFetch,\n encodeIdentifier,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\nimport type { AccountVerification } from '../../taxonomy/verification-providers.js';\nimport type { ActivityFeedResponse } from './activity.js';\n\nexport interface FollowProfile {\n did: string;\n handle: string;\n displayName?: string;\n headline?: string;\n avatarUrl?: string;\n source: string;\n claimed: boolean;\n followedAt: string;\n blueskyVerified?: boolean;\n blueskyVerifiedAt?: string | null;\n /**\n * Every verification the account holds, across all recognized providers\n * (Bluesky and firehose-sourced ones like mu). Supersedes the Bluesky-only\n * `blueskyVerified` pair for badge rendering. Absent on older API responses.\n */\n verificationBadges?: AccountVerification[];\n}\n\nexport interface FollowingResponse {\n follows: FollowProfile[];\n cursor?: string;\n}\n\n/** People the authenticated user follows. Empty on error. */\nexport async function fetchFollowing(\n config: SifaApiConfig,\n opts: { source?: string; cursor?: string; limit?: number } & ApiFetchOptions = {},\n): Promise<FollowingResponse> {\n const params = new URLSearchParams();\n if (opts.source) params.set('source', opts.source);\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n\n try {\n return await apiFetch<FollowingResponse>(config, `/api/following${qs ? `?${qs}` : ''}`, {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n });\n } catch {\n return { follows: [] };\n }\n}\n\n/**\n * Result of {@link followUser}. Extends {@link WriteResult} with the\n * follow `rkey` returned by sifa-api on success. Self-follow + invalid\n * handle surface as `success: false` with the server-provided message;\n * dup-follow is idempotent (sifa-api E7) and resolves as `success: true`.\n */\nexport type FollowUserResult = WriteResult<{\n rkey?: string;\n /** DID of the followed subject (server-resolved from the handle). */\n subjectDid?: string;\n}>;\n\n/**\n * Create an `id.sifa.graph.follow` record on the caller's PDS via the\n * AppView. Idempotent on duplicate (server catches the unique-violation\n * and returns 200, per sifa-api#673 E7).\n */\nexport function followUser(\n config: SifaApiConfig,\n handle: string,\n opts: { note?: string } & Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<FollowUserResult> {\n const { note, ...rest } = opts;\n return apiWrite<{ rkey?: string; subjectDid?: string }>(\n config,\n `/api/follow/${encodeIdentifier(handle)}`,\n 'POST',\n {\n body: note !== undefined ? { note } : undefined,\n ...rest,\n },\n );\n}\n\n/** Delete the authenticated viewer's `id.sifa.graph.follow` for `handle`. */\nexport function unfollowUser(\n config: SifaApiConfig,\n handle: string,\n opts: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n return apiWrite(config, `/api/follow/${encodeIdentifier(handle)}`, 'DELETE', opts);\n}\n\nexport interface FollowListPage {\n follows: FollowProfile[];\n cursor: string | null;\n}\n\nexport interface FetchFollowListOptions extends ApiFetchOptions {\n cursor?: string;\n limit?: number;\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls\n * (mirrors {@link FetchActivityFeedOptions}; required for authenticated\n * server fetches because `credentials: 'include'` does not propagate\n * cookies from RSC).\n */\n cookieHeader?: string;\n}\n\nfunction buildListPath(prefix: string, opts: FetchFollowListOptions): string {\n const params = new URLSearchParams();\n if (opts.cursor) params.set('cursor', opts.cursor);\n if (opts.limit) params.set('limit', String(opts.limit));\n const qs = params.toString();\n return `${prefix}${qs ? `?${qs}` : ''}`;\n}\n\n/**\n * Paginated list of `handle`'s followers. Returns an empty page on error\n * so the UI can render a graceful \"no followers yet\" state.\n */\nexport async function getFollowers(\n config: SifaApiConfig,\n handle: string,\n opts: FetchFollowListOptions = {},\n): Promise<FollowListPage> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ follows: FollowProfile[]; cursor?: string | null }>(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handle)}/followers`, opts),\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { follows: res.follows, cursor: res.cursor ?? null };\n } catch {\n return { follows: [], cursor: null };\n }\n}\n\n/** Paginated list of who `handle` follows. */\nexport async function getFollowing(\n config: SifaApiConfig,\n handle: string,\n opts: FetchFollowListOptions = {},\n): Promise<FollowListPage> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ follows: FollowProfile[]; cursor?: string | null }>(\n config,\n buildListPath(`/api/profile/${encodeIdentifier(handle)}/following`, opts),\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { follows: res.follows, cursor: res.cursor ?? null };\n } catch {\n return { follows: [], cursor: null };\n }\n}\n\n/** The method binding for the following-feed service-auth token; MUST match the\n * sifa-api endpoint's `lxm`. */\nexport const FOLLOWING_FEED_LXM = 'id.sifa.feed.getFollowingFeed';\n\n/** One app the viewer's network is active on, for the feed's source tabs. */\nexport interface FollowingFeedApp {\n /** Registry app id, e.g. `tangled`. Pass back as {@link FetchFollowingFeedOptions.app}. */\n id: string;\n name: string;\n /** Summed recent activity across the network; the tab ordering. */\n count: number;\n}\n\n/**\n * Why a following-feed page came back empty. Lets a client say something true\n * per case instead of one catch-all sentence, and point at the right next step.\n */\nexport type FollowingFeedEmptyReason =\n | 'no_follows'\n | 'no_visible_follows'\n | 'no_cross_app_activity'\n | 'no_recent_records'\n | 'all_hidden'\n | 'nothing_renderable'\n | 'hydration_failed'\n /** The feed is still being built. Nothing is wrong: ask again shortly. */\n | 'building';\n\n/** Options for {@link fetchFollowingFeed}. */\nexport interface FetchFollowingFeedOptions extends ApiFetchOptions {\n limit?: number;\n /**\n * Opt in to the viewer's Bluesky activity too. Off by default: the point of\n * the feed is what connections do on OTHER apps.\n *\n * Ignored when {@link app} is set, since a source tab selects one app.\n */\n includeBluesky?: boolean;\n /**\n * Restrict the page to one app (a registry id from the response's `apps`).\n * This is what a source tab selects. `app: 'bluesky'` selects Bluesky even\n * though it is excluded from the default mixed view.\n */\n app?: string;\n /** Forward a `Cookie` header on Next.js RSC server-side calls (web). */\n cookieHeader?: string;\n}\n\n/** The following feed's response: an activity feed plus its tab metadata. */\nexport interface FollowingFeedResponse extends ActivityFeedResponse {\n /**\n * Apps the viewer's network is actually active on, most active first.\n * Present on empty pages too, so a client's tabs survive a quiet tab.\n */\n apps?: FollowingFeedApp[];\n /** Set only when `items` is empty. */\n reason?: FollowingFeedEmptyReason;\n /** When this feed was built (ISO 8601). Absent on a `building` answer. */\n builtAt?: string;\n /**\n * Fingerprint of the items shown. Equal for a rebuild that found nothing\n * new, so compare it (with {@link isNewerFollowingFeed}) rather than times.\n */\n contentHash?: string;\n /**\n * True when this is an older build, served while a newer one is built in\n * the background. Poll {@link fetchFollowingFeedVersion} to learn when the\n * newer one is ready.\n */\n stale?: boolean;\n}\n\n/** Query string and auth headers shared by the feed and its version check. */\nasync function followingFeedRequest(config: SifaApiConfig, opts: FetchFollowingFeedOptions) {\n const params = new URLSearchParams();\n if (opts.limit) params.set('limit', String(opts.limit));\n // A selected tab decides Bluesky on its own, so the flag is not also sent.\n if (opts.app) params.set('app', opts.app);\n else if (opts.includeBluesky) params.set('includeBluesky', 'true');\n const qs = params.toString();\n\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n if (config.getAuthToken) {\n const token = await config.getAuthToken(FOLLOWING_FEED_LXM);\n if (token) headers.Authorization = `Bearer ${token}`;\n }\n return { query: qs ? `?${qs}` : '', headers };\n}\n\n/**\n * The viewer's cross-app following feed: what OTHER apps their connections use\n * (Tangled, WhiteWind, Smoke Signal, ...) — Bluesky is excluded server-side by\n * default, as it is the least interesting part and other apps already surface\n * it. Pass `includeBluesky: true` to bring it back in.\n *\n * Auth is identity-only server-side, so the NATIVE app supplies\n * `config.getAuthToken` to mint a service-auth Bearer, while WEB relies on its\n * session cookie (`credentials: 'include'`). Returns `null` on error. v1 is a\n * finite first page (no cursor yet).\n */\nexport async function fetchFollowingFeed(\n config: SifaApiConfig,\n opts: FetchFollowingFeedOptions = {},\n): Promise<FollowingFeedResponse | null> {\n const { query, headers } = await followingFeedRequest(config, opts);\n try {\n return await apiFetch<FollowingFeedResponse>(config, `/api/following/feed${query}`, {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n headers,\n });\n } catch {\n return null;\n }\n}\n\n/** When the cached following feed for a query was built. */\nexport interface FollowingFeedVersion {\n /** ISO 8601, or null when nothing is cached for this query. */\n builtAt: string | null;\n /** Fingerprint of the cached feed's items, or null when unknown. */\n contentHash: string | null;\n}\n\n/**\n * When the cached following feed for the same query was built. Cheap: it never\n * builds a feed. A client showing a `stale` feed polls this and offers the\n * newer one once {@link isNewerFollowingFeed} says so. Returns `null` on error.\n */\nexport async function fetchFollowingFeedVersion(\n config: SifaApiConfig,\n opts: FetchFollowingFeedOptions = {},\n): Promise<FollowingFeedVersion | null> {\n const { query, headers } = await followingFeedRequest(config, opts);\n try {\n const body = await apiFetch<unknown>(config, `/api/following/feed/version${query}`, {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n headers,\n });\n return isFollowingFeedVersion(body) ? body : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Shape check for the version response. Hand-written rather than a zod schema:\n * this runs in the browser, and zod is kept out of client bundles.\n */\nfunction isFollowingFeedVersion(value: unknown): value is FollowingFeedVersion {\n if (typeof value !== 'object' || value === null) return false;\n const { builtAt, contentHash } = value as Record<string, unknown>;\n const stringOrNull = (v: unknown) => v === null || typeof v === 'string';\n return (\n stringOrNull(builtAt) &&\n stringOrNull(contentHash) &&\n (builtAt === null || !Number.isNaN(Date.parse(builtAt)))\n );\n}\n\n/** The parts of a feed build that {@link isNewerFollowingFeed} compares. */\nexport type FollowingFeedBuild = Partial<FollowingFeedVersion>;\n\n/**\n * True when `latest` is a newer build than the one shown AND shows different\n * items. A rebuild that found nothing new has the same fingerprint, and\n * offering it would show nothing new. Missing data on either side is false:\n * better to miss an offer than to make an empty one.\n */\nexport function isNewerFollowingFeed(\n shown: FollowingFeedBuild | null | undefined,\n latest: FollowingFeedBuild | null | undefined,\n): boolean {\n if (\n shown?.builtAt == null ||\n latest?.builtAt == null ||\n shown.contentHash == null ||\n latest.contentHash == null\n ) {\n return false;\n }\n return (\n Date.parse(latest.builtAt) > Date.parse(shown.builtAt) &&\n latest.contentHash !== shown.contentHash\n );\n}\n"],"mappings":"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","names":[]}
@@ -852,11 +852,17 @@ async function switchAccount(config, did, options = {}) {
852
852
  var EMPTY_SEARCH = { profiles: [], total: 0, limit: 20, offset: 0 };
853
853
  var EMPTY_FILTERS = { countries: [], industries: [], apps: [], openTo: [] };
854
854
  var EMPTY_COMPANY_SEARCH = { results: [], hasMore: false };
855
+ function appendAll(params, key, value) {
856
+ if (!value) return;
857
+ for (const v of Array.isArray(value) ? value : [value]) {
858
+ if (v) params.append(key, v);
859
+ }
860
+ }
855
861
  async function fetchSearchProfiles(config, filters, options = {}) {
856
862
  const params = new URLSearchParams();
857
863
  if (filters.q) params.set("q", filters.q);
858
- if (filters.skill) params.set("skill", filters.skill);
859
- if (filters.country) params.set("country", filters.country);
864
+ appendAll(params, "skill", filters.skill);
865
+ appendAll(params, "country", filters.country);
860
866
  if (filters.industry) params.set("industry", filters.industry);
861
867
  if (filters.domain) params.set("domain", filters.domain);
862
868
  if (filters.workplace) params.set("workplace", filters.workplace);
@@ -1113,19 +1119,28 @@ async function fetchFollowingFeed(config, opts = {}) {
1113
1119
  async function fetchFollowingFeedVersion(config, opts = {}) {
1114
1120
  const { query, headers } = await followingFeedRequest(config, opts);
1115
1121
  try {
1116
- return await apiFetch(config, `/api/following/feed/version${query}`, {
1122
+ const body = await apiFetch(config, `/api/following/feed/version${query}`, {
1117
1123
  credentials: "include",
1118
1124
  cache: "no-store",
1119
1125
  ...opts,
1120
1126
  headers
1121
1127
  });
1128
+ return isFollowingFeedVersion(body) ? body : null;
1122
1129
  } catch {
1123
1130
  return null;
1124
1131
  }
1125
1132
  }
1126
- function isNewerFollowingFeed(shownBuiltAt, latestBuiltAt) {
1127
- if (!shownBuiltAt || !latestBuiltAt) return false;
1128
- return Date.parse(latestBuiltAt) > Date.parse(shownBuiltAt);
1133
+ function isFollowingFeedVersion(value) {
1134
+ if (typeof value !== "object" || value === null) return false;
1135
+ const { builtAt, contentHash } = value;
1136
+ const stringOrNull = (v) => v === null || typeof v === "string";
1137
+ return stringOrNull(builtAt) && stringOrNull(contentHash) && (builtAt === null || !Number.isNaN(Date.parse(builtAt)));
1138
+ }
1139
+ function isNewerFollowingFeed(shown, latest) {
1140
+ if (shown?.builtAt == null || latest?.builtAt == null || shown.contentHash == null || latest.contentHash == null) {
1141
+ return false;
1142
+ }
1143
+ return Date.parse(latest.builtAt) > Date.parse(shown.builtAt) && latest.contentHash !== shown.contentHash;
1129
1144
  }
1130
1145
 
1131
1146
  // src/query/fetchers/follow-extras.ts