birdclaw 0.6.0 → 0.8.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 (62) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +32 -2
  3. package/package.json +29 -30
  4. package/scripts/build-docs-site.mjs +39 -12
  5. package/src/cli.ts +457 -26
  6. package/src/components/AppNav.tsx +10 -0
  7. package/src/components/MarkdownViewer.tsx +438 -72
  8. package/src/components/ProfileAnalysisStream.tsx +428 -0
  9. package/src/components/ProfilePreview.tsx +120 -9
  10. package/src/components/SavedTimelineView.tsx +30 -8
  11. package/src/components/SyncNowButton.tsx +5 -2
  12. package/src/components/TimelineCard.tsx +20 -4
  13. package/src/components/TimelineRouteFrame.tsx +16 -0
  14. package/src/components/TweetRichText.tsx +36 -12
  15. package/src/components/useTimelineRouteData.ts +74 -6
  16. package/src/lib/account-sync-job.ts +15 -3
  17. package/src/lib/archive-finder.ts +1 -1
  18. package/src/lib/archive-import.ts +245 -7
  19. package/src/lib/authored-live.ts +1 -0
  20. package/src/lib/avatar-cache.ts +50 -0
  21. package/src/lib/backup.ts +4 -3
  22. package/src/lib/bird.ts +33 -0
  23. package/src/lib/config.ts +35 -2
  24. package/src/lib/data-sources.ts +219 -0
  25. package/src/lib/db.ts +62 -1
  26. package/src/lib/geocoding.ts +296 -0
  27. package/src/lib/link-insights.ts +2 -0
  28. package/src/lib/location.ts +137 -0
  29. package/src/lib/mention-threads-live.ts +94 -1
  30. package/src/lib/mentions-live.ts +187 -40
  31. package/src/lib/network-map.ts +382 -0
  32. package/src/lib/period-digest.ts +468 -29
  33. package/src/lib/profile-analysis.ts +1272 -0
  34. package/src/lib/profile-bio-entities.ts +1 -1
  35. package/src/lib/queries.ts +14 -4
  36. package/src/lib/search-discussion.ts +1016 -0
  37. package/src/lib/timeline-live.ts +272 -19
  38. package/src/lib/tweet-account-edges.ts +2 -0
  39. package/src/lib/tweet-render.ts +141 -1
  40. package/src/lib/tweet-search-live.ts +565 -0
  41. package/src/lib/types.ts +37 -2
  42. package/src/lib/ui.ts +1 -1
  43. package/src/lib/web-sync.ts +7 -2
  44. package/src/lib/xurl-rate-limits.ts +267 -0
  45. package/src/lib/xurl.ts +551 -41
  46. package/src/routeTree.gen.ts +231 -0
  47. package/src/routes/__root.tsx +5 -6
  48. package/src/routes/api/data-sources.tsx +24 -0
  49. package/src/routes/api/network-map.tsx +55 -0
  50. package/src/routes/api/period-digest.tsx +29 -3
  51. package/src/routes/api/profile-analysis.tsx +152 -0
  52. package/src/routes/api/query.tsx +1 -0
  53. package/src/routes/api/search-discussion.tsx +169 -0
  54. package/src/routes/api/xurl-rate-limits.tsx +24 -0
  55. package/src/routes/data-sources.tsx +257 -0
  56. package/src/routes/discuss.tsx +419 -0
  57. package/src/routes/network-map.tsx +1035 -0
  58. package/src/routes/profile-analyze.tsx +112 -0
  59. package/src/routes/profiles.$handle.tsx +228 -0
  60. package/src/routes/rate-limits.tsx +309 -0
  61. package/src/routes/today.tsx +22 -8
  62. package/src/styles.css +22 -0
@@ -10,22 +10,33 @@
10
10
 
11
11
  import { Route as rootRouteImport } from './routes/__root'
12
12
  import { Route as TodayRouteImport } from './routes/today'
13
+ import { Route as RateLimitsRouteImport } from './routes/rate-limits'
14
+ import { Route as ProfileAnalyzeRouteImport } from './routes/profile-analyze'
15
+ import { Route as NetworkMapRouteImport } from './routes/network-map'
13
16
  import { Route as MentionsRouteImport } from './routes/mentions'
14
17
  import { Route as LinksRouteImport } from './routes/links'
15
18
  import { Route as LikesRouteImport } from './routes/likes'
16
19
  import { Route as InboxRouteImport } from './routes/inbox'
17
20
  import { Route as DmsRouteImport } from './routes/dms'
