@singi-labs/sifa-sdk 0.19.43 → 0.19.45
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/atproto/index.js +9 -3
- package/dist/atproto/index.js.map +1 -1
- package/dist/badge/index.js +5 -141
- package/dist/badge/index.js.map +1 -1
- package/dist/cards/adult-content.js +14 -0
- package/dist/cards/adult-content.js.map +1 -0
- package/dist/cards/app-url-patterns.js +369 -0
- package/dist/cards/app-url-patterns.js.map +1 -0
- package/dist/cards/index.js +24 -0
- package/dist/cards/index.js.map +1 -0
- package/dist/cards/resolve-card-url.js +198 -0
- package/dist/cards/resolve-card-url.js.map +1 -0
- package/dist/cards/visibility.js +45 -0
- package/dist/cards/visibility.js.map +1 -0
- package/dist/flags/index.js +4 -3
- package/dist/flags/index.js.map +1 -1
- package/dist/format/collapse-contributors.js +19 -0
- package/dist/format/collapse-contributors.js.map +1 -0
- package/dist/format/company-name.js +61 -0
- package/dist/format/company-name.js.map +1 -0
- package/dist/format/compare-text.js +9 -0
- package/dist/format/compare-text.js.map +1 -0
- package/dist/format/doi.js +8 -0
- package/dist/format/doi.js.map +1 -0
- package/dist/format/embed.js +131 -0
- package/dist/format/embed.js.map +1 -0
- package/dist/format/endorsement-context.js +35 -0
- package/dist/format/endorsement-context.js.map +1 -0
- package/dist/format/format-display-url.js +42 -0
- package/dist/format/format-display-url.js.map +1 -0
- package/dist/format/format-duration.js +13 -0
- package/dist/format/format-duration.js.map +1 -0
- package/dist/format/format-time.js +30 -0
- package/dist/format/format-time.js.map +1 -0
- package/dist/format/handle-utils.js +19 -0
- package/dist/format/handle-utils.js.map +1 -0
- package/dist/format/index.js +100 -0
- package/dist/format/index.js.map +1 -0
- package/dist/format/location-segments.js +29 -0
- package/dist/format/location-segments.js.map +1 -0
- package/dist/format/location-utils.js +42 -0
- package/dist/format/location-utils.js.map +1 -0
- package/dist/format/meta-description.js +35 -0
- package/dist/format/meta-description.js.map +1 -0
- package/dist/format/normalize-company-key.js +12 -0
- package/dist/format/normalize-company-key.js.map +1 -0
- package/dist/format/normalize-legal-form.js +71 -0
- package/dist/format/normalize-legal-form.js.map +1 -0
- package/dist/format/pds-utils.js +73 -0
- package/dist/format/pds-utils.js.map +1 -0
- package/dist/format/sort-by-date.js +39 -0
- package/dist/format/sort-by-date.js.map +1 -0
- package/dist/format/summarize-deliveries.js +37 -0
- package/dist/format/summarize-deliveries.js.map +1 -0
- package/dist/format/talk-slug.js +21 -0
- package/dist/format/talk-slug.js.map +1 -0
- package/dist/format/text-sanitize.js +29 -0
- package/dist/format/text-sanitize.js.map +1 -0
- package/dist/format/text-truncate.js +14 -0
- package/dist/format/text-truncate.js.map +1 -0
- package/dist/format/time-utils.js +19 -0
- package/dist/format/time-utils.js.map +1 -0
- package/dist/format/timeline.js +29 -0
- package/dist/format/timeline.js.map +1 -0
- package/dist/format/wcag-contrast.js +34 -0
- package/dist/format/wcag-contrast.js.map +1 -0
- package/dist/import/index.js +22 -0
- package/dist/import/index.js.map +1 -0
- package/dist/import/presentation-csv.js +116 -0
- package/dist/import/presentation-csv.js.map +1 -0
- package/dist/index.cjs +8 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +675 -7080
- package/dist/index.js.map +1 -1
- package/dist/jev/index.js +18 -5
- package/dist/jev/index.js.map +1 -1
- package/dist/jsonld/index.cjs.map +1 -1
- package/dist/jsonld/index.js +30 -987
- package/dist/jsonld/index.js.map +1 -1
- package/dist/jsonld/profile.js +222 -0
- package/dist/jsonld/profile.js.map +1 -0
- package/dist/jsonld/terms.js +496 -0
- package/dist/jsonld/terms.js.map +1 -0
- package/dist/jsonld/url.js +17 -0
- package/dist/jsonld/url.js.map +1 -0
- package/dist/jsonld/works-graph.js +41 -0
- package/dist/jsonld/works-graph.js.map +1 -0
- package/dist/jsonld/works.js +178 -0
- package/dist/jsonld/works.js.map +1 -0
- package/dist/logic/actor-identity.js +8 -0
- package/dist/logic/actor-identity.js.map +1 -0
- package/dist/logic/agent-ref.js +24 -0
- package/dist/logic/agent-ref.js.map +1 -0
- package/dist/logic/company-page-indexable.js +23 -0
- package/dist/logic/company-page-indexable.js.map +1 -0
- package/dist/logic/date-lookahead.js +31 -0
- package/dist/logic/date-lookahead.js.map +1 -0
- package/dist/logic/domain-detect.js +43 -0
- package/dist/logic/domain-detect.js.map +1 -0
- package/dist/logic/entity-disambiguation.js +24 -0
- package/dist/logic/entity-disambiguation.js.map +1 -0
- package/dist/logic/entity-ref-anchor.js +33 -0
- package/dist/logic/entity-ref-anchor.js.map +1 -0
- package/dist/logic/index.js +91 -0
- package/dist/logic/index.js.map +1 -0
- package/dist/logic/org-floor.js +66 -0
- package/dist/logic/org-floor.js.map +1 -0
- package/dist/logic/primary-item.js +9 -0
- package/dist/logic/primary-item.js.map +1 -0
- package/dist/logic/primary-position.js +16 -0
- package/dist/logic/primary-position.js.map +1 -0
- package/dist/logic/profile-completeness.js +21 -0
- package/dist/logic/profile-completeness.js.map +1 -0
- package/dist/logic/profile-dimensions.js +50 -0
- package/dist/logic/profile-dimensions.js.map +1 -0
- package/dist/logic/profile-summary.js +23 -0
- package/dist/logic/profile-summary.js.map +1 -0
- package/dist/logic/pseudo-employer.js +34 -0
- package/dist/logic/pseudo-employer.js.map +1 -0
- package/dist/logic/recent-activity.js +10 -0
- package/dist/logic/recent-activity.js.map +1 -0
- package/dist/logic/self-app.js +10 -0
- package/dist/logic/self-app.js.map +1 -0
- package/dist/{org-BCrvebcf.d.ts → org-CxTEjjrm.d.ts} +1 -1
- package/dist/{org-settings-C73Sin5E.d.ts → org-settings-BShvhyFp.d.ts} +1 -1
- package/dist/profile/headline-role-dedupe.js +12 -0
- package/dist/profile/headline-role-dedupe.js.map +1 -0
- package/dist/profile/highlights.js +200 -0
- package/dist/profile/highlights.js.map +1 -0
- package/dist/profile/index.js +66 -0
- package/dist/profile/index.js.map +1 -0
- package/dist/profile/involvement-grouping.js +31 -0
- package/dist/profile/involvement-grouping.js.map +1 -0
- package/dist/profile/language-sort.js +24 -0
- package/dist/profile/language-sort.js.map +1 -0
- package/dist/profile/publication-versions.js +98 -0
- package/dist/profile/publication-versions.js.map +1 -0
- package/dist/profile/range-sort.js +14 -0
- package/dist/profile/range-sort.js.map +1 -0
- package/dist/profile/section-model.js +122 -0
- package/dist/profile/section-model.js.map +1 -0
- package/dist/profile/section-sorts.js +33 -0
- package/dist/profile/section-sorts.js.map +1 -0
- package/dist/publishers/index.js +16 -0
- package/dist/publishers/index.js.map +1 -0
- package/dist/publishers/registry.js +87 -0
- package/dist/publishers/registry.js.map +1 -0
- package/dist/publishing/index.js +46 -184
- package/dist/publishing/index.js.map +1 -1
- package/dist/publishing/linkblog.js +42 -0
- package/dist/publishing/linkblog.js.map +1 -0
- package/dist/publishing/registry.js +32 -0
- package/dist/publishing/registry.js.map +1 -0
- package/dist/publishing/schemas.js +74 -0
- package/dist/publishing/schemas.js.map +1 -0
- package/dist/publishing/types.js +32 -0
- package/dist/publishing/types.js.map +1 -0
- package/dist/query/client.js +119 -0
- package/dist/query/client.js.map +1 -0
- package/dist/query/config.js +23 -0
- package/dist/query/config.js.map +1 -0
- package/dist/query/fetchers/accounts.js +29 -0
- package/dist/query/fetchers/accounts.js.map +1 -0
- package/dist/query/fetchers/activity-items-hide.js +31 -0
- package/dist/query/fetchers/activity-items-hide.js.map +1 -0
- package/dist/query/fetchers/activity.js +61 -0
- package/dist/query/fetchers/activity.js.map +1 -0
- package/dist/query/fetchers/actor.js +30 -0
- package/dist/query/fetchers/actor.js.map +1 -0
- package/dist/query/fetchers/admin-feature-allowlists.js +41 -0
- package/dist/query/fetchers/admin-feature-allowlists.js.map +1 -0
- package/dist/query/fetchers/admin-review-queues.js +30 -0
- package/dist/query/fetchers/admin-review-queues.js.map +1 -0
- package/dist/query/fetchers/apps.js +31 -0
- package/dist/query/fetchers/apps.js.map +1 -0
- package/dist/query/fetchers/bsky-preferences.js +55 -0
- package/dist/query/fetchers/bsky-preferences.js.map +1 -0
- package/dist/query/fetchers/confirmations.js +55 -0
- package/dist/query/fetchers/confirmations.js.map +1 -0
- package/dist/query/fetchers/destructive.js +34 -0
- package/dist/query/fetchers/destructive.js.map +1 -0
- package/dist/query/fetchers/discovery.js +67 -0
- package/dist/query/fetchers/discovery.js.map +1 -0
- package/dist/query/fetchers/education.js +23 -0
- package/dist/query/fetchers/education.js.map +1 -0
- package/dist/query/fetchers/endorsement-inbox.js +36 -0
- package/dist/query/fetchers/endorsement-inbox.js.map +1 -0
- package/dist/query/fetchers/endorsement.js +23 -0
- package/dist/query/fetchers/endorsement.js.map +1 -0
- package/dist/query/fetchers/endorsements.js +20 -0
- package/dist/query/fetchers/endorsements.js.map +1 -0
- package/dist/query/fetchers/entities.js +65 -0
- package/dist/query/fetchers/entities.js.map +1 -0
- package/dist/query/fetchers/external-accounts.js +74 -0
- package/dist/query/fetchers/external-accounts.js.map +1 -0
- package/dist/query/fetchers/follow-extras.js +38 -0
- package/dist/query/fetchers/follow-extras.js.map +1 -0
- package/dist/query/fetchers/follow.js +105 -0
- package/dist/query/fetchers/follow.js.map +1 -0
- package/dist/query/fetchers/get-profile-view.js +21 -0
- package/dist/query/fetchers/get-profile-view.js.map +1 -0
- package/dist/query/fetchers/github-prs.js +45 -0
- package/dist/query/fetchers/github-prs.js.map +1 -0
- package/dist/query/fetchers/inbox.js +29 -0
- package/dist/query/fetchers/inbox.js.map +1 -0
- package/dist/query/fetchers/index.d.ts +2 -2
- package/dist/query/fetchers/index.js +360 -2045
- package/dist/query/fetchers/index.js.map +1 -1
- package/dist/query/fetchers/investments.js +18 -0
- package/dist/query/fetchers/investments.js.map +1 -0
- package/dist/query/fetchers/keytrace-claims.js +23 -0
- package/dist/query/fetchers/keytrace-claims.js.map +1 -0
- package/dist/query/fetchers/marque-domains.js +23 -0
- package/dist/query/fetchers/marque-domains.js.map +1 -0
- package/dist/query/fetchers/network-map.js +36 -0
- package/dist/query/fetchers/network-map.js.map +1 -0
- package/dist/query/fetchers/org.js +48 -0
- package/dist/query/fetchers/org.js.map +1 -0
- package/dist/query/fetchers/positions.js +77 -0
- package/dist/query/fetchers/positions.js.map +1 -0
- package/dist/query/fetchers/profile-completeness.js +45 -0
- package/dist/query/fetchers/profile-completeness.js.map +1 -0
- package/dist/query/fetchers/profile-items-hide.js +36 -0
- package/dist/query/fetchers/profile-items-hide.js.map +1 -0
- package/dist/query/fetchers/profile-locations.js +23 -0
- package/dist/query/fetchers/profile-locations.js.map +1 -0
- package/dist/query/fetchers/profile-mutations.js +82 -0
- package/dist/query/fetchers/profile-mutations.js.map +1 -0
- package/dist/query/fetchers/profile-summary.js +14 -0
- package/dist/query/fetchers/profile-summary.js.map +1 -0
- package/dist/query/fetchers/profile.js +31 -0
- package/dist/query/fetchers/profile.js.map +1 -0
- package/dist/query/fetchers/publications.js +66 -0
- package/dist/query/fetchers/publications.js.map +1 -0
- package/dist/query/fetchers/quoted-posts.js +40 -0
- package/dist/query/fetchers/quoted-posts.js.map +1 -0
- package/dist/query/fetchers/reactions.js +85 -0
- package/dist/query/fetchers/reactions.js.map +1 -0
- package/dist/query/fetchers/received-endorsements.js +20 -0
- package/dist/query/fetchers/received-endorsements.js.map +1 -0
- package/dist/query/fetchers/reciprocity.js +23 -0
- package/dist/query/fetchers/reciprocity.js.map +1 -0
- package/dist/query/fetchers/records.js +27 -0
- package/dist/query/fetchers/records.js.map +1 -0
- package/dist/query/fetchers/repo-inventory.js +23 -0
- package/dist/query/fetchers/repo-inventory.js.map +1 -0
- package/dist/query/fetchers/roadmap.js +73 -0
- package/dist/query/fetchers/roadmap.js.map +1 -0
- package/dist/query/fetchers/rpg.js +36 -0
- package/dist/query/fetchers/rpg.js.map +1 -0
- package/dist/query/fetchers/search.js +78 -0
- package/dist/query/fetchers/search.js.map +1 -0
- package/dist/query/fetchers/section-primary.js +23 -0
- package/dist/query/fetchers/section-primary.js.map +1 -0
- package/dist/query/fetchers/skills.js +30 -0
- package/dist/query/fetchers/skills.js.map +1 -0
- package/dist/query/fetchers/speakers.js +42 -0
- package/dist/query/fetchers/speakers.js.map +1 -0
- package/dist/query/fetchers/stats.js +16 -0
- package/dist/query/fetchers/stats.js.map +1 -0
- package/dist/query/fetchers/stream.js +30 -0
- package/dist/query/fetchers/stream.js.map +1 -0
- package/dist/query/fetchers/unlinked-positions.js +30 -0
- package/dist/query/fetchers/unlinked-positions.js.map +1 -0
- package/dist/query/hooks/index.d.ts +3 -3
- package/dist/query/hooks/index.js +283 -3555
- package/dist/query/hooks/index.js.map +1 -1
- package/dist/query/hooks/use-accounts.js +19 -0
- package/dist/query/hooks/use-accounts.js.map +1 -0
- package/dist/query/hooks/use-activity-items-hide.js +52 -0
- package/dist/query/hooks/use-activity-items-hide.js.map +1 -0
- package/dist/query/hooks/use-activity.js +44 -0
- package/dist/query/hooks/use-activity.js.map +1 -0
- package/dist/query/hooks/use-admin-review-queues.js +21 -0
- package/dist/query/hooks/use-admin-review-queues.js.map +1 -0
- package/dist/query/hooks/use-apps.js +31 -0
- package/dist/query/hooks/use-apps.js.map +1 -0
- package/dist/query/hooks/use-bsky-content-prefs.js +45 -0
- package/dist/query/hooks/use-bsky-content-prefs.js.map +1 -0
- package/dist/query/hooks/use-confirmations.js +121 -0
- package/dist/query/hooks/use-confirmations.js.map +1 -0
- package/dist/query/hooks/use-create-position.js +28 -0
- package/dist/query/hooks/use-create-position.js.map +1 -0
- package/dist/query/hooks/use-destructive.js +63 -0
- package/dist/query/hooks/use-destructive.js.map +1 -0
- package/dist/query/hooks/use-discovery.js +53 -0
- package/dist/query/hooks/use-discovery.js.map +1 -0
- package/dist/query/hooks/use-education-mutations.js +67 -0
- package/dist/query/hooks/use-education-mutations.js.map +1 -0
- package/dist/query/hooks/use-endorsement-inbox.js +80 -0
- package/dist/query/hooks/use-endorsement-inbox.js.map +1 -0
- package/dist/query/hooks/use-endorsement-mutations.js +33 -0
- package/dist/query/hooks/use-endorsement-mutations.js.map +1 -0
- package/dist/query/hooks/use-endorsement.js +20 -0
- package/dist/query/hooks/use-endorsement.js.map +1 -0
- package/dist/query/hooks/use-entity-search.js +73 -0
- package/dist/query/hooks/use-entity-search.js.map +1 -0
- package/dist/query/hooks/use-external-accounts.js +143 -0
- package/dist/query/hooks/use-external-accounts.js.map +1 -0
- package/dist/query/hooks/use-feature-allowlist.js +104 -0
- package/dist/query/hooks/use-feature-allowlist.js.map +1 -0
- package/dist/query/hooks/use-follow-extras.js +38 -0
- package/dist/query/hooks/use-follow-extras.js.map +1 -0
- package/dist/query/hooks/use-follow.js +113 -0
- package/dist/query/hooks/use-follow.js.map +1 -0
- package/dist/query/hooks/use-get-profile-view.js +20 -0
- package/dist/query/hooks/use-get-profile-view.js.map +1 -0
- package/dist/query/hooks/use-github-prs.js +21 -0
- package/dist/query/hooks/use-github-prs.js.map +1 -0
- package/dist/query/hooks/use-inbox.js +19 -0
- package/dist/query/hooks/use-inbox.js.map +1 -0
- package/dist/query/hooks/use-investment-mutations.js +65 -0
- package/dist/query/hooks/use-investment-mutations.js.map +1 -0
- package/dist/query/hooks/use-keytrace-claims.js +50 -0
- package/dist/query/hooks/use-keytrace-claims.js.map +1 -0
- package/dist/query/hooks/use-location-mutations.js +71 -0
- package/dist/query/hooks/use-location-mutations.js.map +1 -0
- package/dist/query/hooks/use-marque-domains.js +50 -0
- package/dist/query/hooks/use-marque-domains.js.map +1 -0
- package/dist/query/hooks/use-org-claim.js +29 -0
- package/dist/query/hooks/use-org-claim.js.map +1 -0
- package/dist/query/hooks/use-org-domains.js +28 -0
- package/dist/query/hooks/use-org-domains.js.map +1 -0
- package/dist/query/hooks/use-org-notification-emails.js +28 -0
- package/dist/query/hooks/use-org-notification-emails.js.map +1 -0
- package/dist/query/hooks/use-org-profile-settings.js +29 -0
- package/dist/query/hooks/use-org-profile-settings.js.map +1 -0
- package/dist/query/hooks/use-org-profile.js +21 -0
- package/dist/query/hooks/use-org-profile.js.map +1 -0
- package/dist/query/hooks/use-position-mutations.js +128 -0
- package/dist/query/hooks/use-position-mutations.js.map +1 -0
- package/dist/query/hooks/use-profile-completeness.js +21 -0
- package/dist/query/hooks/use-profile-completeness.js.map +1 -0
- package/dist/query/hooks/use-profile-items-hide.js +53 -0
- package/dist/query/hooks/use-profile-items-hide.js.map +1 -0
- package/dist/query/hooks/use-profile-mutations.js +143 -0
- package/dist/query/hooks/use-profile-mutations.js.map +1 -0
- package/dist/query/hooks/use-profile.js +30 -0
- package/dist/query/hooks/use-profile.js.map +1 -0
- package/dist/query/hooks/use-publication-mutations.js +90 -0
- package/dist/query/hooks/use-publication-mutations.js.map +1 -0
- package/dist/query/hooks/use-reaction-mutations.js +48 -0
- package/dist/query/hooks/use-reaction-mutations.js.map +1 -0
- package/dist/query/hooks/use-reactions.js +32 -0
- package/dist/query/hooks/use-reactions.js.map +1 -0
- package/dist/query/hooks/use-received-endorsements.js +23 -0
- package/dist/query/hooks/use-received-endorsements.js.map +1 -0
- package/dist/query/hooks/use-reciprocity.js +19 -0
- package/dist/query/hooks/use-reciprocity.js.map +1 -0
- package/dist/query/hooks/use-record-mutations.js +67 -0
- package/dist/query/hooks/use-record-mutations.js.map +1 -0
- package/dist/query/hooks/use-repo-inventory.js +43 -0
- package/dist/query/hooks/use-repo-inventory.js.map +1 -0
- package/dist/query/hooks/use-roadmap-mutations.js +51 -0
- package/dist/query/hooks/use-roadmap-mutations.js.map +1 -0
- package/dist/query/hooks/use-roadmap.js +31 -0
- package/dist/query/hooks/use-roadmap.js.map +1 -0
- package/dist/query/hooks/use-search.js +63 -0
- package/dist/query/hooks/use-search.js.map +1 -0
- package/dist/query/hooks/use-section-primary-mutations.js +53 -0
- package/dist/query/hooks/use-section-primary-mutations.js.map +1 -0
- package/dist/query/hooks/use-skill-mutations.js +91 -0
- package/dist/query/hooks/use-skill-mutations.js.map +1 -0
- package/dist/query/hooks/use-stats.js +19 -0
- package/dist/query/hooks/use-stats.js.map +1 -0
- package/dist/query/hooks/use-stream.js +20 -0
- package/dist/query/hooks/use-stream.js.map +1 -0
- package/dist/query/hooks/use-unlinked-positions.js +45 -0
- package/dist/query/hooks/use-unlinked-positions.js.map +1 -0
- package/dist/query/index.d.ts +4 -4
- package/dist/query/index.js +685 -3744
- package/dist/query/index.js.map +1 -1
- package/dist/query/keys.js +138 -0
- package/dist/query/keys.js.map +1 -0
- package/dist/repo/groups.js +81 -0
- package/dist/repo/groups.js.map +1 -0
- package/dist/repo/index.js +9 -0
- package/dist/repo/index.js.map +1 -0
- package/dist/repo/labels.js +121 -0
- package/dist/repo/labels.js.map +1 -0
- package/dist/repo/types.js +1 -0
- package/dist/repo/types.js.map +1 -0
- package/dist/resume/index.js +5 -179
- package/dist/resume/index.js.map +1 -1
- package/dist/resume/json-resume.js +153 -0
- package/dist/resume/json-resume.js.map +1 -0
- package/dist/roadmap/index.js +101 -0
- package/dist/roadmap/index.js.map +1 -0
- package/dist/rpg/catalog.js +101 -0
- package/dist/rpg/catalog.js.map +1 -0
- package/dist/rpg/index.js +13 -116
- package/dist/rpg/index.js.map +1 -1
- package/dist/rpg/unlocks.js +21 -0
- package/dist/rpg/unlocks.js.map +1 -0
- package/dist/schemas/blob-ref.js +12 -0
- package/dist/schemas/blob-ref.js.map +1 -0
- package/dist/schemas/confirmation.js +23 -0
- package/dist/schemas/confirmation.js.map +1 -0
- package/dist/schemas/endorsement-confirmation.js +18 -0
- package/dist/schemas/endorsement-confirmation.js.map +1 -0
- package/dist/schemas/endorsement.js +19 -0
- package/dist/schemas/endorsement.js.map +1 -0
- package/dist/schemas/entity.js +74 -0
- package/dist/schemas/entity.js.map +1 -0
- package/dist/schemas/feed.js +73 -0
- package/dist/schemas/feed.js.map +1 -0
- package/dist/schemas/follow-profile.js +32 -0
- package/dist/schemas/follow-profile.js.map +1 -0
- package/dist/schemas/graph-follow.js +19 -0
- package/dist/schemas/graph-follow.js.map +1 -0
- package/dist/schemas/index.js +164 -629
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/org-employment-attestation.js +28 -0
- package/dist/schemas/org-employment-attestation.js.map +1 -0
- package/dist/schemas/org-profile.js +64 -0
- package/dist/schemas/org-profile.js.map +1 -0
- package/dist/schemas/profile-certification.js +28 -0
- package/dist/schemas/profile-certification.js.map +1 -0
- package/dist/schemas/profile-course.js +32 -0
- package/dist/schemas/profile-course.js.map +1 -0
- package/dist/schemas/profile-education.js +33 -0
- package/dist/schemas/profile-education.js.map +1 -0
- package/dist/schemas/profile-external-account.js +15 -0
- package/dist/schemas/profile-external-account.js.map +1 -0
- package/dist/schemas/profile-honor.js +18 -0
- package/dist/schemas/profile-honor.js.map +1 -0
- package/dist/schemas/profile-investment.js +48 -0
- package/dist/schemas/profile-investment.js.map +1 -0
- package/dist/schemas/profile-involvement.js +47 -0
- package/dist/schemas/profile-involvement.js.map +1 -0
- package/dist/schemas/profile-language.js +12 -0
- package/dist/schemas/profile-language.js.map +1 -0
- package/dist/schemas/profile-position.js +42 -0
- package/dist/schemas/profile-position.js.map +1 -0
- package/dist/schemas/profile-presentation-delivery.js +38 -0
- package/dist/schemas/profile-presentation-delivery.js.map +1 -0
- package/dist/schemas/profile-presentation.js +36 -0
- package/dist/schemas/profile-presentation.js.map +1 -0
- package/dist/schemas/profile-project.js +48 -0
- package/dist/schemas/profile-project.js.map +1 -0
- package/dist/schemas/profile-publication.js +30 -0
- package/dist/schemas/profile-publication.js.map +1 -0
- package/dist/schemas/profile-self.js +22 -0
- package/dist/schemas/profile-self.js.map +1 -0
- package/dist/schemas/profile-skill.js +13 -0
- package/dist/schemas/profile-skill.js.map +1 -0
- package/dist/schemas/profile-volunteering.js +20 -0
- package/dist/schemas/profile-volunteering.js.map +1 -0
- package/dist/schemas/shared.js +56 -0
- package/dist/schemas/shared.js.map +1 -0
- package/dist/schemas/write/certification.js +16 -0
- package/dist/schemas/write/certification.js.map +1 -0
- package/dist/schemas/write/course.js +36 -0
- package/dist/schemas/write/course.js.map +1 -0
- package/dist/schemas/write/education.js +18 -0
- package/dist/schemas/write/education.js.map +1 -0
- package/dist/schemas/write/external-account.js +13 -0
- package/dist/schemas/write/external-account.js.map +1 -0
- package/dist/schemas/write/honor.js +14 -0
- package/dist/schemas/write/honor.js.map +1 -0
- package/dist/schemas/write/index.d.ts +1 -1
- package/dist/schemas/write/index.js +89 -593
- package/dist/schemas/write/index.js.map +1 -1
- package/dist/schemas/write/investment.js +32 -0
- package/dist/schemas/write/investment.js.map +1 -0
- package/dist/schemas/write/involvement.js +34 -0
- package/dist/schemas/write/involvement.js.map +1 -0
- package/dist/schemas/write/language.js +10 -0
- package/dist/schemas/write/language.js.map +1 -0
- package/dist/schemas/write/org-claim.js +56 -0
- package/dist/schemas/write/org-claim.js.map +1 -0
- package/dist/schemas/write/org-employment-attestation.js +19 -0
- package/dist/schemas/write/org-employment-attestation.js.map +1 -0
- package/dist/schemas/write/org-profile.js +54 -0
- package/dist/schemas/write/org-profile.js.map +1 -0
- package/dist/schemas/write/org-settings.js +81 -0
- package/dist/schemas/write/org-settings.js.map +1 -0
- package/dist/schemas/write/position.js +24 -0
- package/dist/schemas/write/position.js.map +1 -0
- package/dist/schemas/write/presentation-delivery.js +34 -0
- package/dist/schemas/write/presentation-delivery.js.map +1 -0
- package/dist/schemas/write/presentation.js +23 -0
- package/dist/schemas/write/presentation.js.map +1 -0
- package/dist/schemas/write/profile-location.js +21 -0
- package/dist/schemas/write/profile-location.js.map +1 -0
- package/dist/schemas/write/profile-self.js +27 -0
- package/dist/schemas/write/profile-self.js.map +1 -0
- package/dist/schemas/write/project.js +27 -0
- package/dist/schemas/write/project.js.map +1 -0
- package/dist/schemas/write/publication.js +41 -0
- package/dist/schemas/write/publication.js.map +1 -0
- package/dist/schemas/write/shared.js +96 -0
- package/dist/schemas/write/shared.js.map +1 -0
- package/dist/schemas/write/skill.js +18 -0
- package/dist/schemas/write/skill.js.map +1 -0
- package/dist/schemas/write/volunteering.js +16 -0
- package/dist/schemas/write/volunteering.js.map +1 -0
- package/dist/stream/activity-item.js +1 -0
- package/dist/stream/activity-item.js.map +1 -0
- package/dist/stream/index.js +49 -0
- package/dist/stream/index.js.map +1 -0
- package/dist/stream/stream-card-vm-schema.js +265 -0
- package/dist/stream/stream-card-vm-schema.js.map +1 -0
- package/dist/stream/stream-card-vm.js +1 -0
- package/dist/stream/stream-card-vm.js.map +1 -0
- package/dist/stream/to-stream-card-vm.js +793 -0
- package/dist/stream/to-stream-card-vm.js.map +1 -0
- package/dist/stream/two-tier.js +30 -0
- package/dist/stream/two-tier.js.map +1 -0
- package/dist/stream/verbs.js +120 -0
- package/dist/stream/verbs.js.map +1 -0
- package/dist/taxonomy/activity-tiers.js +956 -0
- package/dist/taxonomy/activity-tiers.js.map +1 -0
- package/dist/taxonomy/app-categories.js +42 -0
- package/dist/taxonomy/app-categories.js.map +1 -0
- package/dist/taxonomy/app-category-map.js +166 -0
- package/dist/taxonomy/app-category-map.js.map +1 -0
- package/dist/taxonomy/artifact-link-kind.js +29 -0
- package/dist/taxonomy/artifact-link-kind.js.map +1 -0
- package/dist/taxonomy/calendar-event.js +28 -0
- package/dist/taxonomy/calendar-event.js.map +1 -0
- package/dist/taxonomy/continents.js +215 -0
- package/dist/taxonomy/continents.js.map +1 -0
- package/dist/taxonomy/countries.js +203 -0
- package/dist/taxonomy/countries.js.map +1 -0
- package/dist/taxonomy/course-role.js +37 -0
- package/dist/taxonomy/course-role.js.map +1 -0
- package/dist/taxonomy/employment-type.js +82 -0
- package/dist/taxonomy/employment-type.js.map +1 -0
- package/dist/taxonomy/eqf-level.js +59 -0
- package/dist/taxonomy/eqf-level.js.map +1 -0
- package/dist/taxonomy/index.js +263 -0
- package/dist/taxonomy/index.js.map +1 -0
- package/dist/taxonomy/industry-taxonomy.js +281 -0
- package/dist/taxonomy/industry-taxonomy.js.map +1 -0
- package/dist/taxonomy/investment.js +54 -0
- package/dist/taxonomy/investment.js.map +1 -0
- package/dist/taxonomy/involvement-kind.js +30 -0
- package/dist/taxonomy/involvement-kind.js.map +1 -0
- package/dist/taxonomy/open-to.js +128 -0
- package/dist/taxonomy/open-to.js.map +1 -0
- package/dist/taxonomy/platforms.js +56 -0
- package/dist/taxonomy/platforms.js.map +1 -0
- package/dist/taxonomy/presentation-link-type.js +22 -0
- package/dist/taxonomy/presentation-link-type.js.map +1 -0
- package/dist/taxonomy/presentation-role.js +21 -0
- package/dist/taxonomy/presentation-role.js.map +1 -0
- package/dist/taxonomy/publication-type.js +54 -0
- package/dist/taxonomy/publication-type.js.map +1 -0
- package/dist/taxonomy/relational.js +25 -0
- package/dist/taxonomy/relational.js.map +1 -0
- package/dist/taxonomy/search-filter-defs.js +66 -0
- package/dist/taxonomy/search-filter-defs.js.map +1 -0
- package/dist/taxonomy/skill-categories.js +28 -0
- package/dist/taxonomy/skill-categories.js.map +1 -0
- package/dist/taxonomy/skill-display-groups.js +12 -0
- package/dist/taxonomy/skill-display-groups.js.map +1 -0
- package/dist/taxonomy/skill-grouping.js +90 -0
- package/dist/taxonomy/skill-grouping.js.map +1 -0
- package/dist/taxonomy/verification-providers.js +69 -0
- package/dist/taxonomy/verification-providers.js.map +1 -0
- package/dist/taxonomy/workplace-type.js +38 -0
- package/dist/taxonomy/workplace-type.js.map +1 -0
- package/dist/tokens/colors.js +11 -0
- package/dist/tokens/colors.js.map +1 -0
- package/dist/tokens/icons.js +15 -0
- package/dist/tokens/icons.js.map +1 -0
- package/dist/tokens/index.js +10 -39
- package/dist/tokens/index.js.map +1 -1
- package/dist/tokens/typography.js +23 -0
- package/dist/tokens/typography.js.map +1 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/profile-view.js +1 -0
- package/dist/types/profile-view.js.map +1 -0
- package/dist/{use-org-notification-emails-0hjt-dEw.d.ts → use-org-notification-emails-CWWi1D8t.d.ts} +2 -2
- package/package.json +4 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/query/client.ts"],"sourcesContent":["/**\n * Foundation HTTP client for talking to the Sifa AppView.\n *\n * Stateless. Consumers supply a {@link SifaApiConfig} per call (the React\n * hooks read it from context; non-React consumers pass it explicitly). No\n * singletons, no module-level state.\n */\n\n/** Configuration passed to every fetcher. */\nexport interface SifaApiConfig {\n /** Base URL of the sifa-api AppView, e.g. `https://api.sifa.id`. No trailing slash. */\n baseUrl: string;\n /**\n * Optional fetch implementation. Defaults to {@link globalThis.fetch}.\n * Lets Next.js consumers pass their cache-enhanced fetch; node/Expo\n * consumers can leave this unset.\n */\n fetch?: typeof fetch;\n /**\n * Optional per-request auth-token minter for auth-required reads. The NATIVE\n * app supplies this (it has no sifa-api session cookie): given a method NSID\n * (`lxm`), it mints a short-lived AT Protocol service-auth JWT on the user's\n * PDS (see the SDK's `/atproto` `mintServiceAuthToken`) and returns it; the\n * fetcher attaches it as `Authorization: Bearer`. Web omits this and relies on\n * its session cookie (`credentials: 'include'`). Return `null` to send no\n * token. See `sifa-api` `createIdentityMiddleware`.\n */\n getAuthToken?: (lxm: string) => Promise<string | null>;\n}\n\n/** Options accepted by {@link apiFetch}. */\nexport interface ApiFetchOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n /** Request body. Serialized to JSON automatically. */\n body?: unknown;\n /** AbortSignal. Defaults to `AbortSignal.timeout(timeoutMs)` if `timeoutMs` is set. */\n signal?: AbortSignal;\n /** Per-call timeout in milliseconds. Default: 10_000. Ignored if `signal` is provided. */\n timeoutMs?: number;\n /** Retry on HTTP 429 up to 3 times with the server's `Retry-After` delay (capped at 3s). */\n retryOn429?: boolean;\n /** Additional headers. `Content-Type: application/json` is set automatically when `body` is present. */\n headers?: Record<string, string>;\n credentials?: RequestCredentials;\n cache?: RequestCache;\n /**\n * Next.js-specific cache hints. Ignored on non-Next runtimes. Passed\n * through transparently as part of {@link RequestInit}.\n */\n next?: { revalidate?: number | false; tags?: string[] };\n}\n\n/** Error thrown by {@link apiFetch} on non-2xx responses. */\nexport class ApiError extends Error {\n readonly status: number;\n readonly body: unknown;\n\n constructor(message: string, status: number, body?: unknown) {\n super(message);\n this.name = 'ApiError';\n this.status = status;\n this.body = body;\n }\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst MAX_RATE_LIMIT_RETRIES = 3;\nconst RATE_LIMIT_RETRY_CAP_SECONDS = 3;\n\n/**\n * Encode a handle or DID for safe interpolation into a request path,\n * idempotently.\n *\n * Plain {@link encodeURIComponent} double-encodes an already-encoded\n * identifier: Next.js hands route params to RSC pages percent-encoded on a\n * hard navigation (`did%3Aplc%3A...`) but decoded on client-side navigation\n * (`did:plc:...`). Encoding the former again turns `%` into `%25`, so the\n * AppView reads `did%3A...` as a literal handle, finds no match, and 404s —\n * which is why DID profile links broke on direct visits but worked when\n * clicked within the app.\n *\n * AT identifiers (handles are domain names, DIDs are `did:method:...`) never\n * contain a literal `%`, so decoding a decoded value is a no-op. A malformed\n * percent sequence (lone `%`) makes {@link decodeURIComponent} throw; in that\n * case we keep the original value so behaviour matches the prior bare\n * `encodeURIComponent`.\n */\nexport function encodeIdentifier(value: string): string {\n let decoded = value;\n try {\n decoded = decodeURIComponent(value);\n } catch {\n // Malformed percent-encoding — fall back to the raw value.\n }\n return encodeURIComponent(decoded);\n}\n\n/**\n * Generic fetcher used by all SDK query and mutation functions.\n *\n * Returns parsed JSON typed as `T`. Throws {@link ApiError} on non-2xx\n * responses. Use {@link apiFetchOrNull} when 404 should resolve to `null`\n * instead.\n */\nexport async function apiFetch<T = unknown>(\n config: SifaApiConfig,\n path: string,\n options: ApiFetchOptions = {},\n): Promise<T> {\n const fetchFn = config.fetch ?? globalThis.fetch;\n const url = `${config.baseUrl}${path}`;\n const maxRetries = options.retryOn429 ? MAX_RATE_LIMIT_RETRIES : 0;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const signal = options.signal ?? AbortSignal.timeout(options.timeoutMs ?? DEFAULT_TIMEOUT_MS);\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n let body: BodyInit | undefined;\n if (options.body !== undefined) {\n headers['Content-Type'] ??= 'application/json';\n body = JSON.stringify(options.body);\n }\n\n // `next` is a Next.js extension to RequestInit; cast through.\n const init = {\n method: options.method ?? 'GET',\n headers,\n body,\n signal,\n credentials: options.credentials,\n cache: options.cache,\n ...(options.next ? { next: options.next } : {}),\n } as RequestInit;\n\n const res = await fetchFn(url, init);\n\n if (res.status === 429 && attempt < maxRetries) {\n const retryAfterRaw = res.headers.get('retry-after');\n const retryAfter = retryAfterRaw ? Number.parseInt(retryAfterRaw, 10) : 2;\n const waitSeconds = Math.min(\n Number.isFinite(retryAfter) ? retryAfter : 2,\n RATE_LIMIT_RETRY_CAP_SECONDS,\n );\n await new Promise((r) => setTimeout(r, waitSeconds * 1000));\n continue;\n }\n\n if (!res.ok) {\n let errBody: unknown;\n try {\n errBody = (await res.json()) as unknown;\n } catch {\n try {\n errBody = await res.text();\n } catch {\n errBody = undefined;\n }\n }\n throw new ApiError(`Sifa API ${res.status} on ${path}`, res.status, errBody);\n }\n\n // 204 and 205 are defined to carry no body, so res.json() throws on them.\n // apiWrite treats that throw as a failed write, which turned every\n // successful no-content response (roadmap unvote, remove reaction,\n // dismiss endorsement) into a reported error.\n if (res.status === 204 || res.status === 205) {\n return undefined as T;\n }\n\n return (await res.json()) as T;\n }\n\n throw new ApiError(`Sifa API exhausted retries on ${path}`, 429);\n}\n\n/**\n * Variant of {@link apiFetch} that resolves to `null` on HTTP 404 instead\n * of throwing. Useful for \"fetch by handle\" reads where missing is\n * expected (e.g. unknown profile).\n */\nexport async function apiFetchOrNull<T>(\n config: SifaApiConfig,\n path: string,\n options: ApiFetchOptions = {},\n): Promise<T | null> {\n try {\n return await apiFetch<T>(config, path, options);\n } catch (e) {\n if (e instanceof ApiError && e.status === 404) return null;\n throw e;\n }\n}\n\n/**\n * Result returned by record-write mutations (create / update / delete).\n *\n * Never throws -- writes against the user's PDS can fail in many ways\n * (network, PDS unreachable, rate limit) and the UI needs structured\n * results to render appropriate messages.\n */\nexport interface WriteResult {\n success: boolean;\n error?: string;\n /**\n * PDS hostname returned by sifa-api when a write failed at the user's\n * Personal Data Server (issue #167). Lets the UI render\n * \"Your data server (eurosky.social) isn't responding\" instead of a\n * generic \"Request failed (500)\".\n */\n pdsHost?: string;\n}\n\n/** Result returned by create mutations. Includes the newly created `rkey`. */\nexport interface CreateResult extends WriteResult {\n rkey?: string;\n}\n\ninterface ApiErrorBody {\n message?: string;\n pdsHost?: string;\n}\n\nfunction extractWriteError(data: unknown, status: number): { error: string; pdsHost?: string } {\n const body = (data ?? {}) as ApiErrorBody;\n return {\n error: body.message ?? `Request failed (${status})`,\n ...(body.pdsHost ? { pdsHost: body.pdsHost } : {}),\n };\n}\n\n/**\n * Write mutation against the Sifa AppView. Wraps {@link apiFetch} with the\n * never-throws contract used by all sifa-web mutations: returns a\n * structured {@link WriteResult} on both success and failure, and\n * preserves the `pdsHost` field when the AppView reports a PDS-side\n * failure (issue #167).\n *\n * On success: returns `{ success: true, ...payload }` where `payload` is\n * whatever the server returned in JSON (or `{}` for 204).\n *\n * On failure: returns `{ success: false, error, pdsHost? }`. Never throws.\n *\n * Use {@link apiWriteCreate} when you specifically need the `rkey` from a\n * create response folded into the result shape.\n */\nexport async function apiWrite<TExtra extends object = Record<never, never>>(\n config: SifaApiConfig,\n path: string,\n method: 'POST' | 'PUT' | 'DELETE' | 'PATCH',\n options: Omit<ApiFetchOptions, 'method'> = {},\n): Promise<WriteResult & TExtra> {\n try {\n const data = await apiFetch<TExtra>(config, path, {\n method,\n credentials: 'include',\n ...options,\n });\n return { success: true, ...(data ?? ({} as TExtra)) };\n } catch (e) {\n if (e instanceof ApiError) {\n return { success: false, ...extractWriteError(e.body, e.status) } as WriteResult & TExtra;\n }\n return { success: false, error: 'Network error' } as WriteResult & TExtra;\n }\n}\n\n/**\n * Write mutation that expects the server to return a record key (`rkey`)\n * in its response body. Wraps {@link apiWrite} and folds the `rkey` into\n * the result shape so consumers get `{ success, rkey?, error?, pdsHost? }`.\n *\n * If the server returns additional fields (e.g. `feedUrl` from external\n * account creation), pass them via the `TExtra` generic to keep them\n * typed.\n */\nexport function apiWriteCreate<TExtra extends object = Record<never, never>>(\n config: SifaApiConfig,\n path: string,\n body: unknown,\n options: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<CreateResult & TExtra> {\n return apiWrite<{ rkey?: string } & TExtra>(config, path, 'POST', {\n body,\n ...options,\n });\n}\n"],"mappings":";AAqDO,IAAM,WAAN,cAAuB,MAAM;AAAA,EACzB;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,QAAgB,MAAgB;AAC3D,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AAAA,EACd;AACF;AAEA,IAAM,qBAAqB;AAC3B,IAAM,yBAAyB;AAC/B,IAAM,+BAA+B;AAoB9B,SAAS,iBAAiB,OAAuB;AACtD,MAAI,UAAU;AACd,MAAI;AACF,cAAU,mBAAmB,KAAK;AAAA,EACpC,QAAQ;AAAA,EAER;AACA,SAAO,mBAAmB,OAAO;AACnC;AASA,eAAsB,SACpB,QACA,MACA,UAA2B,CAAC,GAChB;AACZ,QAAM,UAAU,OAAO,SAAS,WAAW;AAC3C,QAAM,MAAM,GAAG,OAAO,OAAO,GAAG,IAAI;AACpC,QAAM,aAAa,QAAQ,aAAa,yBAAyB;AAEjE,WAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,UAAM,SAAS,QAAQ,UAAU,YAAY,QAAQ,QAAQ,aAAa,kBAAkB;AAE5F,UAAM,UAAkC,EAAE,GAAI,QAAQ,WAAW,CAAC,EAAG;AACrE,QAAI;AACJ,QAAI,QAAQ,SAAS,QAAW;AAC9B,cAAQ,cAAc,MAAM;AAC5B,aAAO,KAAK,UAAU,QAAQ,IAAI;AAAA,IACpC;AAGA,UAAM,OAAO;AAAA,MACX,QAAQ,QAAQ,UAAU;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA,aAAa,QAAQ;AAAA,MACrB,OAAO,QAAQ;AAAA,MACf,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC/C;AAEA,UAAM,MAAM,MAAM,QAAQ,KAAK,IAAI;AAEnC,QAAI,IAAI,WAAW,OAAO,UAAU,YAAY;AAC9C,YAAM,gBAAgB,IAAI,QAAQ,IAAI,aAAa;AACnD,YAAM,aAAa,gBAAgB,OAAO,SAAS,eAAe,EAAE,IAAI;AACxE,YAAM,cAAc,KAAK;AAAA,QACvB,OAAO,SAAS,UAAU,IAAI,aAAa;AAAA,QAC3C;AAAA,MACF;AACA,YAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,cAAc,GAAI,CAAC;AAC1D;AAAA,IACF;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,UAAI;AACJ,UAAI;AACF,kBAAW,MAAM,IAAI,KAAK;AAAA,MAC5B,QAAQ;AACN,YAAI;AACF,oBAAU,MAAM,IAAI,KAAK;AAAA,QAC3B,QAAQ;AACN,oBAAU;AAAA,QACZ;AAAA,MACF;AACA,YAAM,IAAI,SAAS,YAAY,IAAI,MAAM,OAAO,IAAI,IAAI,IAAI,QAAQ,OAAO;AAAA,IAC7E;AAMA,QAAI,IAAI,WAAW,OAAO,IAAI,WAAW,KAAK;AAC5C,aAAO;AAAA,IACT;AAEA,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB;AAEA,QAAM,IAAI,SAAS,iCAAiC,IAAI,IAAI,GAAG;AACjE;AAOA,eAAsB,eACpB,QACA,MACA,UAA2B,CAAC,GACT;AACnB,MAAI;AACF,WAAO,MAAM,SAAY,QAAQ,MAAM,OAAO;AAAA,EAChD,SAAS,GAAG;AACV,QAAI,aAAa,YAAY,EAAE,WAAW,IAAK,QAAO;AACtD,UAAM;AAAA,EACR;AACF;AA+BA,SAAS,kBAAkB,MAAe,QAAqD;AAC7F,QAAM,OAAQ,QAAQ,CAAC;AACvB,SAAO;AAAA,IACL,OAAO,KAAK,WAAW,mBAAmB,MAAM;AAAA,IAChD,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,EAClD;AACF;AAiBA,eAAsB,SACpB,QACA,MACA,QACA,UAA2C,CAAC,GACb;AAC/B,MAAI;AACF,UAAM,OAAO,MAAM,SAAiB,QAAQ,MAAM;AAAA,MAChD;AAAA,MACA,aAAa;AAAA,MACb,GAAG;AAAA,IACL,CAAC;AACD,WAAO,EAAE,SAAS,MAAM,GAAI,QAAS,CAAC,EAAc;AAAA,EACtD,SAAS,GAAG;AACV,QAAI,aAAa,UAAU;AACzB,aAAO,EAAE,SAAS,OAAO,GAAG,kBAAkB,EAAE,MAAM,EAAE,MAAM,EAAE;AAAA,IAClE;AACA,WAAO,EAAE,SAAS,OAAO,OAAO,gBAAgB;AAAA,EAClD;AACF;AAWO,SAAS,eACd,QACA,MACA,MACA,UAAoD,CAAC,GACrB;AAChC,SAAO,SAAqC,QAAQ,MAAM,QAAQ;AAAA,IAChE;AAAA,IACA,GAAG;AAAA,EACL,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/query/config.tsx
|
|
4
|
+
import { createContext, useContext } from "react";
|
|
5
|
+
import { jsx } from "react/jsx-runtime";
|
|
6
|
+
var SifaConfigContext = createContext(null);
|
|
7
|
+
function SifaProvider({ config, children }) {
|
|
8
|
+
return /* @__PURE__ */ jsx(SifaConfigContext.Provider, { value: config, children });
|
|
9
|
+
}
|
|
10
|
+
function useSifaConfig() {
|
|
11
|
+
const ctx = useContext(SifaConfigContext);
|
|
12
|
+
if (!ctx) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
"useSifaConfig must be used inside <SifaProvider>. Wrap your app once with <SifaProvider config={...}>."
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
return ctx;
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
SifaProvider,
|
|
21
|
+
useSifaConfig
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/query/config.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, type ReactNode } from 'react';\n\nimport type { SifaApiConfig } from './client.js';\n\nconst SifaConfigContext = createContext<SifaApiConfig | null>(null);\n\nexport interface SifaProviderProps {\n config: SifaApiConfig;\n children: ReactNode;\n}\n\n/**\n * Provides the {@link SifaApiConfig} that hooks under it can read via\n * {@link useSifaConfig}. Wrap the React tree once; hooks consume it.\n *\n * @example\n * ```tsx\n * <QueryClientProvider client={queryClient}>\n * <SifaProvider config={{ baseUrl: process.env.NEXT_PUBLIC_API_URL! }}>\n * <App />\n * </SifaProvider>\n * </QueryClientProvider>\n * ```\n */\nexport function SifaProvider({ config, children }: SifaProviderProps) {\n return <SifaConfigContext.Provider value={config}>{children}</SifaConfigContext.Provider>;\n}\n\n/**\n * Read the SDK's {@link SifaApiConfig} from context. Throws if no\n * {@link SifaProvider} is mounted above.\n */\nexport function useSifaConfig(): SifaApiConfig {\n const ctx = useContext(SifaConfigContext);\n if (!ctx) {\n throw new Error(\n 'useSifaConfig must be used inside <SifaProvider>. Wrap your app once with <SifaProvider config={...}>.',\n );\n }\n return ctx;\n}\n"],"mappings":";;;AAEA,SAAS,eAAe,kBAAkC;AAyBjD;AArBT,IAAM,oBAAoB,cAAoC,IAAI;AAoB3D,SAAS,aAAa,EAAE,QAAQ,SAAS,GAAsB;AACpE,SAAO,oBAAC,kBAAkB,UAAlB,EAA2B,OAAO,QAAS,UAAS;AAC9D;AAMO,SAAS,gBAA+B;AAC7C,QAAM,MAAM,WAAW,iBAAiB;AACxC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/query/fetchers/accounts.ts
|
|
2
|
+
import { apiFetch } from "../client.js";
|
|
3
|
+
async function fetchAccounts(config, options = {}) {
|
|
4
|
+
const headers = { ...options.headers ?? {} };
|
|
5
|
+
if (options.cookieHeader) headers.cookie = options.cookieHeader;
|
|
6
|
+
try {
|
|
7
|
+
const data = await apiFetch(config, "/api/auth/accounts", {
|
|
8
|
+
credentials: "include",
|
|
9
|
+
...options,
|
|
10
|
+
headers
|
|
11
|
+
});
|
|
12
|
+
return data.accounts;
|
|
13
|
+
} catch {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function switchAccount(config, did, options = {}) {
|
|
18
|
+
await apiFetch(config, "/oauth/switch", {
|
|
19
|
+
method: "POST",
|
|
20
|
+
body: { did },
|
|
21
|
+
credentials: "include",
|
|
22
|
+
...options
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
fetchAccounts,
|
|
27
|
+
switchAccount
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=accounts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/accounts.ts"],"sourcesContent":["import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** One account attached to the current browser, for the account switcher. */\nexport interface AccountSummary {\n did: string;\n handle: string | null;\n displayName: string | null;\n avatarUrl: string | null;\n /**\n * The org's uploaded logo blob CID, for a company account that set one on its\n * `/c/` page; null otherwise. The switcher resolves it to the same logo `/c/`\n * shows (via the shared company-logo resolution), so an uploaded logo appears\n * in the menu rather than the atproto avatar. Omitted by older api responses.\n */\n orgLogoBlob?: string | null;\n /** Whether this is the currently-active account. */\n active: boolean;\n}\n\nexport interface FetchAccountsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Accounts attached to this browser (the account switcher). Requires an\n * authenticated session. Returns `[]` on any error, including the\n * unauthenticated case.\n */\nexport async function fetchAccounts(\n config: SifaApiConfig,\n options: FetchAccountsOptions = {},\n): Promise<AccountSummary[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ accounts: AccountSummary[] }>(config, '/api/auth/accounts', {\n credentials: 'include',\n ...options,\n headers,\n });\n return data.accounts;\n } catch {\n return [];\n }\n}\n\n/**\n * Make an already-attached account the active one. Keyed by DID (public); the\n * server maps it to the browser's session id. Browser-only: the endpoint\n * requires an Origin header, which browsers set automatically on POST. Callers\n * typically reload the app afterwards to reset session-seeded state.\n */\nexport async function switchAccount(\n config: SifaApiConfig,\n did: string,\n options: ApiFetchOptions = {},\n): Promise<void> {\n await apiFetch(config, '/oauth/switch', {\n method: 'POST',\n body: { did },\n credentials: 'include',\n ...options,\n });\n}\n"],"mappings":";AAAA,SAAS,gBAA0D;AAiCnE,eAAsB,cACpB,QACA,UAAgC,CAAC,GACN;AAC3B,QAAM,UAAkC,EAAE,GAAI,QAAQ,WAAW,CAAC,EAAG;AACrE,MAAI,QAAQ,aAAc,SAAQ,SAAS,QAAQ;AAEnD,MAAI;AACF,UAAM,OAAO,MAAM,SAAyC,QAAQ,sBAAsB;AAAA,MACxF,aAAa;AAAA,MACb,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AACD,WAAO,KAAK;AAAA,EACd,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAQA,eAAsB,cACpB,QACA,KACA,UAA2B,CAAC,GACb;AACf,QAAM,SAAS,QAAQ,iBAAiB;AAAA,IACtC,QAAQ;AAAA,IACR,MAAM,EAAE,IAAI;AAAA,IACZ,aAAa;AAAA,IACb,GAAG;AAAA,EACL,CAAC;AACH;","names":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/query/fetchers/activity-items-hide.ts
|
|
2
|
+
import {
|
|
3
|
+
apiFetch,
|
|
4
|
+
apiWrite
|
|
5
|
+
} from "../client.js";
|
|
6
|
+
function hideActivityItem(config, input, options = {}) {
|
|
7
|
+
return apiWrite(config, "/api/activity/items/hide", "POST", { ...options, body: input });
|
|
8
|
+
}
|
|
9
|
+
function unhideActivityItem(config, input, options = {}) {
|
|
10
|
+
return apiWrite(config, "/api/activity/items/hide", "DELETE", { ...options, body: input });
|
|
11
|
+
}
|
|
12
|
+
async function fetchHiddenActivityItems(config, options = {}) {
|
|
13
|
+
const headers = { ...options.headers ?? {} };
|
|
14
|
+
if (options.cookieHeader) headers.cookie = options.cookieHeader;
|
|
15
|
+
try {
|
|
16
|
+
const data = await apiFetch(
|
|
17
|
+
config,
|
|
18
|
+
"/api/activity/hidden-items",
|
|
19
|
+
{ credentials: "include", ...options, headers }
|
|
20
|
+
);
|
|
21
|
+
return data.items;
|
|
22
|
+
} catch {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
fetchHiddenActivityItems,
|
|
28
|
+
hideActivityItem,
|
|
29
|
+
unhideActivityItem
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=activity-items-hide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/activity-items-hide.ts"],"sourcesContent":["import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\nexport interface HideActivityItemInput {\n /** AT-URI of the record, or the item URL for externally-sourced items. */\n uri: string;\n /** Collection NSID (or synthetic collection, e.g. `fediverse.post`). */\n collection: string;\n /**\n * Registry app id the item belongs to. Optional, and used only to take the\n * item out of the owner's OG-image activity spine, which is computed from\n * per-(day, app) counts and never sees a URI.\n */\n appId?: string;\n /** UTC day the item was created (`YYYY-MM-DD`), for the same reason. */\n activityDate?: string;\n}\n\nexport interface UnhideActivityItemInput {\n uri: string;\n}\n\n/** One activity item the authenticated user has hidden from their profile. */\nexport interface HiddenActivityItem {\n uri: string;\n collection: string;\n appId: string | null;\n activityDate: string | null;\n hiddenAt: string;\n}\n\nexport interface FetchHiddenActivityItemsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Hide one activity item from the authenticated user's profile. The record\n * stays on their PDS and stays readable by every other app; only its\n * appearance on sifa.id is suppressed.\n */\nexport function hideActivityItem(\n config: SifaApiConfig,\n input: HideActivityItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/activity/items/hide', 'POST', { ...options, body: input });\n}\n\n/** Restore a previously-hidden activity item. */\nexport function unhideActivityItem(\n config: SifaApiConfig,\n input: UnhideActivityItemInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/activity/items/hide', 'DELETE', { ...options, body: input });\n}\n\n/**\n * Everything the authenticated user has hidden, newest hide first. Returns\n * `[]` on any error so a settings page can still render.\n */\nexport async function fetchHiddenActivityItems(\n config: SifaApiConfig,\n options: FetchHiddenActivityItemsOptions = {},\n): Promise<HiddenActivityItem[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ items: HiddenActivityItem[] }>(\n config,\n '/api/activity/hidden-items',\n { credentials: 'include', ...options, headers },\n );\n return data.items;\n } catch {\n return [];\n }\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AA2CA,SAAS,iBACd,QACA,OACA,UAA2B,CAAC,GACN;AACtB,SAAO,SAAS,QAAQ,4BAA4B,QAAQ,EAAE,GAAG,SAAS,MAAM,MAAM,CAAC;AACzF;AAGO,SAAS,mBACd,QACA,OACA,UAA2B,CAAC,GACN;AACtB,SAAO,SAAS,QAAQ,4BAA4B,UAAU,EAAE,GAAG,SAAS,MAAM,MAAM,CAAC;AAC3F;AAMA,eAAsB,yBACpB,QACA,UAA2C,CAAC,GACb;AAC/B,QAAM,UAAkC,EAAE,GAAI,QAAQ,WAAW,CAAC,EAAG;AACrE,MAAI,QAAQ,aAAc,SAAQ,SAAS,QAAQ;AAEnD,MAAI;AACF,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA,EAAE,aAAa,WAAW,GAAG,SAAS,QAAQ;AAAA,IAChD;AACA,WAAO,KAAK;AAAA,EACd,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;","names":[]}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// src/query/fetchers/activity.ts
|
|
2
|
+
import { encodeIdentifier, apiFetch } from "../client.js";
|
|
3
|
+
async function fetchHeatmapData(config, handleOrDid, days, options = {}) {
|
|
4
|
+
const path = `/api/activity/${encodeIdentifier(handleOrDid)}/heatmap?days=${days}`;
|
|
5
|
+
try {
|
|
6
|
+
return await apiFetch(config, path, {
|
|
7
|
+
next: { revalidate: 900, tags: [`heatmap-${handleOrDid}`] },
|
|
8
|
+
...options
|
|
9
|
+
});
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function fetchActivityTeaser(config, handleOrDid, options = {}) {
|
|
15
|
+
const headers = { ...options.headers ?? {} };
|
|
16
|
+
if (options.cookieHeader) headers.cookie = options.cookieHeader;
|
|
17
|
+
try {
|
|
18
|
+
return await apiFetch(
|
|
19
|
+
config,
|
|
20
|
+
`/api/activity/${encodeIdentifier(handleOrDid)}/teaser`,
|
|
21
|
+
{
|
|
22
|
+
credentials: "include",
|
|
23
|
+
timeoutMs: 8e3,
|
|
24
|
+
next: { revalidate: 300, tags: [`activity-teaser-${handleOrDid}`] },
|
|
25
|
+
...options,
|
|
26
|
+
headers
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
} catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function fetchActivityFeed(config, handleOrDid, options = {}) {
|
|
34
|
+
const params = new URLSearchParams();
|
|
35
|
+
if (options.category) params.set("category", options.category);
|
|
36
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
37
|
+
if (options.cursor) params.set("cursor", options.cursor);
|
|
38
|
+
const qs = params.toString();
|
|
39
|
+
const headers = { ...options.headers ?? {} };
|
|
40
|
+
if (options.cookieHeader) headers.cookie = options.cookieHeader;
|
|
41
|
+
try {
|
|
42
|
+
return await apiFetch(
|
|
43
|
+
config,
|
|
44
|
+
`/api/activity/${encodeIdentifier(handleOrDid)}${qs ? `?${qs}` : ""}`,
|
|
45
|
+
{
|
|
46
|
+
credentials: "include",
|
|
47
|
+
cache: "no-store",
|
|
48
|
+
...options,
|
|
49
|
+
headers
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
} catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
fetchActivityFeed,
|
|
58
|
+
fetchActivityTeaser,
|
|
59
|
+
fetchHeatmapData
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=activity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/activity.ts"],"sourcesContent":["import type { ActivityLabel } from '../../cards/adult-content.js';\nimport { encodeIdentifier, apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\nimport type { QuotedPostResult } from './quoted-posts.js';\n\n/**\n * Liveness of an activity card's destination, as reported by sifa-api's\n * `/api/activity` enrichment (see sifa-api `url-health-checker`). How liveness\n * is measured depends on the card's health strategy (see `resolveCardHealth`):\n * first-party permalinks (`record`) are checked by record existence on the PDS;\n * foreign/derived targets (`url`) by HTTP reachability (HEAD, then GET).\n *\n * ok -- record exists, or the URL returned 2xx/3xx\n * broken -- confirmed dead (record deleted, or >=2 consecutive 4xx / >=5 consecutive 5xx)\n * unverifiable -- 403/429, PDS unreachable, or network error; NOT dead\n * unknown -- newly seen, not yet checked\n *\n * Consumers should only suppress UI on `'broken'`. All other values\n * (including missing) mean \"render normally\".\n */\nexport type ActivityItemLinkHealth = 'ok' | 'broken' | 'unverifiable' | 'unknown';\n\nexport interface HeatmapDay {\n date: string;\n total: number;\n apps: { appId: string; count: number }[];\n}\n\nexport interface HeatmapResponse {\n days: HeatmapDay[];\n appTotals: { appId: string; appName: string; total: number }[];\n thresholds: [number, number, number, number];\n}\n\nexport interface ActivityItem {\n uri: string;\n cid: string;\n collection: string;\n rkey: string;\n record: Record<string, unknown>;\n appId: string;\n appName: string;\n category: string;\n indexedAt: string;\n /**\n * The record author's handle / display name / avatar, injected by the server\n * on MULTI-author feeds (the following feed) so a card can show whose activity\n * it is. Unset on the per-author activity feed (all one author). Mirrors the\n * stream `ActivityItem`'s author fields the view-model transform reads.\n */\n authorHandle?: string;\n authorDisplayName?: string;\n authorAvatar?: string;\n /**\n * Set by the server when an `app.bsky.embed.record` quote was already\n * resolved upstream (AppView path). Mutually exclusive with `quotedPostUri`.\n */\n quotedPost?: QuotedPostResult;\n /**\n * Set by the server when an `app.bsky.embed.record` quote needs client-side\n * resolution (PDS path). Pass batches to {@link resolveQuotedPosts}.\n * Mutually exclusive with `quotedPost`.\n */\n quotedPostUri?: string;\n /**\n * Reachability of the card's external destination as last checked by\n * sifa-api. Undefined for legacy responses; treat as 'unknown'.\n * See {@link ActivityItemLinkHealth}.\n */\n linkHealth?: ActivityItemLinkHealth;\n /**\n * Content labels from `app.bsky.feed.defs#postView.labels`. Set by\n * sifa-api for Bluesky posts; undefined for other sources and legacy\n * responses. Pass items to {@link hasAdultContent} to decide whether to\n * gate media. See {@link ActivityLabel}.\n */\n labels?: ActivityLabel[];\n /**\n * The owner has hidden this item from their profile. Only ever set on the\n * owner's own view of their feed -- every other surface omits hidden items\n * rather than flagging them -- so a card can offer an unhide in place.\n */\n hidden?: boolean;\n}\n\nexport interface ActivityTeaserResponse {\n items: ActivityItem[];\n blueskyGated?: boolean;\n backfillPending?: boolean;\n failedApps?: string[];\n}\n\nexport interface ActivityFeedResponse {\n items: ActivityItem[];\n cursor: string | null;\n hasMore: boolean;\n availableCategories?: string[];\n blueskyGated?: boolean;\n failedApps?: string[];\n}\n\n/**\n * Per-day activity counts for a profile across all ATproto apps. Returns\n * `null` on any error so callers can render a graceful empty state.\n */\nexport async function fetchHeatmapData(\n config: SifaApiConfig,\n handleOrDid: string,\n days: number,\n options: ApiFetchOptions = {},\n): Promise<HeatmapResponse | null> {\n const path = `/api/activity/${encodeIdentifier(handleOrDid)}/heatmap?days=${days}`;\n try {\n return await apiFetch<HeatmapResponse>(config, path, {\n next: { revalidate: 900, tags: [`heatmap-${handleOrDid}`] },\n ...options,\n });\n } catch {\n return null;\n }\n}\n\nexport interface FetchActivityTeaserOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * Required for authenticated server fetches because `credentials: 'include'`\n * does not propagate browser cookies in RSC.\n */\n cookieHeader?: string;\n}\n\n/**\n * Recent activity teaser for a profile (homepage-sized slice). Caps the\n * upstream wait so the SSR path cannot hang. Returns `null` on any error.\n */\nexport async function fetchActivityTeaser(\n config: SifaApiConfig,\n handleOrDid: string,\n options: FetchActivityTeaserOptions = {},\n): Promise<ActivityTeaserResponse | null> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<ActivityTeaserResponse>(\n config,\n `/api/activity/${encodeIdentifier(handleOrDid)}/teaser`,\n {\n credentials: 'include',\n timeoutMs: 8000,\n next: { revalidate: 300, tags: [`activity-teaser-${handleOrDid}`] },\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n\nexport interface FetchActivityFeedOptions extends ApiFetchOptions {\n category?: string;\n limit?: number;\n cursor?: string;\n cookieHeader?: string;\n}\n\n/**\n * Paginated activity feed for a profile. Always fresh (`cache: 'no-store'`).\n * Returns `null` on any error.\n */\nexport async function fetchActivityFeed(\n config: SifaApiConfig,\n handleOrDid: string,\n options: FetchActivityFeedOptions = {},\n): Promise<ActivityFeedResponse | null> {\n const params = new URLSearchParams();\n if (options.category) params.set('category', options.category);\n if (options.limit) params.set('limit', String(options.limit));\n if (options.cursor) params.set('cursor', options.cursor);\n const qs = params.toString();\n\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n return await apiFetch<ActivityFeedResponse>(\n config,\n `/api/activity/${encodeIdentifier(handleOrDid)}${qs ? `?${qs}` : ''}`,\n {\n credentials: 'include',\n cache: 'no-store',\n ...options,\n headers,\n },\n );\n } catch {\n return null;\n }\n}\n"],"mappings":";AACA,SAAS,kBAAkB,gBAA0D;AAuGrF,eAAsB,iBACpB,QACA,aACA,MACA,UAA2B,CAAC,GACK;AACjC,QAAM,OAAO,iBAAiB,iBAAiB,WAAW,CAAC,iBAAiB,IAAI;AAChF,MAAI;AACF,WAAO,MAAM,SAA0B,QAAQ,MAAM;AAAA,MACnD,MAAM,EAAE,YAAY,KAAK,MAAM,CAAC,WAAW,WAAW,EAAE,EAAE;AAAA,MAC1D,GAAG;AAAA,IACL,CAAC;AAAA,EACH,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAeA,eAAsB,oBACpB,QACA,aACA,UAAsC,CAAC,GACC;AACxC,QAAM,UAAkC,EAAE,GAAI,QAAQ,WAAW,CAAC,EAAG;AACrE,MAAI,QAAQ,aAAc,SAAQ,SAAS,QAAQ;AAEnD,MAAI;AACF,WAAO,MAAM;AAAA,MACX;AAAA,MACA,iBAAiB,iBAAiB,WAAW,CAAC;AAAA,MAC9C;AAAA,QACE,aAAa;AAAA,QACb,WAAW;AAAA,QACX,MAAM,EAAE,YAAY,KAAK,MAAM,CAAC,mBAAmB,WAAW,EAAE,EAAE;AAAA,QAClE,GAAG;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAaA,eAAsB,kBACpB,QACA,aACA,UAAoC,CAAC,GACC;AACtC,QAAM,SAAS,IAAI,gBAAgB;AACnC,MAAI,QAAQ,SAAU,QAAO,IAAI,YAAY,QAAQ,QAAQ;AAC7D,MAAI,QAAQ,MAAO,QAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AAC5D,MAAI,QAAQ,OAAQ,QAAO,IAAI,UAAU,QAAQ,MAAM;AACvD,QAAM,KAAK,OAAO,SAAS;AAE3B,QAAM,UAAkC,EAAE,GAAI,QAAQ,WAAW,CAAC,EAAG;AACrE,MAAI,QAAQ,aAAc,SAAQ,SAAS,QAAQ;AAEnD,MAAI;AACF,WAAO,MAAM;AAAA,MACX;AAAA,MACA,iBAAiB,iBAAiB,WAAW,CAAC,GAAG,KAAK,IAAI,EAAE,KAAK,EAAE;AAAA,MACnE;AAAA,QACE,aAAa;AAAA,QACb,OAAO;AAAA,QACP,GAAG;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/query/fetchers/actor.ts
|
|
2
|
+
import { apiFetch, apiFetchOrNull } from "../client.js";
|
|
3
|
+
async function fetchResolveActor(config, handleOrDid, options = {}) {
|
|
4
|
+
const q = handleOrDid.trim().replace(/^@/, "");
|
|
5
|
+
if (!q) return null;
|
|
6
|
+
return apiFetchOrNull(config, `/api/actor/resolve?q=${encodeURIComponent(q)}`, {
|
|
7
|
+
cache: "no-store",
|
|
8
|
+
...options
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
async function fetchTypeaheadActors(config, query, limit = 8, options = {}) {
|
|
12
|
+
const q = query.trim().replace(/^@/, "");
|
|
13
|
+
if (!q) return [];
|
|
14
|
+
const params = new URLSearchParams({ q, limit: String(limit) });
|
|
15
|
+
try {
|
|
16
|
+
const res = await apiFetch(
|
|
17
|
+
config,
|
|
18
|
+
`/api/actor/typeahead?${params.toString()}`,
|
|
19
|
+
{ cache: "no-store", ...options }
|
|
20
|
+
);
|
|
21
|
+
return res.actors ?? [];
|
|
22
|
+
} catch {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
fetchResolveActor,
|
|
28
|
+
fetchTypeaheadActors
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=actor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/actor.ts"],"sourcesContent":["import { apiFetch, apiFetchOrNull, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\nimport type { ActorCard, CoSpeaker } from '../../types/index.js';\n\n/**\n * Resolve any atproto handle (or DID) to a profile card, for the co-speaker\n * picker's \"not on Sifa\" path. Returns `null` when the identity can't be\n * resolved. The Sifa AppView resolves the handle to a DID and hydrates a card\n * (handle, displayName, avatar, and whether they have a claimed Sifa profile).\n */\nexport async function fetchResolveActor(\n config: SifaApiConfig,\n handleOrDid: string,\n options: ApiFetchOptions = {},\n): Promise<CoSpeaker | null> {\n const q = handleOrDid.trim().replace(/^@/, '');\n if (!q) return null;\n return apiFetchOrNull<CoSpeaker>(config, `/api/actor/resolve?q=${encodeURIComponent(q)}`, {\n cache: 'no-store',\n ...options,\n });\n}\n\n/**\n * Typeahead over indexed Sifa profiles by partial name or handle, for the\n * co-speaker, login and search comboboxes. Matches display name and handle only\n * (prefix + trigram), ranks prefix matches first, and returns actor cards.\n * Unlike `/api/search/profiles`, a partial of a dotted custom handle resolves\n * and a partial name surfaces its prefix match rather than an unrelated\n * account. Returns an empty array on a blank query or a failed request; use\n * {@link fetchResolveActor} on Enter to reach a handle that is not on Sifa.\n */\nexport async function fetchTypeaheadActors(\n config: SifaApiConfig,\n query: string,\n limit = 8,\n options: ApiFetchOptions = {},\n): Promise<ActorCard[]> {\n const q = query.trim().replace(/^@/, '');\n if (!q) return [];\n const params = new URLSearchParams({ q, limit: String(limit) });\n try {\n const res = await apiFetch<{ actors: ActorCard[] }>(\n config,\n `/api/actor/typeahead?${params.toString()}`,\n { cache: 'no-store', ...options },\n );\n return res.actors ?? [];\n } catch {\n return [];\n }\n}\n"],"mappings":";AAAA,SAAS,UAAU,sBAAgE;AASnF,eAAsB,kBACpB,QACA,aACA,UAA2B,CAAC,GACD;AAC3B,QAAM,IAAI,YAAY,KAAK,EAAE,QAAQ,MAAM,EAAE;AAC7C,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,eAA0B,QAAQ,wBAAwB,mBAAmB,CAAC,CAAC,IAAI;AAAA,IACxF,OAAO;AAAA,IACP,GAAG;AAAA,EACL,CAAC;AACH;AAWA,eAAsB,qBACpB,QACA,OACA,QAAQ,GACR,UAA2B,CAAC,GACN;AACtB,QAAM,IAAI,MAAM,KAAK,EAAE,QAAQ,MAAM,EAAE;AACvC,MAAI,CAAC,EAAG,QAAO,CAAC;AAChB,QAAM,SAAS,IAAI,gBAAgB,EAAE,GAAG,OAAO,OAAO,KAAK,EAAE,CAAC;AAC9D,MAAI;AACF,UAAM,MAAM,MAAM;AAAA,MAChB;AAAA,MACA,wBAAwB,OAAO,SAAS,CAAC;AAAA,MACzC,EAAE,OAAO,YAAY,GAAG,QAAQ;AAAA,IAClC;AACA,WAAO,IAAI,UAAU,CAAC;AAAA,EACxB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;","names":[]}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/query/fetchers/admin-feature-allowlists.ts
|
|
2
|
+
import {
|
|
3
|
+
apiFetch,
|
|
4
|
+
encodeIdentifier,
|
|
5
|
+
apiWrite
|
|
6
|
+
} from "../client.js";
|
|
7
|
+
async function listFeatureAllowlist(config, flag, opts = {}) {
|
|
8
|
+
const headers = { ...opts.headers ?? {} };
|
|
9
|
+
if (opts.cookieHeader) headers.cookie = opts.cookieHeader;
|
|
10
|
+
try {
|
|
11
|
+
const res = await apiFetch(
|
|
12
|
+
config,
|
|
13
|
+
`/api/admin/feature-allowlists/${encodeURIComponent(flag)}`,
|
|
14
|
+
{ credentials: "include", cache: "no-store", ...opts, headers }
|
|
15
|
+
);
|
|
16
|
+
return { items: res.items ?? [] };
|
|
17
|
+
} catch {
|
|
18
|
+
return { items: [] };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function addFeatureAllowlist(config, flag, did, opts = {}) {
|
|
22
|
+
const { note, ...rest } = opts;
|
|
23
|
+
return apiWrite(config, `/api/admin/feature-allowlists/${encodeURIComponent(flag)}`, "POST", {
|
|
24
|
+
body: note !== void 0 ? { did, note } : { did },
|
|
25
|
+
...rest
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
function removeFeatureAllowlist(config, flag, did, opts = {}) {
|
|
29
|
+
return apiWrite(
|
|
30
|
+
config,
|
|
31
|
+
`/api/admin/feature-allowlists/${encodeURIComponent(flag)}/${encodeIdentifier(did)}`,
|
|
32
|
+
"DELETE",
|
|
33
|
+
opts
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
addFeatureAllowlist,
|
|
38
|
+
listFeatureAllowlist,
|
|
39
|
+
removeFeatureAllowlist
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=admin-feature-allowlists.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/admin-feature-allowlists.ts"],"sourcesContent":["import {\n apiFetch,\n encodeIdentifier,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\nimport type { FeatureAllowlistEntry, FeatureFlag } from '../../schemas/follow-profile.js';\n\n/**\n * Options for {@link listFeatureAllowlist}. Supports the same `cookieHeader`\n * passthrough as the other admin reads for RSC contexts.\n */\nexport interface ListFeatureAllowlistOptions extends ApiFetchOptions {\n cookieHeader?: string;\n}\n\n/** Response shape of `GET /api/admin/feature-allowlists/:flag`. */\nexport interface FeatureAllowlistResponse {\n items: FeatureAllowlistEntry[];\n}\n\n/**\n * List all DIDs on the given feature flag's allowlist. Admin-gated server-\n * side (caller must be an admin). Returns an empty list on error so the UI\n * can render a graceful empty state.\n */\nexport async function listFeatureAllowlist(\n config: SifaApiConfig,\n flag: FeatureFlag,\n opts: ListFeatureAllowlistOptions = {},\n): Promise<FeatureAllowlistResponse> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n try {\n const res = await apiFetch<{ items?: FeatureAllowlistEntry[] }>(\n config,\n `/api/admin/feature-allowlists/${encodeURIComponent(flag)}`,\n { credentials: 'include', cache: 'no-store', ...opts, headers },\n );\n return { items: res.items ?? [] };\n } catch {\n return { items: [] };\n }\n}\n\n/**\n * Add (or upsert the note for) a DID on the given flag's allowlist. Maps to\n * `POST /api/admin/feature-allowlists/{flag}`. Returns a {@link WriteResult};\n * never throws.\n */\nexport function addFeatureAllowlist(\n config: SifaApiConfig,\n flag: FeatureFlag,\n did: string,\n opts: { note?: string } & Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n const { note, ...rest } = opts;\n return apiWrite(config, `/api/admin/feature-allowlists/${encodeURIComponent(flag)}`, 'POST', {\n body: note !== undefined ? { did, note } : { did },\n ...rest,\n });\n}\n\n/**\n * Remove a DID from the given flag's allowlist. Maps to\n * `DELETE /api/admin/feature-allowlists/{flag}/{did}`. Returns a\n * {@link WriteResult}; never throws.\n */\nexport function removeFeatureAllowlist(\n config: SifaApiConfig,\n flag: FeatureFlag,\n did: string,\n opts: Omit<ApiFetchOptions, 'method' | 'body'> = {},\n): Promise<WriteResult> {\n return apiWrite(\n config,\n `/api/admin/feature-allowlists/${encodeURIComponent(flag)}/${encodeIdentifier(did)}`,\n 'DELETE',\n opts,\n );\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAqBP,eAAsB,qBACpB,QACA,MACA,OAAoC,CAAC,GACF;AACnC,QAAM,UAAkC,EAAE,GAAI,KAAK,WAAW,CAAC,EAAG;AAClE,MAAI,KAAK,aAAc,SAAQ,SAAS,KAAK;AAC7C,MAAI;AACF,UAAM,MAAM,MAAM;AAAA,MAChB;AAAA,MACA,iCAAiC,mBAAmB,IAAI,CAAC;AAAA,MACzD,EAAE,aAAa,WAAW,OAAO,YAAY,GAAG,MAAM,QAAQ;AAAA,IAChE;AACA,WAAO,EAAE,OAAO,IAAI,SAAS,CAAC,EAAE;AAAA,EAClC,QAAQ;AACN,WAAO,EAAE,OAAO,CAAC,EAAE;AAAA,EACrB;AACF;AAOO,SAAS,oBACd,QACA,MACA,KACA,OAAqE,CAAC,GAChD;AACtB,QAAM,EAAE,MAAM,GAAG,KAAK,IAAI;AAC1B,SAAO,SAAS,QAAQ,iCAAiC,mBAAmB,IAAI,CAAC,IAAI,QAAQ;AAAA,IAC3F,MAAM,SAAS,SAAY,EAAE,KAAK,KAAK,IAAI,EAAE,IAAI;AAAA,IACjD,GAAG;AAAA,EACL,CAAC;AACH;AAOO,SAAS,uBACd,QACA,MACA,KACA,OAAiD,CAAC,GAC5B;AACtB,SAAO;AAAA,IACL;AAAA,IACA,iCAAiC,mBAAmB,IAAI,CAAC,IAAI,iBAAiB,GAAG,CAAC;AAAA,IAClF;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/query/fetchers/admin-review-queues.ts
|
|
2
|
+
import { apiFetch } from "../client.js";
|
|
3
|
+
async function getAdminReviewQueues(config, opts = {}) {
|
|
4
|
+
const headers = { ...opts.headers ?? {} };
|
|
5
|
+
if (opts.cookieHeader) headers.cookie = opts.cookieHeader;
|
|
6
|
+
const res = await apiFetch(config, "/api/admin/stats/review-queues", {
|
|
7
|
+
credentials: "include",
|
|
8
|
+
cache: "no-store",
|
|
9
|
+
...opts,
|
|
10
|
+
headers
|
|
11
|
+
});
|
|
12
|
+
const ideas = res.ideas ?? 0;
|
|
13
|
+
const nameCorrections = res.nameCorrections ?? 0;
|
|
14
|
+
const pendingCompanies = res.pendingCompanies ?? 0;
|
|
15
|
+
const duplicateOrgs = res.duplicateOrgs ?? 0;
|
|
16
|
+
return {
|
|
17
|
+
ideas,
|
|
18
|
+
nameCorrections,
|
|
19
|
+
pendingCompanies,
|
|
20
|
+
duplicateOrgs,
|
|
21
|
+
// Derived rather than trusted so an API that predates the field still
|
|
22
|
+
// yields a usable pill count.
|
|
23
|
+
total: res.total ?? ideas + nameCorrections + pendingCompanies + duplicateOrgs,
|
|
24
|
+
generatedAt: res.generatedAt ?? ""
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
getAdminReviewQueues
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=admin-review-queues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/admin-review-queues.ts"],"sourcesContent":["import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/**\n * Options for {@link getAdminReviewQueues}. Supports the same `cookieHeader`\n * passthrough as the other admin reads for RSC contexts.\n */\nexport interface GetAdminReviewQueuesOptions extends ApiFetchOptions {\n cookieHeader?: string;\n}\n\n/** Response shape of `GET /api/admin/stats/review-queues`. */\nexport interface AdminReviewQueues {\n ideas: number;\n nameCorrections: number;\n pendingCompanies: number;\n duplicateOrgs: number;\n /** Sum of the queues. */\n total: number;\n generatedAt: string;\n}\n\n/**\n * Open counts for the three admin review queues (ideas, pending companies,\n * name corrections) plus their total.\n *\n * Unlike {@link listFeatureAllowlist} this does NOT swallow errors: a zeroed\n * payload would render as \"all queues clear\" in the admin nav, which is worse\n * than rendering nothing. Callers decide how to degrade.\n */\nexport async function getAdminReviewQueues(\n config: SifaApiConfig,\n opts: GetAdminReviewQueuesOptions = {},\n): Promise<AdminReviewQueues> {\n const headers: Record<string, string> = { ...(opts.headers ?? {}) };\n if (opts.cookieHeader) headers.cookie = opts.cookieHeader;\n\n const res = await apiFetch<Partial<AdminReviewQueues>>(config, '/api/admin/stats/review-queues', {\n credentials: 'include',\n cache: 'no-store',\n ...opts,\n headers,\n });\n\n const ideas = res.ideas ?? 0;\n const nameCorrections = res.nameCorrections ?? 0;\n const pendingCompanies = res.pendingCompanies ?? 0;\n const duplicateOrgs = res.duplicateOrgs ?? 0;\n\n return {\n ideas,\n nameCorrections,\n pendingCompanies,\n duplicateOrgs,\n // Derived rather than trusted so an API that predates the field still\n // yields a usable pill count.\n total: res.total ?? ideas + nameCorrections + pendingCompanies + duplicateOrgs,\n generatedAt: res.generatedAt ?? '',\n };\n}\n"],"mappings":";AAAA,SAAS,gBAA0D;AA6BnE,eAAsB,qBACpB,QACA,OAAoC,CAAC,GACT;AAC5B,QAAM,UAAkC,EAAE,GAAI,KAAK,WAAW,CAAC,EAAG;AAClE,MAAI,KAAK,aAAc,SAAQ,SAAS,KAAK;AAE7C,QAAM,MAAM,MAAM,SAAqC,QAAQ,kCAAkC;AAAA,IAC/F,aAAa;AAAA,IACb,OAAO;AAAA,IACP,GAAG;AAAA,IACH;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,IAAI,SAAS;AAC3B,QAAM,kBAAkB,IAAI,mBAAmB;AAC/C,QAAM,mBAAmB,IAAI,oBAAoB;AACjD,QAAM,gBAAgB,IAAI,iBAAiB;AAE3C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA,OAAO,IAAI,SAAS,QAAQ,kBAAkB,mBAAmB;AAAA,IACjE,aAAa,IAAI,eAAe;AAAA,EAClC;AACF;","names":[]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// src/query/fetchers/apps.ts
|
|
2
|
+
import { apiFetch } from "../client.js";
|
|
3
|
+
async function fetchAppsRegistry(config, options = {}) {
|
|
4
|
+
try {
|
|
5
|
+
return await apiFetch(config, "/api/apps/registry", {
|
|
6
|
+
next: { revalidate: 86400 },
|
|
7
|
+
...options
|
|
8
|
+
});
|
|
9
|
+
} catch {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
async function fetchHiddenApps(config, options = {}) {
|
|
14
|
+
const headers = { ...options.headers ?? {} };
|
|
15
|
+
if (options.cookieHeader) headers.cookie = options.cookieHeader;
|
|
16
|
+
try {
|
|
17
|
+
const data = await apiFetch(config, "/api/profile/hidden-apps", {
|
|
18
|
+
credentials: "include",
|
|
19
|
+
...options,
|
|
20
|
+
headers
|
|
21
|
+
});
|
|
22
|
+
return data.apps;
|
|
23
|
+
} catch {
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
fetchAppsRegistry,
|
|
29
|
+
fetchHiddenApps
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=apps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/apps.ts"],"sourcesContent":["import { apiFetch, type ApiFetchOptions, type SifaApiConfig } from '../client.js';\n\n/** Catalog entry describing an ATproto app that Sifa surfaces activity for. */\nexport interface AppRegistryEntry {\n id: string;\n name: string;\n category: string;\n collectionPrefixes: string[];\n scanCollections: string[];\n urlPattern?: string;\n color: string;\n}\n\n/** Compact app representation returned by the hidden-apps endpoint. */\nexport interface HiddenApp {\n id: string;\n name: string;\n category: string;\n}\n\nexport interface FetchHiddenAppsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Public app registry shown across discovery surfaces. Heavily cached.\n * Returns `[]` on any error.\n */\nexport async function fetchAppsRegistry(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<AppRegistryEntry[]> {\n try {\n return await apiFetch<AppRegistryEntry[]>(config, '/api/apps/registry', {\n next: { revalidate: 86400 },\n ...options,\n });\n } catch {\n return [];\n }\n}\n\n/**\n * Apps the authenticated user has chosen to hide from their activity feed.\n * Requires an authenticated session. Returns `[]` on any error (including\n * the unauthenticated case).\n */\nexport async function fetchHiddenApps(\n config: SifaApiConfig,\n options: FetchHiddenAppsOptions = {},\n): Promise<HiddenApp[]> {\n const headers: Record<string, string> = { ...(options.headers ?? {}) };\n if (options.cookieHeader) headers.cookie = options.cookieHeader;\n\n try {\n const data = await apiFetch<{ apps: HiddenApp[] }>(config, '/api/profile/hidden-apps', {\n credentials: 'include',\n ...options,\n headers,\n });\n return data.apps;\n } catch {\n return [];\n }\n}\n"],"mappings":";AAAA,SAAS,gBAA0D;AAiCnE,eAAsB,kBACpB,QACA,UAA2B,CAAC,GACC;AAC7B,MAAI;AACF,WAAO,MAAM,SAA6B,QAAQ,sBAAsB;AAAA,MACtE,MAAM,EAAE,YAAY,MAAM;AAAA,MAC1B,GAAG;AAAA,IACL,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAOA,eAAsB,gBACpB,QACA,UAAkC,CAAC,GACb;AACtB,QAAM,UAAkC,EAAE,GAAI,QAAQ,WAAW,CAAC,EAAG;AACrE,MAAI,QAAQ,aAAc,SAAQ,SAAS,QAAQ;AAEnD,MAAI;AACF,UAAM,OAAO,MAAM,SAAgC,QAAQ,4BAA4B;AAAA,MACrF,aAAa;AAAA,MACb,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AACD,WAAO,KAAK;AAAA,EACd,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;","names":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/query/fetchers/bsky-preferences.ts
|
|
2
|
+
import { ADULT_CONTENT_LABELS } from "../../cards/adult-content.js";
|
|
3
|
+
import {
|
|
4
|
+
apiFetch,
|
|
5
|
+
apiWrite
|
|
6
|
+
} from "../client.js";
|
|
7
|
+
async function fetchBskyContentLabelPrefs(config, options = {}) {
|
|
8
|
+
const { onNeedsScope, ...fetchOptions } = options;
|
|
9
|
+
try {
|
|
10
|
+
const res = await apiFetch(
|
|
11
|
+
config,
|
|
12
|
+
"/api/bsky/preferences/content-labels",
|
|
13
|
+
{ credentials: "include", ...fetchOptions }
|
|
14
|
+
);
|
|
15
|
+
return res.contentLabels;
|
|
16
|
+
} catch (err) {
|
|
17
|
+
if (err && typeof err === "object" && "status" in err && err.status === 403) {
|
|
18
|
+
onNeedsScope?.();
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function updateBskyContentLabelPrefs(config, body) {
|
|
24
|
+
const result = await apiWrite(config, "/api/bsky/preferences/content-labels", "PUT", {
|
|
25
|
+
headers: { "Content-Type": "application/json" },
|
|
26
|
+
body: JSON.stringify(body)
|
|
27
|
+
});
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
function effectiveContentVisibility(label, prefs, isAuthenticated) {
|
|
31
|
+
if (!isAuthenticated) return "hide";
|
|
32
|
+
const value = prefs?.[label] ?? null;
|
|
33
|
+
return value ?? "hide";
|
|
34
|
+
}
|
|
35
|
+
function shouldGateAdultMedia(labels, prefs, isAuthenticated) {
|
|
36
|
+
if (!labels || labels.length === 0) return false;
|
|
37
|
+
for (const label of labels) {
|
|
38
|
+
if (label.neg) continue;
|
|
39
|
+
if (!ADULT_CONTENT_LABELS.includes(label.val)) continue;
|
|
40
|
+
const visibility = effectiveContentVisibility(
|
|
41
|
+
label.val,
|
|
42
|
+
prefs,
|
|
43
|
+
isAuthenticated
|
|
44
|
+
);
|
|
45
|
+
if (visibility !== "ignore") return true;
|
|
46
|
+
}
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
effectiveContentVisibility,
|
|
51
|
+
fetchBskyContentLabelPrefs,
|
|
52
|
+
shouldGateAdultMedia,
|
|
53
|
+
updateBskyContentLabelPrefs
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=bsky-preferences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/bsky-preferences.ts"],"sourcesContent":["import { ADULT_CONTENT_LABELS, type AdultContentLabel } from '../../cards/adult-content.js';\nimport {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * Visibility values defined by `app.bsky.actor.defs#contentLabelPref`.\n * `null` means the viewer has no explicit pref for that label — call sites\n * decide a default (Sifa hides by default; Bluesky's own client defaults\n * to `warn` for adult labels on new accounts).\n */\nexport type BskyContentLabelVisibility = 'ignore' | 'warn' | 'hide';\n\nexport type BskyContentLabelPrefs = Record<AdultContentLabel, BskyContentLabelVisibility | null>;\n\nexport interface BskyContentLabelPrefsResponse {\n contentLabels: BskyContentLabelPrefs;\n}\n\nexport interface BskyPrefsScopeError {\n error: 'InsufficientScope';\n message?: string;\n needsScope: 'bsky-preferences';\n}\n\n/**\n * Read the viewer's Bluesky content-label preferences via sifa-api's\n * proxy. Returns `null` when the viewer's OAuth grant doesn't include the\n * read scope — sifa-web treats this as \"needs scope upgrade\" and triggers\n * a granular re-auth.\n *\n * Any other failure (network, upstream PDS error) also resolves to `null`\n * so callers always have a safe default (hide everything).\n */\nexport async function fetchBskyContentLabelPrefs(\n config: SifaApiConfig,\n options: ApiFetchOptions & { onNeedsScope?: () => void } = {},\n): Promise<BskyContentLabelPrefs | null> {\n const { onNeedsScope, ...fetchOptions } = options;\n try {\n const res = await apiFetch<BskyContentLabelPrefsResponse>(\n config,\n '/api/bsky/preferences/content-labels',\n { credentials: 'include', ...fetchOptions },\n );\n return res.contentLabels;\n } catch (err) {\n if (\n err &&\n typeof err === 'object' &&\n 'status' in err &&\n (err as { status: number }).status === 403\n ) {\n onNeedsScope?.();\n }\n return null;\n }\n}\n\nexport interface UpdateBskyContentLabelPrefsBody {\n contentLabels: Array<{\n label: AdultContentLabel;\n visibility: BskyContentLabelVisibility;\n }>;\n}\n\n/**\n * Update one or more of the viewer's adult content-label preferences. The\n * sifa-api endpoint merges these into the viewer's existing prefs and\n * writes the whole array back to their PDS — entries we don't touch are\n * preserved.\n *\n * On insufficient-scope returns `{ success: false, error: ..., needsScope }`\n * so the caller can drive a granular re-auth.\n */\nexport async function updateBskyContentLabelPrefs(\n config: SifaApiConfig,\n body: UpdateBskyContentLabelPrefsBody,\n): Promise<\n WriteResult & { contentLabels?: BskyContentLabelPrefs; needsScope?: 'bsky-preferences' }\n> {\n const result = await apiWrite<{\n contentLabels?: BskyContentLabelPrefs;\n needsScope?: 'bsky-preferences';\n }>(config, '/api/bsky/preferences/content-labels', 'PUT', {\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n return result;\n}\n\n/**\n * Compute the effective visibility for a Bluesky adult label.\n *\n * - Anonymous viewer (no prefs): always `hide` — matches Bluesky's logged-out\n * behaviour; sifa-web won't even render a Show button.\n * - Authenticated viewer with no explicit pref: `hide` by default, so Sifa\n * stays safe-by-default and matches the gate that ships in sifa-web#1240\n * today.\n * - Authenticated viewer with an explicit pref: use it directly.\n *\n * Returns `'ignore'` to mean \"render media inline\", `'warn'` and `'hide'`\n * both mean \"placeholder card + reveal button\" — Sifa doesn't distinguish\n * the two today, but keeping them separate matches the lexicon and lets the\n * UI evolve (e.g. blur for warn, full hide for hide) without an SDK change.\n */\nexport function effectiveContentVisibility(\n label: AdultContentLabel,\n prefs: BskyContentLabelPrefs | null,\n isAuthenticated: boolean,\n): BskyContentLabelVisibility {\n if (!isAuthenticated) return 'hide';\n const value = prefs?.[label] ?? null;\n return value ?? 'hide';\n}\n\n/**\n * Whether a labeled item should render its media inline. Convenience over\n * `effectiveContentVisibility` for the common \"any adult label hides\n * everything\" case in BlueskyPostCard.\n */\nexport function shouldGateAdultMedia(\n labels: ReadonlyArray<{ val: string; neg?: boolean }> | undefined,\n prefs: BskyContentLabelPrefs | null,\n isAuthenticated: boolean,\n): boolean {\n if (!labels || labels.length === 0) return false;\n for (const label of labels) {\n if (label.neg) continue;\n if (!(ADULT_CONTENT_LABELS as readonly string[]).includes(label.val)) continue;\n const visibility = effectiveContentVisibility(\n label.val as AdultContentLabel,\n prefs,\n isAuthenticated,\n );\n if (visibility !== 'ignore') return true;\n }\n return false;\n}\n"],"mappings":";AAAA,SAAS,4BAAoD;AAC7D;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AA+BP,eAAsB,2BACpB,QACA,UAA2D,CAAC,GACrB;AACvC,QAAM,EAAE,cAAc,GAAG,aAAa,IAAI;AAC1C,MAAI;AACF,UAAM,MAAM,MAAM;AAAA,MAChB;AAAA,MACA;AAAA,MACA,EAAE,aAAa,WAAW,GAAG,aAAa;AAAA,IAC5C;AACA,WAAO,IAAI;AAAA,EACb,SAAS,KAAK;AACZ,QACE,OACA,OAAO,QAAQ,YACf,YAAY,OACX,IAA2B,WAAW,KACvC;AACA,qBAAe;AAAA,IACjB;AACA,WAAO;AAAA,EACT;AACF;AAkBA,eAAsB,4BACpB,QACA,MAGA;AACA,QAAM,SAAS,MAAM,SAGlB,QAAQ,wCAAwC,OAAO;AAAA,IACxD,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,SAAO;AACT;AAiBO,SAAS,2BACd,OACA,OACA,iBAC4B;AAC5B,MAAI,CAAC,gBAAiB,QAAO;AAC7B,QAAM,QAAQ,QAAQ,KAAK,KAAK;AAChC,SAAO,SAAS;AAClB;AAOO,SAAS,qBACd,QACA,OACA,iBACS;AACT,MAAI,CAAC,UAAU,OAAO,WAAW,EAAG,QAAO;AAC3C,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM,IAAK;AACf,QAAI,CAAE,qBAA2C,SAAS,MAAM,GAAG,EAAG;AACtE,UAAM,aAAa;AAAA,MACjB,MAAM;AAAA,MACN;AAAA,MACA;AAAA,IACF;AACA,QAAI,eAAe,SAAU,QAAO;AAAA,EACtC;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/query/fetchers/confirmations.ts
|
|
2
|
+
import {
|
|
3
|
+
apiFetch,
|
|
4
|
+
apiWrite,
|
|
5
|
+
apiWriteCreate
|
|
6
|
+
} from "../client.js";
|
|
7
|
+
async function fetchPendingConfirmations(config, options = {}) {
|
|
8
|
+
const { cookieHeader, ...rest } = options;
|
|
9
|
+
const headers = { ...rest.headers ?? {} };
|
|
10
|
+
if (cookieHeader) headers.cookie = cookieHeader;
|
|
11
|
+
try {
|
|
12
|
+
const data = await apiFetch(config, "/api/confirmations/pending", {
|
|
13
|
+
cache: "no-store",
|
|
14
|
+
credentials: "include",
|
|
15
|
+
timeoutMs: 5e3,
|
|
16
|
+
...rest,
|
|
17
|
+
headers
|
|
18
|
+
});
|
|
19
|
+
return { confirmations: data?.confirmations ?? [], cursor: data?.cursor };
|
|
20
|
+
} catch {
|
|
21
|
+
return { confirmations: [] };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function fetchGivenConfirmations(config, options = {}) {
|
|
25
|
+
const { cookieHeader, ...rest } = options;
|
|
26
|
+
const headers = { ...rest.headers ?? {} };
|
|
27
|
+
if (cookieHeader) headers.cookie = cookieHeader;
|
|
28
|
+
try {
|
|
29
|
+
const data = await apiFetch(
|
|
30
|
+
config,
|
|
31
|
+
"/api/confirmations/mine",
|
|
32
|
+
{ cache: "no-store", credentials: "include", timeoutMs: 5e3, ...rest, headers }
|
|
33
|
+
);
|
|
34
|
+
return { confirmations: data?.confirmations ?? [] };
|
|
35
|
+
} catch {
|
|
36
|
+
return { confirmations: [] };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function createConfirmation(config, data, options = {}) {
|
|
40
|
+
return apiWriteCreate(config, "/api/confirmation", data, options);
|
|
41
|
+
}
|
|
42
|
+
function dismissConfirmation(config, data, options = {}) {
|
|
43
|
+
return apiWrite(config, "/api/confirmation/dismiss", "POST", { body: data, ...options });
|
|
44
|
+
}
|
|
45
|
+
function revokeConfirmation(config, data, options = {}) {
|
|
46
|
+
return apiWrite(config, "/api/confirmation/revoke", "POST", { body: data, ...options });
|
|
47
|
+
}
|
|
48
|
+
export {
|
|
49
|
+
createConfirmation,
|
|
50
|
+
dismissConfirmation,
|
|
51
|
+
fetchGivenConfirmations,
|
|
52
|
+
fetchPendingConfirmations,
|
|
53
|
+
revokeConfirmation
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=confirmations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/confirmations.ts"],"sourcesContent":["import {\n apiFetch,\n apiWrite,\n apiWriteCreate,\n type ApiFetchOptions,\n type CreateResult,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/** A claim naming the signed-in user that they have neither confirmed nor dismissed. */\nexport interface PendingConfirmation {\n /** DID of the person who wrote the claim. */\n claimerDid: string;\n /**\n * Claimer's handle, when the AppView has resolved one. Absent when they have\n * no Sifa profile: a claim can be written by any AT Protocol app, so the UI\n * needs a fallback for having no name to show.\n */\n claimerHandle?: string;\n claimerDisplayName?: string;\n claimerAvatar?: string;\n /** AT-URI of the record that names you. The confirm mutation needs a strongRef. */\n subjectUri: string;\n /**\n * CID of that record, when the AppView has it. Often absent, since a record\n * indexed from another app can arrive without one. Pass it through when\n * present; the AppView resolves it from the claimer's PDS when it is not.\n * Never substitute a different record's CID.\n */\n subjectCid?: string;\n relation: string;\n /** Name or title the subject record carries right now, for display and snapshotting. */\n subjectName: string;\n /** Role the claimer assigned you, for `projectMember`. Display only. */\n role?: string;\n title?: string;\n createdAt: string;\n}\n\nexport interface PendingConfirmationsPage {\n confirmations: PendingConfirmation[];\n cursor?: string;\n}\n\n/**\n * A confirmation the signed-in user has already given.\n *\n * This is an AppView READ shape, not a PDS record, so it is a hand-written\n * interface like {@link PendingConfirmation} and {@link PendingConfirmation}'s\n * siblings -- the Zod schemas in `../schemas` validate lexicon record writes,\n * not these read DTOs. Fields are additive and passed through verbatim.\n */\nexport interface GivenConfirmation {\n subjectUri: string;\n claimerDid: string;\n claimerHandle?: string;\n /** Claimer's display name (Sifa override wins), for naming them without a handle. */\n claimerDisplayName?: string;\n relation: string;\n /** The name as it stood when confirmed, so a rename shows as a difference. */\n subjectName: string;\n /** The name the record carries now. Absent when the claim no longer exists. */\n currentName?: string;\n /** The record changed materially after it was confirmed. */\n confirmedStale: boolean;\n /** They removed you from the record, or deleted it. Nothing left to withdraw. */\n claimWithdrawn: boolean;\n createdAt: string;\n}\n\n/** Body accepted by {@link createConfirmation}. */\nexport interface ConfirmationInput {\n subjectUri: string;\n subjectCid?: string;\n relation: string;\n /**\n * Snapshot of the subject's name at confirmation time. Stored in your own\n * repo, out of the claimer's reach, so a later rename is detectable.\n */\n subjectName?: string;\n}\n\n/** Body accepted by {@link dismissConfirmation} and {@link revokeConfirmation}. */\nexport interface ConfirmationSubjectInput {\n subjectUri: string;\n}\n\n/** Options for the read fetchers, adding the RSC cookie-forwarding escape hatch. */\nexport interface FetchConfirmationsOptions extends ApiFetchOptions {\n /**\n * Pass the caller's `Cookie` header on Next.js RSC server-side calls.\n * `credentials: 'include'` does NOT propagate browser cookies in RSC,\n * so authenticated server fetches must forward the header explicitly.\n */\n cookieHeader?: string;\n}\n\n/**\n * Claims awaiting the signed-in user's decision. Requires credentials -- the\n * AppView reads the subject DID from the session, not from a parameter, so\n * there is no way to read someone else's inbox.\n *\n * Returns an empty page on failure so a broken inbox degrades to \"nothing\n * pending\" rather than breaking the surface hosting it.\n */\nexport async function fetchPendingConfirmations(\n config: SifaApiConfig,\n options: FetchConfirmationsOptions = {},\n): Promise<PendingConfirmationsPage> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n try {\n const data = await apiFetch<PendingConfirmationsPage>(config, '/api/confirmations/pending', {\n cache: 'no-store',\n credentials: 'include',\n timeoutMs: 5000,\n ...rest,\n headers,\n });\n return { confirmations: data?.confirmations ?? [], cursor: data?.cursor };\n } catch {\n return { confirmations: [] };\n }\n}\n\n/**\n * Confirmations the signed-in user has already given.\n *\n * The surface for changing your mind. Without it a confirmation is one-way in\n * practice: the inbox lists only claims you have not answered, so once answered\n * there is nowhere to see it, let alone withdraw it.\n *\n * Returns an empty list on failure, matching the pending inbox: a broken list\n * should not break the page hosting it.\n */\nexport async function fetchGivenConfirmations(\n config: SifaApiConfig,\n options: FetchConfirmationsOptions = {},\n): Promise<{ confirmations: GivenConfirmation[] }> {\n const { cookieHeader, ...rest } = options;\n const headers: Record<string, string> = { ...(rest.headers ?? {}) };\n if (cookieHeader) headers.cookie = cookieHeader;\n try {\n const data = await apiFetch<{ confirmations: GivenConfirmation[] }>(\n config,\n '/api/confirmations/mine',\n { cache: 'no-store', credentials: 'include', timeoutMs: 5000, ...rest, headers },\n );\n return { confirmations: data?.confirmations ?? [] };\n } catch {\n return { confirmations: [] };\n }\n}\n\n/**\n * Affirm that a record naming you is accurate, writing an `id.sifa.confirmation`\n * to your own PDS. Until this exists the claim renders as a bare handle with no\n * display name, avatar, or link back to you.\n *\n * Confirming does not put the claimer's record on your profile. That record\n * lives in their repository and they can rename it at will; keeping your own\n * entry is a separate, deliberate step.\n */\nexport function createConfirmation(\n config: SifaApiConfig,\n data: ConfirmationInput,\n options: ApiFetchOptions = {},\n): Promise<CreateResult> {\n return apiWriteCreate(config, '/api/confirmation', data, options);\n}\n\n/**\n * Take a claim out of the inbox without confirming it.\n *\n * This writes nothing to any PDS. A claim only gains your identity once you\n * have confirmed it, so declining is already the default state -- the dismissal\n * is a local flag that stops it reappearing, not a published rejection the\n * claimer can read.\n */\nexport function dismissConfirmation(\n config: SifaApiConfig,\n data: ConfirmationSubjectInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/confirmation/dismiss', 'POST', { body: data, ...options });\n}\n\n/**\n * Withdraw a confirmation you previously gave, deleting the record from your\n * PDS. The claim reverts to rendering as a bare handle.\n *\n * The usual reason is drift: the claimer renamed the project or changed the\n * role after you confirmed, so what you affirmed is no longer what is shown.\n * Also writes a dismissal, or the still-live claim returns to your inbox.\n */\nexport function revokeConfirmation(\n config: SifaApiConfig,\n data: ConfirmationSubjectInput,\n options: ApiFetchOptions = {},\n): Promise<WriteResult> {\n return apiWrite(config, '/api/confirmation/revoke', 'POST', { body: data, ...options });\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAKK;AAkGP,eAAsB,0BACpB,QACA,UAAqC,CAAC,GACH;AACnC,QAAM,EAAE,cAAc,GAAG,KAAK,IAAI;AAClC,QAAM,UAAkC,EAAE,GAAI,KAAK,WAAW,CAAC,EAAG;AAClE,MAAI,aAAc,SAAQ,SAAS;AACnC,MAAI;AACF,UAAM,OAAO,MAAM,SAAmC,QAAQ,8BAA8B;AAAA,MAC1F,OAAO;AAAA,MACP,aAAa;AAAA,MACb,WAAW;AAAA,MACX,GAAG;AAAA,MACH;AAAA,IACF,CAAC;AACD,WAAO,EAAE,eAAe,MAAM,iBAAiB,CAAC,GAAG,QAAQ,MAAM,OAAO;AAAA,EAC1E,QAAQ;AACN,WAAO,EAAE,eAAe,CAAC,EAAE;AAAA,EAC7B;AACF;AAYA,eAAsB,wBACpB,QACA,UAAqC,CAAC,GACW;AACjD,QAAM,EAAE,cAAc,GAAG,KAAK,IAAI;AAClC,QAAM,UAAkC,EAAE,GAAI,KAAK,WAAW,CAAC,EAAG;AAClE,MAAI,aAAc,SAAQ,SAAS;AACnC,MAAI;AACF,UAAM,OAAO,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA,EAAE,OAAO,YAAY,aAAa,WAAW,WAAW,KAAM,GAAG,MAAM,QAAQ;AAAA,IACjF;AACA,WAAO,EAAE,eAAe,MAAM,iBAAiB,CAAC,EAAE;AAAA,EACpD,QAAQ;AACN,WAAO,EAAE,eAAe,CAAC,EAAE;AAAA,EAC7B;AACF;AAWO,SAAS,mBACd,QACA,MACA,UAA2B,CAAC,GACL;AACvB,SAAO,eAAe,QAAQ,qBAAqB,MAAM,OAAO;AAClE;AAUO,SAAS,oBACd,QACA,MACA,UAA2B,CAAC,GACN;AACtB,SAAO,SAAS,QAAQ,6BAA6B,QAAQ,EAAE,MAAM,MAAM,GAAG,QAAQ,CAAC;AACzF;AAUO,SAAS,mBACd,QACA,MACA,UAA2B,CAAC,GACN;AACtB,SAAO,SAAS,QAAQ,4BAA4B,QAAQ,EAAE,MAAM,MAAM,GAAG,QAAQ,CAAC;AACxF;","names":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// src/query/fetchers/destructive.ts
|
|
2
|
+
import {
|
|
3
|
+
apiFetch,
|
|
4
|
+
apiWrite
|
|
5
|
+
} from "../client.js";
|
|
6
|
+
function fetchWipePreview(config, options = {}) {
|
|
7
|
+
return apiFetch(config, "/api/profile/wipe-preview", {
|
|
8
|
+
credentials: "include",
|
|
9
|
+
...options
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function resetProfile(config, deletePdsData, options = {}) {
|
|
13
|
+
return apiWrite(config, "/api/profile/reset", "DELETE", {
|
|
14
|
+
body: { deletePdsData },
|
|
15
|
+
...options
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function deleteAccount(config, deletePdsData, options = {}) {
|
|
19
|
+
return apiWrite(
|
|
20
|
+
config,
|
|
21
|
+
"/api/profile/account",
|
|
22
|
+
"DELETE",
|
|
23
|
+
{
|
|
24
|
+
body: { deletePdsData },
|
|
25
|
+
...options
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
export {
|
|
30
|
+
deleteAccount,
|
|
31
|
+
fetchWipePreview,
|
|
32
|
+
resetProfile
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=destructive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/query/fetchers/destructive.ts"],"sourcesContent":["import {\n apiFetch,\n apiWrite,\n type ApiFetchOptions,\n type SifaApiConfig,\n type WriteResult,\n} from '../client.js';\n\n/**\n * What the server managed to remove from the user's PDS.\n *\n * The wipe runs per collection, so it can partly succeed: `success: true` means\n * the account action completed, NOT that the PDS is clean. A UI that ignores\n * this can tell someone their data is gone while it is still on their data\n * server, so treat a non-empty `remaining` as \"not deleted\".\n *\n * Absent when the PDS was not touched (`deletePdsData: false`).\n */\nexport interface PdsWipeOutcome {\n /** Collections whose records were removed. */\n deleted: string[];\n /** Collections whose records are still on the PDS. Non-empty means not done. */\n remaining: string[];\n /**\n * The server could not enumerate the repo, so it does not know what survived.\n * Without this, that case is indistinguishable from \"nothing to delete\".\n */\n unknown: boolean;\n}\n\n/**\n * What a PDS wipe could not remove with the grant the session holds today.\n *\n * Read this BEFORE the destructive step. Deleting an account destroys the\n * session, so a missing scope cannot be granted afterwards -- there is nobody\n * left to ask. A non-empty `needsScopeFor` means the wipe would strand those\n * records on the user's data server.\n */\nexport interface WipePreview {\n /** id.sifa.* collections the current grant cannot delete. */\n needsScopeFor: string[];\n /**\n * The server could not enumerate the repo, so the gap list is not\n * authoritative. Distinct from an empty list, which means \"nothing to ask for\".\n */\n unknown?: boolean;\n}\n\n/**\n * Ask which id.sifa.* collections the current grant cannot delete.\n *\n * Unlike most read fetchers in this file's neighbourhood, a failure is NOT\n * flattened into an empty result: an empty gap list reads as \"a wipe will be\n * clean\", and a caller must not promise that on the strength of a request that\n * never arrived. Let it throw and warn.\n */\nexport function fetchWipePreview(\n config: SifaApiConfig,\n options: ApiFetchOptions = {},\n): Promise<WipePreview> {\n return apiFetch<WipePreview>(config, '/api/profile/wipe-preview', {\n credentials: 'include',\n ...options,\n });\n}\n\n/** Extended write result for {@link resetProfile}. */\nexport interface ResetProfileResult extends WriteResult {\n /** Present when `deletePdsData: true`. See {@link PdsWipeOutcome}. */\n pds?: PdsWipeOutcome;\n}\n\n/** Extended write result for {@link deleteAccount}. */\nexport interface DeleteAccountResult extends WriteResult {\n /** The deleted handle, returned by the server for confirmation UIs. */\n handle?: string;\n /** Present when `deletePdsData: true`. See {@link PdsWipeOutcome}. */\n pds?: PdsWipeOutcome;\n}\n\n/**\n * Reset the authenticated user's Sifa profile.\n *\n * `deletePdsData: true` also deletes the corresponding records on the\n * user's PDS. `deletePdsData: false` only removes the AppView's\n * indexed state -- the records on the PDS are left intact and could be\n * re-indexed later.\n *\n * Destructive. Server enforces session check + attestation; the SDK\n * does not gate on additional confirmation. Wrap call sites in your\n * own modal if you want a UX confirmation step.\n */\nexport function resetProfile(\n config: SifaApiConfig,\n deletePdsData: boolean,\n options: ApiFetchOptions = {},\n): Promise<ResetProfileResult> {\n return apiWrite<{ ok?: boolean; pds?: PdsWipeOutcome }>(config, '/api/profile/reset', 'DELETE', {\n body: { deletePdsData },\n ...options,\n });\n}\n\n/**\n * Delete the authenticated user's account. Returns the deleted handle\n * on success (used by the post-delete confirmation screen).\n *\n * `deletePdsData: true` also deletes the corresponding records on the\n * user's PDS; `false` leaves the PDS records intact.\n *\n * Destructive. Same caveat as {@link resetProfile}.\n */\nexport function deleteAccount(\n config: SifaApiConfig,\n deletePdsData: boolean,\n options: ApiFetchOptions = {},\n): Promise<DeleteAccountResult> {\n return apiWrite<{ ok?: boolean; handle?: string; pds?: PdsWipeOutcome }>(\n config,\n '/api/profile/account',\n 'DELETE',\n {\n body: { deletePdsData },\n ...options,\n },\n );\n}\n"],"mappings":";AAAA;AAAA,EACE;AAAA,EACA;AAAA,OAIK;AAkDA,SAAS,iBACd,QACA,UAA2B,CAAC,GACN;AACtB,SAAO,SAAsB,QAAQ,6BAA6B;AAAA,IAChE,aAAa;AAAA,IACb,GAAG;AAAA,EACL,CAAC;AACH;AA4BO,SAAS,aACd,QACA,eACA,UAA2B,CAAC,GACC;AAC7B,SAAO,SAAiD,QAAQ,sBAAsB,UAAU;AAAA,IAC9F,MAAM,EAAE,cAAc;AAAA,IACtB,GAAG;AAAA,EACL,CAAC;AACH;AAWO,SAAS,cACd,QACA,eACA,UAA2B,CAAC,GACE;AAC9B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACE,MAAM,EAAE,cAAc;AAAA,MACtB,GAAG;AAAA,IACL;AAAA,EACF;AACF;","names":[]}
|