@everfur/sdk 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/CHANGELOG.md +182 -0
  2. package/README.md +9 -8
  3. package/dist/{Chat-BZZ-Py5l.d.ts → Chat-BOX-03ho.d.ts} +17 -3
  4. package/dist/{Chat-Dq4fffIO.d.cts → Chat-TA-aTcVF.d.cts} +17 -3
  5. package/dist/{DepthViews-CkYri51q.d.ts → DepthViews-CgjX2AJ5.d.ts} +1 -1
  6. package/dist/{DepthViews-CL75jyRA.d.cts → DepthViews-Cviea-ri.d.cts} +1 -1
  7. package/dist/{DepthViews-BG3E25MD.d.ts → DepthViews-D2dRqWRq.d.ts} +1 -1
  8. package/dist/{DepthViews-B_hIypI6.d.cts → DepthViews-DSFyaSeL.d.cts} +1 -1
  9. package/dist/{ErrorPolicyPort-CwbfmxzJ.d.ts → ErrorPolicyPort-D22LUVrK.d.ts} +1 -1
  10. package/dist/{ErrorPolicyPort-CNf4uQZP.d.cts → ErrorPolicyPort-D6CybiqJ.d.cts} +1 -1
  11. package/dist/{EverfurResult-DN9pL2Ab.d.cts → EverfurError-DmELDpXp.d.cts} +1 -67
  12. package/dist/{EverfurResult-DN9pL2Ab.d.ts → EverfurError-DmELDpXp.d.ts} +1 -67
  13. package/dist/EverfurResult-SGvHKsCB.d.ts +69 -0
  14. package/dist/EverfurResult-ZtH-YV1h.d.cts +69 -0
  15. package/dist/animations/index.d.cts +6 -5
  16. package/dist/animations/index.d.ts +6 -5
  17. package/dist/{attachments-BrUWQYNK.d.ts → attachments-C_vtFu2f.d.ts} +7 -6
  18. package/dist/{attachments-D_SECjr1.d.cts → attachments-DHvnITuE.d.cts} +7 -6
  19. package/dist/{attachments-DpldrvIW.d.ts → attachments-oD5U2fXI.d.ts} +3 -3
  20. package/dist/{attachments-BorG422I.d.cts → attachments-pIdGOQfm.d.cts} +3 -3
  21. package/dist/{bookingCopy-CqtDYvCR.d.ts → bookingCopy-CJir9mjb.d.ts} +417 -14
  22. package/dist/{bookingCopy-SREvkG19.d.cts → bookingCopy-DfuA13dh.d.cts} +417 -14
  23. package/dist/branding-Xb_wL8N1.d.cts +212 -0
  24. package/dist/branding-xpQ056sM.d.ts +212 -0
  25. package/dist/callCopy-rDH9JTFo.d.cts +45 -0
  26. package/dist/callCopy-rDH9JTFo.d.ts +45 -0
  27. package/dist/callRoom-7wrE3RP2.d.ts +62 -0
  28. package/dist/callRoom-B_EqaUzx.d.cts +62 -0
  29. package/dist/{casesRepository-DwtZVsbj.d.cts → casesRepository-B-Eg8ZJ3.d.cts} +14 -2
  30. package/dist/{casesRepository-v6QczS9N.d.ts → casesRepository-DHgIYKN9.d.ts} +14 -2
  31. package/dist/chat/index.cjs +1 -1
  32. package/dist/chat/index.d.cts +12 -11
  33. package/dist/chat/index.d.ts +12 -11
  34. package/dist/chat/index.js +1 -1
  35. package/dist/client/index.cjs +5 -5
  36. package/dist/client/index.d.cts +14 -12
  37. package/dist/client/index.d.ts +14 -12
  38. package/dist/client/index.js +5 -5
  39. package/dist/{config--Wu1Umhd.d.cts → config-ClI7QxB0.d.ts} +3 -2
  40. package/dist/{config-C7eb_IMD.d.ts → config-DAFbf721.d.cts} +3 -2
  41. package/dist/consent/index.d.cts +9 -8
  42. package/dist/consent/index.d.ts +9 -8
  43. package/dist/{context-CL3lyuy1.d.cts → context-B-dUM1Qf.d.cts} +9 -8
  44. package/dist/{context-CahAEha8.d.ts → context-CZbgF_OH.d.ts} +9 -8
  45. package/dist/{copy-DdVFDL01.d.ts → copy-CeRH3NXy.d.ts} +5 -4
  46. package/dist/{copy-UeUJVk8X.d.cts → copy-CneuYdrO.d.cts} +5 -4
  47. package/dist/core/index.cjs +9 -9
  48. package/dist/core/index.d.cts +19 -17
  49. package/dist/core/index.d.ts +19 -17
  50. package/dist/core/index.js +9 -9
  51. package/dist/{depth-D5HwcvKC.d.cts → depth-B3NFKlF9.d.cts} +6 -5
  52. package/dist/{depth-DvPwPuT_.d.ts → depth-DO3Ko_qs.d.ts} +6 -5
  53. package/dist/{entitlementRepository-B7egEdW6.d.ts → entitlementRepository-74kW5mK0.d.ts} +4 -4
  54. package/dist/{entitlementRepository-BpJ7tiwl.d.cts → entitlementRepository-m6zLUmiB.d.cts} +4 -4
  55. package/dist/{identity-C2-08BZW.d.cts → identity-C7uxGwfT.d.cts} +2 -2
  56. package/dist/{identity-CEi9GRFZ.d.ts → identity-CLAUq-K4.d.ts} +2 -2
  57. package/dist/index.cjs +6 -6
  58. package/dist/index.d.cts +19 -17
  59. package/dist/index.d.ts +19 -17
  60. package/dist/index.js +6 -6
  61. package/dist/{models-D2EUxPZY.d.cts → models-Bn2z0NNo.d.cts} +1 -1
  62. package/dist/{models-B-Uh2LTf.d.ts → models-DSqA5Ahs.d.ts} +1 -1
  63. package/dist/notifications/index.d.cts +5 -4
  64. package/dist/notifications/index.d.ts +5 -4
  65. package/dist/{pets-JVCXgRgR.d.cts → pets-BoB5B7kp.d.cts} +2 -2
  66. package/dist/{pets-DJv2sj2H.d.ts → pets-w4M9d-Dn.d.ts} +2 -2
  67. package/dist/{petsRepository-Bk6GDwLs.d.ts → petsRepository-BjKJ8UsN.d.ts} +2 -2
  68. package/dist/{petsRepository-B_gKbAzJ.d.cts → petsRepository-DZZoEG3r.d.cts} +2 -2
  69. package/dist/photo/index.d.cts +3 -2
  70. package/dist/photo/index.d.ts +3 -2
  71. package/dist/{ports-D7YW8qz9.d.ts → ports-BO3bzTJg.d.ts} +13 -6
  72. package/dist/{ports-BY2ph0_y.d.cts → ports-C2EVK416.d.cts} +13 -6
  73. package/dist/records/depth/index.d.cts +11 -10
  74. package/dist/records/depth/index.d.ts +11 -10
  75. package/dist/records/index.cjs +3 -3
  76. package/dist/records/index.d.cts +25 -14
  77. package/dist/records/index.d.ts +25 -14
  78. package/dist/records/index.js +3 -3
  79. package/dist/{requestFunnel-DFMGcluw.d.ts → requestFunnel-D7ipek3e.d.ts} +5 -4
  80. package/dist/{requestFunnel-BjDpqqvm.d.cts → requestFunnel-Djjwgoe9.d.cts} +5 -4
  81. package/dist/{runtimeTypes-w5KqBMcs.d.ts → runtimeTypes-CTL3yToK.d.ts} +7 -7
  82. package/dist/{runtimeTypes-gZEJu-da.d.cts → runtimeTypes-D2C9uD85.d.cts} +7 -7
  83. package/dist/server/events/index.cjs +1 -1
  84. package/dist/server/events/index.d.cts +4 -3
  85. package/dist/server/events/index.d.ts +4 -3
  86. package/dist/server/events/index.js +1 -1
  87. package/dist/server/index.cjs +1 -1
  88. package/dist/server/index.d.cts +5 -4
  89. package/dist/server/index.d.ts +5 -4
  90. package/dist/server/index.js +1 -1
  91. package/dist/televet/booking/index.cjs +1 -1
  92. package/dist/televet/booking/index.d.cts +303 -31
  93. package/dist/televet/booking/index.d.ts +303 -31
  94. package/dist/televet/booking/index.js +1 -1
  95. package/dist/televet/call/index.cjs +1 -1
  96. package/dist/televet/call/index.d.cts +25 -5
  97. package/dist/televet/call/index.d.ts +25 -5
  98. package/dist/televet/call/index.js +1 -1
  99. package/dist/televet/index.cjs +1 -1
  100. package/dist/televet/index.d.cts +41 -71
  101. package/dist/televet/index.d.ts +41 -71
  102. package/dist/televet/index.js +1 -1
  103. package/dist/televetGlobal-CEk0_cW9.d.cts +34 -0
  104. package/dist/televetGlobal-Cs9Wbqsy.d.ts +34 -0
  105. package/dist/testing/index.cjs +4 -4
  106. package/dist/testing/index.d.cts +3 -2
  107. package/dist/testing/index.d.ts +3 -2
  108. package/dist/testing/index.js +4 -4
  109. package/dist/testing/rn/index.cjs +1 -1
  110. package/dist/testing/rn/index.d.cts +13 -11
  111. package/dist/testing/rn/index.d.ts +13 -11
  112. package/dist/testing/rn/index.js +1 -1
  113. package/dist/testing/web/index.d.cts +14 -13
  114. package/dist/testing/web/index.d.ts +14 -13
  115. package/dist/{timelineRows-C15jxFFH.d.ts → timelineRows-7yFNK_rU.d.ts} +1 -1
  116. package/dist/{timelineRows-odO8g9r2.d.cts → timelineRows-CzR1T2DR.d.cts} +1 -1
  117. package/dist/{branding-CsRdeNwK.d.cts → tokens-CIngRkvt.d.cts} +7 -211
  118. package/dist/{branding-CsRdeNwK.d.ts → tokens-CIngRkvt.d.ts} +7 -211
  119. package/dist/{typeStyle-DmoyacDG.d.ts → typeStyle-DHJzDaUo.d.cts} +2 -1
  120. package/dist/{typeStyle-CKqVYD6L.d.cts → typeStyle-YPS_MXeI.d.ts} +2 -1
  121. package/dist/{useRecordsDepth-C6rjEaLn.d.cts → useRecordsDepth-Bnw36jPr.d.cts} +24 -5
  122. package/dist/{useRecordsDepth-crhBllQK.d.ts → useRecordsDepth-DFF7Faxx.d.ts} +24 -5
  123. package/dist/{useVetVisit-CjmMa896.d.ts → useVetVisit-BsjoDO-n.d.ts} +21 -6
  124. package/dist/{useVetVisit-Bc84hWUU.d.cts → useVetVisit-Ds8f1peV.d.cts} +21 -6
  125. package/dist/video/index.d.cts +3 -2
  126. package/dist/video/index.d.ts +3 -2
  127. package/dist/{view-Bxwxp4xD.d.ts → view-BqcOYFTr.d.ts} +5 -4
  128. package/dist/{view-DyitEO0m.d.cts → view-CaJs8WFH.d.cts} +5 -4
  129. package/dist/web/consent/index.d.cts +9 -8
  130. package/dist/web/consent/index.d.ts +9 -8
  131. package/dist/web/index.cjs +10 -10
  132. package/dist/web/index.d.cts +42 -19
  133. package/dist/web/index.d.ts +42 -19
  134. package/dist/web/index.js +10 -10
  135. package/dist/web/notifications/index.d.cts +7 -6
  136. package/dist/web/notifications/index.d.ts +7 -6
  137. package/dist/web/records/depth/index.cjs +2 -2
  138. package/dist/web/records/depth/index.d.cts +11 -10
  139. package/dist/web/records/depth/index.d.ts +11 -10
  140. package/dist/web/records/depth/index.js +2 -2
  141. package/dist/web/records/index.cjs +3 -3
  142. package/dist/web/records/index.d.cts +53 -35
  143. package/dist/web/records/index.d.ts +53 -35
  144. package/dist/web/records/index.js +3 -3
  145. package/dist/web/televet/booking/index.cjs +2 -1
  146. package/dist/web/televet/booking/index.d.cts +453 -32
  147. package/dist/web/televet/booking/index.d.ts +453 -32
  148. package/dist/web/televet/booking/index.js +2 -1
  149. package/dist/web/televet/call/index.cjs +1 -1
  150. package/dist/web/televet/call/index.d.cts +3 -1
  151. package/dist/web/televet/call/index.d.ts +3 -1
  152. package/dist/web/televet/call/index.js +1 -1
  153. package/dist/web/televet/index.cjs +1 -1
  154. package/dist/web/televet/index.d.cts +40 -74
  155. package/dist/web/televet/index.d.ts +40 -74
  156. package/dist/web/televet/index.js +1 -1
  157. package/package.json +3 -2
  158. package/dist/callCopy-DoQKG3-L.d.cts +0 -40
  159. package/dist/callCopy-DoQKG3-L.d.ts +0 -40