21
+ import { Route as DiscussRouteImport } from './routes/discuss'
22
+ import { Route as DataSourcesRouteImport } from './routes/data-sources'
18
23
  import { Route as BookmarksRouteImport } from './routes/bookmarks'
19
24
  import { Route as BlocksRouteImport } from './routes/blocks'
20
25
  import { Route as IndexRouteImport } from './routes/index'
26
+ import { Route as ProfilesHandleRouteImport } from './routes/profiles.$handle'
27
+ import { Route as ApiXurlRateLimitsRouteImport } from './routes/api/xurl-rate-limits'
21
28
  import { Route as ApiSyncRouteImport } from './routes/api/sync'
22
29
  import { Route as ApiStatusRouteImport } from './routes/api/status'
30
+ import { Route as ApiSearchDiscussionRouteImport } from './routes/api/search-discussion'
23
31
  import { Route as ApiQueryRouteImport } from './routes/api/query'
24
32
  import { Route as ApiProfileHydrateRouteImport } from './routes/api/profile-hydrate'
33
+ import { Route as ApiProfileAnalysisRouteImport } from './routes/api/profile-analysis'
25
34
  import { Route as ApiPeriodDigestRouteImport } from './routes/api/period-digest'
35
+ import { Route as ApiNetworkMapRouteImport } from './routes/api/network-map'
26
36
  import { Route as ApiLinkPreviewRouteImport } from './routes/api/link-preview'
27
37
  import { Route as ApiLinkInsightsRouteImport } from './routes/api/link-insights'
28
38
  import { Route as ApiInboxRouteImport } from './routes/api/inbox'
39
+ import { Route as ApiDataSourcesRouteImport } from './routes/api/data-sources'
29
40
  import { Route as ApiConversationRouteImport } from './routes/api/conversation'
30
41
  import { Route as ApiBlocksRouteImport } from './routes/api/blocks'
31
42
  import { Route as ApiAvatarRouteImport } from './routes/api/avatar'
@@ -36,6 +47,21 @@ const TodayRoute = TodayRouteImport.update({
36
47
  path: '/today',
37
48
  getParentRoute: () => rootRouteImport,
38
49
  } as any)
