portal-mojo 0.1.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 (369) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +55 -0
  3. package/docs/DetailView.md +173 -0
  4. package/docs/ModelTable.md +128 -0
  5. package/docs/README.md +98 -0
  6. package/docs/admin-assistant.md +72 -0
  7. package/docs/admin-bouncer.md +120 -0
  8. package/docs/admin-cloudwatch.md +38 -0
  9. package/docs/admin-credentials.md +116 -0
  10. package/docs/admin-dashboard.md +15 -0
  11. package/docs/admin-devices-geoip.md +284 -0
  12. package/docs/admin-dns-certificates.md +122 -0
  13. package/docs/admin-dns-records.md +65 -0
  14. package/docs/admin-dns-registrar.md +33 -0
  15. package/docs/admin-dns.md +80 -0
  16. package/docs/admin-identity-users.md +103 -0
  17. package/docs/admin-incidents.md +71 -0
  18. package/docs/admin-jobs.md +426 -0
  19. package/docs/admin-members.md +112 -0
  20. package/docs/admin-messaging.md +56 -0
  21. package/docs/admin-metrics-explorer.md +63 -0
  22. package/docs/admin-monitoring.md +99 -0
  23. package/docs/admin-network-security.md +393 -0
  24. package/docs/admin-phonehub.md +27 -0
  25. package/docs/admin-push.md +36 -0
  26. package/docs/admin-rules.md +87 -0
  27. package/docs/admin-security-tickets.md +40 -0
  28. package/docs/admin-settings.md +78 -0
  29. package/docs/admin-shortlinks.md +32 -0
  30. package/docs/admin-storage.md +141 -0
  31. package/docs/auth-pages.md +212 -0
  32. package/docs/auth.md +58 -0
  33. package/docs/calendar.md +122 -0
  34. package/docs/charts.md +303 -0
  35. package/docs/client.md +206 -0
  36. package/docs/collection-multiselect.md +117 -0
  37. package/docs/collection-select.md +132 -0
  38. package/docs/combobox.md +105 -0
  39. package/docs/dataview.md +226 -0
  40. package/docs/datepicker.md +151 -0
  41. package/docs/daterange.md +170 -0
  42. package/docs/datetimepicker.md +249 -0
  43. package/docs/defineModel.md +72 -0
  44. package/docs/detail-primitives.md +174 -0
  45. package/docs/feedback.md +85 -0
  46. package/docs/file-upload-ux.md +146 -0
  47. package/docs/forms.md +435 -0
  48. package/docs/grouping-and-fmt.md +98 -0
  49. package/docs/idioms.md +112 -0
  50. package/docs/image-editor.md +101 -0
  51. package/docs/loading.md +242 -0
  52. package/docs/location-address.md +76 -0
  53. package/docs/markdown.md +203 -0
  54. package/docs/menus-and-access.md +89 -0
  55. package/docs/multiselect-dropdown.md +153 -0
  56. package/docs/params.md +73 -0
  57. package/docs/popover.md +130 -0
  58. package/docs/realtime.md +61 -0
  59. package/docs/record-feed.md +238 -0
  60. package/docs/right-panel.md +42 -0
  61. package/docs/tabs-and-form-wizard.md +60 -0
  62. package/docs/taginput.md +120 -0
  63. package/docs/timepicker.md +173 -0
  64. package/docs/timezone-select.md +147 -0
  65. package/docs/worldmap.md +302 -0
  66. package/package.json +55 -0
  67. package/src/admin/assistant/AssistantFeed.tsx +29 -0
  68. package/src/admin/assistant/AssistantPanel.tsx +65 -0
  69. package/src/admin/assistant/api.ts +17 -0
  70. package/src/admin/assistant/data.ts +63 -0
  71. package/src/admin/assistant/index.ts +21 -0
  72. package/src/admin/assistant/launchers.tsx +33 -0
  73. package/src/admin/assistant/pages.tsx +78 -0
  74. package/src/admin/assistant/streaming.ts +238 -0
  75. package/src/admin/assistant/types.ts +30 -0
  76. package/src/admin/bouncer/devices.tsx +230 -0
  77. package/src/admin/bouncer/index.ts +34 -0
  78. package/src/admin/bouncer/models.ts +199 -0
  79. package/src/admin/bouncer/signals.tsx +182 -0
  80. package/src/admin/bouncer/signatures.tsx +220 -0
  81. package/src/admin/cloudwatch/CloudWatchChart.tsx +61 -0
  82. package/src/admin/cloudwatch/CloudWatchDashboardPage.tsx +52 -0
  83. package/src/admin/cloudwatch/CloudWatchResourceDetail.tsx +33 -0
  84. package/src/admin/cloudwatch/data.ts +163 -0
  85. package/src/admin/cloudwatch/index.ts +16 -0
  86. package/src/admin/credentials/group-api-keys.tsx +433 -0
  87. package/src/admin/credentials/index.ts +4 -0
  88. package/src/admin/credentials/models.ts +244 -0
  89. package/src/admin/credentials/secret-dialog.tsx +77 -0
  90. package/src/admin/credentials/webhook-subscriptions.tsx +423 -0
  91. package/src/admin/dashboard/AdminDashboardPage.tsx +101 -0
  92. package/src/admin/dashboard/data.ts +60 -0
  93. package/src/admin/dashboard/index.ts +2 -0
  94. package/src/admin/dns/CertificateDetail.tsx +115 -0
  95. package/src/admin/dns/CertificateLifecyclePoller.tsx +141 -0
  96. package/src/admin/dns/CertificateRequestDialog.tsx +103 -0
  97. package/src/admin/dns/CertificatesPage.tsx +85 -0
  98. package/src/admin/dns/DnsRecordEditor.tsx +110 -0
  99. package/src/admin/dns/DnsRecordsPage.tsx +36 -0
  100. package/src/admin/dns/DnsRecordsPanel.tsx +71 -0
  101. package/src/admin/dns/DomainCertificatesSection.tsx +40 -0
  102. package/src/admin/dns/DomainDetail.tsx +41 -0
  103. package/src/admin/dns/DomainOnboardingDialog.tsx +27 -0
  104. package/src/admin/dns/DomainPurchaseDetail.tsx +11 -0
  105. package/src/admin/dns/DomainPurchaseWizard.tsx +112 -0
  106. package/src/admin/dns/DomainPurchasesPage.tsx +16 -0
  107. package/src/admin/dns/DomainsPage.tsx +27 -0
  108. package/src/admin/dns/ProviderCredentialsPage.tsx +304 -0
  109. package/src/admin/dns/RegistrantContactPage.tsx +42 -0
  110. package/src/admin/dns/api.ts +515 -0
  111. package/src/admin/dns/certificate-data.ts +221 -0
  112. package/src/admin/dns/data.ts +32 -0
  113. package/src/admin/dns/dns-data.ts +266 -0
  114. package/src/admin/dns/dns-integration.ts +24 -0
  115. package/src/admin/dns/domain-links.ts +37 -0
  116. package/src/admin/dns/index.ts +86 -0
  117. package/src/admin/dns/models.ts +418 -0
  118. package/src/admin/dns/purchase-data.ts +67 -0
  119. package/src/admin/dns/registrant-data.ts +52 -0
  120. package/src/admin/identity/index.ts +5 -0
  121. package/src/admin/identity/members/GroupMembersPanel.tsx +146 -0
  122. package/src/admin/identity/members/MemberDetail.tsx +226 -0
  123. package/src/admin/identity/members/MembersPage.tsx +144 -0
  124. package/src/admin/identity/members/index.ts +24 -0
  125. package/src/admin/identity/members/member-flows.tsx +132 -0
  126. package/src/admin/identity/members/models.ts +204 -0
  127. package/src/admin/identity/users/UserDetail.tsx +257 -0
  128. package/src/admin/identity/users/UsersPage.tsx +163 -0
  129. package/src/admin/identity/users/index.ts +27 -0
  130. package/src/admin/identity/users/models.ts +232 -0
  131. package/src/admin/identity/users/sections/ApiKeysSection.tsx +119 -0
  132. package/src/admin/identity/users/sections/AuditSection.tsx +190 -0
  133. package/src/admin/identity/users/sections/DevicesSection.tsx +140 -0
  134. package/src/admin/identity/users/sections/GroupsSection.tsx +64 -0
  135. package/src/admin/identity/users/sections/LoginsSection.tsx +106 -0
  136. package/src/admin/identity/users/sections/MetadataPanel.tsx +36 -0
  137. package/src/admin/identity/users/sections/NotificationsSection.tsx +117 -0
  138. package/src/admin/identity/users/sections/OAuthSection.tsx +72 -0
  139. package/src/admin/identity/users/sections/OverviewSection.tsx +109 -0
  140. package/src/admin/identity/users/sections/PermissionsSection.tsx +35 -0
  141. package/src/admin/identity/users/sections/PersonalSection.tsx +73 -0
  142. package/src/admin/identity/users/sections/ProfileSection.tsx +175 -0
  143. package/src/admin/identity/users/sections/SecuritySection.tsx +123 -0
  144. package/src/admin/identity/users/sections/actions.tsx +752 -0
  145. package/src/admin/identity/users/sections/permission-catalog.ts +138 -0
  146. package/src/admin/identity/users/sections/queries.ts +74 -0
  147. package/src/admin/identity/users/sections/shared.tsx +299 -0
  148. package/src/admin/incidents/EventDetail.tsx +43 -0
  149. package/src/admin/incidents/EventsPage.tsx +52 -0
  150. package/src/admin/incidents/IncidentDetail.tsx +68 -0
  151. package/src/admin/incidents/IncidentsPage.tsx +102 -0
  152. package/src/admin/incidents/forensics.tsx +73 -0
  153. package/src/admin/incidents/index.ts +16 -0
  154. package/src/admin/incidents/models.ts +113 -0
  155. package/src/admin/incidents/sanitize.ts +71 -0
  156. package/src/admin/index.ts +383 -0
  157. package/src/admin/jobs/JobDashboardPage.tsx +111 -0
  158. package/src/admin/jobs/JobDetail.tsx +721 -0
  159. package/src/admin/jobs/JobRunnersPage.tsx +216 -0
  160. package/src/admin/jobs/JobsTablePage.tsx +122 -0
  161. package/src/admin/jobs/RunnerDetail.tsx +576 -0
  162. package/src/admin/jobs/ScheduledTaskDetail.tsx +421 -0
  163. package/src/admin/jobs/ScheduledTasksPage.tsx +167 -0
  164. package/src/admin/jobs/columns.tsx +297 -0
  165. package/src/admin/jobs/control.ts +488 -0
  166. package/src/admin/jobs/index.ts +85 -0
  167. package/src/admin/jobs/models.ts +599 -0
  168. package/src/admin/jobs/queries.ts +272 -0
  169. package/src/admin/jobs/scheduled-task-form.tsx +493 -0
  170. package/src/admin/jobs/sections/JobChannelsPanel.tsx +142 -0
  171. package/src/admin/jobs/sections/JobOperationsSection.tsx +423 -0
  172. package/src/admin/jobs/sections/JobRunnersStrip.tsx +82 -0
  173. package/src/admin/jobs/sections/JobThroughputSection.tsx +118 -0
  174. package/src/admin/messaging/EmailDomainWizard.tsx +24 -0
  175. package/src/admin/messaging/EmailDomainsPage.tsx +17 -0
  176. package/src/admin/messaging/EmailTemplatesPage.tsx +13 -0
  177. package/src/admin/messaging/MailboxesPage.tsx +15 -0
  178. package/src/admin/messaging/PublicMessagesPage.tsx +13 -0
  179. package/src/admin/messaging/SandboxedEmailPreview.tsx +23 -0
  180. package/src/admin/messaging/SentMessagesPage.tsx +11 -0
  181. package/src/admin/messaging/api.ts +17 -0
  182. package/src/admin/messaging/data.ts +10 -0
  183. package/src/admin/messaging/index.ts +23 -0
  184. package/src/admin/messaging/models.ts +76 -0
  185. package/src/admin/messaging/push/PushPage.tsx +44 -0
  186. package/src/admin/messaging/push/api.ts +17 -0
  187. package/src/admin/messaging/push/index.ts +9 -0
  188. package/src/admin/messaging/push/models.ts +43 -0
  189. package/src/admin/messaging/sanitize.ts +44 -0
  190. package/src/admin/monitoring/LogInspector.tsx +160 -0
  191. package/src/admin/monitoring/LogsPage.tsx +135 -0
  192. package/src/admin/monitoring/MetricsExplorerPage.tsx +360 -0
  193. package/src/admin/monitoring/MetricsPermissionsPage.tsx +166 -0
  194. package/src/admin/monitoring/MetricsSourcePicker.tsx +136 -0
  195. package/src/admin/monitoring/index.ts +55 -0
  196. package/src/admin/monitoring/metrics-explorer-client.ts +229 -0
  197. package/src/admin/monitoring/metrics-explorer-data.ts +158 -0
  198. package/src/admin/monitoring/models.ts +155 -0
  199. package/src/admin/network/BlockedIPsPage.tsx +194 -0
  200. package/src/admin/network/BlockedIpDetail.tsx +262 -0
  201. package/src/admin/network/FirewallLogPage.tsx +115 -0
  202. package/src/admin/network/IPSetDetail.tsx +280 -0
  203. package/src/admin/network/IPSetEditor.tsx +191 -0
  204. package/src/admin/network/IPSetsPage.tsx +177 -0
  205. package/src/admin/network/geofence/BlocksTab.tsx +289 -0
  206. package/src/admin/network/geofence/ExemptionsTab.tsx +349 -0
  207. package/src/admin/network/geofence/GeofencingPage.tsx +119 -0
  208. package/src/admin/network/geofence/PostureHeader.tsx +184 -0
  209. package/src/admin/network/geofence/RuleEditor.tsx +176 -0
  210. package/src/admin/network/geofence/RulesTab.tsx +254 -0
  211. package/src/admin/network/geofence/SimulatorTab.tsx +281 -0
  212. package/src/admin/network/geofence/geofence-data.ts +674 -0
  213. package/src/admin/network/index.ts +68 -0
  214. package/src/admin/network/models.ts +607 -0
  215. package/src/admin/phonehub/PhoneHubPage.tsx +57 -0
  216. package/src/admin/phonehub/api.ts +47 -0
  217. package/src/admin/phonehub/data.ts +6 -0
  218. package/src/admin/phonehub/index.ts +10 -0
  219. package/src/admin/phonehub/models.ts +68 -0
  220. package/src/admin/rules/HandlerChainBuilder.tsx +51 -0
  221. package/src/admin/rules/RuleSetDetailPage.tsx +33 -0
  222. package/src/admin/rules/RuleSetsPage.tsx +33 -0
  223. package/src/admin/rules/editors.tsx +54 -0
  224. package/src/admin/rules/handler-dsl.ts +213 -0
  225. package/src/admin/rules/index.ts +13 -0
  226. package/src/admin/rules/models.ts +112 -0
  227. package/src/admin/security/devices/LoginEventDetail.tsx +123 -0
  228. package/src/admin/security/devices/LoginLocationMap.tsx +321 -0
  229. package/src/admin/security/devices/LoginLocationsPage.tsx +162 -0
  230. package/src/admin/security/devices/UserDeviceDetail.tsx +546 -0
  231. package/src/admin/security/devices/UserDeviceLocationDetail.tsx +272 -0
  232. package/src/admin/security/devices/UserDevicesPage.tsx +84 -0
  233. package/src/admin/security/devices/index.ts +40 -0
  234. package/src/admin/security/devices/models.ts +470 -0
  235. package/src/admin/security/geoip/GeoIpCachePage.tsx +135 -0
  236. package/src/admin/security/geoip/GeoIpDossier.tsx +804 -0
  237. package/src/admin/security/geoip/geoip-forms.ts +102 -0
  238. package/src/admin/security/geoip/index.ts +27 -0
  239. package/src/admin/security/geoip/models.ts +397 -0
  240. package/src/admin/security/index.ts +31 -0
  241. package/src/admin/security/models.ts +137 -0
  242. package/src/admin/security/tickets.tsx +562 -0
  243. package/src/admin/security-permissions.ts +5 -0
  244. package/src/admin/settings/SettingDetail.tsx +57 -0
  245. package/src/admin/settings/SettingEditor.tsx +157 -0
  246. package/src/admin/settings/SettingsPage.tsx +72 -0
  247. package/src/admin/settings/index.ts +19 -0
  248. package/src/admin/settings/model.ts +143 -0
  249. package/src/admin/shortlinks/ShortlinkDetail.tsx +55 -0
  250. package/src/admin/shortlinks/ShortlinkHistoryPage.tsx +18 -0
  251. package/src/admin/shortlinks/ShortlinksPage.tsx +59 -0
  252. package/src/admin/shortlinks/index.ts +18 -0
  253. package/src/admin/shortlinks/models.ts +246 -0
  254. package/src/admin/storage/BackendsPage.tsx +43 -0
  255. package/src/admin/storage/BucketDetail.tsx +77 -0
  256. package/src/admin/storage/BucketsPage.tsx +64 -0
  257. package/src/admin/storage/FileManagerDetail.tsx +36 -0
  258. package/src/admin/storage/FilePreview.tsx +54 -0
  259. package/src/admin/storage/FileUploadSurface.tsx +250 -0
  260. package/src/admin/storage/FileView.tsx +109 -0
  261. package/src/admin/storage/FilesPage.tsx +53 -0
  262. package/src/admin/storage/file-renditions.ts +99 -0
  263. package/src/admin/storage/index.ts +31 -0
  264. package/src/admin/storage/models.ts +585 -0
  265. package/src/admin/storage/storage-dialogs.tsx +80 -0
  266. package/src/charts/CircularProgress.tsx +281 -0
  267. package/src/charts/KPIStrip.tsx +162 -0
  268. package/src/charts/KPITile.tsx +125 -0
  269. package/src/charts/MetricsChart.tsx +459 -0
  270. package/src/charts/MetricsMiniWidget.tsx +588 -0
  271. package/src/charts/MiniChart.tsx +283 -0
  272. package/src/charts/PieChart.tsx +354 -0
  273. package/src/charts/SeriesChart.tsx +378 -0
  274. package/src/charts/chart-dialogs.tsx +149 -0
  275. package/src/charts/exportChart.ts +144 -0
  276. package/src/charts/index.ts +28 -0
  277. package/src/charts/pie-math.ts +127 -0
  278. package/src/charts/stats.ts +265 -0
  279. package/src/charts/worldmap/WorldMap.tsx +649 -0
  280. package/src/charts/worldmap/countryCentroids.ts +304 -0
  281. package/src/charts/worldmap/geo.ts +293 -0
  282. package/src/charts/worldmap/use-world-land.ts +47 -0
  283. package/src/charts/worldmap/world-land.ts +18 -0
  284. package/src/charts/worldmap/worldmap-data.ts +285 -0
  285. package/src/client/auth.ts +737 -0
  286. package/src/client/client.ts +268 -0
  287. package/src/client/duid.ts +31 -0
  288. package/src/client/errors.ts +33 -0
  289. package/src/client/group-context.ts +28 -0
  290. package/src/client/group.tsx +126 -0
  291. package/src/client/hooks.ts +50 -0
  292. package/src/client/index.ts +37 -0
  293. package/src/client/jwt.ts +75 -0
  294. package/src/client/location.ts +285 -0
  295. package/src/client/lookups.ts +41 -0
  296. package/src/client/markdown-fallback.tsx +115 -0
  297. package/src/client/markdown-parse.ts +386 -0
  298. package/src/client/markdown-sanitize.ts +217 -0
  299. package/src/client/markdown.ts +122 -0
  300. package/src/client/me.ts +188 -0
  301. package/src/client/mock.ts +9984 -0
  302. package/src/client/model.ts +227 -0
  303. package/src/client/params.ts +292 -0
  304. package/src/client/realtime-mock.ts +221 -0
  305. package/src/client/realtime.ts +561 -0
  306. package/src/client/record-feed.ts +329 -0
  307. package/src/client/safe-export.ts +71 -0
  308. package/src/client/types.ts +278 -0
  309. package/src/client/upload.ts +421 -0
  310. package/src/ui/AddressField.tsx +273 -0
  311. package/src/ui/AttachmentQueue.tsx +92 -0
  312. package/src/ui/CollectionMultiSelect.tsx +622 -0
  313. package/src/ui/CollectionSelect.tsx +517 -0
  314. package/src/ui/ComboBox.tsx +336 -0
  315. package/src/ui/DetailView.tsx +438 -0
  316. package/src/ui/FileDrop.tsx +194 -0
  317. package/src/ui/FileField.tsx +369 -0
  318. package/src/ui/FilterBar.tsx +269 -0
  319. package/src/ui/FormFields.tsx +77 -0
  320. package/src/ui/FormView.tsx +360 -0
  321. package/src/ui/FormWizard.tsx +336 -0
  322. package/src/ui/GroupSwitcher.tsx +202 -0
  323. package/src/ui/Guarded.tsx +16 -0
  324. package/src/ui/MarkdownView.tsx +89 -0
  325. package/src/ui/ModelTable.tsx +848 -0
  326. package/src/ui/MultiSelectDropdown.tsx +390 -0
  327. package/src/ui/Popover.tsx +204 -0
  328. package/src/ui/RecordFeed.tsx +627 -0
  329. package/src/ui/RequiresGroup.tsx +32 -0
  330. package/src/ui/RightPanel.tsx +107 -0
  331. package/src/ui/SidebarNav.tsx +330 -0
  332. package/src/ui/Tabs.tsx +161 -0
  333. package/src/ui/TagInput.tsx +381 -0
  334. package/src/ui/ThemeProvider.tsx +52 -0
  335. package/src/ui/UploadQueue.tsx +603 -0
  336. package/src/ui/armed-button.tsx +91 -0
  337. package/src/ui/date/Calendar.tsx +498 -0
  338. package/src/ui/date/DatePicker.tsx +289 -0
  339. package/src/ui/date/DateRangePicker.tsx +280 -0
  340. package/src/ui/date/DateTimePicker.tsx +587 -0
  341. package/src/ui/date/PresetRail.tsx +165 -0
  342. package/src/ui/date/TimePicker.tsx +624 -0
  343. package/src/ui/date/TimezoneSelect.tsx +267 -0
  344. package/src/ui/date/fns.ts +679 -0
  345. package/src/ui/detail/DataView.tsx +692 -0
  346. package/src/ui/detail/FlowStrip.tsx +80 -0
  347. package/src/ui/detail/KnownFieldsCard.tsx +121 -0
  348. package/src/ui/detail/MetadataSection.tsx +219 -0
  349. package/src/ui/detail/StackTraceView.tsx +150 -0
  350. package/src/ui/detail/StatusPanel.tsx +73 -0
  351. package/src/ui/detail/Timeline.tsx +52 -0
  352. package/src/ui/detail/index.ts +12 -0
  353. package/src/ui/field-registry.tsx +428 -0
  354. package/src/ui/field-wire.ts +322 -0
  355. package/src/ui/form-autosave.ts +583 -0
  356. package/src/ui/format.ts +444 -0
  357. package/src/ui/grouping.ts +150 -0
  358. package/src/ui/image-editor/ImageEditor.tsx +484 -0
  359. package/src/ui/image-editor/canvas.ts +254 -0
  360. package/src/ui/image-editor/index.ts +3 -0
  361. package/src/ui/image-editor/math.ts +416 -0
  362. package/src/ui/index.ts +58 -0
  363. package/src/ui/loading.tsx +604 -0
  364. package/src/ui/menu-registry.ts +213 -0
  365. package/src/ui/modal.tsx +297 -0
  366. package/src/ui/password.tsx +302 -0
  367. package/src/ui/schema-form-core.tsx +315 -0
  368. package/src/ui/toast.tsx +219 -0
  369. package/src/ui/ui.tsx +45 -0