package/CHANGELOG.md CHANGED
@@ -8,6 +8,188 @@ The line is deliberately pre-1.0: the API is stable enough to build against and
8
8
  is guarded by api-extractor golden reports across all eleven subpaths, but 1.0.0 is a promise about breaking
9
9
  changes that has not been earned by any production integration yet.
10
10
 
11
+ ## [Unreleased]
12
+
13
+ ## [0.5.0] - 2026-09-23
14
+
15
+ 0.4.1 was tagged but never published to npm: its fixes (the five televet refusal screens and the rest
16
+ listed under 0.4.1 below) ship in this release instead.
17
+
18
+ ### Changed: records keep the member inside your app, and the web records page is complete on its own
19
+
20
+ **What an existing integration notices.** Nothing is removed and every signature still compiles, with the one
21
+ exception in the first bullet. What changes is which edges a host navigator receives and where a URL goes when
22
+ you pass no `onOpenUrl`.
23
+
24
+ - `RecordsScreen` gains `requests` (the request list) and `RecordsUrlKind` gains `request_document` (web, one
25
+ uploaded request document). A `switch` over either that ends in an exhaustive `assertNever` stops compiling
26
+ until it handles the new member.
27
+ - A host that routes the records screens itself (`onNavigate`) now receives edges it never received before:
28
+ `requests` from the React Native dashboard's new request-status card, and `clinicPicker` and `request` from
29
+ the web `EverfurRecordsPage` header and request rows. A router with no case for them leaves
30
+ those controls doing nothing, so add the cases (or pass no `onNavigate` on the web page, which then opens
31
+ every screen inside itself).
32
+ - With no `onOpenUrl`, nothing opens a browser or a tab any more. React Native shares a share link through the
33
+ OS share sheet, and the record PDF's short-lived link the same way. The web shares a link with
34
+ `navigator.share`, else copies it, and saves the record PDF and an uploaded document in place. The web save
35
+ needs the API to sign those links as attachments (`response-content-disposition=attachment`); against an API
36
+ that does not yet, the save does not happen and the control shows its existing failure line, and it never
37
+ falls back to a tab.
38
+ - The web `EverfurRecordsPage` is the default web records surface, and the hosted records frame serves it.
39
+ The React Native-shaped web `EverfurRecords` flow stays for existing embeds, and now moves focus to each new
40
+ screen's heading.
41
+ - Frame mode: the loader's sandbox adds `allow-downloads` and it delegates `clipboard-write; web-share` (this
42
+ applies to the chat frame as well). The records frame document's policy adds the consent-signature bucket to
43
+ `connect-src` and `img-src` and the media bucket to `frame-src`. Your page's `frame-src` stays
44
+ `https://sdk.everfur.com`.
45
+
46
+ ### Changed: a vet visit opens INSIDE your app by default, on both platforms
47
+
48
+ **The owner's decision of 2026-09-21: in-app is the default and the hosted redirect is an explicit opt-in.**
49
+ `VetVisitButton`, `useVetVisit().open()` and `openVisit()`, and every vet entry inside `EverfurChat` (the header,
50
+ the urgency pill, the vet-prep chip, the check-in) now resolve one destination, in order: the button's own
51
+ `onStartInApp`, a presenter registered with `registerEverfurTelevetFlow`, else the in-app visit Everfur provides,
52
+ rendered by the new `EverfurTelevetHost` (a full-screen `Modal` on React Native, a modal `<dialog>` in the SDK's own
53
+ DOM subtree on the web). `VetVisitButton` and `EverfurChat` mount that host themselves. Nothing opens the system
54
+ browser or a new tab unless the host passes `prefer="redirect"` (`prefer: 'redirect'` on the hook,
55
+ `vetPrefer="redirect"` on chat), which keeps the 0.4.x handoff byte for byte.
56
+
57
+ **Who is affected: every integration that registered nothing.** In 0.4.x a press with nothing registered minted a
58
+ handoff and opened the hosted page; it now opens the in-app visit. An existing visit (`visitRef`, a tapped push)
59
+ used to skip the registry and always go hosted; it now travels in the request (`request.visitRef`,
60
+ `request.intent`) to the same destinations. A presenter may return `false` to decline a request it does not handle.
61
+ `onStartInApp` now receives the request.
62
+
63
+ **The screens load on demand.** The booking flow is loaded through a dynamic import of
64
+ `@everfur/sdk/televet/booking` (`@everfur/sdk/web/televet/booking`) on the first press, and the call through
65
+ `@everfur/sdk/televet/call` (`@everfur/sdk/web/televet/call`) only when a visit is joined (ruling R11). On the web
66
+ the partner's bundler splits both into their own chunks. On React Native, Metro bundles what is reachable, so the
67
+ booking screens are now part of any app that renders `VetVisitButton` or `EverfurChat`.
68
+
69
+ ### Added
70
+
71
+ - `TelevetBookingController.listConsults`, `getConsult`, `joinConsult` and `cancelConsult`, the clients for the
72
+ served partner routes the SDK had none for (`GET /widget/v1/televet/consults`, `GET .../consults/{id}`,
73
+ `POST .../consults/{id}/join`, `POST .../consults/{id}/cancel`). The join answers the room credential
74
+ (`VetCallCredential`: room, token, `recordingNotice`, `callLimits`) with one attempt and no idempotency key.
75
+ - The `call` screen of `EverfurTelevet`, `TelevetJoinScreen`, `televetScreenForRequest`, `EverfurTelevetModal` /
76
+ `EverfurTelevetDialog`, `useTelevetJoin`.
77
+ - **The member's visits, in the app.** `EverfurTelevet` now lands on `home`: the member's visits when one is still
78
+ ahead, otherwise the booking. React Native ports the consumer mobile app's history and visit screens
79
+ (`TelevetVisitsScreen`, `TelevetConsultScreen`: the time, the vet, a Join that arms on the join window,
80
+ Reschedule, Cancel with the served terms and the server's receipt). The web ports the consumer web app's list
81
+ (`TelevetVisitsScreen`, `TelevetCancelVisitForm`), with Join, Reschedule and Cancel on each row. A reminder's
82
+ `visitRef` opens the visits. `TelevetConsult.hasRoom`; `splitTelevetVisits`, `televetJoinReadiness`,
83
+ `televetJoinDecision`, `canManageTelevetVisit`.
84
+ - **The emergency warning's ways out** (`TelevetEmergencyExits`), on both places the warning appears: the pet's
85
+ clinic (`primaryVet`) and the host's locator (`onFindEmergencyVet`, new). `primaryVet`, `onFindEmergencyVet`
86
+ and `onTriageReason` now pass through `EverfurTelevet`. The consumer web's ASPCA Animal Poison Control card is
87
+ built but not drawn until the owner approves its number and its "a fee may apply" line for partner pages; a
88
+ web warning with no card on screen reads the lede that points at no list.
89
+ - **React Native call controls are glyphs**, with Switch camera (the module's `cycleCamera`; the self-view is
90
+ mirrored only for the front lens) and the speaker route (`setNativeInCallAudioMode`), each drawn only when the
91
+ native module has the method.
92
+ - The recording notice (D8) in `EverfurVetCall` on both platforms, before the room, every mount, with no prop to
93
+ skip it: no call object or frame exists until the member continues.
94
+
95
+ ### Changed: the web booking is the consumer web app's funnel
96
+
97
+ The web booking was a DOM port of the React Native flow in the mobile deck's words. It now draws the consumer web
98
+ funnel: a text Back, a bar of eight segments and an x, a centred heading per step, a main-issues step before the
99
+ description (the reason the vet reads is the chips and the words), and the web app's own strings through a web
100
+ deck (`TELEVET_BOOKING_COPY_WEB`): "Type to the vet what you're seeing", "Which vet would you like to see?",
101
+ "Pick a date and time", "Does this look right?", "You're booked with {vet}", "Add to Calendar". React Native is
102
+ unchanged except that its describe heading takes the mobile app's current "Tell the vet what you are seeing".
103
+
104
+ ### Changed: chat citation sources stay in your app, and chat reads like Everfur's own apps
105
+
106
+ - **Citation sources no longer leave the app by default, on either platform.** Without a host opener a source card
107
+ is the read-only card (title, meta line, excerpt; no link). `EverfurChat` takes `onOpenUrl(url, 'citation')`,
108
+ the same shape as records, called through the host-callback guard. **Who is affected:** an integration that relied
109
+ on sources opening a browser or a new tab must now pass an opener, for example `(url) => Linking.openURL(url)` or
110
+ `(url) => { window.open(url, '_blank', 'noopener'); }`. The CDN frame draws the read-only card, since its sandbox
111
+ has no `allow-popups`.
112
+ - **The web chat lays out by its own box, not the viewport**, like the consumer web app: history is a brand rail at
113
+ 800px and wider, the web app's drawer below that (scrim, focus trap, Escape, focus return); the thread and
114
+ composer keep a centred 768px column; at 1024px and wider the conversation type steps from 15/22 to 17/28. New
115
+ optional `headingLevel` (web, default 2) for the empty-state title.
116
+ - **A keyboard focus ring the host page cannot remove:** drawn inline on keyboard focus in the theme's ink, so a
117
+ host `button:focus { outline: none }` reset no longer leaves chat controls without one.
118
+ - **React Native touch targets reach 44pt:** `PressScale` defaults to the consumer's 12pt hit slop; a caller's own
119
+ slop still wins.
120
+ - **Check-ins follow the consumer rule:** only the newest ask per case is live, and a re-ask after a SAME answer is
121
+ no longer locked behind the case's previous answer. `ChatCheckin.openedAt`, `WatchCase.checkinAskCount` and
122
+ `WatchCase.checkinAnswerCount` are new, optional and additive.
123
+ - **Theme:** the resolver guarantees `brandBorderStrong` reads 3:1 on every ground a control sits on, pushing a
124
+ partner brand that does not; the uploading wash and the starter chip edge now follow the partner's theme.
125
+ - The composer placeholder is the consumer apps' own `Ask me anything!`.
126
+ - Docs: brightness is light by default and `'auto'` opts in to the OS setting; the docs previously said the reverse.
127
+
128
+ ### Breaking
129
+
130
+ - `TelevetConsult` gained a REQUIRED `hasRoom` (from `meeting_url`). A host that builds a `TelevetConsult` by hand,
131
+ for example for `EverfurTelevetReschedule`'s `consult`, must now set it.
132
+ - The `TelevetScreen` and `TelevetBookingStep` unions widened (`home`, `visits`, `consult` on React Native, `call`,
133
+ `visit`; `issues` on the web booking). An exhaustive `switch` over either stops compiling until it handles them.
134
+ - `EverfurTelevet`'s default root moved from the booking to `home`: every opening reads `GET /consults` once, and
135
+ lands on the visits instead of the booking when one is ahead. Pass `initialScreen={{ name: 'booking' }}` for the
136
+ old behaviour.
137
+
138
+ ### Fixed
139
+
140
+ - The landing is held for the whole opening: Back from a visit the member cancelled, or out of a call that ended,
141
+ returns to the visits. It used to read the list again and drop the member into a new booking.
142
+ - On React Native, Android's back press during a call no longer reaches a partner's own navigator (the
143
+ `registerEverfurTelevetFlow` path), which popped the screen and hung up on the vet. Before the call runs it is
144
+ Leave, as it is inside the SDK's modal.
145
+ - A React Native visits list that fails to load still offers the booking beneath the retry, as the vet home does.
146
+ - The React Native speaker toggle asks the native module once per press; it used to ask from inside a state
147
+ updater, which StrictMode runs twice in development.
148
+ - Web a11y: a dark Join names its reason through `aria-describedby`, and the emergency primary-vet hint takes a
149
+ `useId` id, so two warnings on one page no longer share one.
150
+ - The React Native location card no longer tells the member to "Turn on location for Everfur" when the host gave
151
+ the booking no way to resolve one; the developer is told which prop is missing.
152
+ - The chat vet entries honour a registered flow in the PUBLISHED package: the registry lives on a `globalThis`
153
+ slot, so `@everfur/sdk/chat` and `@everfur/sdk/televet` (and their web twins) read one presenter instead of two
154
+ private copies.
155
+ - A dark booking plane (the partner booking routes answering 404) shows the paused state inside the app. It used to
156
+ read the entitlement 404 as "not entitled" and show "A Pro membership is needed to book a video visit." to a
157
+ member whose tenant pays, and its unavailable fallback rendered `VetVisitButton`, which re-presented the same flow
158
+ when one was registered and left the app when none was.
159
+ - The React Native lobby waits on the vet's PRESENCE, not their video track: a vet with the camera off no longer
160
+ leaves the member on "Your vet is joining", and turning the camera off mid-call no longer throws the member back
161
+ to the lobby. The self-view reads "Your camera is off" rather than the control's "Camera on".
162
+ - The route table and `MockTransport` treat the served booking routes, the join route, the pet profile and the
163
+ embed config as served.
164
+
165
+ ## [0.4.1] - 2026-09-23
166
+
167
+ ### Fixed
168
+
169
+ - Televet booking carries the five refusal screens the consumer mobile app has and this package did
170
+ not: the early-emergency interstitial, the empty clinician roster, the unentitled state, the
171
+ unserved-state action and the refused-attachment notice. The funnel matched already; the refusals
172
+ did not exist, so a partner's member who described something urgent, or whose state is not served,
173
+ saw something Everfur's own app does not show. Both platforms, with the triggers and the copy in
174
+ the shared react layer so the two cannot drift.
175
+ - The two televet booking size gates are re-measured on a clean tree, which both of their notes had asked
176
+ for: the previous lines were taken from a tree holding other lanes' uncommitted work. The web booking entry
177
+ moves 37_300 -> 42_600 (measured 40_560) and the React Native booking closure 35_600 -> 39_600 (measured
178
+ 37_694), each the measured size plus 5%. Only the booking lines moved: the visit-button entry, the call
179
+ entry, chat, records and every other closure hold their existing budgets on the same build, and the
180
+ structural checks still prove no foreign capability entered the closure.
181
+ - A televet parity guard now derives the mobile component set from the real everfur-mobile checkout
182
+ and fails by name when a screen is missing. Chat, records and the theme tokens each had such a
183
+ guard; televet did not, which is how five screens stayed absent while parity read as verified.
184
+ - `TelevetBookingFailure` is published as its real union again on both `televet/booking` and
185
+ `web/televet/booking`. It had degraded to an opaque alias (`TelevetBookingFailure_2`) with its seven
186
+ members and their per-member documentation stripped from the generated `.d.ts`, so a partner's editor
187
+ could not tell which failures exist or which of them a retry can fix. The containers now re-export the
188
+ declaration rather than aliasing it.
189
+ - Imports the five-refusal-screen change left behind are removed from the two booking containers, the two
190
+ step files and the two review steps. Nothing rendered changed: every symbol was already used at the file
191
+ the code moved into, which is why the screens themselves were unaffected.
192
+
11
193
  ## [0.4.0] - 2026-09-21
12
194
 
13
195
  ### Changed: a press of `VetVisitButton` opens the visit IN YOUR APP, not the system browser
package/README.md CHANGED
@@ -71,12 +71,13 @@ Two ways, one wire contract, documented in
71
71
 
72
72
  Chat and records are the web surfaces (records on its own subpath and its own frame document, available
73
73
  when Everfur enables records for your account); photo and video remain React Native for now. Vet visits (not yet enabled)
74
- have their own entry on both hosts, `@everfur/sdk/web/televet` and `@everfur/sdk/televet`, and the video call
75
- rendered inside your own app has an entry again beneath each, `@everfur/sdk/web/televet/call` and
76
- `@everfur/sdk/televet/call`, so a partner mounting only the visit button takes no WebRTC dependency. Booking
77
- the visit inside your own React Native app, rather than handing off to the hosted one, is a third entry,
78
- `@everfur/sdk/televet/booking`, split out for the same reason: a partner that mounts only the button never
79
- downloads a scheduler it does not render.
74
+ have their own entry on both hosts, `@everfur/sdk/web/televet` and `@everfur/sdk/televet`, and a visit opens
75
+ INSIDE your app by default: booking, the confirmation and the call run in an Everfur modal (React Native) or
76
+ dialog (web) that `VetVisitButton` and `EverfurChat` mount themselves; the hosted page is an explicit opt-in,
77
+ `prefer="redirect"`. The booking screens (`@everfur/sdk/televet/booking`, `@everfur/sdk/web/televet/booking`)
78
+ and the call (`@everfur/sdk/televet/call`, `@everfur/sdk/web/televet/call`) are their own entries, loaded on
79
+ demand, so a page where nobody opens a visit downloads neither and a page where nobody joins takes no WebRTC
80
+ dependency.
80
81
  [docs/partner-integration/16-TELEVET-VISITS.md](docs/partner-integration/16-TELEVET-VISITS.md).
81
82
 
82
83
  ## Quickstart
@@ -177,13 +178,13 @@ off-state, never a blank region.
177
178
  | Import | Contents |
178
179
  | --- | --- |
179
180
  | `@everfur/sdk` | `EverfurProvider`, `CapabilityGate`, `EverfurChat`, `useEverfurChat`, `CapabilityName`, error/result types, branded id helpers (`petRef`, `userRef`, `conversationId`) |
180
- | `@everfur/sdk/records` | `EverfurRecords`, `EverfurClinicRequest`, `EverfurClinicRequestBatch`, `SignaturePad`, records hooks + types |
181
+ | `@everfur/sdk/records` | `EverfurRecords` (the Everfur app's records flow), the named screens (`EverfurRecordsUpload`, `EverfurRecordsRequests`, `EverfurRecordsRequest`, `EverfurRecordDetail`, ...), `EverfurClinicRequest`, `EverfurClinicRequestBatch`, `SignaturePad`, records hooks + types |
181
182
  | `@everfur/sdk/records/depth`, `@everfur/sdk/web/records/depth` | record depth (the timeline, the withheld record sections, per-document contributions) on their own entries, dark until Everfur enables it per deployment; see [chapter 9](docs/partner-integration/09-GUIDE-RECORDS-AND-CONSENT.md#record-depth-behind-a-separate-switch) |
182
183
  | `@everfur/sdk/video` | gait / live-scan surface |
183
184
  | `@everfur/sdk/photo` | photo checkup surface |
184
185
  | `@everfur/sdk/animations` | server-driven pet-state media surface |
185
186
  | `@everfur/sdk/web` | the browser entry: `EverfurProvider`, `CapabilityGate`, `EverfurChat`, `useEverfurChat`, the theme hook, rendered with `react-dom`; withheld from React Native bundles the way `./server` is |
186
- | `@everfur/sdk/web/records` | records for a browser host: `EverfurRecords`, `useEverfurRecords`, `createWebRecordsUploadTransport`, `fileToHandle`; its own entry, withheld from React Native like `./web`; available when Everfur enables records for the account. Frame mode serves it with `surface: 'records'` (see [chapter 13](docs/partner-integration/13-WEB-INTEGRATION.md)) |
187
+ | `@everfur/sdk/web/records` | records for a browser host: `EverfurRecordsPage` (the Everfur web app's records page, complete on its own: request from a clinic, upload, request status, the full record with vaccinations, all inside your page), the named screens, `EverfurRecords` (the React Native-shaped flow), `useEverfurRecords`, `createWebRecordsUploadTransport`, `fileToHandle`; its own entry, withheld from React Native like `./web`; available when Everfur enables records for the account. Frame mode serves it with `surface: 'records'` (see [chapter 13](docs/partner-integration/13-WEB-INTEGRATION.md)) |
187
188
  | `@everfur/sdk/server` | **server-only** `mintPartnerSession` (no React Native resolution; never bundled on-device) |
188
189
  | `@everfur/sdk/server/events` | **server-only, Node only** partner events (preview): `constructEvent` to verify webhooks, `sendPartnerEvent`; see [chapter 15](docs/partner-integration/15-EVENTS-AND-WEBHOOKS.md) |
189
190
  | `@everfur/sdk/testing`, `@everfur/sdk/testing/rn`, `@everfur/sdk/testing/web` | test seams (`MockTransport`, `useEverfurTestEntitlements`, ...) for your own tests |
@@ -2,9 +2,9 @@ import { ReactNode } from 'react';
2
2
  import { StyleProp, ViewStyle } from 'react-native';
3
3
  import { P as PetRef, C as ConversationId } from './ids-B2GAAifq.js';
4
4
  import { F as FileHandle } from './ports-BN6RHF9W.js';
5
- import { a as ChatCheckinTarget } from './ports-D7YW8qz9.js';
6
- import { W as WidgetPet, P as PetProfileInput } from './petsRepository-Bk6GDwLs.js';
7
- import { U as UrgencyDisplayLevel, L as LifecyclePort, E as EverfurChatDraftStore } from './attachments-BrUWQYNK.js';
5
+ import { a as ChatCheckinTarget } from './ports-BO3bzTJg.js';
6
+ import { W as WidgetPet, P as PetProfileInput } from './petsRepository-BjKJ8UsN.js';
7
+ import { U as UrgencyDisplayLevel, L as LifecyclePort, E as EverfurChatDraftStore } from './attachments-C_vtFu2f.js';
8
8
 
9
9
  /** Where a picked image comes from: the host's photo library, or its camera. */
10
10
  type AttachmentSource = 'photo' | 'camera';
@@ -118,6 +118,20 @@ interface EverfurChatProps {
118
118
  * is available there, so it is never offered to someone who could not book.
119
119
  */
120
120
  readonly vetUsState?: string;
121
+ /**
122
+ * Where every vet entry inside chat takes the member. Defaults to `'in-app'`: your registered presenter
123
+ * (`registerEverfurTelevetFlow`), else the in-app visit Everfur provides, which this surface mounts itself.
124
+ * `'redirect'` is the explicit opt-in to the hosted Everfur visit in the browser.
125
+ */
126
+ readonly vetPrefer?: 'in-app' | 'redirect';
127
+ /**
128
+ * Your opener for a web page chat links to: today, the source page behind a card in an answer's sources
129
+ * deck (`kind` `'citation'`, always an https URL). Absent (the default), a source card is read-only: its
130
+ * title, meta line and excerpt show, and nothing takes the member out of your app. Given, the card is a link
131
+ * and a tap goes here, so you can show the page in your own in-app browser; pass
132
+ * `(url) => Linking.openURL(url)` for the Everfur app's system browser. A throw or a rejection is contained.
133
+ */
134
+ readonly onOpenUrl?: (url: string, kind: 'citation') => void | Promise<void>;
121
135
  }
122
136
  /**
123
137
  * Entitlement-gated, four-state chat surface. Entitlement-OFF renders the CapabilityGate OffState;
@@ -2,9 +2,9 @@ import { ReactNode } from 'react';
2
2
  import { StyleProp, ViewStyle } from 'react-native';
3
3
  import { P as PetRef, C as ConversationId } from './ids-B2GAAifq.cjs';
4
4
  import { F as FileHandle } from './ports-BN6RHF9W.cjs';
5
- import { a as ChatCheckinTarget } from './ports-BY2ph0_y.cjs';
6
- import { W as WidgetPet, P as PetProfileInput } from './petsRepository-B_gKbAzJ.cjs';
7
- import { U as UrgencyDisplayLevel, L as LifecyclePort, E as EverfurChatDraftStore } from './attachments-D_SECjr1.cjs';
5
+ import { a as ChatCheckinTarget } from './ports-C2EVK416.cjs';
6
+ import { W as WidgetPet, P as PetProfileInput } from './petsRepository-DZZoEG3r.cjs';
7
+ import { U as UrgencyDisplayLevel, L as LifecyclePort, E as EverfurChatDraftStore } from './attachments-DHvnITuE.cjs';
8
8
 
9
9
  /** Where a picked image comes from: the host's photo library, or its camera. */
10
10
  type AttachmentSource = 'photo' | 'camera';
@@ -118,6 +118,20 @@ interface EverfurChatProps {
118
118
  * is available there, so it is never offered to someone who could not book.
119
119
  */
120
120
  readonly vetUsState?: string;
121
+ /**
122
+ * Where every vet entry inside chat takes the member. Defaults to `'in-app'`: your registered presenter
123
+ * (`registerEverfurTelevetFlow`), else the in-app visit Everfur provides, which this surface mounts itself.
124
+ * `'redirect'` is the explicit opt-in to the hosted Everfur visit in the browser.
125
+ */
126
+ readonly vetPrefer?: 'in-app' | 'redirect';
127
+ /**
128
+ * Your opener for a web page chat links to: today, the source page behind a card in an answer's sources
129
+ * deck (`kind` `'citation'`, always an https URL). Absent (the default), a source card is read-only: its
130
+ * title, meta line and excerpt show, and nothing takes the member out of your app. Given, the card is a link
131
+ * and a tap goes here, so you can show the page in your own in-app browser; pass
132
+ * `(url) => Linking.openURL(url)` for the Everfur app's system browser. A throw or a rejection is contained.
133
+ */
134
+ readonly onOpenUrl?: (url: string, kind: 'citation') => void | Promise<void>;
121
135
  }
122
136
  /**
123
137
  * Entitlement-gated, four-state chat surface. Entitlement-OFF renders the CapabilityGate OffState;
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { StyleProp, ViewStyle } from 'react-native';
3
- import { f as RecordsScreenBaseProps } from './useRecordsDepth-crhBllQK.js';
3
+ import { f as RecordsScreenBaseProps } from './useRecordsDepth-DFF7Faxx.js';
4
4
 
5
5
  interface EverfurRecordsDepthProps extends Pick<RecordsScreenBaseProps, 'petRef' | 'petName' | 'onNavigate' | 'onBack'> {
6
6
  readonly style?: StyleProp<ViewStyle>;
@@ -1,5 +1,5 @@
1
1
  import { CSSProperties, ReactNode } from 'react';
2
- import { f as RecordsScreenBaseProps } from './useRecordsDepth-C6rjEaLn.cjs';
2
+ import { f as RecordsScreenBaseProps } from './useRecordsDepth-Bnw36jPr.cjs';
3
3
 
4
4
  interface EverfurRecordsDepthProps extends Pick<RecordsScreenBaseProps, 'petRef' | 'petName' | 'onNavigate' | 'onBack'> {
5
5
  readonly style?: CSSProperties;
@@ -1,5 +1,5 @@
1
1
  import { CSSProperties, ReactNode } from 'react';
2
- import { f as RecordsScreenBaseProps } from './useRecordsDepth-crhBllQK.js';
2
+ import { f as RecordsScreenBaseProps } from './useRecordsDepth-DFF7Faxx.js';
3
3
 
4
4
  interface EverfurRecordsDepthProps extends Pick<RecordsScreenBaseProps, 'petRef' | 'petName' | 'onNavigate' | 'onBack'> {
5
5
  readonly style?: CSSProperties;
@@ -1,6 +1,6 @@
1
1
  import { ReactNode } from 'react';
2
2
  import { StyleProp, ViewStyle } from 'react-native';
3
- import { f as RecordsScreenBaseProps } from './useRecordsDepth-C6rjEaLn.cjs';
3
+ import { f as RecordsScreenBaseProps } from './useRecordsDepth-Bnw36jPr.cjs';
4
4
 
5
5
  interface EverfurRecordsDepthProps extends Pick<RecordsScreenBaseProps, 'petRef' | 'petName' | 'onNavigate' | 'onBack'> {
6
6
  readonly style?: StyleProp<ViewStyle>;
@@ -1,4 +1,4 @@
1
- import { b as EverfurErrorCode, E as EverfurError } from './EverfurResult-DN9pL2Ab.js';
1
+ import { b as EverfurErrorCode, E as EverfurError } from './EverfurError-DmELDpXp.js';
2
2
 
3
3
  /**
4
4
  * Recovery policy. A host may narrow retry ceilings (e.g. a metered plan) but can never widen the SDK's
@@ -1,4 +1,4 @@
1
- import { b as EverfurErrorCode, E as EverfurError } from './EverfurResult-DN9pL2Ab.cjs';
1
+ import { b as EverfurErrorCode, E as EverfurError } from './EverfurError-DmELDpXp.cjs';
2
2
 
3
3
  /**
4
4
  * Recovery policy. A host may narrow retry ceilings (e.g. a metered plan) but can never widen the SDK's
@@ -172,70 +172,4 @@ interface MakeEverfurErrorOptions {
172
172
  }
173
173
  declare function makeEverfurError(code: EverfurErrorCode, opts?: MakeEverfurErrorOptions): EverfurError;
174
174
 
175
- /**
176
- * The settle type. An async public operation returns this instead of throwing for an EXPECTED failure.
177
- * A successful result may carry a non-fatal `warning` (e.g. served-stale, degraded path).
178
- */
179
- type EverfurResult<T> = {
180
- readonly ok: true;
181
- readonly value: T;
182
- readonly warning?: EverfurError;
183
- } | {
184
- readonly ok: false;
185
- readonly error: EverfurError;
186
- };
187
- /** Construct a success result. Frozen, public state is immutable end to end. */
188
- declare function ok<T>(value: T, warning?: EverfurError): EverfurResult<T>;
189
- /** Construct a failure result. Frozen. */
190
- declare function err<T = never>(error: EverfurError): EverfurResult<T>;
191
- /** Narrowing guard: true iff the result is a success. */
192
- declare function isOk<T>(r: EverfurResult<T>): r is {
193
- readonly ok: true;
194
- readonly value: T;
195
- readonly warning?: EverfurError;
196
- };
197
- /** Narrowing guard: true iff the result is a failure. */
198
- declare function isErr<T>(r: EverfurResult<T>): r is {
199
- readonly ok: false;
200
- readonly error: EverfurError;
201
- };
202
- /**
203
- * The real `Error` subclass `unwrap` throws, so an imperative call site that lets the throw escape
204
- * produces a proper Error rather than a bare object (which a crash reporter files as
205
- * "Non-Error exception captured", with no stack and no grouping).
206
- *
207
- * `message` is built from the normalized `code` and the frozen, product-owned `displayMessage` ONLY.
208
- * The untrusted `wireMessage` is deliberately NOT in it: `message` is the one field every telemetry
209
- * vendor captures and indexes by default, so putting wire text there would make an untrusted,
210
- * healthcare-adjacent string flow automatically into a partner's third-party tooling. The full
211
- * `EverfurError` hangs off `.error`, where `wireMessage` and `raw` remain non-enumerable.
212
- */
213
- declare class EverfurThrownError extends Error {
214
- /** The settled error this was thrown from. Its `wireMessage` / `raw` stay non-enumerable. */
215
- readonly error: EverfurError;
216
- /** Mirror of `error.code`, so a catch block can branch without reaching through `.error`. */
217
- readonly code: EverfurError['code'];
218
- /** Mirror of `error.category`, the coarse branching axis. */
219
- readonly category: EverfurError['category'];
220
- constructor(error: EverfurError);
221
- }
222
- /**
223
- * Escape hatch for imperative callers: return the value or throw. The throw is an `EverfurThrownError`
224
- * (a real `Error`, safe message); the settled `EverfurError` is on its `.error`.
225
- * Prefer pattern-matching on `ok`; `unwrap` exists for call sites that want the throw.
226
- */
227
- declare function unwrap<T>(r: EverfurResult<T>): T;
228
- /**
229
- * Thrown SYNCHRONOUSLY for programmer error ONLY, never for a network or domain failure.
230
- * Mirrors Flutter `_requireInitialized` (a real guard, not an assert).
231
- *
232
- * - `not-initialized` , a capability used before EverfurProvider mounted / init ran.
233
- * - `invalid-argument` , a malformed id or option shape (e.g. a non-UUID conversation id).
234
- * - `missing-peer-dependency`, a capability subpath used without its required native peer dep.
235
- */
236
- declare class EverfurConfigError extends Error {
237
- readonly kind: 'not-initialized' | 'invalid-argument' | 'missing-peer-dependency';
238
- constructor(kind: 'not-initialized' | 'invalid-argument' | 'missing-peer-dependency', message: string);
239
- }
240
-
241
- export { AUTO_RETRYABLE_CODES as A, BACKOFF_BASE_MS as B, type EverfurError as E, MAX_RETRY_ATTEMPTS as M, RETRYABLE_CONTRACT_CODES as R, type EverfurErrorCategory as a, type EverfurErrorCode as b, type EverfurResult as c, EverfurConfigError as d, EverfurThrownError as e, categoryFor as f, isOk as g, isRetryableCode as h, isErr as i, userFacingError as j, BACKOFF_CAP_MS as k, EVERFUR_ERROR_CATEGORIES as l, EVERFUR_ERROR_CODES as m, type MakeEverfurErrorOptions as n, backoffDelayMs as o, canRecreateOnNotFound as p, err as q, fromHttpStatus as r, fromWire as s, isAutoRetryable as t, unwrap as u, makeEverfurError as v, ok as w, shouldRetry as x };
175
+ export { AUTO_RETRYABLE_CODES as A, BACKOFF_BASE_MS as B, type EverfurError as E, MAX_RETRY_ATTEMPTS as M, RETRYABLE_CONTRACT_CODES as R, type EverfurErrorCategory as a, type EverfurErrorCode as b, categoryFor as c, BACKOFF_CAP_MS as d, EVERFUR_ERROR_CATEGORIES as e, EVERFUR_ERROR_CODES as f, type MakeEverfurErrorOptions as g, backoffDelayMs as h, isRetryableCode as i, canRecreateOnNotFound as j, fromHttpStatus as k, fromWire as l, isAutoRetryable as m, makeEverfurError as n, shouldRetry as s, userFacingError as u };
@@ -172,70 +172,4 @@ interface MakeEverfurErrorOptions {
172
172
  }
173
173
  declare function makeEverfurError(code: EverfurErrorCode, opts?: MakeEverfurErrorOptions): EverfurError;
174
174
 
175
- /**
176
- * The settle type. An async public operation returns this instead of throwing for an EXPECTED failure.
177
- * A successful result may carry a non-fatal `warning` (e.g. served-stale, degraded path).
178
- */
179
- type EverfurResult<T> = {
180
- readonly ok: true;
181
- readonly value: T;
182
- readonly warning?: EverfurError;
183
- } | {
184
- readonly ok: false;
185
- readonly error: EverfurError;
186
- };
187
- /** Construct a success result. Frozen, public state is immutable end to end. */
188
- declare function ok<T>(value: T, warning?: EverfurError): EverfurResult<T>;
189
- /** Construct a failure result. Frozen. */
190
- declare function err<T = never>(error: EverfurError): EverfurResult<T>;
191
- /** Narrowing guard: true iff the result is a success. */
192
- declare function isOk<T>(r: EverfurResult<T>): r is {
193
- readonly ok: true;
194
- readonly value: T;
195
- readonly warning?: EverfurError;
196
- };
197
- /** Narrowing guard: true iff the result is a failure. */
198
- declare function isErr<T>(r: EverfurResult<T>): r is {
199
- readonly ok: false;
200
- readonly error: EverfurError;
201
- };
202
- /**
203
- * The real `Error` subclass `unwrap` throws, so an imperative call site that lets the throw escape
204
- * produces a proper Error rather than a bare object (which a crash reporter files as
205
- * "Non-Error exception captured", with no stack and no grouping).
206
- *
207
- * `message` is built from the normalized `code` and the frozen, product-owned `displayMessage` ONLY.
208
- * The untrusted `wireMessage` is deliberately NOT in it: `message` is the one field every telemetry
209
- * vendor captures and indexes by default, so putting wire text there would make an untrusted,
210
- * healthcare-adjacent string flow automatically into a partner's third-party tooling. The full
211
- * `EverfurError` hangs off `.error`, where `wireMessage` and `raw` remain non-enumerable.
212
- */
213
- declare class EverfurThrownError extends Error {
214
- /** The settled error this was thrown from. Its `wireMessage` / `raw` stay non-enumerable. */
215
- readonly error: EverfurError;
216
- /** Mirror of `error.code`, so a catch block can branch without reaching through `.error`. */
217
- readonly code: EverfurError['code'];
218
- /** Mirror of `error.category`, the coarse branching axis. */
219
- readonly category: EverfurError['category'];
220
- constructor(error: EverfurError);
221
- }
222
- /**
223
- * Escape hatch for imperative callers: return the value or throw. The throw is an `EverfurThrownError`
224
- * (a real `Error`, safe message); the settled `EverfurError` is on its `.error`.
225
- * Prefer pattern-matching on `ok`; `unwrap` exists for call sites that want the throw.
226
- */
227
- declare function unwrap<T>(r: EverfurResult<T>): T;
228
- /**
229
- * Thrown SYNCHRONOUSLY for programmer error ONLY, never for a network or domain failure.
230
- * Mirrors Flutter `_requireInitialized` (a real guard, not an assert).
231
- *
232
- * - `not-initialized` , a capability used before EverfurProvider mounted / init ran.
233
- * - `invalid-argument` , a malformed id or option shape (e.g. a non-UUID conversation id).
234
- * - `missing-peer-dependency`, a capability subpath used without its required native peer dep.
235
- */
236
- declare class EverfurConfigError extends Error {
237
- readonly kind: 'not-initialized' | 'invalid-argument' | 'missing-peer-dependency';
238
- constructor(kind: 'not-initialized' | 'invalid-argument' | 'missing-peer-dependency', message: string);
239
- }
240
-
241
- export { AUTO_RETRYABLE_CODES as A, BACKOFF_BASE_MS as B, type EverfurError as E, MAX_RETRY_ATTEMPTS as M, RETRYABLE_CONTRACT_CODES as R, type EverfurErrorCategory as a, type EverfurErrorCode as b, type EverfurResult as c, EverfurConfigError as d, EverfurThrownError as e, categoryFor as f, isOk as g, isRetryableCode as h, isErr as i, userFacingError as j, BACKOFF_CAP_MS as k, EVERFUR_ERROR_CATEGORIES as l, EVERFUR_ERROR_CODES as m, type MakeEverfurErrorOptions as n, backoffDelayMs as o, canRecreateOnNotFound as p, err as q, fromHttpStatus as r, fromWire as s, isAutoRetryable as t, unwrap as u, makeEverfurError as v, ok as w, shouldRetry as x };
175
+ export { AUTO_RETRYABLE_CODES as A, BACKOFF_BASE_MS as B, type EverfurError as E, MAX_RETRY_ATTEMPTS as M, RETRYABLE_CONTRACT_CODES as R, type EverfurErrorCategory as a, type EverfurErrorCode as b, categoryFor as c, BACKOFF_CAP_MS as d, EVERFUR_ERROR_CATEGORIES as e, EVERFUR_ERROR_CODES as f, type MakeEverfurErrorOptions as g, backoffDelayMs as h, isRetryableCode as i, canRecreateOnNotFound as j, fromHttpStatus as k, fromWire as l, isAutoRetryable as m, makeEverfurError as n, shouldRetry as s, userFacingError as u };
@@ -0,0 +1,69 @@
1
+ import { E as EverfurError } from './EverfurError-DmELDpXp.js';
2
+
3
+ /**
4
+ * The settle type. An async public operation returns this instead of throwing for an EXPECTED failure.
5
+ * A successful result may carry a non-fatal `warning` (e.g. served-stale, degraded path).
6
+ */
7
+ type EverfurResult<T> = {
8
+ readonly ok: true;
9
+ readonly value: T;
10
+ readonly warning?: EverfurError;
11
+ } | {
12
+ readonly ok: false;
13
+ readonly error: EverfurError;
14
+ };
15
+ /** Construct a success result. Frozen, public state is immutable end to end. */
16
+ declare function ok<T>(value: T, warning?: EverfurError): EverfurResult<T>;
17
+ /** Construct a failure result. Frozen. */
18
+ declare function err<T = never>(error: EverfurError): EverfurResult<T>;
19
+ /** Narrowing guard: true iff the result is a success. */
20
+ declare function isOk<T>(r: EverfurResult<T>): r is {
21
+ readonly ok: true;
22
+ readonly value: T;
23
+ readonly warning?: EverfurError;
24
+ };
25
+ /** Narrowing guard: true iff the result is a failure. */
26
+ declare function isErr<T>(r: EverfurResult<T>): r is {
27
+ readonly ok: false;
28
+ readonly error: EverfurError;
29
+ };
30
+ /**
31
+ * The real `Error` subclass `unwrap` throws, so an imperative call site that lets the throw escape
32
+ * produces a proper Error rather than a bare object (which a crash reporter files as
33
+ * "Non-Error exception captured", with no stack and no grouping).
34
+ *
35
+ * `message` is built from the normalized `code` and the frozen, product-owned `displayMessage` ONLY.
36
+ * The untrusted `wireMessage` is deliberately NOT in it: `message` is the one field every telemetry
37
+ * vendor captures and indexes by default, so putting wire text there would make an untrusted,
38
+ * healthcare-adjacent string flow automatically into a partner's third-party tooling. The full
39
+ * `EverfurError` hangs off `.error`, where `wireMessage` and `raw` remain non-enumerable.
40
+ */
41
+ declare class EverfurThrownError extends Error {
42
+ /** The settled error this was thrown from. Its `wireMessage` / `raw` stay non-enumerable. */
43
+ readonly error: EverfurError;
44
+ /** Mirror of `error.code`, so a catch block can branch without reaching through `.error`. */
45
+ readonly code: EverfurError['code'];
46
+ /** Mirror of `error.category`, the coarse branching axis. */
47
+ readonly category: EverfurError['category'];
48
+ constructor(error: EverfurError);
49
+ }
50
+ /**
51
+ * Escape hatch for imperative callers: return the value or throw. The throw is an `EverfurThrownError`
52
+ * (a real `Error`, safe message); the settled `EverfurError` is on its `.error`.
53
+ * Prefer pattern-matching on `ok`; `unwrap` exists for call sites that want the throw.
54
+ */
55
+ declare function unwrap<T>(r: EverfurResult<T>): T;
56
+ /**
57
+ * Thrown SYNCHRONOUSLY for programmer error ONLY, never for a network or domain failure.
58
+ * Mirrors Flutter `_requireInitialized` (a real guard, not an assert).
59
+ *
60
+ * - `not-initialized` , a capability used before EverfurProvider mounted / init ran.
61
+ * - `invalid-argument` , a malformed id or option shape (e.g. a non-UUID conversation id).
62
+ * - `missing-peer-dependency`, a capability subpath used without its required native peer dep.
63
+ */
64
+ declare class EverfurConfigError extends Error {
65
+ readonly kind: 'not-initialized' | 'invalid-argument' | 'missing-peer-dependency';
66
+ constructor(kind: 'not-initialized' | 'invalid-argument' | 'missing-peer-dependency', message: string);
67
+ }
68
+
69
+ export { type EverfurResult as E, EverfurConfigError as a, EverfurThrownError as b, isOk as c, err as e, isErr as i, ok as o, unwrap as u };
@@ -0,0 +1,69 @@
1
+ import { E as EverfurError } from './EverfurError-DmELDpXp.cjs';
2
+
3
+ /**
4
+ * The settle type. An async public operation returns this instead of throwing for an EXPECTED failure.
5
+ * A successful result may carry a non-fatal `warning` (e.g. served-stale, degraded path).
6
+ */
7
+ type EverfurResult<T> = {
8
+ readonly ok: true;
9
+ readonly value: T;
10
+ readonly warning?: EverfurError;
11
+ } | {
12
+ readonly ok: false;
13
+ readonly error: EverfurError;
14
+ };
15
+ /** Construct a success result. Frozen, public state is immutable end to end. */
16
+ declare function ok<T>(value: T, warning?: EverfurError): EverfurResult<T>;
17
+ /** Construct a failure result. Frozen. */
18
+ declare function err<T = never>(error: EverfurError): EverfurResult<T>;
19
+ /** Narrowing guard: true iff the result is a success. */
20
+ declare function isOk<T>(r: EverfurResult<T>): r is {
21
+ readonly ok: true;
22
+ readonly value: T;
23
+ readonly warning?: EverfurError;
24
+ };
25
+ /** Narrowing guard: true iff the result is a failure. */
26
+ declare function isErr<T>(r: EverfurResult<T>): r is {
27
+ readonly ok: false;
28
+ readonly error: EverfurError;
29
+ };
30
+ /**
31
+ * The real `Error` subclass `unwrap` throws, so an imperative call site that lets the throw escape
32
+ * produces a proper Error rather than a bare object (which a crash reporter files as
33
+ * "Non-Error exception captured", with no stack and no grouping).
34
+ *
35
+ * `message` is built from the normalized `code` and the frozen, product-owned `displayMessage` ONLY.
36
+ * The untrusted `wireMessage` is deliberately NOT in it: `message` is the one field every telemetry
37
+ * vendor captures and indexes by default, so putting wire text there would make an untrusted,
38
+ * healthcare-adjacent string flow automatically into a partner's third-party tooling. The full
39
+ * `EverfurError` hangs off `.error`, where `wireMessage` and `raw` remain non-enumerable.
40
+ */
41
+ declare class EverfurThrownError extends Error {
42
+ /** The settled error this was thrown from. Its `wireMessage` / `raw` stay non-enumerable. */
43
+ readonly error: EverfurError;
44
+ /** Mirror of `error.code`, so a catch block can branch without reaching through `.error`. */
45
+ readonly code: EverfurError['code'];
46
+ /** Mirror of `error.category`, the coarse branching axis. */
47
+ readonly category: EverfurError['category'];
48
+ constructor(error: EverfurError);
49
+ }
50
+ /**
51
+ * Escape hatch for imperative callers: return the value or throw. The throw is an `EverfurThrownError`
52
+ * (a real `Error`, safe message); the settled `EverfurError` is on its `.error`.
53
+ * Prefer pattern-matching on `ok`; `unwrap` exists for call sites that want the throw.
54
+ */
55
+ declare function unwrap<T>(r: EverfurResult<T>): T;
56
+ /**
57
+ * Thrown SYNCHRONOUSLY for programmer error ONLY, never for a network or domain failure.
58
+ * Mirrors Flutter `_requireInitialized` (a real guard, not an assert).
59
+ *
60
+ * - `not-initialized` , a capability used before EverfurProvider mounted / init ran.
61
+ * - `invalid-argument` , a malformed id or option shape (e.g. a non-UUID conversation id).
62
+ * - `missing-peer-dependency`, a capability subpath used without its required native peer dep.
63
+ */
64
+ declare class EverfurConfigError extends Error {
65
+ readonly kind: 'not-initialized' | 'invalid-argument' | 'missing-peer-dependency';
66
+ constructor(kind: 'not-initialized' | 'invalid-argument' | 'missing-peer-dependency', message: string);
67
+ }
68
+
69
+ export { type EverfurResult as E, EverfurConfigError as a, EverfurThrownError as b, isOk as c, err as e, isErr as i, ok as o, unwrap as u };