50
+ const RateLimitsRoute = RateLimitsRouteImport.update({
51
+ id: '/rate-limits',
52
+ path: '/rate-limits',
53
+ getParentRoute: () => rootRouteImport,
54
+ } as any)
55
+ const ProfileAnalyzeRoute = ProfileAnalyzeRouteImport.update({
56
+ id: '/profile-analyze',
57
+ path: '/profile-analyze',
58
+ getParentRoute: () => rootRouteImport,
59
+ } as any)
60
+ const NetworkMapRoute = NetworkMapRouteImport.update({
61
+ id: '/network-map',
62
+ path: '/network-map',
63
+ getParentRoute: () => rootRouteImport,
64
+ } as any)
39
65
  const MentionsRoute = MentionsRouteImport.update({
40
66
  id: '/mentions',
41
67
  path: '/mentions',
@@ -61,6 +87,16 @@ const DmsRoute = DmsRouteImport.update({
61
87
  path: '/dms',
62
88
  getParentRoute: () => rootRouteImport,
63
89
  } as any)
90
+ const DiscussRoute = DiscussRouteImport.update({
91
+ id: '/discuss',
92
+ path: '/discuss',
93
+ getParentRoute: () => rootRouteImport,
94
+ } as any)
95
+ const DataSourcesRoute = DataSourcesRouteImport.update({
96
+ id: '/data-sources',
97
+ path: '/data-sources',
98
+ getParentRoute: () => rootRouteImport,
99
+ } as any)
64
100
  const BookmarksRoute = BookmarksRouteImport.update({
65
101
  id: '/bookmarks',
66
102
  path: '/bookmarks',
@@ -76,6 +112,16 @@ const IndexRoute = IndexRouteImport.update({
76
112
  path: '/',
77
113
  getParentRoute: () => rootRouteImport,
78
114
  } as any)
115
+ const ProfilesHandleRoute = ProfilesHandleRouteImport.update({
116
+ id: '/profiles/$handle',
117
+ path: '/profiles/$handle',
118
+ getParentRoute: () => rootRouteImport,
119
+ } as any)
120
+ const ApiXurlRateLimitsRoute = ApiXurlRateLimitsRouteImport.update({
121
+ id: '/api/xurl-rate-limits',
122
+ path: '/api/xurl-rate-limits',
123
+ getParentRoute: () => rootRouteImport,
124
+ } as any)
79
125
  const ApiSyncRoute = ApiSyncRouteImport.update({
80
126
  id: '/api/sync',
81
127
  path: '/api/sync',
@@ -86,6 +132,11 @@ const ApiStatusRoute = ApiStatusRouteImport.update({
86
132
  path: '/api/status',
87
133
  getParentRoute: () => rootRouteImport,
88
134
  } as any)
135
+ const ApiSearchDiscussionRoute = ApiSearchDiscussionRouteImport.update({
136
+ id: '/api/search-discussion',
137
+ path: '/api/search-discussion',
138
+ getParentRoute: () => rootRouteImport,
139
+ } as any)
89
140
  const ApiQueryRoute = ApiQueryRouteImport.update({
90
141
  id: '/api/query',
91
142
  path: '/api/query',
@@ -96,11 +147,21 @@ const ApiProfileHydrateRoute = ApiProfileHydrateRouteImport.update({
96
147
  path: '/api/profile-hydrate',
97
148
  getParentRoute: () => rootRouteImport,
98
149
  } as any)
150
+ const ApiProfileAnalysisRoute = ApiProfileAnalysisRouteImport.update({
151
+ id: '/api/profile-analysis',
152
+ path: '/api/profile-analysis',
153
+ getParentRoute: () => rootRouteImport,
154
+ } as any)
99
155
  const ApiPeriodDigestRoute = ApiPeriodDigestRouteImport.update({
100
156
  id: '/api/period-digest',
101
157
  path: '/api/period-digest',
102
158
  getParentRoute: () => rootRouteImport,
103
159
  } as any)
160
+ const ApiNetworkMapRoute = ApiNetworkMapRouteImport.update({
161
+ id: '/api/network-map',
162
+ path: '/api/network-map',
163
+ getParentRoute: () => rootRouteImport,
164
+ } as any)
104
165
  const ApiLinkPreviewRoute = ApiLinkPreviewRouteImport.update({
105
166
  id: '/api/link-preview',
106
167
  path: '/api/link-preview',
@@ -116,6 +177,11 @@ const ApiInboxRoute = ApiInboxRouteImport.update({
116
177
  path: '/api/inbox',
117
178
  getParentRoute: () => rootRouteImport,
118
179
  } as any)
180
+ const ApiDataSourcesRoute = ApiDataSourcesRouteImport.update({
181
+ id: '/api/data-sources',
182
+ path: '/api/data-sources',
183
+ getParentRoute: () => rootRouteImport,
184
+ } as any)
119
185
  const ApiConversationRoute = ApiConversationRouteImport.update({
120
186
  id: '/api/conversation',
121
187
  path: '/api/conversation',
@@ -141,71 +207,104 @@ export interface FileRoutesByFullPath {
141
207
  '/': typeof IndexRoute
142
208
  '/blocks': typeof BlocksRoute
143
209
  '/bookmarks': typeof BookmarksRoute
210
+ '/data-sources': typeof DataSourcesRoute
211
+ '/discuss': typeof DiscussRoute
144
212
  '/dms': typeof DmsRoute
145
213
  '/inbox': typeof InboxRoute
146
214
  '/likes': typeof LikesRoute
147
215
  '/links': typeof LinksRoute
148
216
  '/mentions': typeof MentionsRoute
217
+ '/network-map': typeof NetworkMapRoute
218
+ '/profile-analyze': typeof ProfileAnalyzeRoute
219
+ '/rate-limits': typeof RateLimitsRoute
149
220
  '/today': typeof TodayRoute
150
221
  '/api/action': typeof ApiActionRoute
151
222
  '/api/avatar': typeof ApiAvatarRoute
152
223
  '/api/blocks': typeof ApiBlocksRoute
153
224
  '/api/conversation': typeof ApiConversationRoute
225
+ '/api/data-sources': typeof ApiDataSourcesRoute
154
226
  '/api/inbox': typeof ApiInboxRoute
155
227
  '/api/link-insights': typeof ApiLinkInsightsRoute
156
228
  '/api/link-preview': typeof ApiLinkPreviewRoute
229
+ '/api/network-map': typeof ApiNetworkMapRoute
157
230
  '/api/period-digest': typeof ApiPeriodDigestRoute
231
+ '/api/profile-analysis': typeof ApiProfileAnalysisRoute
158
232
  '/api/profile-hydrate': typeof ApiProfileHydrateRoute
159
233
  '/api/query': typeof ApiQueryRoute
234
+ '/api/search-discussion': typeof ApiSearchDiscussionRoute
160
235
  '/api/status': typeof ApiStatusRoute
161
236
  '/api/sync': typeof ApiSyncRoute
237
+ '/api/xurl-rate-limits': typeof ApiXurlRateLimitsRoute
238
+ '/profiles/$handle': typeof ProfilesHandleRoute
162
239
  }
163
240
  export interface FileRoutesByTo {
164
241
  '/': typeof IndexRoute
165
242
  '/blocks': typeof BlocksRoute
166
243
  '/bookmarks': typeof BookmarksRoute
244
+ '/data-sources': typeof DataSourcesRoute
245
+ '/discuss': typeof DiscussRoute
167
246
  '/dms': typeof DmsRoute
168
247
  '/inbox': typeof InboxRoute
169
248
  '/likes': typeof LikesRoute
170
249
  '/links': typeof LinksRoute
171
250
  '/mentions': typeof MentionsRoute
251
+ '/network-map': typeof NetworkMapRoute
252
+ '/profile-analyze': typeof ProfileAnalyzeRoute
253
+ '/rate-limits': typeof RateLimitsRoute
172
254
  '/today': typeof TodayRoute
173
255
  '/api/action': typeof ApiActionRoute
174
256
  '/api/avatar': typeof ApiAvatarRoute
175
257
  '/api/blocks': typeof ApiBlocksRoute
176
258
  '/api/conversation': typeof ApiConversationRoute
259
+ '/api/data-sources': typeof ApiDataSourcesRoute
177
260
  '/api/inbox': typeof ApiInboxRoute
178
261
  '/api/link-insights': typeof ApiLinkInsightsRoute
179
262
  '/api/link-preview': typeof ApiLinkPreviewRoute
263
+ '/api/network-map': typeof ApiNetworkMapRoute
180
264
  '/api/period-digest': typeof ApiPeriodDigestRoute
265
+ '/api/profile-analysis': typeof ApiProfileAnalysisRoute
181
266
  '/api/profile-hydrate': typeof ApiProfileHydrateRoute
182
267
  '/api/query': typeof ApiQueryRoute
268
+ '/api/search-discussion': typeof ApiSearchDiscussionRoute
183
269
  '/api/status': typeof ApiStatusRoute
184
270
  '/api/sync': typeof ApiSyncRoute
271
+ '/api/xurl-rate-limits': typeof ApiXurlRateLimitsRoute
272
+ '/profiles/$handle': typeof ProfilesHandleRoute
185
273
  }
186
274
  export interface FileRoutesById {
187
275
  __root__: typeof rootRouteImport
188
276
  '/': typeof IndexRoute
189
277
  '/blocks': typeof BlocksRoute
190
278
  '/bookmarks': typeof BookmarksRoute
279
+ '/data-sources': typeof DataSourcesRoute
280
+ '/discuss': typeof DiscussRoute
191
281
  '/dms': typeof DmsRoute
192
282
  '/inbox': typeof InboxRoute
193
283
  '/likes': typeof LikesRoute
194
284
  '/links': typeof LinksRoute
195
285
  '/mentions': typeof MentionsRoute
286
+ '/network-map': typeof NetworkMapRoute
287
+ '/profile-analyze': typeof ProfileAnalyzeRoute
288
+ '/rate-limits': typeof RateLimitsRoute
196
289
  '/today': typeof TodayRoute
197
290
  '/api/action': typeof ApiActionRoute
198
291
  '/api/avatar': typeof ApiAvatarRoute
199
292
  '/api/blocks': typeof ApiBlocksRoute
200
293
  '/api/conversation': typeof ApiConversationRoute
294
+ '/api/data-sources': typeof ApiDataSourcesRoute
201
295
  '/api/inbox': typeof ApiInboxRoute
202
296
  '/api/link-insights': typeof ApiLinkInsightsRoute
203
297
  '/api/link-preview': typeof ApiLinkPreviewRoute
298
+ '/api/network-map': typeof ApiNetworkMapRoute
204
299
  '/api/period-digest': typeof ApiPeriodDigestRoute
300
+ '/api/profile-analysis': typeof ApiProfileAnalysisRoute
205
301
  '/api/profile-hydrate': typeof ApiProfileHydrateRoute
206
302
  '/api/query': typeof ApiQueryRoute
303
+ '/api/search-discussion': typeof ApiSearchDiscussionRoute
207
304
  '/api/status': typeof ApiStatusRoute
208
305
  '/api/sync': typeof ApiSyncRoute
306
+ '/api/xurl-rate-limits': typeof ApiXurlRateLimitsRoute
307
+ '/profiles/$handle': typeof ProfilesHandleRoute
209
308
  }
210
309
  export interface FileRouteTypes {
211
310
  fileRoutesByFullPath: FileRoutesByFullPath
@@ -213,94 +312,138 @@ export interface FileRouteTypes {
213
312
  | '/'
214
313
  | '/blocks'
215
314
  | '/bookmarks'
315
+ | '/data-sources'
316
+ | '/discuss'
216
317
  | '/dms'
217
318
  | '/inbox'
218
319
  | '/likes'
219
320
  | '/links'
220
321
  | '/mentions'
322
+ | '/network-map'
323
+ | '/profile-analyze'
324
+ | '/rate-limits'
221
325
  | '/today'
222
326
  | '/api/action'
223
327
  | '/api/avatar'
224
328
  | '/api/blocks'
225
329
  | '/api/conversation'
330
+ | '/api/data-sources'
226
331
  | '/api/inbox'
227
332
  | '/api/link-insights'
228
333
  | '/api/link-preview'
334
+ | '/api/network-map'
229
335
  | '/api/period-digest'
336
+ | '/api/profile-analysis'
230
337
  | '/api/profile-hydrate'
231
338
  | '/api/query'
339
+ | '/api/search-discussion'
232
340
  | '/api/status'
233
341
  | '/api/sync'
342
+ | '/api/xurl-rate-limits'
343
+ | '/profiles/$handle'
234
344
  fileRoutesByTo: FileRoutesByTo
235
345
  to:
236
346
  | '/'
237
347
  | '/blocks'
238
348
  | '/bookmarks'
349
+ | '/data-sources'
350
+ | '/discuss'
239
351
  | '/dms'
240
352
  | '/inbox'
241
353
  | '/likes'
242
354
  | '/links'
243
355
  | '/mentions'
356
+ | '/network-map'
357
+ | '/profile-analyze'
358
+ | '/rate-limits'
244
359
  | '/today'
245
360
  | '/api/action'
246
361
  | '/api/avatar'
247
362
  | '/api/blocks'
248
363
  | '/api/conversation'
364
+ | '/api/data-sources'
249
365
  | '/api/inbox'
250
366
  | '/api/link-insights'
251
367
  | '/api/link-preview'
368
+ | '/api/network-map'
252
369
  | '/api/period-digest'
370
+ | '/api/profile-analysis'
253
371
  | '/api/profile-hydrate'
254
372
  | '/api/query'
373
+ | '/api/search-discussion'
255
374
  | '/api/status'
256
375
  | '/api/sync'
376
+ | '/api/xurl-rate-limits'
377
+ | '/profiles/$handle'
257
378
  id:
258
379
  | '__root__'
259
380
  | '/'
260
381
  | '/blocks'
261
382
  | '/bookmarks'
383
+ | '/data-sources'
384
+ | '/discuss'
262
385
  | '/dms'
263
386
  | '/inbox'
264
387
  | '/likes'
265
388
  | '/links'
266
389
  | '/mentions'
390
+ | '/network-map'
391
+ | '/profile-analyze'
392
+ | '/rate-limits'
267
393
  | '/today'
268
394
  | '/api/action'
269
395
  | '/api/avatar'
270
396
  | '/api/blocks'
271
397
  | '/api/conversation'
398
+ | '/api/data-sources'
272
399
  | '/api/inbox'
273
400
  | '/api/link-insights'
274
401
  | '/api/link-preview'
402
+ | '/api/network-map'
275
403
  | '/api/period-digest'
404
+ | '/api/profile-analysis'
276
405
  | '/api/profile-hydrate'
277
406
  | '/api/query'
407
+ | '/api/search-discussion'
278
408
  | '/api/status'
279
409
  | '/api/sync'
410
+ | '/api/xurl-rate-limits'
411
+ | '/profiles/$handle'
280
412
  fileRoutesById: FileRoutesById
281
413
  }
282
414
  export interface RootRouteChildren {
283
415
  IndexRoute: typeof IndexRoute
284
416
  BlocksRoute: typeof BlocksRoute
285
417
  BookmarksRoute: typeof BookmarksRoute
418
+ DataSourcesRoute: typeof DataSourcesRoute
419
+ DiscussRoute: typeof DiscussRoute
286
420
  DmsRoute: typeof DmsRoute
287
421
  InboxRoute: typeof InboxRoute
288
422
  LikesRoute: typeof LikesRoute
289
423
  LinksRoute: typeof LinksRoute
290
424
  MentionsRoute: typeof MentionsRoute
425
+ NetworkMapRoute: typeof NetworkMapRoute
426
+ ProfileAnalyzeRoute: typeof ProfileAnalyzeRoute
427
+ RateLimitsRoute: typeof RateLimitsRoute
291
428
  TodayRoute: typeof TodayRoute
292
429
  ApiActionRoute: typeof ApiActionRoute
293
430
  ApiAvatarRoute: typeof ApiAvatarRoute
294
431
  ApiBlocksRoute: typeof ApiBlocksRoute
295
432
  ApiConversationRoute: typeof ApiConversationRoute
433
+ ApiDataSourcesRoute: typeof ApiDataSourcesRoute
296
434
  ApiInboxRoute: typeof ApiInboxRoute
297
435
  ApiLinkInsightsRoute: typeof ApiLinkInsightsRoute
298
436
  ApiLinkPreviewRoute: typeof ApiLinkPreviewRoute
437
+ ApiNetworkMapRoute: typeof ApiNetworkMapRoute
299
438
  ApiPeriodDigestRoute: typeof ApiPeriodDigestRoute
439
+ ApiProfileAnalysisRoute: typeof ApiProfileAnalysisRoute
300
440
  ApiProfileHydrateRoute: typeof ApiProfileHydrateRoute
301
441
  ApiQueryRoute: typeof ApiQueryRoute
442
+ ApiSearchDiscussionRoute: typeof ApiSearchDiscussionRoute
302
443
  ApiStatusRoute: typeof ApiStatusRoute
303
444
  ApiSyncRoute: typeof ApiSyncRoute
445
+ ApiXurlRateLimitsRoute: typeof ApiXurlRateLimitsRoute
446
+ ProfilesHandleRoute: typeof ProfilesHandleRoute
304
447
  }
305
448
 
306
449
  declare module '@tanstack/react-router' {
@@ -312,6 +455,27 @@ declare module '@tanstack/react-router' {
312
455
  preLoaderRoute: typeof TodayRouteImport
313
456
  parentRoute: typeof rootRouteImport
314
457
  }
458
+ '/rate-limits': {
459
+ id: '/rate-limits'
460
+ path: '/rate-limits'
461
+ fullPath: '/rate-limits'
462
+ preLoaderRoute: typeof RateLimitsRouteImport
463
+ parentRoute: typeof rootRouteImport
464
+ }
465
+ '/profile-analyze': {
466
+ id: '/profile-analyze'
467
+ path: '/profile-analyze'
468
+ fullPath: '/profile-analyze'
469
+ preLoaderRoute: typeof ProfileAnalyzeRouteImport
470
+ parentRoute: typeof rootRouteImport
471
+ }
472
+ '/network-map': {
473
+ id: '/network-map'
474
+ path: '/network-map'
475
+ fullPath: '/network-map'
476
+ preLoaderRoute: typeof NetworkMapRouteImport
477
+ parentRoute: typeof rootRouteImport
478
+ }
315
479
  '/mentions': {
316
480
  id: '/mentions'
317
481
  path: '/mentions'
@@ -347,6 +511,20 @@ declare module '@tanstack/react-router' {
347
511
  preLoaderRoute: typeof DmsRouteImport
348
512
  parentRoute: typeof rootRouteImport
349
513
  }
514
+ '/discuss': {
515
+ id: '/discuss'
516
+ path: '/discuss'
517
+ fullPath: '/discuss'
518
+ preLoaderRoute: typeof DiscussRouteImport
519
+ parentRoute: typeof rootRouteImport
520
+ }
521
+ '/data-sources': {
522
+ id: '/data-sources'
523
+ path: '/data-sources'
524
+ fullPath: '/data-sources'
525
+ preLoaderRoute: typeof DataSourcesRouteImport
526
+ parentRoute: typeof rootRouteImport
527
+ }
350
528
  '/bookmarks': {
351
529
  id: '/bookmarks'
352
530
  path: '/bookmarks'
@@ -368,6 +546,20 @@ declare module '@tanstack/react-router' {
368
546
  preLoaderRoute: typeof IndexRouteImport
369
547
  parentRoute: typeof rootRouteImport
370
548
  }
549
+ '/profiles/$handle': {
550
+ id: '/profiles/$handle'
551
+ path: '/profiles/$handle'
552
+ fullPath: '/profiles/$handle'
553
+ preLoaderRoute: typeof ProfilesHandleRouteImport
554
+ parentRoute: typeof rootRouteImport
555
+ }
556
+ '/api/xurl-rate-limits': {
557
+ id: '/api/xurl-rate-limits'
558
+ path: '/api/xurl-rate-limits'
559
+ fullPath: '/api/xurl-rate-limits'
560
+ preLoaderRoute: typeof ApiXurlRateLimitsRouteImport
561
+ parentRoute: typeof rootRouteImport
562
+ }
371
563
  '/api/sync': {
372
564
  id: '/api/sync'
373
565
  path: '/api/sync'
@@ -382,6 +574,13 @@ declare module '@tanstack/react-router' {
382
574
  preLoaderRoute: typeof ApiStatusRouteImport
383
575
  parentRoute: typeof rootRouteImport
384
576
  }
577
+ '/api/search-discussion': {
578
+ id: '/api/search-discussion'
579
+ path: '/api/search-discussion'
580
+ fullPath: '/api/search-discussion'
581
+ preLoaderRoute: typeof ApiSearchDiscussionRouteImport
582
+ parentRoute: typeof rootRouteImport
583
+ }
385
584
  '/api/query': {
386
585
  id: '/api/query'
387
586
  path: '/api/query'
@@ -396,6 +595,13 @@ declare module '@tanstack/react-router' {
396
595
  preLoaderRoute: typeof ApiProfileHydrateRouteImport
397
596
  parentRoute: typeof rootRouteImport
398
597
  }
598
+ '/api/profile-analysis': {
599
+ id: '/api/profile-analysis'
600
+ path: '/api/profile-analysis'
601
+ fullPath: '/api/profile-analysis'
602
+ preLoaderRoute: typeof ApiProfileAnalysisRouteImport
603
+ parentRoute: typeof rootRouteImport
604
+ }
399
605
  '/api/period-digest': {
400
606
  id: '/api/period-digest'
401
607
  path: '/api/period-digest'
@@ -403,6 +609,13 @@ declare module '@tanstack/react-router' {
403
609
  preLoaderRoute: typeof ApiPeriodDigestRouteImport
404
610
  parentRoute: typeof rootRouteImport
405
611
  }
612
+ '/api/network-map': {
613
+ id: '/api/network-map'
614
+ path: '/api/network-map'
615
+ fullPath: '/api/network-map'
616
+ preLoaderRoute: typeof ApiNetworkMapRouteImport
617
+ parentRoute: typeof rootRouteImport
618
+ }
406
619
  '/api/link-preview': {
407
620
  id: '/api/link-preview'
408
621
  path: '/api/link-preview'
@@ -424,6 +637,13 @@ declare module '@tanstack/react-router' {
424
637
  preLoaderRoute: typeof ApiInboxRouteImport
425
638
  parentRoute: typeof rootRouteImport
426
639
  }
640
+ '/api/data-sources': {
641
+ id: '/api/data-sources'
642
+ path: '/api/data-sources'
643
+ fullPath: '/api/data-sources'
644
+ preLoaderRoute: typeof ApiDataSourcesRouteImport
645
+ parentRoute: typeof rootRouteImport
646
+ }
427
647
  '/api/conversation': {
428
648
  id: '/api/conversation'
429
649
  path: '/api/conversation'
@@ -459,24 +679,35 @@ const rootRouteChildren: RootRouteChildren = {
459
679
  IndexRoute: IndexRoute,
460
680
  BlocksRoute: BlocksRoute,
461
681
  BookmarksRoute: BookmarksRoute,
682
+ DataSourcesRoute: DataSourcesRoute,
683
+ DiscussRoute: DiscussRoute,
462
684
  DmsRoute: DmsRoute,
463
685
  InboxRoute: InboxRoute,
464
686
  LikesRoute: LikesRoute,
465
687
  LinksRoute: LinksRoute,
466
688
  MentionsRoute: MentionsRoute,
689
+ NetworkMapRoute: NetworkMapRoute,
690
+ ProfileAnalyzeRoute: ProfileAnalyzeRoute,
691
+ RateLimitsRoute: RateLimitsRoute,
467
692
  TodayRoute: TodayRoute,
468
693
  ApiActionRoute: ApiActionRoute,
469
694
  ApiAvatarRoute: ApiAvatarRoute,
470
695
  ApiBlocksRoute: ApiBlocksRoute,
471
696
  ApiConversationRoute: ApiConversationRoute,
697
+ ApiDataSourcesRoute: ApiDataSourcesRoute,
472
698
  ApiInboxRoute: ApiInboxRoute,
473
699
  ApiLinkInsightsRoute: ApiLinkInsightsRoute,
474
700
  ApiLinkPreviewRoute: ApiLinkPreviewRoute,
701
+ ApiNetworkMapRoute: ApiNetworkMapRoute,
475
702
  ApiPeriodDigestRoute: ApiPeriodDigestRoute,
703
+ ApiProfileAnalysisRoute: ApiProfileAnalysisRoute,
476
704
  ApiProfileHydrateRoute: ApiProfileHydrateRoute,
477
705
  ApiQueryRoute: ApiQueryRoute,
706
+ ApiSearchDiscussionRoute: ApiSearchDiscussionRoute,
478
707
  ApiStatusRoute: ApiStatusRoute,
479
708
  ApiSyncRoute: ApiSyncRoute,
709
+ ApiXurlRateLimitsRoute: ApiXurlRateLimitsRoute,
710
+ ProfilesHandleRoute: ProfilesHandleRoute,
480
711
  }
481
712
  export const routeTree = rootRouteImport
482
713
  ._addFileChildren(rootRouteChildren)
@@ -56,7 +56,8 @@ function RootDocument({ children }: { children: ReactNode }) {
56
56
  const pathname = useRouterState({
57
57
  select: (state) => state.location.pathname,
58
58
  });
59
- const messagesMode = pathname.startsWith("/dms");
59
+ const wideMode =
60
+ pathname.startsWith("/dms") || pathname.startsWith("/network-map");
60
61
 
61
62
  return (
62
63
  <html lang="en" suppressHydrationWarning>
@@ -66,11 +67,9 @@ function RootDocument({ children }: { children: ReactNode }) {
66
67
  </head>
67
68
  <body className={bodyClass}>
68
69
  <ThemeProvider>
69
- <div className={messagesMode ? siteShellDmClass : siteShellClass}>
70
- <AppNav compact={messagesMode} />
71
- <main
72
- className={messagesMode ? mainColumnDmClass : mainColumnClass}
73
- >
70
+ <div className={wideMode ? siteShellDmClass : siteShellClass}>
71
+ <AppNav compact={wideMode} />
72
+ <main className={wideMode ? mainColumnDmClass : mainColumnClass}>
74
73
  {children}
75
74
  </main>
76
75
  </div>
@@ -0,0 +1,24 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { Effect } from "effect";
3
+ import { getLiveDataSourcesEffect } from "#/lib/data-sources";
4
+ import {
5
+ jsonResponse,
6
+ runRouteEffect,
7
+ sensitiveRequestErrorResponse,
8
+ } from "#/lib/http-effect";
9
+
10
+ export const Route = createFileRoute("/api/data-sources")({
11
+ server: {
12
+ handlers: {
13
+ GET: ({ request }) =>
14
+ runRouteEffect(
15
+ Effect.gen(function* () {
16
+ const denied = sensitiveRequestErrorResponse(request);
17
+ if (denied) return denied;
18
+
19
+ return jsonResponse(yield* getLiveDataSourcesEffect());
20
+ }),
21
+ ),
22
+ },
23
+ },
24
+ });
@@ -0,0 +1,55 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { Effect } from "effect";
3
+ import { maybeAutoUpdateBackupEffect } from "#/lib/backup";
4
+ import {
5
+ jsonResponse,
6
+ parseBoundedInteger,
7
+ runRouteEffect,
8
+ sensitiveRequestErrorResponse,
9
+ } from "#/lib/http-effect";
10
+ import { getNetworkMap, type NetworkMapKind } from "#/lib/network-map";
11
+
12
+ function parseType(value: string | null): NetworkMapKind {
13
+ if (
14
+ value === "followers" ||
15
+ value === "following" ||
16
+ value === "mutual" ||
17
+ value === "all"
18
+ ) {
19
+ return value;
20
+ }
21
+ return "all";
22
+ }
23
+
24
+ export const Route = createFileRoute("/api/network-map")({
25
+ server: {
26
+ handlers: {
27
+ GET: ({ request }) =>
28
+ runRouteEffect(
29
+ Effect.gen(function* () {
30
+ const denied = sensitiveRequestErrorResponse(request);
31
+ if (denied) return denied;
32
+
33
+ yield* maybeAutoUpdateBackupEffect();
34
+ const url = new URL(request.url);
35
+ const response = yield* Effect.promise(() =>
36
+ getNetworkMap({
37
+ account: url.searchParams.get("account") ?? undefined,
38
+ type: parseType(url.searchParams.get("type")),
39
+ limit: parseBoundedInteger(url.searchParams.get("limit"), {
40
+ max: 50_000,
41
+ }),
42
+ geocodeLimit: parseBoundedInteger(
43
+ url.searchParams.get("geocodeLimit"),
44
+ { max: 500, min: 0 },
45
+ ),
46
+ refresh: url.searchParams.get("refresh") === "true",
47
+ signal: request.signal,
48
+ }),
49
+ );
50
+ return jsonResponse(response);
51
+ }),
52
+ ),
53
+ },
54
+ },
55
+ });