@@ -0,0 +1,221 @@
1
+ import type { RealtimeSocket, RealtimeSocketFactory } from './realtime';
2
+
3
+ export type RealtimeMockAuthMode = 'success' | 'fail-open';
4
+
5
+ export interface RealtimeMockOptions {
6
+ autoOpen?: boolean;
7
+ autoAuthRequired?: boolean;
8
+ autoPong?: boolean;
9
+ authMode?: RealtimeMockAuthMode;
10
+ deniedTopics?: readonly string[];
11
+ userId?: number;
12
+ autoAssistant?: boolean;
13
+ }
14
+
15
+ export interface RealtimeMockObservation {
16
+ connection: number;
17
+ kind: 'authenticate' | 'topic' | 'ping' | 'assistant';
18
+ action?: string;
19
+ topic?: string;
20
+ hasToken?: boolean;
21
+ conversationId?: number | null;
22
+ messageLength?: number;
23
+ }
24
+
25
+ class MemoryRealtimeSocket implements RealtimeSocket {
26
+ readyState = 0;
27
+ onopen: ((event: unknown) => void) | null = null;
28
+ onmessage: ((event: { data: unknown }) => void) | null = null;
29
+ onerror: ((event: unknown) => void) | null = null;
30
+ onclose: ((event: { code: number; reason?: string; wasClean?: boolean }) => void) | null = null;
31
+ readonly topics = new Set<string>();
32
+ authenticated = false;
33
+ closed = false;
34
+
35
+ constructor(readonly id: number, private readonly server: RealtimeMockServer) {}
36
+
37
+ send(data: string): void {
38
+ if (this.readyState !== 1) throw new Error('Mock socket is not open');
39
+ this.server.receive(this, data);
40
+ }
41
+
42
+ close(code = 1000, reason = ''): void {
43
+ this.server.close(this, code, reason, true);
44
+ }
45
+
46
+ open(): void {
47
+ if (this.closed || this.readyState !== 0) return;
48
+ this.readyState = 1;
49
+ this.onopen?.({});
50
+ }
51
+
52
+ frame(value: Record<string, unknown>): void {
53
+ if (this.readyState === 1) this.onmessage?.({ data: JSON.stringify(value) });
54
+ }
55
+ }
56
+
57
+ export class RealtimeMockServer {
58
+ readonly sockets: MemoryRealtimeSocket[] = [];
59
+ readonly observations: RealtimeMockObservation[] = [];
60
+ readonly factory: RealtimeSocketFactory;
61
+ autoPong: boolean;
62
+ authMode: RealtimeMockAuthMode;
63
+ readonly deniedTopics: Set<string>;
64
+ private nextConversationId = 9000;
65
+ private nextMessageId = 9500;
66
+ private timestamp = 1_800_000_000;
67
+ private readonly autoOpen: boolean;
68
+ private readonly autoAuthRequired: boolean;
69
+ private readonly userId: number;
70
+ private readonly autoAssistant: boolean;
71
+
72
+ constructor(options: RealtimeMockOptions = {}) {
73
+ this.autoOpen = options.autoOpen !== false;
74
+ this.autoAuthRequired = options.autoAuthRequired !== false;
75
+ this.autoPong = options.autoPong !== false;
76
+ this.authMode = options.authMode ?? 'success';
77
+ this.deniedTopics = new Set(options.deniedTopics ?? []);
78
+ this.userId = options.userId ?? 14;
79
+ this.autoAssistant = options.autoAssistant !== false;
80
+ this.factory = (_url) => {
81
+ const socket = new MemoryRealtimeSocket(this.sockets.length + 1, this);
82
+ this.sockets.push(socket);
83
+ if (this.autoOpen) queueMicrotask(() => {
84
+ socket.open();
85
+ if (this.autoAuthRequired) socket.frame({ type: 'auth_required', timeout: 10 });
86
+ });
87
+ return socket;
88
+ };
89
+ }
90
+
91
+ get activeConnections(): number {
92
+ return this.sockets.filter((socket) => socket.readyState === 1).length;
93
+ }
94
+
95
+ open(connection?: number): void {
96
+ for (const socket of this.select(connection)) socket.open();
97
+ }
98
+
99
+ authRequired(connection?: number): void {
100
+ for (const socket of this.select(connection)) socket.frame({ type: 'auth_required', timeout: 10 });
101
+ }
102
+
103
+ authSuccess(connection?: number): void {
104
+ for (const socket of this.select(connection)) {
105
+ socket.authenticated = true;
106
+ socket.frame({ type: 'auth_success', user_type: 'user', user_id: this.userId });
107
+ }
108
+ }
109
+
110
+ authFailureLeftOpen(connection?: number): void {
111
+ for (const socket of this.select(connection)) socket.frame({ type: 'error', message: 'Authentication failed' });
112
+ }
113
+
114
+ preacceptRateLimit(connection?: number): void {
115
+ for (const socket of this.select(connection)) this.close(socket, 4429, '', false);
116
+ }
117
+
118
+ wrapped(data: Record<string, unknown>, topic?: string, connection?: number): void {
119
+ for (const socket of this.select(connection)) socket.frame({
120
+ type: 'message', data, timestamp: ++this.timestamp, ...(topic ? { topic } : {}),
121
+ });
122
+ }
123
+
124
+ direct(data: Record<string, unknown>, connection?: number): void {
125
+ for (const socket of this.select(connection)) socket.frame(data);
126
+ }
127
+
128
+ pong(connection?: number): void {
129
+ for (const socket of this.select(connection)) socket.frame({ type: 'pong', user_type: 'user', user_id: this.userId });
130
+ }
131
+
132
+ forceDisconnect(connection?: number): void {
133
+ this.wrapped({ type: 'disconnect', reason: 'forced_disconnect' }, undefined, connection);
134
+ }
135
+
136
+ finishAssistant(conversationId: number, response = 'The deterministic realtime response is ready.', connection?: number): void {
137
+ this.direct({
138
+ type: 'assistant_response', conversation_id: conversationId,
139
+ message_id: ++this.nextMessageId, created: new Date(this.timestamp * 1000).toISOString(),
140
+ response, blocks: null, tool_calls_made: [{ tool: 'mock_private_tool', input: { withheld: true } }],
141
+ duration_ms: 250,
142
+ }, connection);
143
+ }
144
+
145
+ failAssistant(conversationId: number, connection?: number): void {
146
+ this.direct({ type: 'assistant_error', conversation_id: conversationId, error: 'Deterministic Assistant failure' }, connection);
147
+ }
148
+
149
+ assistantLifecycle(conversationId: number, connection?: number, wrapped = false): void {
150
+ const deliver = (event: Record<string, unknown>) => wrapped ? this.wrapped(event, undefined, connection) : this.direct(event, connection);
151
+ deliver({ type: 'assistant_thinking', conversation_id: conversationId });
152
+ deliver({ type: 'assistant_text', conversation_id: conversationId, text: 'Checking the bounded mock plan.', blocks: null });
153
+ deliver({ type: 'assistant_tool_call', conversation_id: conversationId, tool: 'query_health', input: { private: 'never observed or projected' } });
154
+ deliver({ type: 'assistant_plan', conversation_id: conversationId, plan: { plan_id: 'mock-plan', title: 'Health check', steps: [{ id: 1, description: 'Check health', status: 'pending', parallel: false, tool: 'query_health', tool_input: { private: true } }] } });
155
+ deliver({ type: 'assistant_plan_update', conversation_id: conversationId, plan_id: 'mock-plan', step_id: 1, status: 'done', summary: 'Healthy' });
156
+ deliver({ type: 'assistant_response', conversation_id: conversationId, message_id: ++this.nextMessageId, created: new Date(this.timestamp * 1000).toISOString(), response: 'The deterministic realtime response is ready.', blocks: null, tool_calls_made: [{ tool: 'query_health', input: { private: true } }], duration_ms: 250 });
157
+ }
158
+
159
+ clearObservations(): void {
160
+ this.observations.length = 0;
161
+ }
162
+
163
+ receive(socket: MemoryRealtimeSocket, raw: string): void {
164
+ let message: Record<string, unknown>;
165
+ try {
166
+ const value = JSON.parse(raw) as unknown;
167
+ if (value == null || typeof value !== 'object' || Array.isArray(value)) return;
168
+ message = value as Record<string, unknown>;
169
+ } catch { return; }
170
+ const type = typeof message.type === 'string' ? message.type : typeof message.action === 'string' ? message.action : '';
171
+ if (type === 'authenticate') {
172
+ this.observations.push({ connection: socket.id, kind: 'authenticate', hasToken: typeof message.token === 'string' && message.token.length > 0 });
173
+ if (this.authMode === 'success') this.authSuccess(socket.id);
174
+ else this.authFailureLeftOpen(socket.id);
175
+ return;
176
+ }
177
+ if (type === 'ping') {
178
+ this.observations.push({ connection: socket.id, kind: 'ping' });
179
+ if (this.autoPong) this.pong(socket.id);
180
+ return;
181
+ }
182
+ if (type === 'subscribe' || type === 'unsubscribe') {
183
+ const topic = typeof message.topic === 'string' ? message.topic : '';
184
+ this.observations.push({ connection: socket.id, kind: 'topic', action: type, topic });
185
+ if (type === 'subscribe' && this.deniedTopics.has(topic)) {
186
+ socket.frame({ type: 'error', message: `Access denied to topic: ${topic}` });
187
+ } else {
188
+ if (type === 'subscribe') socket.topics.add(topic); else socket.topics.delete(topic);
189
+ socket.frame({ type: type === 'subscribe' ? 'subscribed' : 'unsubscribed', topic });
190
+ }
191
+ return;
192
+ }
193
+ if (type === 'assistant_message' || type === 'assistant_action') {
194
+ const conversationId = typeof message.conversation_id === 'number' ? message.conversation_id : ++this.nextConversationId;
195
+ const text = type === 'assistant_action' ? message.value : message.message;
196
+ this.observations.push({
197
+ connection: socket.id, kind: 'assistant', action: type,
198
+ conversationId: typeof message.conversation_id === 'number' ? message.conversation_id : null,
199
+ messageLength: typeof text === 'string' ? text.length : 0,
200
+ });
201
+ if (!this.autoAssistant) return;
202
+ socket.frame({ type: 'assistant_thinking', conversation_id: conversationId });
203
+ queueMicrotask(() => this.finishAssistant(conversationId, undefined, socket.id));
204
+ }
205
+ }
206
+
207
+ close(socket: MemoryRealtimeSocket, code: number, reason: string, wasClean: boolean): void {
208
+ if (socket.closed) return;
209
+ socket.closed = true;
210
+ socket.readyState = 3;
211
+ socket.onclose?.({ code, reason, wasClean });
212
+ }
213
+
214
+ private select(connection?: number): MemoryRealtimeSocket[] {
215
+ return connection == null ? this.sockets.filter((socket) => !socket.closed) : this.sockets.filter((socket) => socket.id === connection && !socket.closed);
216
+ }
217
+ }
218
+
219
+ export function createRealtimeMock(options: RealtimeMockOptions = {}): RealtimeMockServer {
220
+ return new RealtimeMockServer(options);
221
+ }