@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.
Files changed (579) hide show
  1. package/dist/atproto/index.js +9 -3
  2. package/dist/atproto/index.js.map +1 -1
  3. package/dist/badge/index.js +5 -141
  4. package/dist/badge/index.js.map +1 -1
  5. package/dist/cards/adult-content.js +14 -0
  6. package/dist/cards/adult-content.js.map +1 -0
  7. package/dist/cards/app-url-patterns.js +369 -0
  8. package/dist/cards/app-url-patterns.js.map +1 -0
  9. package/dist/cards/index.js +24 -0
  10. package/dist/cards/index.js.map +1 -0
  11. package/dist/cards/resolve-card-url.js +198 -0
  12. package/dist/cards/resolve-card-url.js.map +1 -0
  13. package/dist/cards/visibility.js +45 -0
  14. package/dist/cards/visibility.js.map +1 -0
  15. package/dist/flags/index.js +4 -3
  16. package/dist/flags/index.js.map +1 -1
  17. package/dist/format/collapse-contributors.js +19 -0
  18. package/dist/format/collapse-contributors.js.map +1 -0
  19. package/dist/format/company-name.js +61 -0
  20. package/dist/format/company-name.js.map +1 -0
  21. package/dist/format/compare-text.js +9 -0
  22. package/dist/format/compare-text.js.map +1 -0
  23. package/dist/format/doi.js +8 -0
  24. package/dist/format/doi.js.map +1 -0
  25. package/dist/format/embed.js +131 -0
  26. package/dist/format/embed.js.map +1 -0
  27. package/dist/format/endorsement-context.js +35 -0
  28. package/dist/format/endorsement-context.js.map +1 -0
  29. package/dist/format/format-display-url.js +42 -0
  30. package/dist/format/format-display-url.js.map +1 -0
  31. package/dist/format/format-duration.js +13 -0
  32. package/dist/format/format-duration.js.map +1 -0
  33. package/dist/format/format-time.js +30 -0
  34. package/dist/format/format-time.js.map +1 -0
  35. package/dist/format/handle-utils.js +19 -0
  36. package/dist/format/handle-utils.js.map +1 -0
  37. package/dist/format/index.js +100 -0
  38. package/dist/format/index.js.map +1 -0
  39. package/dist/format/location-segments.js +29 -0
  40. package/dist/format/location-segments.js.map +1 -0
  41. package/dist/format/location-utils.js +42 -0
  42. package/dist/format/location-utils.js.map +1 -0
  43. package/dist/format/meta-description.js +35 -0
  44. package/dist/format/meta-description.js.map +1 -0
  45. package/dist/format/normalize-company-key.js +12 -0
  46. package/dist/format/normalize-company-key.js.map +1 -0
  47. package/dist/format/normalize-legal-form.js +71 -0
  48. package/dist/format/normalize-legal-form.js.map +1 -0
  49. package/dist/format/pds-utils.js +73 -0
  50. package/dist/format/pds-utils.js.map +1 -0
  51. package/dist/format/sort-by-date.js +39 -0
  52. package/dist/format/sort-by-date.js.map +1 -0
  53. package/dist/format/summarize-deliveries.js +37 -0
  54. package/dist/format/summarize-deliveries.js.map +1 -0
  55. package/dist/format/talk-slug.js +21 -0
  56. package/dist/format/talk-slug.js.map +1 -0
  57. package/dist/format/text-sanitize.js +29 -0
  58. package/dist/format/text-sanitize.js.map +1 -0
  59. package/dist/format/text-truncate.js +14 -0
  60. package/dist/format/text-truncate.js.map +1 -0
  61. package/dist/format/time-utils.js +19 -0
  62. package/dist/format/time-utils.js.map +1 -0
  63. package/dist/format/timeline.js +29 -0
  64. package/dist/format/timeline.js.map +1 -0
  65. package/dist/format/wcag-contrast.js +34 -0
  66. package/dist/format/wcag-contrast.js.map +1 -0
  67. package/dist/import/index.js +22 -0
  68. package/dist/import/index.js.map +1 -0
  69. package/dist/import/presentation-csv.js +116 -0
  70. package/dist/import/presentation-csv.js.map +1 -0
  71. package/dist/index.cjs +8 -1
  72. package/dist/index.cjs.map +1 -1
  73. package/dist/index.d.cts +11 -1
  74. package/dist/index.d.ts +11 -1
  75. package/dist/index.js +675 -7080
  76. package/dist/index.js.map +1 -1
  77. package/dist/jev/index.js +18 -5
  78. package/dist/jev/index.js.map +1 -1
  79. package/dist/jsonld/index.cjs.map +1 -1
  80. package/dist/jsonld/index.js +30 -987
  81. package/dist/jsonld/index.js.map +1 -1
  82. package/dist/jsonld/profile.js +222 -0
  83. package/dist/jsonld/profile.js.map +1 -0
  84. package/dist/jsonld/terms.js +496 -0
  85. package/dist/jsonld/terms.js.map +1 -0
  86. package/dist/jsonld/url.js +17 -0
  87. package/dist/jsonld/url.js.map +1 -0
  88. package/dist/jsonld/works-graph.js +41 -0
  89. package/dist/jsonld/works-graph.js.map +1 -0
  90. package/dist/jsonld/works.js +178 -0
  91. package/dist/jsonld/works.js.map +1 -0
  92. package/dist/logic/actor-identity.js +8 -0
  93. package/dist/logic/actor-identity.js.map +1 -0
  94. package/dist/logic/agent-ref.js +24 -0
  95. package/dist/logic/agent-ref.js.map +1 -0
  96. package/dist/logic/company-page-indexable.js +23 -0
  97. package/dist/logic/company-page-indexable.js.map +1 -0
  98. package/dist/logic/date-lookahead.js +31 -0
  99. package/dist/logic/date-lookahead.js.map +1 -0
  100. package/dist/logic/domain-detect.js +43 -0
  101. package/dist/logic/domain-detect.js.map +1 -0
  102. package/dist/logic/entity-disambiguation.js +24 -0
  103. package/dist/logic/entity-disambiguation.js.map +1 -0
  104. package/dist/logic/entity-ref-anchor.js +33 -0
  105. package/dist/logic/entity-ref-anchor.js.map +1 -0
  106. package/dist/logic/index.js +91 -0
  107. package/dist/logic/index.js.map +1 -0
  108. package/dist/logic/org-floor.js +66 -0
  109. package/dist/logic/org-floor.js.map +1 -0
  110. package/dist/logic/primary-item.js +9 -0
  111. package/dist/logic/primary-item.js.map +1 -0
  112. package/dist/logic/primary-position.js +16 -0
  113. package/dist/logic/primary-position.js.map +1 -0
  114. package/dist/logic/profile-completeness.js +21 -0
  115. package/dist/logic/profile-completeness.js.map +1 -0
  116. package/dist/logic/profile-dimensions.js +50 -0
  117. package/dist/logic/profile-dimensions.js.map +1 -0
  118. package/dist/logic/profile-summary.js +23 -0
  119. package/dist/logic/profile-summary.js.map +1 -0
  120. package/dist/logic/pseudo-employer.js +34 -0
  121. package/dist/logic/pseudo-employer.js.map +1 -0
  122. package/dist/logic/recent-activity.js +10 -0
  123. package/dist/logic/recent-activity.js.map +1 -0
  124. package/dist/logic/self-app.js +10 -0
  125. package/dist/logic/self-app.js.map +1 -0
  126. package/dist/{org-BCrvebcf.d.ts → org-CxTEjjrm.d.ts} +1 -1
  127. package/dist/{org-settings-C73Sin5E.d.ts → org-settings-BShvhyFp.d.ts} +1 -1
  128. package/dist/profile/headline-role-dedupe.js +12 -0
  129. package/dist/profile/headline-role-dedupe.js.map +1 -0
  130. package/dist/profile/highlights.js +200 -0
  131. package/dist/profile/highlights.js.map +1 -0
  132. package/dist/profile/index.js +66 -0
  133. package/dist/profile/index.js.map +1 -0
  134. package/dist/profile/involvement-grouping.js +31 -0
  135. package/dist/profile/involvement-grouping.js.map +1 -0
  136. package/dist/profile/language-sort.js +24 -0
  137. package/dist/profile/language-sort.js.map +1 -0
  138. package/dist/profile/publication-versions.js +98 -0
  139. package/dist/profile/publication-versions.js.map +1 -0
  140. package/dist/profile/range-sort.js +14 -0
  141. package/dist/profile/range-sort.js.map +1 -0
  142. package/dist/profile/section-model.js +122 -0
  143. package/dist/profile/section-model.js.map +1 -0
  144. package/dist/profile/section-sorts.js +33 -0
  145. package/dist/profile/section-sorts.js.map +1 -0
  146. package/dist/publishers/index.js +16 -0
  147. package/dist/publishers/index.js.map +1 -0
  148. package/dist/publishers/registry.js +87 -0
  149. package/dist/publishers/registry.js.map +1 -0
  150. package/dist/publishing/index.js +46 -184
  151. package/dist/publishing/index.js.map +1 -1
  152. package/dist/publishing/linkblog.js +42 -0
  153. package/dist/publishing/linkblog.js.map +1 -0
  154. package/dist/publishing/registry.js +32 -0
  155. package/dist/publishing/registry.js.map +1 -0
  156. package/dist/publishing/schemas.js +74 -0
  157. package/dist/publishing/schemas.js.map +1 -0
  158. package/dist/publishing/types.js +32 -0
  159. package/dist/publishing/types.js.map +1 -0
  160. package/dist/query/client.js +119 -0
  161. package/dist/query/client.js.map +1 -0
  162. package/dist/query/config.js +23 -0
  163. package/dist/query/config.js.map +1 -0
  164. package/dist/query/fetchers/accounts.js +29 -0
  165. package/dist/query/fetchers/accounts.js.map +1 -0
  166. package/dist/query/fetchers/activity-items-hide.js +31 -0
  167. package/dist/query/fetchers/activity-items-hide.js.map +1 -0
  168. package/dist/query/fetchers/activity.js +61 -0
  169. package/dist/query/fetchers/activity.js.map +1 -0
  170. package/dist/query/fetchers/actor.js +30 -0
  171. package/dist/query/fetchers/actor.js.map +1 -0
  172. package/dist/query/fetchers/admin-feature-allowlists.js +41 -0
  173. package/dist/query/fetchers/admin-feature-allowlists.js.map +1 -0
  174. package/dist/query/fetchers/admin-review-queues.js +30 -0
  175. package/dist/query/fetchers/admin-review-queues.js.map +1 -0
  176. package/dist/query/fetchers/apps.js +31 -0
  177. package/dist/query/fetchers/apps.js.map +1 -0
  178. package/dist/query/fetchers/bsky-preferences.js +55 -0
  179. package/dist/query/fetchers/bsky-preferences.js.map +1 -0
  180. package/dist/query/fetchers/confirmations.js +55 -0
  181. package/dist/query/fetchers/confirmations.js.map +1 -0
  182. package/dist/query/fetchers/destructive.js +34 -0
  183. package/dist/query/fetchers/destructive.js.map +1 -0
  184. package/dist/query/fetchers/discovery.js +67 -0
  185. package/dist/query/fetchers/discovery.js.map +1 -0
  186. package/dist/query/fetchers/education.js +23 -0
  187. package/dist/query/fetchers/education.js.map +1 -0
  188. package/dist/query/fetchers/endorsement-inbox.js +36 -0
  189. package/dist/query/fetchers/endorsement-inbox.js.map +1 -0
  190. package/dist/query/fetchers/endorsement.js +23 -0
  191. package/dist/query/fetchers/endorsement.js.map +1 -0
  192. package/dist/query/fetchers/endorsements.js +20 -0
  193. package/dist/query/fetchers/endorsements.js.map +1 -0
  194. package/dist/query/fetchers/entities.js +65 -0
  195. package/dist/query/fetchers/entities.js.map +1 -0
  196. package/dist/query/fetchers/external-accounts.js +74 -0
  197. package/dist/query/fetchers/external-accounts.js.map +1 -0
  198. package/dist/query/fetchers/follow-extras.js +38 -0
  199. package/dist/query/fetchers/follow-extras.js.map +1 -0
  200. package/dist/query/fetchers/follow.js +105 -0
  201. package/dist/query/fetchers/follow.js.map +1 -0
  202. package/dist/query/fetchers/get-profile-view.js +21 -0
  203. package/dist/query/fetchers/get-profile-view.js.map +1 -0
  204. package/dist/query/fetchers/github-prs.js +45 -0
  205. package/dist/query/fetchers/github-prs.js.map +1 -0
  206. package/dist/query/fetchers/inbox.js +29 -0
  207. package/dist/query/fetchers/inbox.js.map +1 -0
  208. package/dist/query/fetchers/index.d.ts +2 -2
  209. package/dist/query/fetchers/index.js +360 -2045
  210. package/dist/query/fetchers/index.js.map +1 -1
  211. package/dist/query/fetchers/investments.js +18 -0
  212. package/dist/query/fetchers/investments.js.map +1 -0
  213. package/dist/query/fetchers/keytrace-claims.js +23 -0
  214. package/dist/query/fetchers/keytrace-claims.js.map +1 -0
  215. package/dist/query/fetchers/marque-domains.js +23 -0
  216. package/dist/query/fetchers/marque-domains.js.map +1 -0
  217. package/dist/query/fetchers/network-map.js +36 -0
  218. package/dist/query/fetchers/network-map.js.map +1 -0
  219. package/dist/query/fetchers/org.js +48 -0
  220. package/dist/query/fetchers/org.js.map +1 -0
  221. package/dist/query/fetchers/positions.js +77 -0
  222. package/dist/query/fetchers/positions.js.map +1 -0
  223. package/dist/query/fetchers/profile-completeness.js +45 -0
  224. package/dist/query/fetchers/profile-completeness.js.map +1 -0
  225. package/dist/query/fetchers/profile-items-hide.js +36 -0
  226. package/dist/query/fetchers/profile-items-hide.js.map +1 -0
  227. package/dist/query/fetchers/profile-locations.js +23 -0
  228. package/dist/query/fetchers/profile-locations.js.map +1 -0
  229. package/dist/query/fetchers/profile-mutations.js +82 -0
  230. package/dist/query/fetchers/profile-mutations.js.map +1 -0
  231. package/dist/query/fetchers/profile-summary.js +14 -0
  232. package/dist/query/fetchers/profile-summary.js.map +1 -0
  233. package/dist/query/fetchers/profile.js +31 -0
  234. package/dist/query/fetchers/profile.js.map +1 -0
  235. package/dist/query/fetchers/publications.js +66 -0
  236. package/dist/query/fetchers/publications.js.map +1 -0
  237. package/dist/query/fetchers/quoted-posts.js +40 -0
  238. package/dist/query/fetchers/quoted-posts.js.map +1 -0
  239. package/dist/query/fetchers/reactions.js +85 -0
  240. package/dist/query/fetchers/reactions.js.map +1 -0
  241. package/dist/query/fetchers/received-endorsements.js +20 -0
  242. package/dist/query/fetchers/received-endorsements.js.map +1 -0
  243. package/dist/query/fetchers/reciprocity.js +23 -0
  244. package/dist/query/fetchers/reciprocity.js.map +1 -0
  245. package/dist/query/fetchers/records.js +27 -0
  246. package/dist/query/fetchers/records.js.map +1 -0
  247. package/dist/query/fetchers/repo-inventory.js +23 -0
  248. package/dist/query/fetchers/repo-inventory.js.map +1 -0
  249. package/dist/query/fetchers/roadmap.js +73 -0
  250. package/dist/query/fetchers/roadmap.js.map +1 -0
  251. package/dist/query/fetchers/rpg.js +36 -0
  252. package/dist/query/fetchers/rpg.js.map +1 -0
  253. package/dist/query/fetchers/search.js +78 -0
  254. package/dist/query/fetchers/search.js.map +1 -0
  255. package/dist/query/fetchers/section-primary.js +23 -0
  256. package/dist/query/fetchers/section-primary.js.map +1 -0
  257. package/dist/query/fetchers/skills.js +30 -0
  258. package/dist/query/fetchers/skills.js.map +1 -0
  259. package/dist/query/fetchers/speakers.js +42 -0
  260. package/dist/query/fetchers/speakers.js.map +1 -0
  261. package/dist/query/fetchers/stats.js +16 -0
  262. package/dist/query/fetchers/stats.js.map +1 -0
  263. package/dist/query/fetchers/stream.js +30 -0
  264. package/dist/query/fetchers/stream.js.map +1 -0
  265. package/dist/query/fetchers/unlinked-positions.js +30 -0
  266. package/dist/query/fetchers/unlinked-positions.js.map +1 -0
  267. package/dist/query/hooks/index.d.ts +3 -3
  268. package/dist/query/hooks/index.js +283 -3555
  269. package/dist/query/hooks/index.js.map +1 -1
  270. package/dist/query/hooks/use-accounts.js +19 -0
  271. package/dist/query/hooks/use-accounts.js.map +1 -0
  272. package/dist/query/hooks/use-activity-items-hide.js +52 -0
  273. package/dist/query/hooks/use-activity-items-hide.js.map +1 -0
  274. package/dist/query/hooks/use-activity.js +44 -0
  275. package/dist/query/hooks/use-activity.js.map +1 -0
  276. package/dist/query/hooks/use-admin-review-queues.js +21 -0
  277. package/dist/query/hooks/use-admin-review-queues.js.map +1 -0
  278. package/dist/query/hooks/use-apps.js +31 -0
  279. package/dist/query/hooks/use-apps.js.map +1 -0
  280. package/dist/query/hooks/use-bsky-content-prefs.js +45 -0
  281. package/dist/query/hooks/use-bsky-content-prefs.js.map +1 -0
  282. package/dist/query/hooks/use-confirmations.js +121 -0
  283. package/dist/query/hooks/use-confirmations.js.map +1 -0
  284. package/dist/query/hooks/use-create-position.js +28 -0
  285. package/dist/query/hooks/use-create-position.js.map +1 -0
  286. package/dist/query/hooks/use-destructive.js +63 -0
  287. package/dist/query/hooks/use-destructive.js.map +1 -0
  288. package/dist/query/hooks/use-discovery.js +53 -0
  289. package/dist/query/hooks/use-discovery.js.map +1 -0
  290. package/dist/query/hooks/use-education-mutations.js +67 -0
  291. package/dist/query/hooks/use-education-mutations.js.map +1 -0
  292. package/dist/query/hooks/use-endorsement-inbox.js +80 -0
  293. package/dist/query/hooks/use-endorsement-inbox.js.map +1 -0
  294. package/dist/query/hooks/use-endorsement-mutations.js +33 -0
  295. package/dist/query/hooks/use-endorsement-mutations.js.map +1 -0
  296. package/dist/query/hooks/use-endorsement.js +20 -0
  297. package/dist/query/hooks/use-endorsement.js.map +1 -0
  298. package/dist/query/hooks/use-entity-search.js +73 -0
  299. package/dist/query/hooks/use-entity-search.js.map +1 -0
  300. package/dist/query/hooks/use-external-accounts.js +143 -0
  301. package/dist/query/hooks/use-external-accounts.js.map +1 -0
  302. package/dist/query/hooks/use-feature-allowlist.js +104 -0
  303. package/dist/query/hooks/use-feature-allowlist.js.map +1 -0
  304. package/dist/query/hooks/use-follow-extras.js +38 -0
  305. package/dist/query/hooks/use-follow-extras.js.map +1 -0
  306. package/dist/query/hooks/use-follow.js +113 -0
  307. package/dist/query/hooks/use-follow.js.map +1 -0
  308. package/dist/query/hooks/use-get-profile-view.js +20 -0
  309. package/dist/query/hooks/use-get-profile-view.js.map +1 -0
  310. package/dist/query/hooks/use-github-prs.js +21 -0
  311. package/dist/query/hooks/use-github-prs.js.map +1 -0
  312. package/dist/query/hooks/use-inbox.js +19 -0
  313. package/dist/query/hooks/use-inbox.js.map +1 -0
  314. package/dist/query/hooks/use-investment-mutations.js +65 -0
  315. package/dist/query/hooks/use-investment-mutations.js.map +1 -0
  316. package/dist/query/hooks/use-keytrace-claims.js +50 -0
  317. package/dist/query/hooks/use-keytrace-claims.js.map +1 -0
  318. package/dist/query/hooks/use-location-mutations.js +71 -0
  319. package/dist/query/hooks/use-location-mutations.js.map +1 -0
  320. package/dist/query/hooks/use-marque-domains.js +50 -0
  321. package/dist/query/hooks/use-marque-domains.js.map +1 -0
  322. package/dist/query/hooks/use-org-claim.js +29 -0
  323. package/dist/query/hooks/use-org-claim.js.map +1 -0
  324. package/dist/query/hooks/use-org-domains.js +28 -0
  325. package/dist/query/hooks/use-org-domains.js.map +1 -0
  326. package/dist/query/hooks/use-org-notification-emails.js +28 -0
  327. package/dist/query/hooks/use-org-notification-emails.js.map +1 -0
  328. package/dist/query/hooks/use-org-profile-settings.js +29 -0
  329. package/dist/query/hooks/use-org-profile-settings.js.map +1 -0
  330. package/dist/query/hooks/use-org-profile.js +21 -0
  331. package/dist/query/hooks/use-org-profile.js.map +1 -0
  332. package/dist/query/hooks/use-position-mutations.js +128 -0
  333. package/dist/query/hooks/use-position-mutations.js.map +1 -0
  334. package/dist/query/hooks/use-profile-completeness.js +21 -0
  335. package/dist/query/hooks/use-profile-completeness.js.map +1 -0
  336. package/dist/query/hooks/use-profile-items-hide.js +53 -0
  337. package/dist/query/hooks/use-profile-items-hide.js.map +1 -0
  338. package/dist/query/hooks/use-profile-mutations.js +143 -0
  339. package/dist/query/hooks/use-profile-mutations.js.map +1 -0
  340. package/dist/query/hooks/use-profile.js +30 -0
  341. package/dist/query/hooks/use-profile.js.map +1 -0
  342. package/dist/query/hooks/use-publication-mutations.js +90 -0
  343. package/dist/query/hooks/use-publication-mutations.js.map +1 -0
  344. package/dist/query/hooks/use-reaction-mutations.js +48 -0
  345. package/dist/query/hooks/use-reaction-mutations.js.map +1 -0
  346. package/dist/query/hooks/use-reactions.js +32 -0
  347. package/dist/query/hooks/use-reactions.js.map +1 -0
  348. package/dist/query/hooks/use-received-endorsements.js +23 -0
  349. package/dist/query/hooks/use-received-endorsements.js.map +1 -0
  350. package/dist/query/hooks/use-reciprocity.js +19 -0
  351. package/dist/query/hooks/use-reciprocity.js.map +1 -0
  352. package/dist/query/hooks/use-record-mutations.js +67 -0
  353. package/dist/query/hooks/use-record-mutations.js.map +1 -0
  354. package/dist/query/hooks/use-repo-inventory.js +43 -0
  355. package/dist/query/hooks/use-repo-inventory.js.map +1 -0
  356. package/dist/query/hooks/use-roadmap-mutations.js +51 -0
  357. package/dist/query/hooks/use-roadmap-mutations.js.map +1 -0
  358. package/dist/query/hooks/use-roadmap.js +31 -0
  359. package/dist/query/hooks/use-roadmap.js.map +1 -0
  360. package/dist/query/hooks/use-search.js +63 -0
  361. package/dist/query/hooks/use-search.js.map +1 -0
  362. package/dist/query/hooks/use-section-primary-mutations.js +53 -0
  363. package/dist/query/hooks/use-section-primary-mutations.js.map +1 -0
  364. package/dist/query/hooks/use-skill-mutations.js +91 -0
  365. package/dist/query/hooks/use-skill-mutations.js.map +1 -0
  366. package/dist/query/hooks/use-stats.js +19 -0
  367. package/dist/query/hooks/use-stats.js.map +1 -0
  368. package/dist/query/hooks/use-stream.js +20 -0
  369. package/dist/query/hooks/use-stream.js.map +1 -0
  370. package/dist/query/hooks/use-unlinked-positions.js +45 -0
  371. package/dist/query/hooks/use-unlinked-positions.js.map +1 -0
  372. package/dist/query/index.d.ts +4 -4
  373. package/dist/query/index.js +685 -3744
  374. package/dist/query/index.js.map +1 -1
  375. package/dist/query/keys.js +138 -0
  376. package/dist/query/keys.js.map +1 -0
  377. package/dist/repo/groups.js +81 -0
  378. package/dist/repo/groups.js.map +1 -0
  379. package/dist/repo/index.js +9 -0
  380. package/dist/repo/index.js.map +1 -0
  381. package/dist/repo/labels.js +121 -0
  382. package/dist/repo/labels.js.map +1 -0
  383. package/dist/repo/types.js +1 -0
  384. package/dist/repo/types.js.map +1 -0
  385. package/dist/resume/index.js +5 -179
  386. package/dist/resume/index.js.map +1 -1
  387. package/dist/resume/json-resume.js +153 -0
  388. package/dist/resume/json-resume.js.map +1 -0
  389. package/dist/roadmap/index.js +101 -0
  390. package/dist/roadmap/index.js.map +1 -0
  391. package/dist/rpg/catalog.js +101 -0
  392. package/dist/rpg/catalog.js.map +1 -0
  393. package/dist/rpg/index.js +13 -116
  394. package/dist/rpg/index.js.map +1 -1
  395. package/dist/rpg/unlocks.js +21 -0
  396. package/dist/rpg/unlocks.js.map +1 -0
  397. package/dist/schemas/blob-ref.js +12 -0
  398. package/dist/schemas/blob-ref.js.map +1 -0
  399. package/dist/schemas/confirmation.js +23 -0
  400. package/dist/schemas/confirmation.js.map +1 -0
  401. package/dist/schemas/endorsement-confirmation.js +18 -0
  402. package/dist/schemas/endorsement-confirmation.js.map +1 -0
  403. package/dist/schemas/endorsement.js +19 -0
  404. package/dist/schemas/endorsement.js.map +1 -0
  405. package/dist/schemas/entity.js +74 -0
  406. package/dist/schemas/entity.js.map +1 -0
  407. package/dist/schemas/feed.js +73 -0
  408. package/dist/schemas/feed.js.map +1 -0
  409. package/dist/schemas/follow-profile.js +32 -0
  410. package/dist/schemas/follow-profile.js.map +1 -0
  411. package/dist/schemas/graph-follow.js +19 -0
  412. package/dist/schemas/graph-follow.js.map +1 -0
  413. package/dist/schemas/index.js +164 -629
  414. package/dist/schemas/index.js.map +1 -1
  415. package/dist/schemas/org-employment-attestation.js +28 -0
  416. package/dist/schemas/org-employment-attestation.js.map +1 -0
  417. package/dist/schemas/org-profile.js +64 -0
  418. package/dist/schemas/org-profile.js.map +1 -0
  419. package/dist/schemas/profile-certification.js +28 -0
  420. package/dist/schemas/profile-certification.js.map +1 -0
  421. package/dist/schemas/profile-course.js +32 -0
  422. package/dist/schemas/profile-course.js.map +1 -0
  423. package/dist/schemas/profile-education.js +33 -0
  424. package/dist/schemas/profile-education.js.map +1 -0
  425. package/dist/schemas/profile-external-account.js +15 -0
  426. package/dist/schemas/profile-external-account.js.map +1 -0
  427. package/dist/schemas/profile-honor.js +18 -0
  428. package/dist/schemas/profile-honor.js.map +1 -0
  429. package/dist/schemas/profile-investment.js +48 -0
  430. package/dist/schemas/profile-investment.js.map +1 -0
  431. package/dist/schemas/profile-involvement.js +47 -0
  432. package/dist/schemas/profile-involvement.js.map +1 -0
  433. package/dist/schemas/profile-language.js +12 -0
  434. package/dist/schemas/profile-language.js.map +1 -0
  435. package/dist/schemas/profile-position.js +42 -0
  436. package/dist/schemas/profile-position.js.map +1 -0
  437. package/dist/schemas/profile-presentation-delivery.js +38 -0
  438. package/dist/schemas/profile-presentation-delivery.js.map +1 -0
  439. package/dist/schemas/profile-presentation.js +36 -0
  440. package/dist/schemas/profile-presentation.js.map +1 -0
  441. package/dist/schemas/profile-project.js +48 -0
  442. package/dist/schemas/profile-project.js.map +1 -0
  443. package/dist/schemas/profile-publication.js +30 -0
  444. package/dist/schemas/profile-publication.js.map +1 -0
  445. package/dist/schemas/profile-self.js +22 -0
  446. package/dist/schemas/profile-self.js.map +1 -0
  447. package/dist/schemas/profile-skill.js +13 -0
  448. package/dist/schemas/profile-skill.js.map +1 -0
  449. package/dist/schemas/profile-volunteering.js +20 -0
  450. package/dist/schemas/profile-volunteering.js.map +1 -0
  451. package/dist/schemas/shared.js +56 -0
  452. package/dist/schemas/shared.js.map +1 -0
  453. package/dist/schemas/write/certification.js +16 -0
  454. package/dist/schemas/write/certification.js.map +1 -0
  455. package/dist/schemas/write/course.js +36 -0
  456. package/dist/schemas/write/course.js.map +1 -0
  457. package/dist/schemas/write/education.js +18 -0
  458. package/dist/schemas/write/education.js.map +1 -0
  459. package/dist/schemas/write/external-account.js +13 -0
  460. package/dist/schemas/write/external-account.js.map +1 -0
  461. package/dist/schemas/write/honor.js +14 -0
  462. package/dist/schemas/write/honor.js.map +1 -0
  463. package/dist/schemas/write/index.d.ts +1 -1
  464. package/dist/schemas/write/index.js +89 -593
  465. package/dist/schemas/write/index.js.map +1 -1
  466. package/dist/schemas/write/investment.js +32 -0
  467. package/dist/schemas/write/investment.js.map +1 -0
  468. package/dist/schemas/write/involvement.js +34 -0
  469. package/dist/schemas/write/involvement.js.map +1 -0
  470. package/dist/schemas/write/language.js +10 -0
  471. package/dist/schemas/write/language.js.map +1 -0
  472. package/dist/schemas/write/org-claim.js +56 -0
  473. package/dist/schemas/write/org-claim.js.map +1 -0
  474. package/dist/schemas/write/org-employment-attestation.js +19 -0
  475. package/dist/schemas/write/org-employment-attestation.js.map +1 -0
  476. package/dist/schemas/write/org-profile.js +54 -0
  477. package/dist/schemas/write/org-profile.js.map +1 -0
  478. package/dist/schemas/write/org-settings.js +81 -0
  479. package/dist/schemas/write/org-settings.js.map +1 -0
  480. package/dist/schemas/write/position.js +24 -0
  481. package/dist/schemas/write/position.js.map +1 -0
  482. package/dist/schemas/write/presentation-delivery.js +34 -0
  483. package/dist/schemas/write/presentation-delivery.js.map +1 -0
  484. package/dist/schemas/write/presentation.js +23 -0
  485. package/dist/schemas/write/presentation.js.map +1 -0
  486. package/dist/schemas/write/profile-location.js +21 -0
  487. package/dist/schemas/write/profile-location.js.map +1 -0
  488. package/dist/schemas/write/profile-self.js +27 -0
  489. package/dist/schemas/write/profile-self.js.map +1 -0
  490. package/dist/schemas/write/project.js +27 -0
  491. package/dist/schemas/write/project.js.map +1 -0
  492. package/dist/schemas/write/publication.js +41 -0
  493. package/dist/schemas/write/publication.js.map +1 -0
  494. package/dist/schemas/write/shared.js +96 -0
  495. package/dist/schemas/write/shared.js.map +1 -0
  496. package/dist/schemas/write/skill.js +18 -0
  497. package/dist/schemas/write/skill.js.map +1 -0
  498. package/dist/schemas/write/volunteering.js +16 -0
  499. package/dist/schemas/write/volunteering.js.map +1 -0
  500. package/dist/stream/activity-item.js +1 -0
  501. package/dist/stream/activity-item.js.map +1 -0
  502. package/dist/stream/index.js +49 -0
  503. package/dist/stream/index.js.map +1 -0
  504. package/dist/stream/stream-card-vm-schema.js +265 -0
  505. package/dist/stream/stream-card-vm-schema.js.map +1 -0
  506. package/dist/stream/stream-card-vm.js +1 -0
  507. package/dist/stream/stream-card-vm.js.map +1 -0
  508. package/dist/stream/to-stream-card-vm.js +793 -0
  509. package/dist/stream/to-stream-card-vm.js.map +1 -0
  510. package/dist/stream/two-tier.js +30 -0
  511. package/dist/stream/two-tier.js.map +1 -0
  512. package/dist/stream/verbs.js +120 -0
  513. package/dist/stream/verbs.js.map +1 -0
  514. package/dist/taxonomy/activity-tiers.js +956 -0
  515. package/dist/taxonomy/activity-tiers.js.map +1 -0
  516. package/dist/taxonomy/app-categories.js +42 -0
  517. package/dist/taxonomy/app-categories.js.map +1 -0
  518. package/dist/taxonomy/app-category-map.js +166 -0
  519. package/dist/taxonomy/app-category-map.js.map +1 -0
  520. package/dist/taxonomy/artifact-link-kind.js +29 -0
  521. package/dist/taxonomy/artifact-link-kind.js.map +1 -0
  522. package/dist/taxonomy/calendar-event.js +28 -0
  523. package/dist/taxonomy/calendar-event.js.map +1 -0
  524. package/dist/taxonomy/continents.js +215 -0
  525. package/dist/taxonomy/continents.js.map +1 -0
  526. package/dist/taxonomy/countries.js +203 -0
  527. package/dist/taxonomy/countries.js.map +1 -0
  528. package/dist/taxonomy/course-role.js +37 -0
  529. package/dist/taxonomy/course-role.js.map +1 -0
  530. package/dist/taxonomy/employment-type.js +82 -0
  531. package/dist/taxonomy/employment-type.js.map +1 -0
  532. package/dist/taxonomy/eqf-level.js +59 -0
  533. package/dist/taxonomy/eqf-level.js.map +1 -0
  534. package/dist/taxonomy/index.js +263 -0
  535. package/dist/taxonomy/index.js.map +1 -0
  536. package/dist/taxonomy/industry-taxonomy.js +281 -0
  537. package/dist/taxonomy/industry-taxonomy.js.map +1 -0
  538. package/dist/taxonomy/investment.js +54 -0
  539. package/dist/taxonomy/investment.js.map +1 -0
  540. package/dist/taxonomy/involvement-kind.js +30 -0
  541. package/dist/taxonomy/involvement-kind.js.map +1 -0
  542. package/dist/taxonomy/open-to.js +128 -0
  543. package/dist/taxonomy/open-to.js.map +1 -0
  544. package/dist/taxonomy/platforms.js +56 -0
  545. package/dist/taxonomy/platforms.js.map +1 -0
  546. package/dist/taxonomy/presentation-link-type.js +22 -0
  547. package/dist/taxonomy/presentation-link-type.js.map +1 -0
  548. package/dist/taxonomy/presentation-role.js +21 -0
  549. package/dist/taxonomy/presentation-role.js.map +1 -0
  550. package/dist/taxonomy/publication-type.js +54 -0
  551. package/dist/taxonomy/publication-type.js.map +1 -0
  552. package/dist/taxonomy/relational.js +25 -0
  553. package/dist/taxonomy/relational.js.map +1 -0
  554. package/dist/taxonomy/search-filter-defs.js +66 -0
  555. package/dist/taxonomy/search-filter-defs.js.map +1 -0
  556. package/dist/taxonomy/skill-categories.js +28 -0
  557. package/dist/taxonomy/skill-categories.js.map +1 -0
  558. package/dist/taxonomy/skill-display-groups.js +12 -0
  559. package/dist/taxonomy/skill-display-groups.js.map +1 -0
  560. package/dist/taxonomy/skill-grouping.js +90 -0
  561. package/dist/taxonomy/skill-grouping.js.map +1 -0
  562. package/dist/taxonomy/verification-providers.js +69 -0
  563. package/dist/taxonomy/verification-providers.js.map +1 -0
  564. package/dist/taxonomy/workplace-type.js +38 -0
  565. package/dist/taxonomy/workplace-type.js.map +1 -0
  566. package/dist/tokens/colors.js +11 -0
  567. package/dist/tokens/colors.js.map +1 -0
  568. package/dist/tokens/icons.js +15 -0
  569. package/dist/tokens/icons.js.map +1 -0
  570. package/dist/tokens/index.js +10 -39
  571. package/dist/tokens/index.js.map +1 -1
  572. package/dist/tokens/typography.js +23 -0
  573. package/dist/tokens/typography.js.map +1 -0
  574. package/dist/types/index.js +10 -0
  575. package/dist/types/index.js.map +1 -0
  576. package/dist/types/profile-view.js +1 -0
  577. package/dist/types/profile-view.js.map +1 -0
  578. package/dist/{use-org-notification-emails-0hjt-dEw.d.ts → use-org-notification-emails-CWWi1D8t.d.ts} +2 -2
  579. package/package.json +4 -3
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/stream/to-stream-card-vm.ts"],"sourcesContent":["import { resolveCardUrl } from '../cards/resolve-card-url.js';\nimport { isVisibleActivityItem } from '../cards/visibility.js';\nimport { isValidRgbColor } from '../format/wcag-contrast.js';\nimport { matchPublisherByUri } from '../publishing/index.js';\nimport { getActivityTier } from '../taxonomy/activity-tiers.js';\nimport type { ActivityItem } from './activity-item.js';\nimport type {\n StreamAddress,\n StreamAuthor,\n StreamCardBody,\n StreamCardSubject,\n StreamCardVM,\n StreamExternalLink,\n StreamGeo,\n StreamMedia,\n StreamRichSegment,\n StreamSource,\n StreamTheme,\n} from './stream-card-vm.js';\nimport { verbForCollection, type StreamVerb } from './verbs.js';\n\n/** Neutral fallback token — matches sifa-api's synthetic app-registry entry. */\nconst DEFAULT_SOURCE_COLOR = 'slate';\n\n/**\n * Options for {@link toStreamCardVM}. Kept out of the record so the transform\n * stays pure (no I/O): the app registry is runtime data, so callers inject a\n * color resolver built from the registry they already fetched.\n */\nexport interface ToStreamCardVMOptions {\n /**\n * Resolve an app's design-token color NAME (not a hex literal) from its\n * appId. Falls back to `slate` when unresolved.\n */\n resolveSourceColor?: (appId: string) => string | undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Small pure helpers\n// ---------------------------------------------------------------------------\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === 'object' ? (value as Record<string, unknown>) : null;\n}\n\nfunction asNonEmptyString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\n/** at://did:plc:xxx/collection/rkey → the authoring DID. */\nfunction didFromUri(uri: string): string | undefined {\n const match = uri.match(/^at:\\/\\/(did:[^/]+)\\//);\n return match?.[1];\n}\n\n/** Extract the CID from an AT Protocol blob ref (`ref.$link` or a bare string). */\nfunction blobCid(blob: unknown): string | undefined {\n const rec = asRecord(blob);\n if (!rec) return undefined;\n const ref = rec.ref;\n if (typeof ref === 'string') return ref;\n const link = asRecord(ref)?.['$link'];\n return typeof link === 'string' ? link : undefined;\n}\n\nfunction aspectRatio(value: unknown): { width: number; height: number } | undefined {\n const rec = asRecord(value);\n const width = rec?.width;\n const height = rec?.height;\n if (typeof width === 'number' && typeof height === 'number') return { width, height };\n return undefined;\n}\n\nfunction asFiniteNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\n/**\n * Extract a blob CID tolerating both a proper blob (`ref.$link`) and the\n * denormalized `{ cid }` shape some apps (BookHive, Colibri) store.\n */\nfunction looseBlobCid(value: unknown): string | undefined {\n const viaRef = blobCid(value);\n if (viaRef) return viaRef;\n const cid = asRecord(value)?.cid;\n return typeof cid === 'string' && cid.length > 0 ? cid : undefined;\n}\n\n/** A single blob-ref media item from a blob value, or undefined when absent. */\nfunction blobMedia(value: unknown, did: string, alt: string): StreamMedia | undefined {\n const cid = looseBlobCid(value);\n if (!cid) return undefined;\n const media: StreamMedia = { did, cid, alt };\n const ratio = aspectRatio(asRecord(value)?.aspectRatio);\n if (ratio) media.aspectRatio = ratio;\n const mimeType = asNonEmptyString(asRecord(value)?.mimeType);\n if (mimeType) media.mimeType = mimeType;\n return media;\n}\n\n/** The `#suffix` of an NSID-with-hash value (`x#going` → `#going`), else ''. */\nfunction hashSuffix(value: string): string {\n const i = value.lastIndexOf('#');\n return i >= 0 ? value.slice(i) : '';\n}\n\nconst WORDS_PER_MINUTE = 200;\n\n/** Estimated reading time in minutes from body text (matches sifa-web). */\nfunction estimateReadingTime(text: string | undefined): number | undefined {\n if (!text) return undefined;\n const words = text.trim().split(/\\s+/).filter(Boolean).length;\n if (words === 0) return undefined;\n return Math.max(1, Math.round(words / WORDS_PER_MINUTE));\n}\n\n/** Parse a beacon `location` into numeric geo. Lat/long may be string or number. */\nfunction beaconGeo(value: unknown): StreamGeo | undefined {\n const rec = asRecord(value);\n if (!rec) return undefined;\n const { latitude, longitude } = rec;\n const okType = (v: unknown): v is string | number =>\n typeof v === 'string' || typeof v === 'number';\n if (!okType(latitude) || !okType(longitude)) return undefined;\n const lat = Number(latitude);\n const lng = Number(longitude);\n if (!Number.isFinite(lat) || !Number.isFinite(lng)) return undefined;\n return { latitude: lat, longitude: lng };\n}\n\n/** Parse a beacon `addressDetails` into a structured address, or undefined. */\nfunction beaconAddress(value: unknown): StreamAddress | undefined {\n const rec = asRecord(value);\n if (!rec) return undefined;\n const address: StreamAddress = {};\n const name = asNonEmptyString(rec.name);\n if (name) address.name = name;\n const street = asNonEmptyString(rec.street);\n if (street) address.street = street;\n const locality = asNonEmptyString(rec.locality);\n if (locality) address.locality = locality;\n const region = asNonEmptyString(rec.region);\n if (region) address.region = region;\n const country = asNonEmptyString(rec.country);\n if (country) address.country = country;\n const postalCode = asNonEmptyString(rec.postalCode);\n if (postalCode) address.postalCode = postalCode;\n return Object.keys(address).length > 0 ? address : undefined;\n}\n\n/** Split BookHive's tab-separated authors into a trimmed, non-empty list. */\nfunction parseAuthors(value: unknown): string[] {\n if (typeof value !== 'string') return [];\n return value\n .split('\\t')\n .map((a) => a.trim())\n .filter((a) => a.length > 0);\n}\n\n// ---------------------------------------------------------------------------\n// Chrome\n// ---------------------------------------------------------------------------\n\nfunction buildSource(item: ActivityItem, options: ToStreamCardVMOptions): StreamSource {\n return {\n appId: item.appId,\n label: item.appName,\n color: options.resolveSourceColor?.(item.appId) ?? DEFAULT_SOURCE_COLOR,\n };\n}\n\n/**\n * The author identity for a card, from the AppView-injected handle / display\n * name / avatar and the DID parsed from the record uri. Returns undefined when\n * nothing is known (e.g. a Fediverse post whose uri is an http permalink, not\n * an at-uri, and carries no injected author fields), so the field stays absent\n * rather than an empty object.\n */\nfunction buildAuthor(item: ActivityItem): StreamAuthor | undefined {\n const did = didFromUri(item.uri);\n const handle = asNonEmptyString(item.authorHandle);\n const displayName = asNonEmptyString(item.authorDisplayName);\n const avatar = asNonEmptyString(item.authorAvatar);\n if (!did && !handle && !displayName && !avatar) return undefined;\n const author: StreamAuthor = {};\n if (did) author.did = did;\n if (handle) author.handle = handle;\n if (displayName) author.displayName = displayName;\n if (avatar) author.avatar = avatar;\n return author;\n}\n\n// Post-type verbs drop the app name (the source pill already shows it, so\n// \"Posted on Bluesky network\" reads as redundant); verbs where the platform\n// adds meaning keep \"on {App}\".\n// Relational verbs read as a sentence with the subject the two-tier line renders\n// after them. Those with a preposition drop it when no subject was found, so the\n// phrase never dangles (\"Commented on {doc}\" with a subject, \"Commented\" without).\n// App-name verbs stay bare: the source pill next to the line already shows the\n// app, so \"Shipped on Tangled\" beside a Tangled pill is redundant and (on a\n// narrow screen) truncates to \"Shipped on...\". The verb carries the action; the\n// pill carries the app. Relational verbs keep their preposition, which points at\n// the SUBJECT the line renders after them (not the app), e.g. \"Commented on {doc}\".\nconst TITLE_BY_VERB: Record<StreamVerb, (label: string, hasSubject: boolean) => string> = {\n posted: () => 'Posted',\n reposted: () => 'Reposted',\n published: () => 'Published',\n presented: () => 'Gave a presentation',\n endorsed: () => 'Wrote an endorsement',\n joined: () => 'Joined',\n shipped: () => 'Shipped',\n reviewed: () => 'Reviewed',\n created: () => 'Shared',\n commented: (_label, hasSubject) => (hasSubject ? 'Commented on' : 'Commented'),\n replied: (_label, hasSubject) => (hasSubject ? 'Replied to' : 'Replied'),\n rsvped: (_label, hasSubject) => (hasSubject ? \"RSVP'd to\" : \"RSVP'd\"),\n liked: () => 'Liked',\n followed: () => 'Followed',\n bookmarked: () => 'Bookmarked',\n registered: () => 'Registered',\n annotated: () => 'Annotated',\n streamed: () => 'Streamed',\n wrote: () => 'Wrote',\n wasAt: () => 'Was at',\n metWith: () => 'Met with',\n supported: () => 'Supported',\n verified: () => 'Verified',\n received: () => 'Received',\n styledCharacter: () => 'Styled a character',\n};\n\nfunction buildTitle(verb: StreamVerb, label: string, hasSubject: boolean): string {\n return TITLE_BY_VERB[verb](label, hasSubject);\n}\n\n/**\n * Whether the record points at another record it acted on: a strongRef\n * `subject.uri`, a bare `at://` `subject`, or a reply `parent`/`root`. Drives\n * the connector in a relational verb's title.\n */\nfunction recordHasSubjectRef(record: Record<string, unknown> | null | undefined): boolean {\n if (!record) return false;\n const subject = record.subject;\n if (typeof subject === 'string' && subject.startsWith('at://')) return true;\n if (subject && typeof subject === 'object') {\n const uri = (subject as Record<string, unknown>).uri;\n if (typeof uri === 'string' && uri.length > 0) return true;\n }\n const reply = record.reply as Record<string, unknown> | undefined;\n if (reply && typeof reply === 'object') {\n for (const key of ['parent', 'root'] as const) {\n const ref = reply[key] as Record<string, unknown> | undefined;\n if (ref && typeof ref === 'object' && typeof ref.uri === 'string') return true;\n }\n }\n return false;\n}\n\n/**\n * The canonical http(s) permalink to this record on its source app, or\n * undefined. Delegates to the shared, pure {@link resolveCardUrl} using the\n * author DID parsed from the uri and the author handle — the AppView-injected\n * {@link ActivityItem.authorHandle}, falling back to a handle the record itself\n * carries. With a handle, handle-keyed apps (Bluesky, Popfeed, Tangled, ...)\n * resolve; did/uri/record.url-addressable apps (Smokesignal events, GitHub PRs,\n * Standard.site docs, ...) resolve from the uri alone. Only non-null http(s)\n * URLs are returned.\n */\nfunction resolveSourceUrl(item: ActivityItem, record: Record<string, unknown>): string | undefined {\n // A did-less uri does NOT mean no link: record-derived URLs (a Standard\n // site's siteUrl + path, an ad-hoc record.url) resolve without any author\n // identity. The following feed can key an item by handle, so bailing on a\n // missing did dropped those links. Pass an empty did through instead; the\n // pattern interpolator returns null for any `{did}`/`{handle}` it can't fill,\n // so did/handle-only apps (Bluesky) still yield no fabricated link.\n const authorDid = didFromUri(item.uri) ?? '';\n const authorHandle = asNonEmptyString(item.authorHandle) ?? asNonEmptyString(record.handle);\n const url = resolveCardUrl({\n collection: item.collection,\n record,\n uri: item.uri,\n rkey: item.rkey,\n authorDid,\n ...(authorHandle ? { authorHandle } : {}),\n });\n return url && /^https?:\\/\\//i.test(url) ? url : undefined;\n}\n\n/** Per-record RGB theme (publication / standard-site cards). Validated. */\nfunction readTheme(record: Record<string, unknown> | null): StreamTheme | undefined {\n const theme = asRecord(record?.publicationTheme ?? record?.theme);\n if (!theme) return undefined;\n const { background, foreground, accent } = theme;\n if (isValidRgbColor(background) && isValidRgbColor(foreground) && isValidRgbColor(accent)) {\n return { background, foreground, accent };\n }\n return undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Bluesky post body\n// ---------------------------------------------------------------------------\n\nfunction bskyImages(embed: Record<string, unknown>, did: string): StreamMedia[] {\n const images = embed.images;\n if (!Array.isArray(images)) return [];\n const out: StreamMedia[] = [];\n for (const raw of images) {\n const img = asRecord(raw);\n if (!img) continue;\n const alt = asNonEmptyString(img.alt) ?? '';\n const ratio = aspectRatio(img.aspectRatio);\n\n // AppView-hydrated `app.bsky.embed.images#view`: the item carries resolved\n // CDN URLs (`thumb`/`fullsize`) and no `image` blob. This is the shape\n // sifa-api feeds the transform (mergeResolvedEmbed swaps the raw embed for\n // the AppView view). Prefer the feed-sized `thumb`, matching sifa-web's\n // `/activity` card.\n const resolvedUrl = asNonEmptyString(img.thumb) ?? asNonEmptyString(img.fullsize);\n if (resolvedUrl) {\n const media: StreamMedia = { url: resolvedUrl, alt };\n if (ratio) media.aspectRatio = ratio;\n out.push(media);\n continue;\n }\n\n // Raw record shape: images carry a blob ref; the host builds the CDN URL.\n const cid = blobCid(img.image);\n if (!cid) continue;\n const media: StreamMedia = { did, cid, alt };\n if (ratio) media.aspectRatio = ratio;\n const mimeType = asNonEmptyString(asRecord(img.image)?.mimeType);\n if (mimeType) media.mimeType = mimeType;\n out.push(media);\n }\n return out;\n}\n\nfunction bskyExternal(embed: Record<string, unknown>): StreamExternalLink | undefined {\n const external = asRecord(embed.external);\n if (!external) return undefined;\n const url = asNonEmptyString(external.uri);\n if (!url) return undefined;\n const link: StreamExternalLink = { url };\n const title = asNonEmptyString(external.title);\n if (title) link.title = title;\n // AppView-hydrated `app.bsky.embed.external#view` carries a resolved CDN\n // `thumb` URL (the raw record's thumb is a blob, but sifa-api's\n // mergeResolvedEmbed swaps in the AppView view before the transform runs).\n // Carrying it lets page.sifa.id render link/GIF posters instead of a bare\n // text link. Only a string is accepted, so a raw blob ref is ignored.\n const thumb = asNonEmptyString(external.thumb);\n if (thumb) link.thumb = thumb;\n return link;\n}\n\ninterface BskyEmbedContent {\n media?: StreamMedia[];\n externalLink?: StreamExternalLink;\n}\n\nfunction bskyEmbedContent(record: Record<string, unknown>, did: string): BskyEmbedContent {\n const embed = asRecord(record.embed);\n if (!embed) return {};\n\n // recordWithMedia wraps the media (images/external) alongside a quoted record.\n // Match both the raw record type and the AppView `#view` variant, since\n // sifa-api feeds the hydrated view.\n const type = asNonEmptyString(embed['$type']);\n const isRecordWithMedia =\n type === 'app.bsky.embed.recordWithMedia' || type === 'app.bsky.embed.recordWithMedia#view';\n const target = isRecordWithMedia ? asRecord(embed.media) : embed;\n if (!target) return {};\n\n if (Array.isArray(target.images)) {\n const media = bskyImages(target, did);\n return media.length > 0 ? { media } : {};\n }\n if (target.external != null) {\n const externalLink = bskyExternal(target);\n return externalLink ? { externalLink } : {};\n }\n return {};\n}\n\nfunction applyBskyPost(\n vm: StreamCardVM,\n item: ActivityItem,\n record: Record<string, unknown> | null,\n): StreamCardVM {\n if (!record) {\n vm.body = { kind: 'generic' };\n return vm;\n }\n\n const did = didFromUri(item.uri);\n const text = asNonEmptyString(record.text);\n const { media, externalLink } = did ? bskyEmbedContent(record, did) : {};\n if (media) vm.media = media;\n if (externalLink) vm.externalLink = externalLink;\n\n // An embed is the post's primary content and must win over the caption. If\n // `text` took the body, the dispatch would render the caption alone and drop\n // the image / link preview entirely (a bare box). The caption instead rides\n // along on the media / link body's `text`.\n let body: StreamCardBody;\n if (vm.media) body = text ? { kind: 'media', text } : { kind: 'media' };\n else if (vm.externalLink) body = text ? { kind: 'link', text } : { kind: 'link' };\n else if (text) body = { kind: 'text', text };\n else body = { kind: 'generic' };\n vm.body = body;\n return vm;\n}\n\n// ---------------------------------------------------------------------------\n// App-specific body variants\n// ---------------------------------------------------------------------------\n\n/** Fall back to a generic body when the record is missing/invalid. */\nfunction withGeneric(vm: StreamCardVM): StreamCardVM {\n vm.body = { kind: 'generic' };\n return vm;\n}\n\n/**\n * Ingested Fediverse post (`fediverse.post`). Its `url` is the post's own\n * permalink, so it becomes the card's `sourceUrl` (the renderer makes the whole\n * card clickable) rather than an `externalLink` (which would render the raw URL\n * as visible text). The item uri is that http permalink, not an at-uri, so the\n * generic `resolveSourceUrl` path -- which parses a DID out of the uri -- can't\n * set it; do it here.\n */\nfunction applyFediversePost(vm: StreamCardVM, record: Record<string, unknown>): StreamCardVM {\n const url = httpUrl(record.url);\n if (url) vm.sourceUrl = url;\n const text = asNonEmptyString(record.excerpt);\n vm.body = text ? { kind: 'text', text } : { kind: 'generic' };\n return vm;\n}\n\nfunction applyGithubPr(vm: StreamCardVM, record: Record<string, unknown>): StreamCardVM {\n const body: Extract<StreamCardBody, { kind: 'github-pr' }> = {\n kind: 'github-pr',\n repoOwner: asNonEmptyString(record.repoOwner) ?? '',\n repoName: asNonEmptyString(record.repoName) ?? '',\n prNumber: asFiniteNumber(record.prNumber) ?? 0,\n title: asNonEmptyString(record.title) ?? '',\n additions: asFiniteNumber(record.additions) ?? 0,\n deletions: asFiniteNumber(record.deletions) ?? 0,\n };\n const url = asNonEmptyString(record.url);\n if (url) body.url = url;\n const language = asNonEmptyString(record.language);\n if (language) body.language = language;\n const mergedAt = asNonEmptyString(record.mergedAt);\n if (mergedAt) body.mergedAt = mergedAt;\n vm.body = body;\n return vm;\n}\n\nfunction applyBook(\n vm: StreamCardVM,\n item: ActivityItem,\n record: Record<string, unknown>,\n): StreamCardVM {\n const title = asNonEmptyString(record.title) ?? 'Untitled book';\n const body: Extract<StreamCardBody, { kind: 'book' }> = {\n kind: 'book',\n title,\n authors: parseAuthors(record.authors),\n };\n const stars = asFiniteNumber(record.stars);\n if (stars !== undefined && stars > 0) body.stars = stars;\n const status = asNonEmptyString(record.status);\n if (status) body.status = status;\n const review = asNonEmptyString(\n typeof record.review === 'string' ? record.review.trim() : undefined,\n );\n if (review) body.review = review;\n vm.body = body;\n\n const did = didFromUri(item.uri);\n if (did) {\n const cover = blobMedia(record.cover, did, `The cover of ${title}`);\n if (cover) vm.media = [cover];\n }\n return vm;\n}\n\nfunction popfeedReviewKind(collection: string): 'review' | 'post' | 'note' | 'other' {\n if (collection.endsWith('.review')) return 'review';\n if (collection.endsWith('.post')) return 'post';\n if (collection.endsWith('.note')) return 'note';\n return 'other';\n}\n\nfunction applyMediaReview(\n vm: StreamCardVM,\n item: ActivityItem,\n record: Record<string, unknown>,\n): StreamCardVM {\n const title = asNonEmptyString(record.title) ?? asNonEmptyString(record.name);\n const body: Extract<StreamCardBody, { kind: 'media-review' }> = {\n kind: 'media-review',\n reviewKind: popfeedReviewKind(item.collection),\n isRevisit: record.isRevisit === true,\n };\n if (title) body.title = title;\n const mediaType = asNonEmptyString(record.creativeWorkType);\n if (mediaType) body.mediaType = mediaType;\n const rating = asFiniteNumber(record.rating);\n if (rating !== undefined) body.rating = rating;\n const mainCredit = asNonEmptyString(record.mainCredit);\n if (mainCredit) body.mainCredit = mainCredit;\n const reviewText = asNonEmptyString(record.text);\n if (reviewText) body.reviewText = reviewText;\n vm.body = body;\n\n const posterUrl = asNonEmptyString(record.posterUrl);\n if (posterUrl) vm.media = [{ url: posterUrl, alt: title ? `${title} poster` : '' }];\n return vm;\n}\n\nconst RSVP_STATUS: Record<string, 'going' | 'interested' | 'notgoing'> = {\n '#going': 'going',\n '#interested': 'interested',\n '#notgoing': 'notgoing',\n};\n\nconst RSVP_MODE: Record<string, 'inperson' | 'virtual' | 'hybrid'> = {\n '#inperson': 'inperson',\n '#virtual': 'virtual',\n '#hybrid': 'hybrid',\n};\n\nfunction applyEventRsvp(vm: StreamCardVM, record: Record<string, unknown>): StreamCardVM {\n const status = asNonEmptyString(record.status);\n const body: Extract<StreamCardBody, { kind: 'event-rsvp' }> = {\n kind: 'event-rsvp',\n rsvpStatus: (status ? RSVP_STATUS[hashSuffix(status)] : undefined) ?? 'unknown',\n };\n const meta = asRecord(record.eventMeta);\n if (meta) {\n const eventName = asNonEmptyString(meta.name);\n if (eventName) body.eventName = eventName;\n const startsAt = asNonEmptyString(meta.startsAt);\n if (startsAt) body.startsAt = startsAt;\n const endsAt = asNonEmptyString(meta.endsAt);\n if (endsAt) body.endsAt = endsAt;\n const mode = asNonEmptyString(meta.mode);\n const modeEnum = mode ? RSVP_MODE[hashSuffix(mode)] : undefined;\n if (modeEnum) body.mode = modeEnum;\n const locationName = asNonEmptyString(meta.locationName);\n if (locationName) body.locationName = locationName;\n const locationLocality = asNonEmptyString(meta.locationLocality);\n if (locationLocality) body.locationLocality = locationLocality;\n const locationCountry = asNonEmptyString(meta.locationCountry);\n if (locationCountry) body.locationCountry = locationCountry;\n }\n vm.body = body;\n // Expose the event as the line subject so \"RSVP'd to {event}\" reads as a\n // sentence rather than a dangling \"RSVP'd to\". The event page is the record's\n // own sourceUrl, so the subject needs no separate url.\n const eventUri = nonBlankString(asRecord(record.subject)?.uri);\n if (eventUri) {\n vm.subject = {\n kind: 'record',\n uri: eventUri,\n ...(body.eventName ? { title: body.eventName } : {}),\n };\n }\n return vm;\n}\n\nfunction applyKeytraceVerification(\n vm: StreamCardVM,\n record: Record<string, unknown>,\n): StreamCardVM {\n const identity = asRecord(record.identity) ?? {};\n const subject = asNonEmptyString(identity.subject);\n const displayName = asNonEmptyString(identity.displayName);\n const body: Extract<StreamCardBody, { kind: 'verification' }> = {\n kind: 'verification',\n platform: asNonEmptyString(record.type) ?? 'unknown',\n verified: record.status === 'verified',\n };\n const subjectLabel = displayName ?? subject;\n if (subjectLabel) body.subjectLabel = subjectLabel;\n const profileUrl = asNonEmptyString(identity.profileUrl);\n if (profileUrl) body.profileUrl = profileUrl;\n vm.body = body;\n // A Keytrace claim proves ownership of an EXTERNAL account, so the line reads\n // \"Verified {account}\" and links out to it. Expose the external identity as\n // the subject (its own record) so the compact line renders and links it,\n // rather than showing a bare \"Verified\" with no object.\n const accountLabel = subjectLabel ?? asNonEmptyString(record.type);\n if (accountLabel) {\n vm.subject = {\n kind: 'record',\n uri: '',\n title: accountLabel,\n ...(profileUrl ? { url: profileUrl } : {}),\n };\n }\n return vm;\n}\n\nfunction applyBskyVerification(vm: StreamCardVM, record: Record<string, unknown>): StreamCardVM {\n const handle = asNonEmptyString(record.handle);\n const displayName = asNonEmptyString(record.displayName);\n const body: Extract<StreamCardBody, { kind: 'verification' }> = {\n kind: 'verification',\n platform: 'bluesky',\n verified: true,\n };\n const subjectLabel = displayName ?? handle;\n if (subjectLabel) body.subjectLabel = subjectLabel;\n if (handle) body.handle = handle;\n vm.body = body;\n return vm;\n}\n\nfunction applyMembership(vm: StreamCardVM, record: Record<string, unknown>): StreamCardVM {\n const body: Extract<StreamCardBody, { kind: 'membership' }> = { kind: 'membership' };\n const communityUri = asNonEmptyString(record.community);\n if (communityUri) body.communityUri = communityUri;\n\n const meta = asRecord(record.communityMeta);\n const communityName = meta ? asNonEmptyString(meta.name) : undefined;\n if (communityName) body.communityName = communityName;\n const description = meta ? asNonEmptyString(meta.description) : undefined;\n if (description) body.description = description;\n vm.body = body;\n\n if (meta) {\n const ownerDid =\n asNonEmptyString(meta.ownerDid) ?? (communityUri ? didFromUri(communityUri) : undefined);\n if (ownerDid) {\n const picture = blobMedia(meta.picture, ownerDid, communityName ?? '');\n if (picture) vm.media = [picture];\n }\n }\n return vm;\n}\n\nfunction applyLocation(vm: StreamCardVM, record: Record<string, unknown>): StreamCardVM {\n const body: Extract<StreamCardBody, { kind: 'location' }> = { kind: 'location' };\n const venueName = asNonEmptyString(record.venueName);\n if (venueName) body.venueName = venueName;\n const shout = asNonEmptyString(record.shout);\n if (shout) body.shout = shout;\n const address = beaconAddress(record.addressDetails);\n if (address) body.address = address;\n const geo = beaconGeo(record.location);\n if (geo) body.geo = geo;\n vm.body = body;\n return vm;\n}\n\nfunction applyTravel(vm: StreamCardVM, record: Record<string, unknown>): StreamCardVM {\n const body: Extract<StreamCardBody, { kind: 'travel' }> = { kind: 'travel' };\n const origin = asNonEmptyString(record.originTransportCode);\n if (origin) body.origin = origin;\n const destination = asNonEmptyString(record.destinationTransportCode);\n if (destination) body.destination = destination;\n const transportation = asNonEmptyString(record.transportation);\n if (transportation) body.transportation = transportation;\n const carrier = asNonEmptyString(record.carrier);\n if (carrier) body.carrier = carrier;\n const carrierCode = asNonEmptyString(record.carrierCode);\n if (carrierCode) body.carrierCode = carrierCode;\n const startDate = asNonEmptyString(record.startDate);\n if (startDate) body.startDate = startDate;\n const endDate = asNonEmptyString(record.endDate);\n if (endDate) body.endDate = endDate;\n vm.body = body;\n return vm;\n}\n\nfunction applyStandardSite(vm: StreamCardVM, record: Record<string, unknown>): StreamCardVM {\n const body: Extract<StreamCardBody, { kind: 'standard-site' }> = { kind: 'standard-site' };\n const title = asNonEmptyString(record.title);\n if (title) body.title = title;\n const description = asNonEmptyString(record.description);\n if (description) body.description = description;\n const siteUrl = asNonEmptyString(record.siteUrl);\n if (siteUrl) {\n body.siteUrl = siteUrl;\n const publisherName = matchPublisherByUri(siteUrl)?.name;\n if (publisherName) body.publisherName = publisherName;\n }\n const path = asNonEmptyString(record.path);\n if (path) body.path = path;\n const icon = asNonEmptyString(record.publicationIcon);\n if (icon) body.icon = icon;\n const coverImageUrl = asNonEmptyString(record.coverImageUrl);\n if (coverImageUrl) body.coverImageUrl = coverImageUrl;\n const readingTime = estimateReadingTime(asNonEmptyString(record.textContent));\n if (readingTime !== undefined) body.readingTime = readingTime;\n const publishedAt = asNonEmptyString(record.publishedAt);\n if (publishedAt) body.publishedAt = publishedAt;\n vm.body = body;\n return vm;\n}\n\n/**\n * at.youandme.connection: the record's `subject` is a bare person DID. Fold the\n * api-resolved handle/display name onto it (like the generic person path), so\n * the \"Met with {name}\" line names and links the other person.\n */\nfunction applyYouAndMe(\n vm: StreamCardVM,\n record: Record<string, unknown>,\n item: ActivityItem,\n): StreamCardVM {\n const did = asNonEmptyString(record.subject);\n if (did) vm.subject = withResolvedSubjectMeta({ kind: 'person', did }, item);\n vm.body = { kind: 'generic' };\n return vm;\n}\n\n/** fyi.asq.answer: the record's `subject.uri` is the answered question. */\nfunction applyAsqAnswer(vm: StreamCardVM, record: Record<string, unknown>): StreamCardVM {\n const uri = asNonEmptyString(asRecord(record.subject)?.uri);\n if (uri) vm.subject = { kind: 'record', uri };\n vm.body = { kind: 'generic' };\n return vm;\n}\n\n// ---------------------------------------------------------------------------\n// Generic content extraction (base collections + unknown / future apps)\n// ---------------------------------------------------------------------------\n//\n// Collections without a typed body variant (Margin, Tangled, KipClip, Grain,\n// asq questions, Semble, Passports fifty-states, Streamplace, and every\n// unrecognized/future app) fall here. The rules below are GROUNDED in the\n// sifa-web card sources so each base collection reproduces the visible content\n// its dedicated card renders; for genuinely unknown records the same shapes act\n// as a best-effort heuristic, degrading to an empty generic body when a record\n// carries no recognizable text, media, link, or subject.\n\n/** A string with at least one non-whitespace character, else undefined. */\nfunction nonBlankString(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim().length > 0 ? value : undefined;\n}\n\n/** Read a `body` field that is a plain string OR `{ value: string }` (Margin). */\nfunction readBodyField(value: unknown): string | undefined {\n const direct = nonBlankString(value);\n if (direct) return direct;\n return nonBlankString(asRecord(value)?.value);\n}\n\n/** An http(s) URL string, else undefined. */\nfunction httpUrl(value: unknown): string | undefined {\n return typeof value === 'string' && /^https?:\\/\\//i.test(value) ? value : undefined;\n}\n\n/**\n * Ordered human-visible text fields. `body` (handled specially for the\n * `{ value }` shape) follows `content` and `excerpt`, before `message`. Mirrors\n * the union of fields the base cards read (generic\n * `text|title|name|description|content`, Tangled `name|title|text|message`,\n * Margin `body`, asq `title|body`). `excerpt` carries the post text for\n * external-feed items (Fediverse `fediverse.post`, RSS), which have no\n * `text`/`content` field.\n */\nconst GENERIC_TEXT_ORDER = [\n 'text',\n 'title',\n 'name',\n 'description',\n 'content',\n 'excerpt',\n 'body',\n 'message',\n 'note',\n 'caption',\n 'summary',\n 'domain',\n 'status',\n] as const;\n\n/** The record's primary human-visible text, or undefined. */\nfunction genericText(collection: string, record: Record<string, unknown>): string | undefined {\n // Passports fifty-states carries no free-text field — its card composes\n // \"Visited {city}, {state}\". Only `city` is a real record string; the state\n // name mapping (US-NC → North Carolina) and the verb are surface concerns, so\n // the VM text is just the city (intentionally partial, never invented).\n if (collection === 'social.passports.fiftyStates.visit') {\n return nonBlankString(record.city);\n }\n for (const field of GENERIC_TEXT_ORDER) {\n if (field === 'body') {\n const body = readBodyField(record.body);\n if (body) return body;\n continue;\n }\n const value = nonBlankString(record[field]);\n if (value) return value;\n }\n return undefined;\n}\n\n/** Non-empty string tags off `record.tags`, or undefined. */\nfunction genericTags(record: Record<string, unknown>): string[] | undefined {\n const tags = record.tags;\n if (!Array.isArray(tags)) return undefined;\n const out = tags.filter((t): t is string => typeof t === 'string' && t.length > 0);\n return out.length > 0 ? out : undefined;\n}\n\n/**\n * Blob-ref image media from the common record shapes (reuses M1's blob helpers;\n * never builds a URL). Prefers an `images[]` / `embed.images[]` array (all\n * valid items), then single-blob fields, then Grain's bare `galleryMeta\n * .coverPhotoCid`.\n */\nfunction genericMedia(record: Record<string, unknown>, did: string, alt: string): StreamMedia[] {\n const fromArray = (raw: unknown): StreamMedia | undefined => {\n const img = asRecord(raw);\n if (!img) return undefined;\n return blobMedia(img.image ?? raw, did, asNonEmptyString(img.alt) ?? alt);\n };\n\n const images = record.images;\n if (Array.isArray(images)) {\n const out = images.map(fromArray).filter((m): m is StreamMedia => m !== undefined);\n if (out.length > 0) return out;\n }\n\n const embed = asRecord(record.embed);\n if (embed && Array.isArray(embed.images)) {\n const out = embed.images.map(fromArray).filter((m): m is StreamMedia => m !== undefined);\n if (out.length > 0) return out;\n }\n\n const single =\n blobMedia(record.image, did, alt) ??\n blobMedia(record.thumbnail, did, alt) ??\n blobMedia(record.thumb, did, alt) ??\n blobMedia(record.photo, did, alt) ??\n (embed ? blobMedia(embed.thumbnail, did, alt) : undefined);\n if (single) return [single];\n\n // Grain galleries store the cover as a bare CID string, not a blob object.\n const coverCid = asRecord(record.galleryMeta)?.coverPhotoCid;\n if (typeof coverCid === 'string' && coverCid.length > 0) {\n return [{ did, cid: coverCid, alt }];\n }\n return [];\n}\n\n/**\n * An outbound link from the common shapes: a Bluesky-style `embed.external`,\n * then a bare URL in `source` (Margin bookmark), `subject` (KipClip), or `url`.\n */\nfunction genericExternalLink(record: Record<string, unknown>): StreamExternalLink | undefined {\n const embed = asRecord(record.embed);\n if (embed) {\n const fromEmbed = bskyExternal(embed);\n if (fromEmbed) return fromEmbed;\n }\n const url = httpUrl(record.source) ?? httpUrl(record.subject) ?? httpUrl(record.url);\n return url ? { url } : undefined;\n}\n\n/**\n * A reply/quote/answer target from common reference shapes: `subject` as an\n * `at://` uri or a bare `did:` (person), or `subject.uri` (strongRef). A bare\n * http(s) `subject` is a bookmark target, handled as `externalLink` instead.\n */\nfunction genericSubject(record: Record<string, unknown>): StreamCardSubject | undefined {\n const subject = record.subject;\n if (typeof subject === 'string') {\n if (subject.startsWith('at://')) return { kind: 'record', uri: subject };\n if (subject.startsWith('did:')) return { kind: 'person', did: subject };\n return undefined;\n }\n const uri = nonBlankString(asRecord(subject)?.uri);\n if (uri && uri.startsWith('at://')) return { kind: 'record', uri };\n // Reply records name their target as `reply.parent.uri` (bsky-shaped).\n const parentUri = nonBlankString(asRecord(asRecord(record.reply)?.parent)?.uri);\n if (parentUri && parentUri.startsWith('at://')) return { kind: 'record', uri: parentUri };\n // W3C-annotation shape: `target` names the annotated resource with a title\n // and an http(s) `source` (Margin notes and highlights). The source is both\n // the subject key and its link, so the line shows \"Annotated {page title}\".\n const target = asRecord(record.target);\n if (target) {\n const source = httpUrl(target.source);\n if (source) {\n const title = nonBlankString(target.title);\n return { kind: 'record', uri: source, ...(title ? { title } : {}), url: source };\n }\n }\n return undefined;\n}\n\n/**\n * Fold the api-resolved subject metadata onto the subject, so the line reads\n * with the real name and links out. For a record subject that is the referenced\n * record's title/url (\"Commented on {title}\"); for a person subject (a follow,\n * a block, whose subject is a bare DID) that is the resolved handle/display\n * name, so the line reads \"Followed {name}\" and links to the profile.\n */\nfunction withResolvedSubjectMeta(\n subject: StreamCardSubject,\n item: ActivityItem,\n): StreamCardSubject {\n if (subject.kind === 'person') {\n const handle = nonBlankString(item.subjectHandle) ?? subject.handle;\n const displayName = nonBlankString(item.subjectDisplayName) ?? subject.displayName;\n return {\n ...subject,\n ...(handle ? { handle } : {}),\n ...(displayName ? { displayName } : {}),\n };\n }\n if (subject.kind !== 'record') return subject;\n const title = nonBlankString(item.subjectTitle) ?? subject.title;\n const url = nonBlankString(item.subjectUrl);\n return { ...subject, ...(title ? { title } : {}), ...(url ? { url } : {}) };\n}\n\n/** Recognize one facet feature (link / mention / tag), tolerating a missing $type. */\nfunction parseFacetFeature(\n features: unknown[],\n): Pick<StreamRichSegment, 'link' | 'mention' | 'tag'> | undefined {\n for (const raw of features) {\n const feat = asRecord(raw);\n if (!feat) continue;\n const type = asNonEmptyString(feat['$type']) ?? '';\n const uri = asNonEmptyString(feat.uri);\n const did = asNonEmptyString(feat.did);\n const tag = asNonEmptyString(feat.tag);\n if (type.endsWith('#link') && uri) return { link: uri };\n if (type.endsWith('#mention') && did) return { mention: did };\n if (type.endsWith('#tag') && tag) return { tag };\n // No / unknown $type: fall back to whichever identifying field is present.\n if (uri) return { link: uri };\n if (did) return { mention: did };\n if (tag) return { tag };\n }\n return undefined;\n}\n\n/**\n * Slice `text` into rich segments using `app.bsky.richtext.facet`-style\n * byte-offset facets. Heuristic and additive: `body.text` always holds the full\n * plain string, so a renderer may ignore this. Returns undefined unless at least\n * one enriched (link/mention/tag) span is produced.\n */\nfunction genericRichSegments(\n text: string,\n record: Record<string, unknown>,\n): StreamRichSegment[] | undefined {\n const facets = record.facets;\n if (!Array.isArray(facets)) return undefined;\n\n const parsed: { start: number; end: number; link?: string; mention?: string; tag?: string }[] =\n [];\n for (const raw of facets) {\n const facet = asRecord(raw);\n const index = asRecord(facet?.index);\n const start = asFiniteNumber(index?.byteStart);\n const end = asFiniteNumber(index?.byteEnd);\n if (start === undefined || end === undefined || start < 0 || end <= start) continue;\n const features = facet?.features;\n if (!Array.isArray(features)) continue;\n const feature = parseFacetFeature(features);\n if (!feature) continue;\n parsed.push({ start, end, ...feature });\n }\n if (parsed.length === 0) return undefined;\n\n const bytes = new TextEncoder().encode(text);\n const decoder = new TextDecoder();\n parsed.sort((a, b) => a.start - b.start);\n\n const segments: StreamRichSegment[] = [];\n let cursor = 0;\n for (const span of parsed) {\n if (span.start < cursor || span.start > bytes.length) continue; // overlap / OOB\n const end = Math.min(span.end, bytes.length);\n if (span.start > cursor) {\n const plain = decoder.decode(bytes.slice(cursor, span.start));\n if (plain) segments.push({ text: plain });\n }\n const seg: StreamRichSegment = { text: decoder.decode(bytes.slice(span.start, end)) };\n if (span.link) seg.link = span.link;\n if (span.mention) seg.mention = span.mention;\n if (span.tag) seg.tag = span.tag;\n segments.push(seg);\n cursor = end;\n }\n if (cursor < bytes.length) {\n const rest = decoder.decode(bytes.slice(cursor));\n if (rest) segments.push({ text: rest });\n }\n\n return segments.some((s) => s.link ?? s.mention ?? s.tag) ? segments : undefined;\n}\n\n/**\n * Populate a generic body with any real content the record carries — text,\n * media (blob refs), an external link, and a reply/quote/answer subject —\n * choosing `body.kind` the same way the Bluesky path does (text, else media,\n * else link, else generic).\n */\nfunction applyGeneric(\n vm: StreamCardVM,\n item: ActivityItem,\n record: Record<string, unknown> | null,\n): StreamCardVM {\n if (!record) return withGeneric(vm);\n\n const text = genericText(item.collection, record);\n const tags = genericTags(record);\n const did = didFromUri(item.uri);\n if (did) {\n const media = genericMedia(record, did, text ?? '');\n if (media.length > 0) vm.media = media;\n }\n const externalLink = genericExternalLink(record);\n if (externalLink) vm.externalLink = externalLink;\n // Don't clobber a repost/reply subject already normalized from item.subject.\n if (!vm.subject) {\n const subject = genericSubject(record);\n if (subject) vm.subject = withResolvedSubjectMeta(subject, item);\n }\n\n let body: StreamCardBody;\n if (text) {\n body = { kind: 'text', text };\n const richSegments = genericRichSegments(text, record);\n if (richSegments) body.richSegments = richSegments;\n if (tags) body.tags = tags;\n } else if (vm.media) {\n body = { kind: 'media' };\n if (tags) body.tags = tags;\n } else if (vm.externalLink) {\n body = { kind: 'link' };\n if (tags) body.tags = tags;\n } else {\n body = { kind: 'generic' };\n if (tags) body.tags = tags;\n }\n vm.body = body;\n return vm;\n}\n\n// ---------------------------------------------------------------------------\n// Entry points\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize one {@link ActivityItem} into a framework-free {@link StreamCardVM}.\n * Pure: no I/O, no React, no DOM, and no resolved CDN URLs (media carries raw\n * blob refs so each surface builds its own URL). Total: always returns a VM.\n *\n * Reference implementations: the generic/unknown case, `app.bsky.feed.post`\n * (text + images + external embed), and reposts (whose `subject` is normalized\n * through this same function). Collections with a typed body variant\n * (`github-pr`, `book`, `media-review`, `event-rsvp`, `verification`,\n * `membership`, `location`, `travel`, `standard-site`) are enriched from their\n * raw record below; `at.youandme.connection` and `fyi.asq.answer` populate a\n * person / record `subject`. Everything else (base collections + unknown apps)\n * flows through {@link applyGeneric}, which extracts text / media / link /\n * subject from common record shapes, degrading to an empty generic body.\n */\nexport function toStreamCardVM(\n item: ActivityItem,\n options: ToStreamCardVMOptions = {},\n): StreamCardVM {\n const verb = verbForCollection(item.collection);\n const source = buildSource(item, options);\n const record = asRecord(item.record);\n const timestamp = (record ? asNonEmptyString(record.createdAt) : undefined) ?? item.indexedAt;\n\n const vm: StreamCardVM = {\n uri: item.uri,\n cid: item.cid,\n verb,\n source,\n tier: getActivityTier(item.collection),\n timestamp,\n title: buildTitle(verb, source.label, recordHasSubjectRef(record)),\n };\n\n const author = buildAuthor(item);\n if (author) vm.author = author;\n\n const theme = readTheme(record);\n if (theme) vm.theme = theme;\n\n // Link to the record on its source app. Set before the switch so every\n // body-variant return path (each mutates and returns this same vm) keeps it.\n if (record) {\n const sourceUrl = resolveSourceUrl(item, record);\n if (sourceUrl) vm.sourceUrl = sourceUrl;\n }\n\n // Hypercert credit roll + outbound links, resolved by sifa-api out of\n // sidecar records. Set before the switch, like sourceUrl above, so every\n // body-variant return path keeps it.\n if (item.hypercertDetails) vm.hypercertDetails = item.hypercertDetails;\n if (item.certifiedDetails) vm.certifiedDetails = item.certifiedDetails;\n\n // Repost / reply target, normalized through the same transform. Its own\n // sourceUrl is computed by this recursion.\n if (item.subject) {\n vm.subject = { kind: 'post', post: toStreamCardVM(item.subject, options) };\n }\n\n switch (item.collection) {\n case 'app.bsky.feed.post':\n return applyBskyPost(vm, item, record);\n case 'github.pull_request':\n return record ? applyGithubPr(vm, record) : withGeneric(vm);\n case 'buzz.bookhive.book':\n return record ? applyBook(vm, item, record) : withGeneric(vm);\n case 'community.lexicon.calendar.rsvp':\n return record ? applyEventRsvp(vm, record) : withGeneric(vm);\n case 'dev.keytrace.claim':\n return record ? applyKeytraceVerification(vm, record) : withGeneric(vm);\n case 'app.bsky.graph.verification':\n return record ? applyBskyVerification(vm, record) : withGeneric(vm);\n case 'social.colibri.membership':\n return record ? applyMembership(vm, record) : withGeneric(vm);\n case 'app.beaconbits.beacon':\n return record ? applyLocation(vm, record) : withGeneric(vm);\n case 'social.passports.travel.leg':\n return record ? applyTravel(vm, record) : withGeneric(vm);\n case 'site.standard.document':\n return record ? applyStandardSite(vm, record) : withGeneric(vm);\n case 'at.youandme.connection':\n return record ? applyYouAndMe(vm, record, item) : withGeneric(vm);\n case 'fyi.asq.answer':\n return record ? applyAsqAnswer(vm, record) : withGeneric(vm);\n case 'fediverse.post':\n return record ? applyFediversePost(vm, record) : withGeneric(vm);\n }\n\n // social.popfeed.feed.{post,note,review} — registered by prefix in sifa-web.\n if (record && item.collection.startsWith('social.popfeed.feed.')) {\n return applyMediaReview(vm, item, record);\n }\n\n // Base collections + unknown / future apps: extract real content generically.\n return applyGeneric(vm, item, record);\n}\n\n/**\n * Map a list of activity items to VMs, applying {@link isVisibleActivityItem}\n * first so both surfaces (sifa-web, page.sifa.id) filter identically — a\n * filtered item produces no VM rather than a null-rendering card.\n */\nexport function toStreamCardVMs(\n items: ActivityItem[],\n options: ToStreamCardVMOptions = {},\n): StreamCardVM[] {\n const out: StreamCardVM[] = [];\n for (const item of items) {\n if (isVisibleActivityItem(item.collection, item.record)) {\n out.push(toStreamCardVM(item, options));\n }\n }\n return out;\n}\n"],"mappings":"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","names":["media"]}
@@ -0,0 +1,30 @@
1
+ // src/stream/two-tier.ts
2
+ import { isRelationalActivity } from "../taxonomy/relational.js";
3
+ function collectionOf(uri) {
4
+ return uri.split("/")[3] ?? "";
5
+ }
6
+ var RICH_BODY_KINDS = /* @__PURE__ */ new Set([
7
+ "github-pr",
8
+ "book",
9
+ "media-review",
10
+ "media",
11
+ "track"
12
+ ]);
13
+ function isRich(vm) {
14
+ if (vm.media && vm.media.length > 0) return true;
15
+ if (vm.externalLink) return true;
16
+ if (vm.body && RICH_BODY_KINDS.has(vm.body.kind)) return true;
17
+ return false;
18
+ }
19
+ function isSelfAuthoredRich(vm) {
20
+ if (isRelationalActivity(collectionOf(vm.uri))) return false;
21
+ return vm.tier === "creation" && isRich(vm);
22
+ }
23
+ function renderAsLine(vm) {
24
+ return !isSelfAuthoredRich(vm);
25
+ }
26
+ export {
27
+ isSelfAuthoredRich,
28
+ renderAsLine
29
+ };
30
+ //# sourceMappingURL=two-tier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/stream/two-tier.ts"],"sourcesContent":["import { isRelationalActivity } from '../taxonomy/relational.js';\nimport type { StreamCardBody, StreamCardVM } from './stream-card-vm.js';\n\n/** The collection NSID from an at-uri (at://did/collection/rkey). */\nfunction collectionOf(uri: string): string {\n return uri.split('/')[3] ?? '';\n}\n\n/**\n * Body kinds whose content is inherently rich enough to warrant a card when the\n * actor authored it: structured records that a one-line summary would gut\n * (a merged PR with diff stats, a book log, a media review, a music track, an\n * embedded media body). Plain `text` and `generic` are deliberately NOT here:\n * a text post renders inline on the line, keeping the timeline compact.\n */\nconst RICH_BODY_KINDS: ReadonlySet<StreamCardBody['kind']> = new Set([\n 'github-pr',\n 'book',\n 'media-review',\n 'media',\n 'track',\n]);\n\n/**\n * Whether a view-model carries rich content worth a card (as opposed to a\n * compact line): resolved media, an external-link card, or a structured rich\n * body. Independent of who authored it — {@link isSelfAuthoredRich} adds the\n * authorship gate.\n */\nfunction isRich(vm: StreamCardVM): boolean {\n if (vm.media && vm.media.length > 0) return true;\n if (vm.externalLink) return true;\n if (vm.body && RICH_BODY_KINDS.has(vm.body.kind)) return true;\n return false;\n}\n\n/**\n * The two-tier timeline rule: a `StreamCardVM` upgrades from a compact line to\n * a rich card only when BOTH hold — it is the actor's OWN creation\n * (`tier === 'creation'`, not a relational `action` like an RSVP, reply, or\n * endorsement) AND it carries rich content ({@link isRich}). A followee's own\n * photo or book log becomes a card; their comment on someone else's photo, or a\n * bare `:)` post, stays a line.\n *\n * A relational activity (comment, reply, RSVP, endorsement, membership, ...) is\n * NEVER rich, even when it carries media: the line shows what was acted on and\n * links out, rather than reproducing someone else's content.\n */\nexport function isSelfAuthoredRich(vm: StreamCardVM): boolean {\n if (isRelationalActivity(collectionOf(vm.uri))) return false;\n return vm.tier === 'creation' && isRich(vm);\n}\n\n/** Convenience inverse of {@link isSelfAuthoredRich}: render this VM as a line. */\nexport function renderAsLine(vm: StreamCardVM): boolean {\n return !isSelfAuthoredRich(vm);\n}\n"],"mappings":";AAAA,SAAS,4BAA4B;AAIrC,SAAS,aAAa,KAAqB;AACzC,SAAO,IAAI,MAAM,GAAG,EAAE,CAAC,KAAK;AAC9B;AASA,IAAM,kBAAuD,oBAAI,IAAI;AAAA,EACnE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAQD,SAAS,OAAO,IAA2B;AACzC,MAAI,GAAG,SAAS,GAAG,MAAM,SAAS,EAAG,QAAO;AAC5C,MAAI,GAAG,aAAc,QAAO;AAC5B,MAAI,GAAG,QAAQ,gBAAgB,IAAI,GAAG,KAAK,IAAI,EAAG,QAAO;AACzD,SAAO;AACT;AAcO,SAAS,mBAAmB,IAA2B;AAC5D,MAAI,qBAAqB,aAAa,GAAG,GAAG,CAAC,EAAG,QAAO;AACvD,SAAO,GAAG,SAAS,cAAc,OAAO,EAAE;AAC5C;AAGO,SAAS,aAAa,IAA2B;AACtD,SAAO,CAAC,mBAAmB,EAAE;AAC/B;","names":[]}
@@ -0,0 +1,120 @@
1
+ // src/stream/verbs.ts
2
+ import { z } from "zod";
3
+
4
+ // src/stream/verbs.json
5
+ var verbs_default = {
6
+ $schema: "https://sifa.id/schemas/activity-verbs/v1.json",
7
+ version: "1.7.0",
8
+ updated: "2026-09-26",
9
+ defaultVerb: "created",
10
+ verbs: {
11
+ "actor.rpg.sprite": "styledCharacter",
12
+ "agency.portable.membership": "joined",
13
+ "app.beaconbits.beacon": "wasAt",
14
+ "app.atmobb.discussion.reply": "replied",
15
+ "app.bsky.feed.post": "posted",
16
+ "app.bsky.feed.repost": "reposted",
17
+ "app.sidetrail.trail": "shipped",
18
+ "app.sidetrail.walk": "shipped",
19
+ "app.userinput.reply": "replied",
20
+ "at.margin.annotation": "annotated",
21
+ "at.margin.bookmark": "bookmarked",
22
+ "at.margin.note": "annotated",
23
+ "at.marque.domain": "registered",
24
+ "at.youandme.connection": "metWith",
25
+ "blog.pckt.mini.post": "wrote",
26
+ "blue.flashes.feed.post": "posted",
27
+ "buzz.bookhive.book": "reviewed",
28
+ "com.whtwnd.blog.entry": "published",
29
+ "community.lexicon.calendar.rsvp": "rsvped",
30
+ "community.nooki.comments": "commented",
31
+ "community.nooki.membership": "joined",
32
+ "community.opensocial.membership": "joined",
33
+ "computer.aetheros.page": "published",
34
+ "dev.keytrace.claim": "verified",
35
+ "equipment.rpg.item": "received",
36
+ "eu.atcommons.member": "joined",
37
+ "fm.plyr.comment": "commented",
38
+ "forum.barazo.post": "posted",
39
+ "fund.at.graph.endorse": "supported",
40
+ "fyi.atstore.listing.review": "reviewed",
41
+ "fyi.unravel.frontpage.post": "posted",
42
+ "id.sifa.endorsement": "endorsed",
43
+ "id.sifa.graph.connection": "joined",
44
+ "id.sifa.profile.presentation": "presented",
45
+ "id.sifa.profile.presentationDelivery": "presented",
46
+ "link.pastesphere.snippet": "published",
47
+ "org.impactindexer.review.comment": "commented",
48
+ "pub.leaflet.comment": "commented",
49
+ "sh.tangled.repo": "shipped",
50
+ "sh.tangled.repo.issue": "shipped",
51
+ "sh.tangled.repo.pull": "shipped",
52
+ "site.standard.document": "published",
53
+ "social.colibri.membership": "joined",
54
+ "social.grain.gallery": "posted",
55
+ "place.stream.livestream": "streamed",
56
+ "social.kut.community.membership": "joined",
57
+ "social.popfeed.feed.note": "posted",
58
+ "social.popfeed.feed.post": "posted",
59
+ "social.popfeed.feed.review": "reviewed",
60
+ "social.psky.feed.post": "posted"
61
+ }
62
+ };
63
+
64
+ // src/stream/verbs.ts
65
+ var STREAM_VERBS = [
66
+ "posted",
67
+ "reposted",
68
+ "published",
69
+ "presented",
70
+ "endorsed",
71
+ "joined",
72
+ "shipped",
73
+ "reviewed",
74
+ "created",
75
+ // Relational verbs: a reaction or reference to someone else's thing. These
76
+ // read with the subject the two-tier line renders after them ("Commented on
77
+ // {doc}", "Followed {person}").
78
+ "commented",
79
+ "replied",
80
+ "rsvped",
81
+ "liked",
82
+ "followed",
83
+ "bookmarked",
84
+ "registered",
85
+ "annotated",
86
+ "streamed",
87
+ "wrote",
88
+ "wasAt",
89
+ "metWith",
90
+ "supported",
91
+ "verified",
92
+ // rpg.actor: accepting an equipment item, and (re)composing the character's
93
+ // pixel-art sprite.
94
+ "received",
95
+ "styledCharacter"
96
+ ];
97
+ var streamVerbSchema = z.enum(STREAM_VERBS);
98
+ var verbMapSchema = z.object({
99
+ version: z.string(),
100
+ updated: z.string(),
101
+ defaultVerb: streamVerbSchema,
102
+ verbs: z.record(z.string(), streamVerbSchema)
103
+ });
104
+ var parsed = verbMapSchema.parse(verbs_default);
105
+ var ACTIVITY_VERBS = Object.freeze(parsed);
106
+ function verbForCollection(collection) {
107
+ if (!collection) return ACTIVITY_VERBS.defaultVerb;
108
+ return ACTIVITY_VERBS.verbs[collection] ?? ACTIVITY_VERBS.defaultVerb;
109
+ }
110
+ function getActivityVerbsVersion() {
111
+ return { version: ACTIVITY_VERBS.version, updated: ACTIVITY_VERBS.updated };
112
+ }
113
+ export {
114
+ ACTIVITY_VERBS,
115
+ STREAM_VERBS,
116
+ getActivityVerbsVersion,
117
+ streamVerbSchema,
118
+ verbForCollection
119
+ };
120
+ //# sourceMappingURL=verbs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/stream/verbs.ts","../../src/stream/verbs.json"],"sourcesContent":["import { z } from 'zod';\n\nimport rawVerbs from './verbs.json' with { type: 'json' };\n\n/**\n * The human action a stream item represents — a layer on top of `collection`\n * + `tier`. Groups semantically across apps (\"published\" spans WhiteWind and\n * standard-site; \"posted\" spans Bluesky and Picosky) so a day-grouped feed\n * reads like sentences.\n */\nexport const STREAM_VERBS = [\n 'posted',\n 'reposted',\n 'published',\n 'presented',\n 'endorsed',\n 'joined',\n 'shipped',\n 'reviewed',\n 'created',\n // Relational verbs: a reaction or reference to someone else's thing. These\n // read with the subject the two-tier line renders after them (\"Commented on\n // {doc}\", \"Followed {person}\").\n 'commented',\n 'replied',\n 'rsvped',\n 'liked',\n 'followed',\n 'bookmarked',\n 'registered',\n 'annotated',\n 'streamed',\n 'wrote',\n 'wasAt',\n 'metWith',\n 'supported',\n 'verified',\n // rpg.actor: accepting an equipment item, and (re)composing the character's\n // pixel-art sprite.\n 'received',\n 'styledCharacter',\n] as const;\n\nexport type StreamVerb = (typeof STREAM_VERBS)[number];\n\n/** Zod enum for a {@link StreamVerb}, shared with the view-model schema. */\nexport const streamVerbSchema = z.enum(STREAM_VERBS);\n\nexport interface ActivityVerbMap {\n version: string;\n updated: string;\n /** Verb returned for any collection not present in `verbs`. */\n defaultVerb: StreamVerb;\n /** Verb keyed by lexicon NSID. */\n verbs: Record<string, StreamVerb>;\n}\n\nconst verbMapSchema = z.object({\n version: z.string(),\n updated: z.string(),\n defaultVerb: streamVerbSchema,\n verbs: z.record(z.string(), streamVerbSchema),\n});\n\nconst parsed: ActivityVerbMap = verbMapSchema.parse(rawVerbs);\n\n/**\n * The verb map, keyed by lexicon NSID. Versioned independently from\n * `activity-tiers.json` so tier and verb evolve on their own cadence.\n */\nexport const ACTIVITY_VERBS: Readonly<ActivityVerbMap> = Object.freeze(parsed);\n\n/**\n * Returns the {@link StreamVerb} for an AT Protocol collection NSID. Unknown\n * or empty collections fall back to the map's `defaultVerb` (`created`).\n */\nexport function verbForCollection(collection: string): StreamVerb {\n if (!collection) return ACTIVITY_VERBS.defaultVerb;\n return ACTIVITY_VERBS.verbs[collection] ?? ACTIVITY_VERBS.defaultVerb;\n}\n\n/** Verb-map version + updated date, for diagnostics and version-skew checks. */\nexport function getActivityVerbsVersion(): { version: string; updated: string } {\n return { version: ACTIVITY_VERBS.version, updated: ACTIVITY_VERBS.updated };\n}\n","{\n \"$schema\": \"https://sifa.id/schemas/activity-verbs/v1.json\",\n \"version\": \"1.7.0\",\n \"updated\": \"2026-09-26\",\n \"defaultVerb\": \"created\",\n \"verbs\": {\n \"actor.rpg.sprite\": \"styledCharacter\",\n \"agency.portable.membership\": \"joined\",\n \"app.beaconbits.beacon\": \"wasAt\",\n \"app.atmobb.discussion.reply\": \"replied\",\n \"app.bsky.feed.post\": \"posted\",\n \"app.bsky.feed.repost\": \"reposted\",\n \"app.sidetrail.trail\": \"shipped\",\n \"app.sidetrail.walk\": \"shipped\",\n \"app.userinput.reply\": \"replied\",\n \"at.margin.annotation\": \"annotated\",\n \"at.margin.bookmark\": \"bookmarked\",\n \"at.margin.note\": \"annotated\",\n \"at.marque.domain\": \"registered\",\n \"at.youandme.connection\": \"metWith\",\n \"blog.pckt.mini.post\": \"wrote\",\n \"blue.flashes.feed.post\": \"posted\",\n \"buzz.bookhive.book\": \"reviewed\",\n \"com.whtwnd.blog.entry\": \"published\",\n \"community.lexicon.calendar.rsvp\": \"rsvped\",\n \"community.nooki.comments\": \"commented\",\n \"community.nooki.membership\": \"joined\",\n \"community.opensocial.membership\": \"joined\",\n \"computer.aetheros.page\": \"published\",\n \"dev.keytrace.claim\": \"verified\",\n \"equipment.rpg.item\": \"received\",\n \"eu.atcommons.member\": \"joined\",\n \"fm.plyr.comment\": \"commented\",\n \"forum.barazo.post\": \"posted\",\n \"fund.at.graph.endorse\": \"supported\",\n \"fyi.atstore.listing.review\": \"reviewed\",\n \"fyi.unravel.frontpage.post\": \"posted\",\n \"id.sifa.endorsement\": \"endorsed\",\n \"id.sifa.graph.connection\": \"joined\",\n \"id.sifa.profile.presentation\": \"presented\",\n \"id.sifa.profile.presentationDelivery\": \"presented\",\n \"link.pastesphere.snippet\": \"published\",\n \"org.impactindexer.review.comment\": \"commented\",\n \"pub.leaflet.comment\": \"commented\",\n \"sh.tangled.repo\": \"shipped\",\n \"sh.tangled.repo.issue\": \"shipped\",\n \"sh.tangled.repo.pull\": \"shipped\",\n \"site.standard.document\": \"published\",\n \"social.colibri.membership\": \"joined\",\n \"social.grain.gallery\": \"posted\",\n \"place.stream.livestream\": \"streamed\",\n \"social.kut.community.membership\": \"joined\",\n \"social.popfeed.feed.note\": \"posted\",\n \"social.popfeed.feed.post\": \"posted\",\n \"social.popfeed.feed.review\": \"reviewed\",\n \"social.psky.feed.post\": \"posted\"\n }\n}\n"],"mappings":";AAAA,SAAS,SAAS;;;ACAlB;AAAA,EACE,SAAW;AAAA,EACX,SAAW;AAAA,EACX,SAAW;AAAA,EACX,aAAe;AAAA,EACf,OAAS;AAAA,IACP,oBAAoB;AAAA,IACpB,8BAA8B;AAAA,IAC9B,yBAAyB;AAAA,IACzB,+BAA+B;AAAA,IAC/B,sBAAsB;AAAA,IACtB,wBAAwB;AAAA,IACxB,uBAAuB;AAAA,IACvB,sBAAsB;AAAA,IACtB,uBAAuB;AAAA,IACvB,wBAAwB;AAAA,IACxB,sBAAsB;AAAA,IACtB,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B,sBAAsB;AAAA,IACtB,yBAAyB;AAAA,IACzB,mCAAmC;AAAA,IACnC,4BAA4B;AAAA,IAC5B,8BAA8B;AAAA,IAC9B,mCAAmC;AAAA,IACnC,0BAA0B;AAAA,IAC1B,sBAAsB;AAAA,IACtB,sBAAsB;AAAA,IACtB,uBAAuB;AAAA,IACvB,mBAAmB;AAAA,IACnB,qBAAqB;AAAA,IACrB,yBAAyB;AAAA,IACzB,8BAA8B;AAAA,IAC9B,8BAA8B;AAAA,IAC9B,uBAAuB;AAAA,IACvB,4BAA4B;AAAA,IAC5B,gCAAgC;AAAA,IAChC,wCAAwC;AAAA,IACxC,4BAA4B;AAAA,IAC5B,oCAAoC;AAAA,IACpC,uBAAuB;AAAA,IACvB,mBAAmB;AAAA,IACnB,yBAAyB;AAAA,IACzB,wBAAwB;AAAA,IACxB,0BAA0B;AAAA,IAC1B,6BAA6B;AAAA,IAC7B,wBAAwB;AAAA,IACxB,2BAA2B;AAAA,IAC3B,mCAAmC;AAAA,IACnC,4BAA4B;AAAA,IAC5B,4BAA4B;AAAA,IAC5B,8BAA8B;AAAA,IAC9B,yBAAyB;AAAA,EAC3B;AACF;;;AD/CO,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA,EAGA;AAAA,EACA;AACF;AAKO,IAAM,mBAAmB,EAAE,KAAK,YAAY;AAWnD,IAAM,gBAAgB,EAAE,OAAO;AAAA,EAC7B,SAAS,EAAE,OAAO;AAAA,EAClB,SAAS,EAAE,OAAO;AAAA,EAClB,aAAa;AAAA,EACb,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,gBAAgB;AAC9C,CAAC;AAED,IAAM,SAA0B,cAAc,MAAM,aAAQ;AAMrD,IAAM,iBAA4C,OAAO,OAAO,MAAM;AAMtE,SAAS,kBAAkB,YAAgC;AAChE,MAAI,CAAC,WAAY,QAAO,eAAe;AACvC,SAAO,eAAe,MAAM,UAAU,KAAK,eAAe;AAC5D;AAGO,SAAS,0BAAgE;AAC9E,SAAO,EAAE,SAAS,eAAe,SAAS,SAAS,eAAe,QAAQ;AAC5E;","names":[]}