Demo using Slices Network GraphQL Relay API to make a teal.fm client

use quickslice ⭐️

+2 -2
package.json
··· 8 8 "build": "tsc -b && vite build", 9 9 "lint": "eslint .", 10 10 "preview": "vite preview", 11 - "schema:dev": "npx get-graphql-schema 'http://localhost:3000/graphql?slice=at://did:plc:fpruhuo22xkm5o7ttr2ktxdo/network.slices.slice/3m257yljpbg2a' > schema.graphql", 12 - "schema:prod": "npx get-graphql-schema 'https://api.slices.network/graphql?slice=at://did:plc:fpruhuo22xkm5o7ttr2ktxdo/network.slices.slice/3m257yljpbg2a' > schema.graphql" 11 + "schema:dev": "npx get-graphql-schema 'http://localhost:8000/graphql' > schema.graphql", 12 + "schema:prod": "npx get-graphql-schema 'https://quickslice-production-d668.up.railway.app/graphql' > schema.graphql" 13 13 }, 14 14 "dependencies": { 15 15 "graphql-ws": "^6.0.6",
+760 -1139
schema.graphql
··· 1 - """ 2 - Indicates that an Input Object is a OneOf Input Object (and thus requires exactly one of its field be provided) 3 - """ 4 - directive @oneOf on INPUT_OBJECT 5 - 6 - """ 7 - Provides a scalar specification URL for specifying the behavior of custom scalar types. 8 - """ 9 - directive @specifiedBy( 10 - """URL that specifies the behavior of this scalar.""" 11 - url: String! 12 - ) on SCALAR 13 - 1 + """Order aggregation results by count""" 14 2 input AggregationOrderBy { 3 + """Order by count (asc or desc)""" 15 4 count: SortDirection 16 5 } 17 6 7 + """Record type: app.bsky.actor.profile""" 18 8 type AppBskyActorProfile { 19 - id: ID! 20 - uri: String! 21 - cid: String! 22 - did: String! 23 - indexedAt: String! 9 + """Record URI""" 10 + uri: String 11 + 12 + """Record CID""" 13 + cid: String 14 + 15 + """DID of record author""" 16 + did: String 17 + 18 + """Collection name""" 19 + collection: String 20 + 21 + """When record was indexed""" 22 + indexedAt: String 23 + 24 + """Handle of the actor who created this record""" 24 25 actorHandle: String 26 + 27 + """Field from lexicon""" 25 28 avatar: Blob 29 + 30 + """Field from lexicon""" 26 31 banner: Blob 32 + 33 + """Field from lexicon""" 27 34 createdAt: String 35 + 36 + """Field from lexicon""" 28 37 description: String 38 + 39 + """Field from lexicon""" 29 40 displayName: String 30 - joinedViaStarterPack: JSON 31 - labels: JSON 32 - pinnedPost: JSON 33 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 34 - appBskyFeedPostgatesCount: Int! 35 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 36 - appBskyFeedThreadgatesCount: Int! 37 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 38 - appBskyActorProfilesCount: Int! 39 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 40 - fmTealAlphaFeedPlaysCount: Int! 41 + 42 + """Field from lexicon""" 43 + joinedViaStarterPack: String 44 + 45 + """Field from lexicon""" 46 + labels: String 47 + 48 + """Field from lexicon""" 49 + pinnedPost: String 50 + 51 + """Field from lexicon""" 52 + pronouns: String 53 + 54 + """Field from lexicon""" 55 + website: String 56 + 57 + """Forward join to referenced record""" 58 + pinnedPostResolved: Record 59 + 60 + """Forward join to referenced record""" 61 + joinedViaStarterPackResolved: Record 62 + 63 + """ 64 + DID join: records in fm.teal.alpha.feed.play that share the same DID as this record 65 + """ 66 + fmTealAlphaFeedPlayByDid( 67 + """Returns the first n items from the list""" 68 + first: Int 69 + 70 + """Returns items after the given cursor""" 71 + after: String 72 + 73 + """Returns the last n items from the list""" 74 + last: Int 75 + 76 + """Returns items before the given cursor""" 77 + before: String 78 + 79 + """Sort order for the connection""" 80 + sortBy: [FmTealAlphaFeedPlaySortFieldInput!] 81 + 82 + """Filter conditions for the query""" 83 + where: FmTealAlphaFeedPlayWhereInput 84 + ): FmTealAlphaFeedPlayConnection 41 85 } 42 86 87 + """Aggregated results for app.bsky.actor.profile""" 43 88 type AppBskyActorProfileAggregated { 44 - avatar: JSON 45 - banner: JSON 46 - createdAt: JSON 47 - description: JSON 48 - displayName: JSON 49 - joinedViaStarterPack: JSON 50 - labels: JSON 51 - pinnedPost: JSON 89 + """Grouped field value""" 90 + uri: String 91 + 92 + """Grouped field value""" 93 + cid: String 94 + 95 + """Grouped field value""" 96 + did: String 97 + 98 + """Grouped field value""" 99 + collection: String 100 + 101 + """Grouped field value""" 102 + indexed_at: String 103 + 104 + """Grouped field value""" 105 + avatar: String 106 + 107 + """Grouped field value""" 108 + banner: String 109 + 110 + """Grouped field value""" 111 + createdAt: String 112 + 113 + """Grouped field value""" 114 + description: String 115 + 116 + """Grouped field value""" 117 + displayName: String 118 + 119 + """Grouped field value""" 120 + joinedViaStarterPack: String 121 + 122 + """Grouped field value""" 123 + labels: String 124 + 125 + """Grouped field value""" 126 + pinnedPost: String 127 + 128 + """Grouped field value""" 129 + pronouns: String 130 + 131 + """Grouped field value""" 132 + website: String 133 + 134 + """Count of records in this group""" 52 135 count: Int! 53 136 } 54 137 138 + """A connection to a list of items for AppBskyActorProfile""" 55 139 type AppBskyActorProfileConnection { 56 - totalCount: Int! 57 - pageInfo: PageInfo! 140 + """A list of edges""" 58 141 edges: [AppBskyActorProfileEdge!]! 59 - nodes: [AppBskyActorProfile!]! 142 + 143 + """Information to aid in pagination""" 144 + pageInfo: PageInfo! 145 + 146 + """Total number of items in the connection""" 147 + totalCount: Int 60 148 } 61 149 150 + """An edge in a connection for AppBskyActorProfile""" 62 151 type AppBskyActorProfileEdge { 152 + """The item at the end of the edge""" 63 153 node: AppBskyActorProfile! 154 + 155 + """A cursor for use in pagination""" 64 156 cursor: String! 65 157 } 66 158 159 + """Filter operators for AppBskyActorProfile fields""" 160 + input AppBskyActorProfileFieldCondition { 161 + """Exact match (equals)""" 162 + eq: String 163 + 164 + """Match any value in the list""" 165 + in: [String!] 166 + 167 + """Case-insensitive substring match (string fields only)""" 168 + contains: String 169 + 170 + """Greater than""" 171 + gt: String 172 + 173 + """Greater than or equal to""" 174 + gte: String 175 + 176 + """Less than""" 177 + lt: String 178 + 179 + """Less than or equal to""" 180 + lte: String 181 + } 182 + 183 + """Available groupBy fields for AppBskyActorProfile""" 67 184 enum AppBskyActorProfileGroupByField { 185 + """Group by uri""" 186 + uri 187 + 188 + """Group by cid""" 189 + cid 190 + 191 + """Group by did""" 192 + did 193 + 194 + """Group by collection""" 195 + collection 196 + 197 + """Group by indexedAt""" 68 198 indexedAt 69 - avatar 70 - banner 199 + 200 + """Group by actorHandle""" 201 + actorHandle 202 + 203 + """Group by createdAt""" 71 204 createdAt 205 + 206 + """Group by description""" 72 207 description 208 + 209 + """Group by displayName""" 73 210 displayName 74 - joinedViaStarterPack 211 + 212 + """Group by labels""" 75 213 labels 76 - pinnedPost 214 + 215 + """Group by pronouns""" 216 + pronouns 217 + 218 + """Group by website""" 219 + website 77 220 } 78 221 222 + """Specifies a field to group by with optional date truncation""" 79 223 input AppBskyActorProfileGroupByFieldInput { 224 + """Field name to group by""" 80 225 field: AppBskyActorProfileGroupByField! 226 + 227 + """Date truncation interval (for datetime fields)""" 81 228 interval: DateInterval 82 229 } 83 230 231 + """Input type for AppBskyActorProfileInput""" 84 232 input AppBskyActorProfileInput { 85 - avatar: JSON 86 - banner: JSON 87 - createdAt: String 88 - description: String 89 - displayName: String 90 - joinedViaStarterPack: JSON 91 - labels: JSON 92 - pinnedPost: JSON 93 - } 233 + """Input field for avatar""" 234 + avatar: BlobInput 94 235 95 - input AppBskyActorProfileSortFieldInput { 96 - field: AppBskyActorProfileGroupByField! 97 - direction: SortDirection 98 - } 236 + """Input field for banner""" 237 + banner: BlobInput 99 238 100 - input AppBskyActorProfileWhereInput { 101 - indexedAt: DateTimeFilter 102 - uri: StringFilter 103 - cid: StringFilter 104 - did: StringFilter 105 - collection: StringFilter 106 - actorHandle: StringFilter 107 - avatar: StringFilter 108 - banner: StringFilter 109 - createdAt: StringFilter 110 - description: StringFilter 111 - displayName: StringFilter 112 - joinedViaStarterPack: StringFilter 113 - labels: StringFilter 114 - pinnedPost: StringFilter 115 - json: StringFilter 116 - and: [AppBskyActorProfileWhereInput] 117 - or: [AppBskyActorProfileWhereInput] 118 - } 239 + """Input field for createdAt""" 240 + createdAt: String 119 241 120 - type AppBskyEmbedDefsAspectRatio { 121 - height: Int 122 - width: Int 123 - } 242 + """Input field for description""" 243 + description: String 124 244 125 - type AppBskyEmbedExternal { 126 - id: ID! 127 - uri: String! 128 - cid: String! 129 - did: String! 130 - indexedAt: String! 131 - actorHandle: String 132 - external: AppBskyEmbedExternalExternal! 133 - appBskyActorProfile: AppBskyActorProfile 134 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 135 - appBskyFeedPostgatesCount: Int! 136 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 137 - appBskyFeedThreadgatesCount: Int! 138 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 139 - appBskyActorProfilesCount: Int! 140 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 141 - fmTealAlphaFeedPlaysCount: Int! 142 - } 245 + """Input field for displayName""" 246 + displayName: String 143 247 144 - type AppBskyEmbedExternalAggregated { 145 - external: JSON 146 - count: Int! 147 - } 248 + """Input field for joinedViaStarterPack""" 249 + joinedViaStarterPack: String 148 250 149 - type AppBskyEmbedExternalConnection { 150 - totalCount: Int! 151 - pageInfo: PageInfo! 152 - edges: [AppBskyEmbedExternalEdge!]! 153 - nodes: [AppBskyEmbedExternal!]! 154 - } 251 + """Input field for labels""" 252 + labels: String 155 253 156 - type AppBskyEmbedExternalEdge { 157 - node: AppBskyEmbedExternal! 158 - cursor: String! 159 - } 254 + """Input field for pinnedPost""" 255 + pinnedPost: String 160 256 161 - type AppBskyEmbedExternalExternal { 162 - description: String 163 - thumb: Blob 164 - title: String 165 - uri: String 166 - } 257 + """Input field for pronouns""" 258 + pronouns: String 167 259 168 - enum AppBskyEmbedExternalGroupByField { 169 - indexedAt 170 - external 260 + """Input field for website""" 261 + website: String 171 262 } 172 263 173 - input AppBskyEmbedExternalGroupByFieldInput { 174 - field: AppBskyEmbedExternalGroupByField! 175 - interval: DateInterval 176 - } 264 + """Available sort fields for AppBskyActorProfile""" 265 + enum AppBskyActorProfileSortField { 266 + """Sort by uri""" 267 + uri 177 268 178 - input AppBskyEmbedExternalInput { 179 - external: JSON! 180 - } 269 + """Sort by cid""" 270 + cid 181 271 182 - input AppBskyEmbedExternalSortFieldInput { 183 - field: AppBskyEmbedExternalGroupByField! 184 - direction: SortDirection 185 - } 272 + """Sort by did""" 273 + did 186 274 187 - input AppBskyEmbedExternalWhereInput { 188 - indexedAt: DateTimeFilter 189 - uri: StringFilter 190 - cid: StringFilter 191 - did: StringFilter 192 - collection: StringFilter 193 - actorHandle: StringFilter 194 - external: StringFilter 195 - json: StringFilter 196 - and: [AppBskyEmbedExternalWhereInput] 197 - or: [AppBskyEmbedExternalWhereInput] 198 - } 275 + """Sort by collection""" 276 + collection 199 277 200 - type AppBskyEmbedImages { 201 - id: ID! 202 - uri: String! 203 - cid: String! 204 - did: String! 205 - indexedAt: String! 206 - actorHandle: String 207 - images: [AppBskyEmbedImagesImage!] 208 - appBskyActorProfile: AppBskyActorProfile 209 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 210 - appBskyFeedPostgatesCount: Int! 211 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 212 - appBskyFeedThreadgatesCount: Int! 213 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 214 - appBskyActorProfilesCount: Int! 215 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 216 - fmTealAlphaFeedPlaysCount: Int! 217 - } 218 - 219 - type AppBskyEmbedImagesAggregated { 220 - images: JSON 221 - count: Int! 222 - } 223 - 224 - type AppBskyEmbedImagesConnection { 225 - totalCount: Int! 226 - pageInfo: PageInfo! 227 - edges: [AppBskyEmbedImagesEdge!]! 228 - nodes: [AppBskyEmbedImages!]! 229 - } 230 - 231 - type AppBskyEmbedImagesEdge { 232 - node: AppBskyEmbedImages! 233 - cursor: String! 234 - } 235 - 236 - enum AppBskyEmbedImagesGroupByField { 278 + """Sort by indexedAt""" 237 279 indexedAt 238 - images 239 - } 240 280 241 - input AppBskyEmbedImagesGroupByFieldInput { 242 - field: AppBskyEmbedImagesGroupByField! 243 - interval: DateInterval 244 - } 281 + """Sort by createdAt""" 282 + createdAt 245 283 246 - type AppBskyEmbedImagesImage { 247 - alt: String 248 - aspectRatio: JSON 249 - image: Blob 250 - } 284 + """Sort by description""" 285 + description 251 286 252 - input AppBskyEmbedImagesInput { 253 - images: JSON! 254 - } 287 + """Sort by displayName""" 288 + displayName 255 289 256 - input AppBskyEmbedImagesSortFieldInput { 257 - field: AppBskyEmbedImagesGroupByField! 258 - direction: SortDirection 259 - } 290 + """Sort by labels""" 291 + labels 260 292 261 - input AppBskyEmbedImagesWhereInput { 262 - indexedAt: DateTimeFilter 263 - uri: StringFilter 264 - cid: StringFilter 265 - did: StringFilter 266 - collection: StringFilter 267 - actorHandle: StringFilter 268 - images: StringFilter 269 - json: StringFilter 270 - and: [AppBskyEmbedImagesWhereInput] 271 - or: [AppBskyEmbedImagesWhereInput] 272 - } 293 + """Sort by pronouns""" 294 + pronouns 273 295 274 - type AppBskyEmbedRecord { 275 - record: JSON 296 + """Sort by website""" 297 + website 276 298 } 277 299 278 - type AppBskyEmbedRecordAggregated { 279 - record: JSON 280 - count: Int! 281 - } 300 + """Specifies a field to sort by and its direction for AppBskyActorProfile""" 301 + input AppBskyActorProfileSortFieldInput { 302 + """Field to sort by""" 303 + field: AppBskyActorProfileSortField! 282 304 283 - type AppBskyEmbedRecordConnection { 284 - totalCount: Int! 285 - pageInfo: PageInfo! 286 - edges: [AppBskyEmbedRecordEdge!]! 287 - nodes: [AppBskyEmbedRecord!]! 305 + """Sort direction (ASC or DESC)""" 306 + direction: SortDirection! 288 307 } 289 308 290 - type AppBskyEmbedRecordEdge { 291 - node: AppBskyEmbedRecord! 292 - cursor: String! 293 - } 309 + """Filter conditions for AppBskyActorProfile with nested AND/OR support""" 310 + input AppBskyActorProfileWhereInput { 311 + """Filter by uri""" 312 + uri: AppBskyActorProfileFieldCondition 294 313 295 - enum AppBskyEmbedRecordGroupByField { 296 - indexedAt 297 - record 298 - } 314 + """Filter by cid""" 315 + cid: AppBskyActorProfileFieldCondition 299 316 300 - input AppBskyEmbedRecordGroupByFieldInput { 301 - field: AppBskyEmbedRecordGroupByField! 302 - interval: DateInterval 303 - } 317 + """Filter by did""" 318 + did: AppBskyActorProfileFieldCondition 304 319 305 - input AppBskyEmbedRecordInput { 306 - record: JSON! 307 - } 320 + """Filter by collection""" 321 + collection: AppBskyActorProfileFieldCondition 308 322 309 - input AppBskyEmbedRecordSortFieldInput { 310 - field: AppBskyEmbedRecordGroupByField! 311 - direction: SortDirection 312 - } 323 + """Filter by indexedAt""" 324 + indexedAt: AppBskyActorProfileFieldCondition 313 325 314 - input AppBskyEmbedRecordWhereInput { 315 - indexedAt: DateTimeFilter 316 - uri: StringFilter 317 - cid: StringFilter 318 - did: StringFilter 319 - collection: StringFilter 320 - actorHandle: StringFilter 321 - record: StringFilter 322 - json: StringFilter 323 - and: [AppBskyEmbedRecordWhereInput] 324 - or: [AppBskyEmbedRecordWhereInput] 325 - } 326 + """Filter by actorHandle""" 327 + actorHandle: AppBskyActorProfileFieldCondition 326 328 327 - type AppBskyEmbedRecordWithMedia { 328 - id: ID! 329 - uri: String! 330 - cid: String! 331 - did: String! 332 - indexedAt: String! 333 - actorHandle: String 334 - media: JSON! 335 - record: AppBskyEmbedRecord! 336 - appBskyActorProfile: AppBskyActorProfile 337 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 338 - appBskyFeedPostgatesCount: Int! 339 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 340 - appBskyFeedThreadgatesCount: Int! 341 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 342 - appBskyActorProfilesCount: Int! 343 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 344 - fmTealAlphaFeedPlaysCount: Int! 345 - } 329 + """Filter by createdAt""" 330 + createdAt: AppBskyActorProfileFieldCondition 346 331 347 - type AppBskyEmbedRecordWithMediaAggregated { 348 - media: JSON 349 - record: JSON 350 - count: Int! 351 - } 332 + """Filter by description""" 333 + description: AppBskyActorProfileFieldCondition 352 334 353 - type AppBskyEmbedRecordWithMediaConnection { 354 - totalCount: Int! 355 - pageInfo: PageInfo! 356 - edges: [AppBskyEmbedRecordWithMediaEdge!]! 357 - nodes: [AppBskyEmbedRecordWithMedia!]! 358 - } 335 + """Filter by displayName""" 336 + displayName: AppBskyActorProfileFieldCondition 359 337 360 - type AppBskyEmbedRecordWithMediaEdge { 361 - node: AppBskyEmbedRecordWithMedia! 362 - cursor: String! 363 - } 338 + """Filter by labels""" 339 + labels: AppBskyActorProfileFieldCondition 364 340 365 - enum AppBskyEmbedRecordWithMediaGroupByField { 366 - indexedAt 367 - media 368 - record 369 - } 341 + """Filter by pronouns""" 342 + pronouns: AppBskyActorProfileFieldCondition 370 343 371 - input AppBskyEmbedRecordWithMediaGroupByFieldInput { 372 - field: AppBskyEmbedRecordWithMediaGroupByField! 373 - interval: DateInterval 374 - } 344 + """Filter by website""" 345 + website: AppBskyActorProfileFieldCondition 375 346 376 - input AppBskyEmbedRecordWithMediaInput { 377 - media: JSON! 378 - record: JSON! 379 - } 347 + """All conditions must match (AND logic)""" 348 + and: [AppBskyActorProfileWhereInput!] 380 349 381 - input AppBskyEmbedRecordWithMediaSortFieldInput { 382 - field: AppBskyEmbedRecordWithMediaGroupByField! 383 - direction: SortDirection 350 + """Any condition must match (OR logic)""" 351 + or: [AppBskyActorProfileWhereInput!] 384 352 } 385 353 386 - input AppBskyEmbedRecordWithMediaWhereInput { 387 - indexedAt: DateTimeFilter 388 - uri: StringFilter 389 - cid: StringFilter 390 - did: StringFilter 391 - collection: StringFilter 392 - actorHandle: StringFilter 393 - media: StringFilter 394 - record: StringFilter 395 - json: StringFilter 396 - and: [AppBskyEmbedRecordWithMediaWhereInput] 397 - or: [AppBskyEmbedRecordWithMediaWhereInput] 398 - } 354 + """A blob reference with metadata and URL generation""" 355 + type Blob { 356 + """CID reference to the blob""" 357 + ref: String! 399 358 400 - type AppBskyEmbedVideo { 401 - id: ID! 402 - uri: String! 403 - cid: String! 404 - did: String! 405 - indexedAt: String! 406 - actorHandle: String 407 - alt: String 408 - aspectRatio: AppBskyEmbedDefsAspectRatio 409 - captions: [AppBskyEmbedVideoCaption] 410 - video: Blob 411 - appBskyActorProfile: AppBskyActorProfile 412 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 413 - appBskyFeedPostgatesCount: Int! 414 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 415 - appBskyFeedThreadgatesCount: Int! 416 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 417 - appBskyActorProfilesCount: Int! 418 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 419 - fmTealAlphaFeedPlaysCount: Int! 420 - } 359 + """MIME type of the blob""" 360 + mimeType: String! 421 361 422 - type AppBskyEmbedVideoAggregated { 423 - alt: JSON 424 - aspectRatio: JSON 425 - captions: JSON 426 - video: JSON 427 - count: Int! 428 - } 362 + """Size in bytes""" 363 + size: Int! 429 364 430 - type AppBskyEmbedVideoCaption { 431 - file: Blob 432 - lang: String 365 + """ 366 + Generate CDN URL for the blob with the specified preset (avatar, banner, feed_thumbnail, feed_fullsize) 367 + """ 368 + url( 369 + """Image preset: avatar, banner, feed_thumbnail, feed_fullsize""" 370 + preset: String 371 + ): String! 433 372 } 434 373 435 - type AppBskyEmbedVideoConnection { 436 - totalCount: Int! 437 - pageInfo: PageInfo! 438 - edges: [AppBskyEmbedVideoEdge!]! 439 - nodes: [AppBskyEmbedVideo!]! 440 - } 374 + """Input type for blob references""" 375 + input BlobInput { 376 + """CID reference to the blob""" 377 + ref: String! 441 378 442 - type AppBskyEmbedVideoEdge { 443 - node: AppBskyEmbedVideo! 444 - cursor: String! 445 - } 379 + """MIME type of the blob""" 380 + mimeType: String! 446 381 447 - enum AppBskyEmbedVideoGroupByField { 448 - indexedAt 449 - alt 450 - aspectRatio 451 - captions 452 - video 382 + """Size in bytes""" 383 + size: Int! 453 384 } 454 385 455 - input AppBskyEmbedVideoGroupByFieldInput { 456 - field: AppBskyEmbedVideoGroupByField! 457 - interval: DateInterval 458 - } 386 + """Response from uploading a blob""" 387 + type BlobUploadResponse { 388 + """CID reference to the blob""" 389 + ref: String! 459 390 460 - input AppBskyEmbedVideoInput { 461 - alt: String 462 - aspectRatio: JSON 463 - captions: JSON 464 - video: JSON! 465 - } 391 + """MIME type of the blob""" 392 + mimeType: String! 466 393 467 - input AppBskyEmbedVideoSortFieldInput { 468 - field: AppBskyEmbedVideoGroupByField! 469 - direction: SortDirection 394 + """Size in bytes""" 395 + size: Int! 470 396 } 471 397 472 - input AppBskyEmbedVideoWhereInput { 473 - indexedAt: DateTimeFilter 474 - uri: StringFilter 475 - cid: StringFilter 476 - did: StringFilter 477 - collection: StringFilter 478 - actorHandle: StringFilter 479 - alt: StringFilter 480 - aspectRatio: StringFilter 481 - captions: StringFilter 482 - video: StringFilter 483 - json: StringFilter 484 - and: [AppBskyEmbedVideoWhereInput] 485 - or: [AppBskyEmbedVideoWhereInput] 486 - } 398 + """Date truncation intervals for aggregation""" 399 + enum DateInterval { 400 + """Truncate to hour""" 401 + HOUR 487 402 488 - type AppBskyFeedPostgate { 489 - id: ID! 490 - uri: String! 491 - cid: String! 492 - did: String! 493 - indexedAt: String! 494 - actorHandle: String 495 - createdAt: String! 496 - detachedEmbeddingUris: [String] 497 - embeddingRules: JSON 498 - post: String! 499 - appBskyFeedThreadgate: AppBskyFeedThreadgate 500 - appBskyActorProfile: AppBskyActorProfile 501 - fmTealAlphaFeedPlay: FmTealAlphaFeedPlay 502 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 503 - appBskyFeedPostgatesCount: Int! 504 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 505 - appBskyFeedThreadgatesCount: Int! 506 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 507 - appBskyActorProfilesCount: Int! 508 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 509 - fmTealAlphaFeedPlaysCount: Int! 510 - } 403 + """Truncate to day""" 404 + DAY 511 405 512 - type AppBskyFeedPostgateAggregated { 513 - createdAt: JSON 514 - detachedEmbeddingUris: JSON 515 - embeddingRules: JSON 516 - post: JSON 517 - count: Int! 518 - } 406 + """Truncate to week""" 407 + WEEK 519 408 520 - type AppBskyFeedPostgateConnection { 521 - totalCount: Int! 522 - pageInfo: PageInfo! 523 - edges: [AppBskyFeedPostgateEdge!]! 524 - nodes: [AppBskyFeedPostgate!]! 409 + """Truncate to month""" 410 + MONTH 525 411 } 526 412 527 - type AppBskyFeedPostgateEdge { 528 - node: AppBskyFeedPostgate! 529 - cursor: String! 413 + """Result of a delete mutation""" 414 + type DeleteResult { 415 + """URI of deleted record""" 416 + uri: String 530 417 } 531 418 532 - enum AppBskyFeedPostgateGroupByField { 533 - indexedAt 534 - createdAt 535 - detachedEmbeddingUris 536 - embeddingRules 537 - post 538 - } 419 + """Record type: fm.teal.alpha.feed.play""" 420 + type FmTealAlphaFeedPlay { 421 + """Record URI""" 422 + uri: String 539 423 540 - input AppBskyFeedPostgateGroupByFieldInput { 541 - field: AppBskyFeedPostgateGroupByField! 542 - interval: DateInterval 543 - } 424 + """Record CID""" 425 + cid: String 544 426 545 - input AppBskyFeedPostgateInput { 546 - createdAt: String! 547 - detachedEmbeddingUris: [String] 548 - embeddingRules: JSON 549 - post: String! 550 - } 427 + """DID of record author""" 428 + did: String 551 429 552 - input AppBskyFeedPostgateSortFieldInput { 553 - field: AppBskyFeedPostgateGroupByField! 554 - direction: SortDirection 555 - } 430 + """Collection name""" 431 + collection: String 556 432 557 - input AppBskyFeedPostgateWhereInput { 558 - indexedAt: DateTimeFilter 559 - uri: StringFilter 560 - cid: StringFilter 561 - did: StringFilter 562 - collection: StringFilter 563 - actorHandle: StringFilter 564 - createdAt: StringFilter 565 - detachedEmbeddingUris: StringFilter 566 - embeddingRules: StringFilter 567 - post: StringFilter 568 - json: StringFilter 569 - and: [AppBskyFeedPostgateWhereInput] 570 - or: [AppBskyFeedPostgateWhereInput] 571 - } 433 + """When record was indexed""" 434 + indexedAt: String 572 435 573 - type AppBskyFeedThreadgate { 574 - id: ID! 575 - uri: String! 576 - cid: String! 577 - did: String! 578 - indexedAt: String! 436 + """Handle of the actor who created this record""" 579 437 actorHandle: String 580 - allow: JSON 581 - createdAt: String! 582 - hiddenReplies: [String] 583 - post: String! 584 - appBskyFeedPostgate: AppBskyFeedPostgate 585 - appBskyActorProfile: AppBskyActorProfile 586 - fmTealAlphaFeedPlay: FmTealAlphaFeedPlay 587 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 588 - appBskyFeedPostgatesCount: Int! 589 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 590 - appBskyFeedThreadgatesCount: Int! 591 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 592 - appBskyActorProfilesCount: Int! 593 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 594 - fmTealAlphaFeedPlaysCount: Int! 595 - } 438 + 439 + """Field from lexicon""" 440 + artistMbIds: String 596 441 597 - type AppBskyFeedThreadgateAggregated { 598 - allow: JSON 599 - createdAt: JSON 600 - hiddenReplies: JSON 601 - post: JSON 602 - count: Int! 603 - } 442 + """Field from lexicon""" 443 + artistNames: String 604 444 605 - type AppBskyFeedThreadgateConnection { 606 - totalCount: Int! 607 - pageInfo: PageInfo! 608 - edges: [AppBskyFeedThreadgateEdge!]! 609 - nodes: [AppBskyFeedThreadgate!]! 610 - } 445 + """Field from lexicon""" 446 + artists: String 611 447 612 - type AppBskyFeedThreadgateEdge { 613 - node: AppBskyFeedThreadgate! 614 - cursor: String! 615 - } 448 + """Field from lexicon""" 449 + duration: Int 616 450 617 - enum AppBskyFeedThreadgateGroupByField { 618 - indexedAt 619 - allow 620 - createdAt 621 - hiddenReplies 622 - post 623 - } 451 + """Field from lexicon""" 452 + isrc: String 624 453 625 - input AppBskyFeedThreadgateGroupByFieldInput { 626 - field: AppBskyFeedThreadgateGroupByField! 627 - interval: DateInterval 628 - } 454 + """Field from lexicon""" 455 + musicServiceBaseDomain: String 629 456 630 - input AppBskyFeedThreadgateInput { 631 - allow: JSON 632 - createdAt: String! 633 - hiddenReplies: [String] 634 - post: String! 635 - } 457 + """Field from lexicon""" 458 + originUrl: String 636 459 637 - input AppBskyFeedThreadgateSortFieldInput { 638 - field: AppBskyFeedThreadgateGroupByField! 639 - direction: SortDirection 640 - } 460 + """Field from lexicon""" 461 + playedTime: String 641 462 642 - input AppBskyFeedThreadgateWhereInput { 643 - indexedAt: DateTimeFilter 644 - uri: StringFilter 645 - cid: StringFilter 646 - did: StringFilter 647 - collection: StringFilter 648 - actorHandle: StringFilter 649 - allow: StringFilter 650 - createdAt: StringFilter 651 - hiddenReplies: StringFilter 652 - post: StringFilter 653 - json: StringFilter 654 - and: [AppBskyFeedThreadgateWhereInput] 655 - or: [AppBskyFeedThreadgateWhereInput] 656 - } 463 + """Field from lexicon""" 464 + recordingMbId: String 657 465 658 - type AppBskyRichtextFacet { 659 - id: ID! 660 - uri: String! 661 - cid: String! 662 - did: String! 663 - indexedAt: String! 664 - actorHandle: String 665 - features: JSON! 666 - index: AppBskyRichtextFacetByteSlice! 667 - appBskyActorProfile: AppBskyActorProfile 668 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 669 - appBskyFeedPostgatesCount: Int! 670 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 671 - appBskyFeedThreadgatesCount: Int! 672 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 673 - appBskyActorProfilesCount: Int! 674 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 675 - fmTealAlphaFeedPlaysCount: Int! 676 - } 466 + """Field from lexicon""" 467 + releaseMbId: String 677 468 678 - type AppBskyRichtextFacetAggregated { 679 - features: JSON 680 - index: JSON 681 - count: Int! 682 - } 469 + """Field from lexicon""" 470 + releaseName: String 683 471 684 - type AppBskyRichtextFacetByteSlice { 685 - byteEnd: Int 686 - byteStart: Int 687 - } 472 + """Field from lexicon""" 473 + submissionClientAgent: String 688 474 689 - type AppBskyRichtextFacetConnection { 690 - totalCount: Int! 691 - pageInfo: PageInfo! 692 - edges: [AppBskyRichtextFacetEdge!]! 693 - nodes: [AppBskyRichtextFacet!]! 694 - } 475 + """Field from lexicon""" 476 + trackMbId: String 695 477 696 - type AppBskyRichtextFacetEdge { 697 - node: AppBskyRichtextFacet! 698 - cursor: String! 699 - } 478 + """Field from lexicon""" 479 + trackName: String 700 480 701 - enum AppBskyRichtextFacetGroupByField { 702 - indexedAt 703 - features 704 - index 705 - } 481 + """ 482 + Reverse join: records in app.bsky.actor.profile that reference this record via joinedViaStarterPack 483 + """ 484 + appBskyActorProfileViaJoinedViaStarterPack( 485 + """Returns the first n items from the list""" 486 + first: Int 706 487 707 - input AppBskyRichtextFacetGroupByFieldInput { 708 - field: AppBskyRichtextFacetGroupByField! 709 - interval: DateInterval 710 - } 488 + """Returns items after the given cursor""" 489 + after: String 711 490 712 - input AppBskyRichtextFacetInput { 713 - features: JSON! 714 - index: JSON! 715 - } 491 + """Returns the last n items from the list""" 492 + last: Int 716 493 717 - input AppBskyRichtextFacetSortFieldInput { 718 - field: AppBskyRichtextFacetGroupByField! 719 - direction: SortDirection 720 - } 494 + """Returns items before the given cursor""" 495 + before: String 721 496 722 - input AppBskyRichtextFacetWhereInput { 723 - indexedAt: DateTimeFilter 724 - uri: StringFilter 725 - cid: StringFilter 726 - did: StringFilter 727 - collection: StringFilter 728 - actorHandle: StringFilter 729 - features: StringFilter 730 - index: StringFilter 731 - json: StringFilter 732 - and: [AppBskyRichtextFacetWhereInput] 733 - or: [AppBskyRichtextFacetWhereInput] 734 - } 497 + """Sort order for the connection""" 498 + sortBy: [AppBskyActorProfileSortFieldInput!] 735 499 736 - type Blob { 737 - ref: String! 738 - mimeType: String! 739 - size: Int! 500 + """Filter conditions for the query""" 501 + where: AppBskyActorProfileWhereInput 502 + ): AppBskyActorProfileConnection 740 503 741 504 """ 742 - Generate CDN URL for the blob with the specified preset (avatar, banner, feed_thumbnail, feed_fullsize) 505 + Reverse join: records in app.bsky.actor.profile that reference this record via pinnedPost 743 506 """ 744 - url(preset: String): String! 745 - } 507 + appBskyActorProfileViaPinnedPost( 508 + """Returns the first n items from the list""" 509 + first: Int 746 510 747 - type BlobUploadResponse { 748 - blob: Blob! 749 - } 511 + """Returns items after the given cursor""" 512 + after: String 750 513 751 - type CollectionSummary { 752 - collection: String! 753 - estimatedRepos: Int! 754 - isExternal: Boolean! 755 - } 514 + """Returns the last n items from the list""" 515 + last: Int 756 516 757 - type ComAtprotoRepoStrongRef { 758 - id: ID! 759 - did: String! 760 - indexedAt: String! 761 - actorHandle: String 762 - cid: String! 763 - uri: String! 764 - appBskyFeedPostgate: AppBskyFeedPostgate 765 - appBskyFeedThreadgate: AppBskyFeedThreadgate 766 - appBskyActorProfile: AppBskyActorProfile 767 - fmTealAlphaFeedPlay: FmTealAlphaFeedPlay 768 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 769 - appBskyFeedPostgatesCount: Int! 770 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 771 - appBskyFeedThreadgatesCount: Int! 772 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 773 - appBskyActorProfilesCount: Int! 774 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 775 - fmTealAlphaFeedPlaysCount: Int! 776 - } 517 + """Returns items before the given cursor""" 518 + before: String 777 519 778 - type ComAtprotoRepoStrongRefAggregated { 779 - cid: JSON 780 - uri: JSON 781 - count: Int! 782 - } 520 + """Sort order for the connection""" 521 + sortBy: [AppBskyActorProfileSortFieldInput!] 783 522 784 - type ComAtprotoRepoStrongRefConnection { 785 - totalCount: Int! 786 - pageInfo: PageInfo! 787 - edges: [ComAtprotoRepoStrongRefEdge!]! 788 - nodes: [ComAtprotoRepoStrongRef!]! 789 - } 523 + """Filter conditions for the query""" 524 + where: AppBskyActorProfileWhereInput 525 + ): AppBskyActorProfileConnection 790 526 791 - type ComAtprotoRepoStrongRefEdge { 792 - node: ComAtprotoRepoStrongRef! 793 - cursor: String! 527 + """ 528 + DID join: record in app.bsky.actor.profile that shares the same DID as this record 529 + """ 530 + appBskyActorProfileByDid: AppBskyActorProfile 794 531 } 795 532 796 - enum ComAtprotoRepoStrongRefGroupByField { 797 - indexedAt 798 - cid 799 - uri 800 - } 533 + """Aggregated results for fm.teal.alpha.feed.play""" 534 + type FmTealAlphaFeedPlayAggregated { 535 + """Grouped field value""" 536 + uri: String 801 537 802 - input ComAtprotoRepoStrongRefGroupByFieldInput { 803 - field: ComAtprotoRepoStrongRefGroupByField! 804 - interval: DateInterval 805 - } 538 + """Grouped field value""" 539 + cid: String 806 540 807 - input ComAtprotoRepoStrongRefInput { 808 - cid: String! 809 - uri: String! 810 - } 541 + """Grouped field value""" 542 + did: String 811 543 812 - input ComAtprotoRepoStrongRefSortFieldInput { 813 - field: ComAtprotoRepoStrongRefGroupByField! 814 - direction: SortDirection 815 - } 544 + """Grouped field value""" 545 + collection: String 816 546 817 - input ComAtprotoRepoStrongRefWhereInput { 818 - indexedAt: DateTimeFilter 819 - did: StringFilter 820 - collection: StringFilter 821 - actorHandle: StringFilter 822 - cid: StringFilter 823 - uri: StringFilter 824 - json: StringFilter 825 - and: [ComAtprotoRepoStrongRefWhereInput] 826 - or: [ComAtprotoRepoStrongRefWhereInput] 827 - } 547 + """Grouped field value""" 548 + indexed_at: String 828 549 829 - enum DateInterval { 830 - second 831 - minute 832 - hour 833 - day 834 - week 835 - month 836 - quarter 837 - year 838 - } 550 + """Grouped field value""" 551 + artistMbIds: String 839 552 840 - input DateTimeFilter { 841 - eq: String 842 - gt: String 843 - gte: String 844 - lt: String 845 - lte: String 846 - } 553 + """Grouped field value""" 554 + artistNames: String 847 555 848 - type DeleteSliceRecordsOutput { 849 - message: String! 850 - recordsDeleted: Int! 851 - actorsDeleted: Int! 852 - } 556 + """Grouped field value""" 557 + artists: String 853 558 854 - type FmTealAlphaFeedDefsArtist { 855 - artistMbId: String 856 - artistName: String 857 - } 559 + """Grouped field value""" 560 + duration: String 858 561 859 - type FmTealAlphaFeedPlay { 860 - id: ID! 861 - uri: String! 862 - cid: String! 863 - did: String! 864 - indexedAt: String! 865 - actorHandle: String 866 - artistMbIds: [String] 867 - artistNames: [String] 868 - artists: [FmTealAlphaFeedDefsArtist] 869 - duration: Int 562 + """Grouped field value""" 870 563 isrc: String 564 + 565 + """Grouped field value""" 871 566 musicServiceBaseDomain: String 567 + 568 + """Grouped field value""" 872 569 originUrl: String 570 + 571 + """Grouped field value""" 873 572 playedTime: String 573 + 574 + """Grouped field value""" 874 575 recordingMbId: String 576 + 577 + """Grouped field value""" 875 578 releaseMbId: String 579 + 580 + """Grouped field value""" 876 581 releaseName: String 582 + 583 + """Grouped field value""" 877 584 submissionClientAgent: String 585 + 586 + """Grouped field value""" 878 587 trackMbId: String 879 - trackName: String! 880 - appBskyActorProfile: AppBskyActorProfile 881 - appBskyFeedPostgates(limit: Int): [AppBskyFeedPostgate!]! 882 - appBskyFeedPostgatesCount: Int! 883 - appBskyFeedThreadgates(limit: Int): [AppBskyFeedThreadgate!]! 884 - appBskyFeedThreadgatesCount: Int! 885 - appBskyActorProfiles(limit: Int): [AppBskyActorProfile!]! 886 - appBskyActorProfilesCount: Int! 887 - fmTealAlphaFeedPlays(limit: Int): [FmTealAlphaFeedPlay!]! 888 - fmTealAlphaFeedPlaysCount: Int! 889 - } 588 + 589 + """Grouped field value""" 590 + trackName: String 890 591 891 - type FmTealAlphaFeedPlayAggregated { 892 - artistMbIds: JSON 893 - artistNames: JSON 894 - artists: JSON 895 - duration: JSON 896 - isrc: JSON 897 - musicServiceBaseDomain: JSON 898 - originUrl: JSON 899 - playedTime: JSON 900 - recordingMbId: JSON 901 - releaseMbId: JSON 902 - releaseName: JSON 903 - submissionClientAgent: JSON 904 - trackMbId: JSON 905 - trackName: JSON 592 + """Count of records in this group""" 906 593 count: Int! 907 594 } 908 595 596 + """A connection to a list of items for FmTealAlphaFeedPlay""" 909 597 type FmTealAlphaFeedPlayConnection { 910 - totalCount: Int! 598 + """A list of edges""" 599 + edges: [FmTealAlphaFeedPlayEdge!]! 600 + 601 + """Information to aid in pagination""" 911 602 pageInfo: PageInfo! 912 - edges: [FmTealAlphaFeedPlayEdge!]! 913 - nodes: [FmTealAlphaFeedPlay!]! 603 + 604 + """Total number of items in the connection""" 605 + totalCount: Int 914 606 } 915 607 608 + """An edge in a connection for FmTealAlphaFeedPlay""" 916 609 type FmTealAlphaFeedPlayEdge { 610 + """The item at the end of the edge""" 917 611 node: FmTealAlphaFeedPlay! 612 + 613 + """A cursor for use in pagination""" 918 614 cursor: String! 919 615 } 920 616 617 + """Filter operators for FmTealAlphaFeedPlay fields""" 618 + input FmTealAlphaFeedPlayFieldCondition { 619 + """Exact match (equals)""" 620 + eq: String 621 + 622 + """Match any value in the list""" 623 + in: [String!] 624 + 625 + """Case-insensitive substring match (string fields only)""" 626 + contains: String 627 + 628 + """Greater than""" 629 + gt: String 630 + 631 + """Greater than or equal to""" 632 + gte: String 633 + 634 + """Less than""" 635 + lt: String 636 + 637 + """Less than or equal to""" 638 + lte: String 639 + } 640 + 641 + """Available groupBy fields for FmTealAlphaFeedPlay""" 921 642 enum FmTealAlphaFeedPlayGroupByField { 643 + """Group by uri""" 644 + uri 645 + 646 + """Group by cid""" 647 + cid 648 + 649 + """Group by did""" 650 + did 651 + 652 + """Group by collection""" 653 + collection 654 + 655 + """Group by indexedAt""" 922 656 indexedAt 657 + 658 + """Group by actorHandle""" 659 + actorHandle 660 + 661 + """Group by artistMbIds""" 923 662 artistMbIds 663 + 664 + """Group by artistNames""" 924 665 artistNames 666 + 667 + """Group by artists""" 925 668 artists 669 + 670 + """Group by duration""" 926 671 duration 672 + 673 + """Group by isrc""" 927 674 isrc 675 + 676 + """Group by musicServiceBaseDomain""" 928 677 musicServiceBaseDomain 678 + 679 + """Group by originUrl""" 929 680 originUrl 681 + 682 + """Group by playedTime""" 930 683 playedTime 684 + 685 + """Group by recordingMbId""" 931 686 recordingMbId 687 + 688 + """Group by releaseMbId""" 932 689 releaseMbId 690 + 691 + """Group by releaseName""" 933 692 releaseName 693 + 694 + """Group by submissionClientAgent""" 934 695 submissionClientAgent 696 + 697 + """Group by trackMbId""" 935 698 trackMbId 699 + 700 + """Group by trackName""" 936 701 trackName 937 702 } 938 703 704 + """Specifies a field to group by with optional date truncation""" 939 705 input FmTealAlphaFeedPlayGroupByFieldInput { 706 + """Field name to group by""" 940 707 field: FmTealAlphaFeedPlayGroupByField! 708 + 709 + """Date truncation interval (for datetime fields)""" 941 710 interval: DateInterval 942 711 } 943 712 713 + """Input type for FmTealAlphaFeedPlayInput""" 944 714 input FmTealAlphaFeedPlayInput { 945 - artistMbIds: [String] 946 - artistNames: [String] 947 - artists: JSON 715 + """Input field for artistMbIds""" 716 + artistMbIds: String 717 + 718 + """Input field for artistNames""" 719 + artistNames: String 720 + 721 + """Input field for artists""" 722 + artists: String 723 + 724 + """Input field for duration""" 948 725 duration: Int 726 + 727 + """Input field for isrc""" 949 728 isrc: String 729 + 730 + """Input field for musicServiceBaseDomain""" 950 731 musicServiceBaseDomain: String 732 + 733 + """Input field for originUrl""" 951 734 originUrl: String 735 + 736 + """Input field for playedTime""" 952 737 playedTime: String 738 + 739 + """Input field for recordingMbId""" 953 740 recordingMbId: String 741 + 742 + """Input field for releaseMbId""" 954 743 releaseMbId: String 744 + 745 + """Input field for releaseName""" 955 746 releaseName: String 747 + 748 + """Input field for submissionClientAgent""" 956 749 submissionClientAgent: String 750 + 751 + """Input field for trackMbId""" 957 752 trackMbId: String 753 + 754 + """Input field for trackName""" 958 755 trackName: String! 959 756 } 960 757 961 - input FmTealAlphaFeedPlaySortFieldInput { 962 - field: FmTealAlphaFeedPlayGroupByField! 963 - direction: SortDirection 964 - } 758 + """Available sort fields for FmTealAlphaFeedPlay""" 759 + enum FmTealAlphaFeedPlaySortField { 760 + """Sort by uri""" 761 + uri 965 762 966 - input FmTealAlphaFeedPlayWhereInput { 967 - indexedAt: DateTimeFilter 968 - uri: StringFilter 969 - cid: StringFilter 970 - did: StringFilter 971 - collection: StringFilter 972 - actorHandle: StringFilter 973 - artistMbIds: StringFilter 974 - artistNames: StringFilter 975 - artists: StringFilter 976 - duration: IntFilter 977 - isrc: StringFilter 978 - musicServiceBaseDomain: StringFilter 979 - originUrl: StringFilter 980 - playedTime: StringFilter 981 - recordingMbId: StringFilter 982 - releaseMbId: StringFilter 983 - releaseName: StringFilter 984 - submissionClientAgent: StringFilter 985 - trackMbId: StringFilter 986 - trackName: StringFilter 987 - json: StringFilter 988 - and: [FmTealAlphaFeedPlayWhereInput] 989 - or: [FmTealAlphaFeedPlayWhereInput] 990 - } 763 + """Sort by cid""" 764 + cid 991 765 992 - input IntFilter { 993 - eq: Int 994 - in: [Int] 995 - gt: Int 996 - gte: Int 997 - lt: Int 998 - lte: Int 999 - } 766 + """Sort by did""" 767 + did 1000 768 1001 - type JetstreamLogEntry { 1002 - id: String! 1003 - createdAt: String! 1004 - logType: String! 1005 - jobId: String 1006 - userDid: String 1007 - sliceUri: String 1008 - level: String! 1009 - message: String! 1010 - metadata: JSON 1011 - } 769 + """Sort by collection""" 770 + collection 1012 771 1013 - scalar JSON 772 + """Sort by indexedAt""" 773 + indexedAt 1014 774 1015 - type Mutation { 1016 - """Sync user collections for a given DID""" 1017 - syncUserCollections(did: String!): SyncResult! 775 + """Sort by duration""" 776 + duration 1018 777 1019 - """Create a new app.bsky.embed.record record""" 1020 - createAppBskyEmbedRecord(input: AppBskyEmbedRecordInput!, rkey: String): AppBskyEmbedRecord! 778 + """Sort by isrc""" 779 + isrc 1021 780 1022 - """Update a app.bsky.embed.record record""" 1023 - updateAppBskyEmbedRecord(rkey: String!, input: AppBskyEmbedRecordInput!): AppBskyEmbedRecord! 781 + """Sort by musicServiceBaseDomain""" 782 + musicServiceBaseDomain 1024 783 1025 - """Delete a app.bsky.embed.record record""" 1026 - deleteAppBskyEmbedRecord(rkey: String!): AppBskyEmbedRecord! 784 + """Sort by originUrl""" 785 + originUrl 1027 786 1028 - """Create a new app.bsky.embed.images record""" 1029 - createAppBskyEmbedImages(input: AppBskyEmbedImagesInput!, rkey: String): AppBskyEmbedImages! 787 + """Sort by playedTime""" 788 + playedTime 789 + 790 + """Sort by recordingMbId""" 791 + recordingMbId 1030 792 1031 - """Update a app.bsky.embed.images record""" 1032 - updateAppBskyEmbedImages(rkey: String!, input: AppBskyEmbedImagesInput!): AppBskyEmbedImages! 793 + """Sort by releaseMbId""" 794 + releaseMbId 1033 795 1034 - """Delete a app.bsky.embed.images record""" 1035 - deleteAppBskyEmbedImages(rkey: String!): AppBskyEmbedImages! 796 + """Sort by releaseName""" 797 + releaseName 1036 798 1037 - """Create a new app.bsky.embed.recordWithMedia record""" 1038 - createAppBskyEmbedRecordWithMedia(input: AppBskyEmbedRecordWithMediaInput!, rkey: String): AppBskyEmbedRecordWithMedia! 799 + """Sort by submissionClientAgent""" 800 + submissionClientAgent 1039 801 1040 - """Update a app.bsky.embed.recordWithMedia record""" 1041 - updateAppBskyEmbedRecordWithMedia(rkey: String!, input: AppBskyEmbedRecordWithMediaInput!): AppBskyEmbedRecordWithMedia! 802 + """Sort by trackMbId""" 803 + trackMbId 1042 804 1043 - """Delete a app.bsky.embed.recordWithMedia record""" 1044 - deleteAppBskyEmbedRecordWithMedia(rkey: String!): AppBskyEmbedRecordWithMedia! 805 + """Sort by trackName""" 806 + trackName 807 + } 1045 808 1046 - """Create a new app.bsky.embed.video record""" 1047 - createAppBskyEmbedVideo(input: AppBskyEmbedVideoInput!, rkey: String): AppBskyEmbedVideo! 809 + """Specifies a field to sort by and its direction for FmTealAlphaFeedPlay""" 810 + input FmTealAlphaFeedPlaySortFieldInput { 811 + """Field to sort by""" 812 + field: FmTealAlphaFeedPlaySortField! 1048 813 1049 - """Update a app.bsky.embed.video record""" 1050 - updateAppBskyEmbedVideo(rkey: String!, input: AppBskyEmbedVideoInput!): AppBskyEmbedVideo! 814 + """Sort direction (ASC or DESC)""" 815 + direction: SortDirection! 816 + } 1051 817 1052 - """Delete a app.bsky.embed.video record""" 1053 - deleteAppBskyEmbedVideo(rkey: String!): AppBskyEmbedVideo! 818 + """Filter conditions for FmTealAlphaFeedPlay with nested AND/OR support""" 819 + input FmTealAlphaFeedPlayWhereInput { 820 + """Filter by uri""" 821 + uri: FmTealAlphaFeedPlayFieldCondition 1054 822 1055 - """Create a new app.bsky.embed.external record""" 1056 - createAppBskyEmbedExternal(input: AppBskyEmbedExternalInput!, rkey: String): AppBskyEmbedExternal! 823 + """Filter by cid""" 824 + cid: FmTealAlphaFeedPlayFieldCondition 1057 825 1058 - """Update a app.bsky.embed.external record""" 1059 - updateAppBskyEmbedExternal(rkey: String!, input: AppBskyEmbedExternalInput!): AppBskyEmbedExternal! 826 + """Filter by did""" 827 + did: FmTealAlphaFeedPlayFieldCondition 1060 828 1061 - """Delete a app.bsky.embed.external record""" 1062 - deleteAppBskyEmbedExternal(rkey: String!): AppBskyEmbedExternal! 829 + """Filter by collection""" 830 + collection: FmTealAlphaFeedPlayFieldCondition 1063 831 1064 - """Create a new app.bsky.feed.postgate record""" 1065 - createAppBskyFeedPostgate(input: AppBskyFeedPostgateInput!, rkey: String): AppBskyFeedPostgate! 832 + """Filter by indexedAt""" 833 + indexedAt: FmTealAlphaFeedPlayFieldCondition 1066 834 1067 - """Update a app.bsky.feed.postgate record""" 1068 - updateAppBskyFeedPostgate(rkey: String!, input: AppBskyFeedPostgateInput!): AppBskyFeedPostgate! 835 + """Filter by actorHandle""" 836 + actorHandle: FmTealAlphaFeedPlayFieldCondition 1069 837 1070 - """Delete a app.bsky.feed.postgate record""" 1071 - deleteAppBskyFeedPostgate(rkey: String!): AppBskyFeedPostgate! 838 + """Filter by duration""" 839 + duration: FmTealAlphaFeedPlayFieldCondition 1072 840 1073 - """Create a new app.bsky.feed.threadgate record""" 1074 - createAppBskyFeedThreadgate(input: AppBskyFeedThreadgateInput!, rkey: String): AppBskyFeedThreadgate! 841 + """Filter by isrc""" 842 + isrc: FmTealAlphaFeedPlayFieldCondition 1075 843 1076 - """Update a app.bsky.feed.threadgate record""" 1077 - updateAppBskyFeedThreadgate(rkey: String!, input: AppBskyFeedThreadgateInput!): AppBskyFeedThreadgate! 844 + """Filter by musicServiceBaseDomain""" 845 + musicServiceBaseDomain: FmTealAlphaFeedPlayFieldCondition 1078 846 1079 - """Delete a app.bsky.feed.threadgate record""" 1080 - deleteAppBskyFeedThreadgate(rkey: String!): AppBskyFeedThreadgate! 847 + """Filter by originUrl""" 848 + originUrl: FmTealAlphaFeedPlayFieldCondition 1081 849 1082 - """Create a new app.bsky.richtext.facet record""" 1083 - createAppBskyRichtextFacet(input: AppBskyRichtextFacetInput!, rkey: String): AppBskyRichtextFacet! 850 + """Filter by playedTime""" 851 + playedTime: FmTealAlphaFeedPlayFieldCondition 1084 852 1085 - """Update a app.bsky.richtext.facet record""" 1086 - updateAppBskyRichtextFacet(rkey: String!, input: AppBskyRichtextFacetInput!): AppBskyRichtextFacet! 853 + """Filter by recordingMbId""" 854 + recordingMbId: FmTealAlphaFeedPlayFieldCondition 1087 855 1088 - """Delete a app.bsky.richtext.facet record""" 1089 - deleteAppBskyRichtextFacet(rkey: String!): AppBskyRichtextFacet! 856 + """Filter by releaseMbId""" 857 + releaseMbId: FmTealAlphaFeedPlayFieldCondition 1090 858 1091 - """Create a new app.bsky.actor.profile record""" 1092 - createAppBskyActorProfile(input: AppBskyActorProfileInput!, rkey: String): AppBskyActorProfile! 859 + """Filter by releaseName""" 860 + releaseName: FmTealAlphaFeedPlayFieldCondition 1093 861 1094 - """Update a app.bsky.actor.profile record""" 1095 - updateAppBskyActorProfile(rkey: String!, input: AppBskyActorProfileInput!): AppBskyActorProfile! 862 + """Filter by submissionClientAgent""" 863 + submissionClientAgent: FmTealAlphaFeedPlayFieldCondition 1096 864 1097 - """Delete a app.bsky.actor.profile record""" 1098 - deleteAppBskyActorProfile(rkey: String!): AppBskyActorProfile! 865 + """Filter by trackMbId""" 866 + trackMbId: FmTealAlphaFeedPlayFieldCondition 1099 867 1100 - """Create a new com.atproto.repo.strongRef record""" 1101 - createComAtprotoRepoStrongRef(input: ComAtprotoRepoStrongRefInput!, rkey: String): ComAtprotoRepoStrongRef! 868 + """Filter by trackName""" 869 + trackName: FmTealAlphaFeedPlayFieldCondition 1102 870 1103 - """Update a com.atproto.repo.strongRef record""" 1104 - updateComAtprotoRepoStrongRef(rkey: String!, input: ComAtprotoRepoStrongRefInput!): ComAtprotoRepoStrongRef! 871 + """All conditions must match (AND logic)""" 872 + and: [FmTealAlphaFeedPlayWhereInput!] 1105 873 1106 - """Delete a com.atproto.repo.strongRef record""" 1107 - deleteComAtprotoRepoStrongRef(rkey: String!): ComAtprotoRepoStrongRef! 874 + """Any condition must match (OR logic)""" 875 + or: [FmTealAlphaFeedPlayWhereInput!] 876 + } 1108 877 1109 - """Create a new fm.teal.alpha.feed.play record""" 1110 - createFmTealAlphaFeedPlay(input: FmTealAlphaFeedPlayInput!, rkey: String): FmTealAlphaFeedPlay! 878 + """Root mutation type""" 879 + type Mutation { 880 + """Upload a blob to the PDS""" 881 + uploadBlob( 882 + """Base64 encoded blob data""" 883 + data: String! 1111 884 1112 - """Update a fm.teal.alpha.feed.play record""" 1113 - updateFmTealAlphaFeedPlay(rkey: String!, input: FmTealAlphaFeedPlayInput!): FmTealAlphaFeedPlay! 885 + """MIME type of the blob""" 886 + mimeType: String! 887 + ): BlobUploadResponse! 1114 888 1115 - """Delete a fm.teal.alpha.feed.play record""" 1116 - deleteFmTealAlphaFeedPlay(rkey: String!): FmTealAlphaFeedPlay! 889 + """Create a new fm.teal.alpha.feed.play record""" 890 + createFmTealAlphaFeedPlay( 891 + """Record data""" 892 + input: FmTealAlphaFeedPlayInput! 1117 893 1118 - """Start a sync job to backfill collections from the ATProto relay""" 1119 - startSync(slice: String, collections: [String], externalCollections: [String], repos: [String], limitPerRepo: Int, skipValidation: Boolean, maxRepos: Int): StartSyncOutput! 894 + """Optional record key (defaults to TID)""" 895 + rkey: String 896 + ): FmTealAlphaFeedPlay 1120 897 1121 - """Cancel a pending or running sync job""" 1122 - cancelJob(jobId: String!): Boolean! 898 + """Update an existing fm.teal.alpha.feed.play record""" 899 + updateFmTealAlphaFeedPlay( 900 + """Record key to update""" 901 + rkey: String! 1123 902 1124 - """Delete a sync job from the database""" 1125 - deleteJob(id: ID!): ID 903 + """Updated record data""" 904 + input: FmTealAlphaFeedPlayInput! 905 + ): FmTealAlphaFeedPlay 1126 906 1127 - """Upload a blob to the user's AT Protocol repository""" 1128 - uploadBlob(data: String!, mimeType: String!): BlobUploadResponse! 907 + """Delete a fm.teal.alpha.feed.play record""" 908 + deleteFmTealAlphaFeedPlay( 909 + """Record key to delete""" 910 + rkey: String! 911 + ): DeleteResult 1129 912 1130 - """Register a new OAuth client for a slice""" 1131 - createOAuthClient(sliceUri: String!, clientName: String!, redirectUris: [String!]!, scope: String!, clientUri: String, logoUri: String, tosUri: String, policyUri: String): OAuthClient! 913 + """Create a new app.bsky.actor.profile record""" 914 + createAppBskyActorProfile( 915 + """Record data""" 916 + input: AppBskyActorProfileInput! 1132 917 1133 - """Update an OAuth client""" 1134 - updateOAuthClient(clientId: String!, clientName: String, redirectUris: [String], scope: String, clientUri: String, logoUri: String, tosUri: String, policyUri: String): OAuthClient! 918 + """Optional record key (defaults to TID)""" 919 + rkey: String 920 + ): AppBskyActorProfile 1135 921 1136 - """Delete an OAuth client""" 1137 - deleteOAuthClient(clientId: String!): Boolean! 922 + """Update an existing app.bsky.actor.profile record""" 923 + updateAppBskyActorProfile( 924 + """Record key to update""" 925 + rkey: String! 1138 926 1139 - """ 1140 - Delete all records and actors from a slice index. Requires authentication and slice ownership. 1141 - """ 1142 - deleteSliceRecords(slice: String): DeleteSliceRecordsOutput! 1143 - } 927 + """Updated record data""" 928 + input: AppBskyActorProfileInput! 929 + ): AppBskyActorProfile 1144 930 1145 - type OAuthClient { 1146 - clientId: String! 1147 - clientSecret: String 1148 - clientName: String! 1149 - redirectUris: [String!]! 1150 - grantTypes: [String!]! 1151 - responseTypes: [String!]! 1152 - scope: String 1153 - clientUri: String 1154 - logoUri: String 1155 - tosUri: String 1156 - policyUri: String 1157 - createdAt: String! 1158 - createdByDid: String! 931 + """Delete a app.bsky.actor.profile record""" 932 + deleteAppBskyActorProfile( 933 + """Record key to delete""" 934 + rkey: String! 935 + ): DeleteResult 1159 936 } 1160 937 938 + """Information about pagination in a connection""" 1161 939 type PageInfo { 940 + """When paginating forwards, are there more items?""" 1162 941 hasNextPage: Boolean! 942 + 943 + """When paginating backwards, are there more items?""" 1163 944 hasPreviousPage: Boolean! 945 + 946 + """Cursor corresponding to the first item in the page""" 1164 947 startCursor: String 948 + 949 + """Cursor corresponding to the last item in the page""" 1165 950 endCursor: String 1166 951 } 1167 952 953 + """Root query type""" 1168 954 type Query { 1169 - """Query app.bsky.embed.record records""" 1170 - appBskyEmbedRecords(first: Int, after: String, last: Int, before: String, sortBy: [AppBskyEmbedRecordSortFieldInput], where: AppBskyEmbedRecordWhereInput): AppBskyEmbedRecordConnection! 1171 - 1172 - """ 1173 - Aggregated query for app.bsky.embed.record records with GROUP BY support 1174 - """ 1175 - appBskyEmbedRecordsAggregated(groupBy: [AppBskyEmbedRecordGroupByFieldInput!], where: AppBskyEmbedRecordWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedRecordAggregated!]! 1176 - 1177 - """Query app.bsky.embed.images records""" 1178 - appBskyEmbedImageses(first: Int, after: String, last: Int, before: String, sortBy: [AppBskyEmbedImagesSortFieldInput], where: AppBskyEmbedImagesWhereInput): AppBskyEmbedImagesConnection! 1179 - 1180 - """ 1181 - Aggregated query for app.bsky.embed.images records with GROUP BY support 1182 - """ 1183 - appBskyEmbedImagesesAggregated(groupBy: [AppBskyEmbedImagesGroupByFieldInput!], where: AppBskyEmbedImagesWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedImagesAggregated!]! 1184 - 1185 - """Query app.bsky.embed.recordWithMedia records""" 1186 - appBskyEmbedRecordWithMedias(first: Int, after: String, last: Int, before: String, sortBy: [AppBskyEmbedRecordWithMediaSortFieldInput], where: AppBskyEmbedRecordWithMediaWhereInput): AppBskyEmbedRecordWithMediaConnection! 1187 - 1188 - """ 1189 - Aggregated query for app.bsky.embed.recordWithMedia records with GROUP BY support 1190 - """ 1191 - appBskyEmbedRecordWithMediasAggregated(groupBy: [AppBskyEmbedRecordWithMediaGroupByFieldInput!], where: AppBskyEmbedRecordWithMediaWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedRecordWithMediaAggregated!]! 1192 - 1193 - """Query app.bsky.embed.video records""" 1194 - appBskyEmbedVideos(first: Int, after: String, last: Int, before: String, sortBy: [AppBskyEmbedVideoSortFieldInput], where: AppBskyEmbedVideoWhereInput): AppBskyEmbedVideoConnection! 955 + """Query fm.teal.alpha.feed.play with cursor pagination and sorting""" 956 + fmTealAlphaFeedPlay( 957 + """Returns the first n items from the list""" 958 + first: Int 1195 959 1196 - """ 1197 - Aggregated query for app.bsky.embed.video records with GROUP BY support 1198 - """ 1199 - appBskyEmbedVideosAggregated(groupBy: [AppBskyEmbedVideoGroupByFieldInput!], where: AppBskyEmbedVideoWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedVideoAggregated!]! 1200 - 1201 - """Query app.bsky.embed.external records""" 1202 - appBskyEmbedExternals(first: Int, after: String, last: Int, before: String, sortBy: [AppBskyEmbedExternalSortFieldInput], where: AppBskyEmbedExternalWhereInput): AppBskyEmbedExternalConnection! 1203 - 1204 - """ 1205 - Aggregated query for app.bsky.embed.external records with GROUP BY support 1206 - """ 1207 - appBskyEmbedExternalsAggregated(groupBy: [AppBskyEmbedExternalGroupByFieldInput!], where: AppBskyEmbedExternalWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyEmbedExternalAggregated!]! 1208 - 1209 - """Query app.bsky.feed.postgate records""" 1210 - appBskyFeedPostgates(first: Int, after: String, last: Int, before: String, sortBy: [AppBskyFeedPostgateSortFieldInput], where: AppBskyFeedPostgateWhereInput): AppBskyFeedPostgateConnection! 1211 - 1212 - """ 1213 - Aggregated query for app.bsky.feed.postgate records with GROUP BY support 1214 - """ 1215 - appBskyFeedPostgatesAggregated(groupBy: [AppBskyFeedPostgateGroupByFieldInput!], where: AppBskyFeedPostgateWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyFeedPostgateAggregated!]! 1216 - 1217 - """Query app.bsky.feed.threadgate records""" 1218 - appBskyFeedThreadgates(first: Int, after: String, last: Int, before: String, sortBy: [AppBskyFeedThreadgateSortFieldInput], where: AppBskyFeedThreadgateWhereInput): AppBskyFeedThreadgateConnection! 1219 - 1220 - """ 1221 - Aggregated query for app.bsky.feed.threadgate records with GROUP BY support 1222 - """ 1223 - appBskyFeedThreadgatesAggregated(groupBy: [AppBskyFeedThreadgateGroupByFieldInput!], where: AppBskyFeedThreadgateWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyFeedThreadgateAggregated!]! 1224 - 1225 - """Query app.bsky.richtext.facet records""" 1226 - appBskyRichtextFacets(first: Int, after: String, last: Int, before: String, sortBy: [AppBskyRichtextFacetSortFieldInput], where: AppBskyRichtextFacetWhereInput): AppBskyRichtextFacetConnection! 1227 - 1228 - """ 1229 - Aggregated query for app.bsky.richtext.facet records with GROUP BY support 1230 - """ 1231 - appBskyRichtextFacetsAggregated(groupBy: [AppBskyRichtextFacetGroupByFieldInput!], where: AppBskyRichtextFacetWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyRichtextFacetAggregated!]! 960 + """Returns items after the given cursor""" 961 + after: String 1232 962 1233 - """Query app.bsky.actor.profile records""" 1234 - appBskyActorProfiles(first: Int, after: String, last: Int, before: String, sortBy: [AppBskyActorProfileSortFieldInput], where: AppBskyActorProfileWhereInput): AppBskyActorProfileConnection! 963 + """Returns the last n items from the list""" 964 + last: Int 1235 965 1236 - """ 1237 - Aggregated query for app.bsky.actor.profile records with GROUP BY support 1238 - """ 1239 - appBskyActorProfilesAggregated(groupBy: [AppBskyActorProfileGroupByFieldInput!], where: AppBskyActorProfileWhereInput, orderBy: AggregationOrderBy, limit: Int): [AppBskyActorProfileAggregated!]! 966 + """Returns items before the given cursor""" 967 + before: String 1240 968 1241 - """Query com.atproto.repo.strongRef records""" 1242 - comAtprotoRepoStrongRefs(first: Int, after: String, last: Int, before: String, sortBy: [ComAtprotoRepoStrongRefSortFieldInput], where: ComAtprotoRepoStrongRefWhereInput): ComAtprotoRepoStrongRefConnection! 969 + """Sort order for the connection""" 970 + sortBy: [FmTealAlphaFeedPlaySortFieldInput!] 1243 971 1244 - """ 1245 - Aggregated query for com.atproto.repo.strongRef records with GROUP BY support 1246 - """ 1247 - comAtprotoRepoStrongRefsAggregated(groupBy: [ComAtprotoRepoStrongRefGroupByFieldInput!], where: ComAtprotoRepoStrongRefWhereInput, orderBy: AggregationOrderBy, limit: Int): [ComAtprotoRepoStrongRefAggregated!]! 972 + """Filter conditions for the query""" 973 + where: FmTealAlphaFeedPlayWhereInput 974 + ): FmTealAlphaFeedPlayConnection 1248 975 1249 - """Query fm.teal.alpha.feed.play records""" 1250 - fmTealAlphaFeedPlays(first: Int, after: String, last: Int, before: String, sortBy: [FmTealAlphaFeedPlaySortFieldInput], where: FmTealAlphaFeedPlayWhereInput): FmTealAlphaFeedPlayConnection! 976 + """Query app.bsky.actor.profile with cursor pagination and sorting""" 977 + appBskyActorProfile( 978 + """Returns the first n items from the list""" 979 + first: Int 1251 980 1252 - """ 1253 - Aggregated query for fm.teal.alpha.feed.play records with GROUP BY support 1254 - """ 1255 - fmTealAlphaFeedPlaysAggregated(groupBy: [FmTealAlphaFeedPlayGroupByFieldInput!], where: FmTealAlphaFeedPlayWhereInput, orderBy: AggregationOrderBy, limit: Int): [FmTealAlphaFeedPlayAggregated!]! 981 + """Returns items after the given cursor""" 982 + after: String 1256 983 1257 - """ 1258 - Get logs from the Jetstream real-time indexing service, optionally filtered by slice 1259 - """ 1260 - jetstreamLogs(slice: String, limit: Int): [JetstreamLogEntry!]! 984 + """Returns the last n items from the list""" 985 + last: Int 1261 986 1262 - """Get status of a specific sync job""" 1263 - syncJob(jobId: String!): SyncJob 987 + """Returns items before the given cursor""" 988 + before: String 1264 989 1265 - """Get sync job history for a slice""" 1266 - syncJobs(slice: String, limit: Int): [SyncJob!]! 990 + """Sort order for the connection""" 991 + sortBy: [AppBskyActorProfileSortFieldInput!] 1267 992 1268 - """Get logs for a specific sync job""" 1269 - syncJobLogs(jobId: String!, limit: Int): [JetstreamLogEntry!]! 993 + """Filter conditions for the query""" 994 + where: AppBskyActorProfileWhereInput 995 + ): AppBskyActorProfileConnection 1270 996 1271 - """Get summary of repos that would be synced based on collection filters""" 1272 - getSyncSummary(slice: String!, collections: [String], externalCollections: [String], repos: [String]): SyncSummary! 997 + """Aggregated query for fm.teal.alpha.feed.play""" 998 + fmTealAlphaFeedPlayAggregated( 999 + """Fields to group by (required)""" 1000 + groupBy: [FmTealAlphaFeedPlayGroupByFieldInput!] 1273 1001 1274 - """ 1275 - Get sparkline data for multiple slices showing record indexing activity over time 1276 - """ 1277 - sparklines(slices: [String!]!, interval: String, duration: String): [SliceSparkline!]! 1002 + """Filter records before aggregation""" 1003 + where: FmTealAlphaFeedPlayWhereInput 1278 1004 1279 - """ 1280 - Query records across all collections in a slice with filtering and pagination. 1281 - Provide either sliceUri or both actorHandle and rkey. 1282 - """ 1283 - sliceRecords(sliceUri: String, actorHandle: String, rkey: String, first: Int, after: String, where: SliceRecordsWhereInput): SliceRecordsConnection! 1005 + """Order by count (default: desc)""" 1006 + orderBy: AggregationOrderBy 1284 1007 1285 - """Get all OAuth clients for a slice""" 1286 - oauthClients(slice: String): [OAuthClient!]! 1287 - } 1008 + """Maximum number of results (default 50, max 1000)""" 1009 + limit: Int 1010 + ): [FmTealAlphaFeedPlayAggregated!] 1288 1011 1289 - type SliceRecord { 1290 - uri: String! 1291 - cid: String! 1292 - did: String! 1293 - collection: String! 1294 - value: String! 1295 - indexedAt: String! 1296 - } 1012 + """Aggregated query for app.bsky.actor.profile""" 1013 + appBskyActorProfileAggregated( 1014 + """Fields to group by (required)""" 1015 + groupBy: [AppBskyActorProfileGroupByFieldInput!] 1297 1016 1298 - type SliceRecordEdge { 1299 - node: SliceRecord! 1300 - cursor: String! 1301 - } 1017 + """Filter records before aggregation""" 1018 + where: AppBskyActorProfileWhereInput 1302 1019 1303 - type SliceRecordsConnection { 1304 - totalCount: Int! 1305 - edges: [SliceRecordEdge!]! 1306 - pageInfo: PageInfo! 1307 - } 1020 + """Order by count (default: desc)""" 1021 + orderBy: AggregationOrderBy 1308 1022 1309 - input SliceRecordsWhereInput { 1310 - collection: StringFilter 1311 - did: StringFilter 1312 - uri: StringFilter 1313 - cid: StringFilter 1314 - indexedAt: DateTimeFilter 1315 - json: StringFilter 1316 - or: [SliceRecordsWhereInput] 1023 + """Maximum number of results (default 50, max 1000)""" 1024 + limit: Int 1025 + ): [AppBskyActorProfileAggregated!] 1317 1026 } 1318 1027 1319 - type SliceSparkline { 1320 - sliceUri: String! 1321 - points: [SparklinePoint!]! 1322 - } 1028 + union Record = AppBskyActorProfile | FmTealAlphaFeedPlay 1323 1029 1030 + """Sort direction for query results""" 1324 1031 enum SortDirection { 1325 - asc 1326 - desc 1327 - } 1328 - 1329 - type SparklinePoint { 1330 - timestamp: String! 1331 - count: Int! 1332 - } 1333 - 1334 - type StartSyncOutput { 1335 - jobId: String! 1336 - message: String! 1337 - } 1032 + """Ascending order""" 1033 + ASC 1338 1034 1339 - input StringFilter { 1340 - eq: String 1341 - in: [String] 1342 - contains: String 1343 - fuzzy: String 1344 - gt: String 1345 - gte: String 1346 - lt: String 1347 - lte: String 1035 + """Descending order""" 1036 + DESC 1348 1037 } 1349 1038 1039 + """GraphQL subscription root""" 1350 1040 type Subscription { 1351 - """Subscribe to app.bsky.feed.postgate record creation events""" 1352 - appBskyFeedPostgateCreated: AppBskyFeedPostgate! 1353 - 1354 - """Subscribe to app.bsky.feed.postgate record update events""" 1355 - appBskyFeedPostgateUpdated: AppBskyFeedPostgate! 1356 - 1357 - """ 1358 - Subscribe to app.bsky.feed.postgate record deletion events. Returns the URI of deleted records. 1359 - """ 1360 - appBskyFeedPostgateDeleted: String! 1361 - 1362 - """Subscribe to app.bsky.feed.threadgate record creation events""" 1363 - appBskyFeedThreadgateCreated: AppBskyFeedThreadgate! 1364 - 1365 - """Subscribe to app.bsky.feed.threadgate record update events""" 1366 - appBskyFeedThreadgateUpdated: AppBskyFeedThreadgate! 1367 - 1368 - """ 1369 - Subscribe to app.bsky.feed.threadgate record deletion events. Returns the URI of deleted records. 1370 - """ 1371 - appBskyFeedThreadgateDeleted: String! 1372 - 1373 - """Subscribe to app.bsky.actor.profile record creation events""" 1374 - appBskyActorProfileCreated: AppBskyActorProfile! 1375 - 1376 - """Subscribe to app.bsky.actor.profile record update events""" 1377 - appBskyActorProfileUpdated: AppBskyActorProfile! 1378 - 1379 - """ 1380 - Subscribe to app.bsky.actor.profile record deletion events. Returns the URI of deleted records. 1381 - """ 1382 - appBskyActorProfileDeleted: String! 1383 - 1384 - """Subscribe to fm.teal.alpha.feed.play record creation events""" 1041 + """Emitted when a new fm.teal.alpha.feed.play record is created""" 1385 1042 fmTealAlphaFeedPlayCreated: FmTealAlphaFeedPlay! 1386 1043 1387 - """Subscribe to fm.teal.alpha.feed.play record update events""" 1044 + """Emitted when a fm.teal.alpha.feed.play record is updated""" 1388 1045 fmTealAlphaFeedPlayUpdated: FmTealAlphaFeedPlay! 1389 1046 1390 - """ 1391 - Subscribe to fm.teal.alpha.feed.play record deletion events. Returns the URI of deleted records. 1392 - """ 1393 - fmTealAlphaFeedPlayDeleted: String! 1047 + """Emitted when a fm.teal.alpha.feed.play record is deleted""" 1048 + fmTealAlphaFeedPlayDeleted: FmTealAlphaFeedPlay! 1394 1049 1395 - """Subscribe to new Jetstream log entries, optionally filtered by slice""" 1396 - jetstreamLogsCreated(slice: String): JetstreamLogEntry! 1050 + """Emitted when a new app.bsky.actor.profile record is created""" 1051 + appBskyActorProfileCreated: AppBskyActorProfile! 1397 1052 1398 - """Subscribe to sync job status updates""" 1399 - syncJobUpdated(jobId: String, slice: String): SyncJob! 1400 - } 1053 + """Emitted when a app.bsky.actor.profile record is updated""" 1054 + appBskyActorProfileUpdated: AppBskyActorProfile! 1401 1055 1402 - type SyncJob { 1403 - id: ID! 1404 - jobId: String! 1405 - sliceUri: String! 1406 - status: String! 1407 - createdAt: String! 1408 - startedAt: String 1409 - completedAt: String 1410 - result: SyncJobResult 1411 - error: String 1412 - retryCount: Int! 1413 - } 1414 - 1415 - type SyncJobResult { 1416 - success: Boolean! 1417 - totalRecords: Int! 1418 - collectionsSynced: [String!]! 1419 - reposProcessed: Int! 1420 - message: String! 1421 - } 1422 - 1423 - type SyncResult { 1424 - success: Boolean! 1425 - reposProcessed: Int! 1426 - recordsSynced: Int! 1427 - timedOut: Boolean! 1428 - message: String! 1429 - } 1430 - 1431 - type SyncSummary { 1432 - totalRepos: Int! 1433 - cappedRepos: Int! 1434 - wouldBeCapped: Boolean! 1435 - appliedLimit: Int! 1436 - collectionsSummary: [CollectionSummary!]! 1056 + """Emitted when a app.bsky.actor.profile record is deleted""" 1057 + appBskyActorProfileDeleted: AppBskyActorProfile! 1437 1058 } 1438 1059
+79 -63
src/App.tsx
··· 4 4 usePaginationFragment, 5 5 useSubscription, 6 6 } from "react-relay"; 7 - import { useEffect, useRef, useMemo } from "react"; 7 + import { useEffect, useMemo, useRef } from "react"; 8 8 import type { AppQuery } from "./__generated__/AppQuery.graphql"; 9 9 import type { App_plays$key } from "./__generated__/App_plays.graphql"; 10 10 import type { AppSubscription } from "./__generated__/AppSubscription.graphql"; ··· 39 39 ...ScrobbleChart_data 40 40 } 41 41 `, 42 - queryVariables 42 + queryVariables, 43 43 ); 44 44 45 45 const { data, loadNext, hasNext, isLoadingNext } = usePaginationFragment< ··· 53 53 cursor: { type: "String" } 54 54 count: { type: "Int", defaultValue: 20 } 55 55 ) { 56 - fmTealAlphaFeedPlays( 56 + fmTealAlphaFeedPlay( 57 57 first: $count 58 58 after: $cursor 59 - sortBy: [{ field: playedTime, direction: desc }] 60 - ) @connection(key: "App_fmTealAlphaFeedPlays", filters: ["sortBy"]) { 59 + sortBy: [{ field: playedTime, direction: DESC }] 60 + ) @connection(key: "App_fmTealAlphaFeedPlay", filters: ["sortBy"]) { 61 61 totalCount 62 62 edges { 63 63 node { ··· 68 68 } 69 69 } 70 70 `, 71 - queryData 71 + queryData, 72 72 ); 73 73 74 74 const loadMoreRef = useRef<HTMLDivElement>(null); 75 + const loadNextRef = useRef(loadNext); 76 + const isLoadingRef = useRef(false); 77 + loadNextRef.current = loadNext; 75 78 76 79 // Subscribe to new plays 77 - const subscriptionConfig: GraphQLSubscriptionConfig<AppSubscription> = { 78 - subscription: graphql` 80 + const subscriptionConfig: GraphQLSubscriptionConfig<AppSubscription> = 81 + useMemo(() => ({ 82 + subscription: graphql` 79 83 subscription AppSubscription { 80 84 fmTealAlphaFeedPlayCreated { 81 85 uri ··· 84 88 } 85 89 } 86 90 `, 87 - variables: {}, 88 - updater: (store) => { 89 - const newPlay = store.getRootField("fmTealAlphaFeedPlayCreated"); 90 - if (!newPlay) return; 91 + variables: {}, 92 + updater: (store) => { 93 + const newPlay = store.getRootField("fmTealAlphaFeedPlayCreated"); 94 + if (!newPlay) return; 91 95 92 - // Only add plays from the last 24 hours 93 - const playedTime = newPlay.getValue("playedTime") as string | null; 94 - if (!playedTime) return; 96 + // Only add plays from the last 24 hours 97 + const playedTime = newPlay.getValue("playedTime") as string | null; 98 + if (!playedTime) return; 95 99 96 - const playDate = new Date(playedTime); 97 - const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000); 100 + const playDate = new Date(playedTime); 101 + const cutoff = new Date(Date.now() - 24 * 60 * 60 * 1000); 98 102 99 - if (playDate < cutoff) { 100 - // Play is too old, don't add it to the feed 101 - return; 102 - } 103 + if (playDate < cutoff) { 104 + // Play is too old, don't add it to the feed 105 + return; 106 + } 103 107 104 - const root = store.getRoot(); 105 - const connection = ConnectionHandler.getConnection( 106 - root, 107 - "App_fmTealAlphaFeedPlays", 108 - { sortBy: [{ field: "playedTime", direction: "desc" }] } 109 - ); 108 + const root = store.getRoot(); 109 + const connection = ConnectionHandler.getConnection( 110 + root, 111 + "App_fmTealAlphaFeedPlay", 112 + { sortBy: [{ field: "playedTime", direction: "DESC" }] }, 113 + ); 110 114 111 - if (!connection) return; 115 + if (!connection) return; 112 116 113 - const edge = ConnectionHandler.createEdge( 114 - store, 115 - connection, 116 - newPlay, 117 - "FmTealAlphaFeedPlayEdge" 118 - ); 117 + const edge = ConnectionHandler.createEdge( 118 + store, 119 + connection, 120 + newPlay, 121 + "FmTealAlphaFeedPlayEdge", 122 + ); 119 123 120 - ConnectionHandler.insertEdgeBefore(connection, edge); 124 + ConnectionHandler.insertEdgeBefore(connection, edge); 121 125 122 - // Update totalCount 123 - const totalCountRecord = root.getLinkedRecord("fmTealAlphaFeedPlays", { 124 - sortBy: [{ field: "playedTime", direction: "desc" }], 125 - }); 126 - if (totalCountRecord) { 127 - const currentCount = totalCountRecord.getValue("totalCount") as number; 128 - if (typeof currentCount === "number") { 129 - totalCountRecord.setValue(currentCount + 1, "totalCount"); 126 + // Update totalCount 127 + const totalCountRecord = root.getLinkedRecord("fmTealAlphaFeedPlay", { 128 + sortBy: [{ field: "playedTime", direction: "DESC" }], 129 + }); 130 + if (totalCountRecord) { 131 + const currentCount = totalCountRecord.getValue( 132 + "totalCount", 133 + ) as number; 134 + if (typeof currentCount === "number") { 135 + totalCountRecord.setValue(currentCount + 1, "totalCount"); 136 + } 130 137 } 131 - } 132 - }, 133 - }; 138 + }, 139 + }), []); 134 140 135 141 useSubscription(subscriptionConfig); 136 142 ··· 138 144 window.scrollTo(0, 0); 139 145 }, []); 140 146 141 - const plays = 142 - data?.fmTealAlphaFeedPlays?.edges 143 - ?.map((edge) => edge.node) 144 - .filter((n) => n != null) || []; 147 + const plays = data?.fmTealAlphaFeedPlay?.edges 148 + ?.map((edge) => edge.node) 149 + .filter((n) => n != null) || []; 150 + 151 + // Sync the loading ref with isLoadingNext 152 + useEffect(() => { 153 + isLoadingRef.current = isLoadingNext; 154 + }, [isLoadingNext]); 145 155 146 156 useEffect(() => { 147 157 if (!loadMoreRef.current || !hasNext) return; 148 158 159 + const element = loadMoreRef.current; 149 160 const observer = new IntersectionObserver( 150 161 (entries) => { 151 - if (entries[0].isIntersecting && hasNext && !isLoadingNext) { 152 - loadNext(20); 162 + if (entries[0].isIntersecting && !isLoadingRef.current) { 163 + isLoadingRef.current = true; 164 + loadNextRef.current(20); 153 165 } 154 166 }, 155 - { threshold: 0.1 } 167 + { threshold: 0.1 }, 156 168 ); 157 169 158 - observer.observe(loadMoreRef.current); 170 + observer.observe(element); 159 171 160 172 return () => observer.disconnect(); 161 - }, [hasNext, isLoadingNext, loadNext]); 173 + }, [hasNext]); 162 174 163 175 // Group plays by date 164 176 const groupedPlays: { date: string; plays: typeof plays }[] = []; ··· 186 198 <Layout headerChart={<ScrobbleChart queryRef={queryData} />}> 187 199 <div className="mb-8"> 188 200 <p className="text-xs text-zinc-500 uppercase tracking-wider"> 189 - {data?.fmTealAlphaFeedPlays?.totalCount?.toLocaleString()} scrobbles 201 + {data?.fmTealAlphaFeedPlay?.totalCount?.toLocaleString()} scrobbles 190 202 </p> 191 203 </div> 192 204 ··· 207 219 208 220 {hasNext && ( 209 221 <div ref={loadMoreRef} className="py-12 text-center"> 210 - {isLoadingNext ? ( 211 - <p className="text-xs text-zinc-600 uppercase tracking-wider"> 212 - Loading... 213 - </p> 214 - ) : ( 215 - <p className="text-xs text-zinc-700 uppercase tracking-wider">·</p> 216 - )} 222 + {isLoadingNext 223 + ? ( 224 + <p className="text-xs text-zinc-600 uppercase tracking-wider"> 225 + Loading... 226 + </p> 227 + ) 228 + : ( 229 + <p className="text-xs text-zinc-700 uppercase tracking-wider"> 230 + · 231 + </p> 232 + )} 217 233 </div> 218 234 )} 219 235 </Layout>
+40 -26
src/Profile.tsx
··· 1 1 import { graphql, useLazyLoadQuery, usePaginationFragment } from "react-relay"; 2 - import { useParams, Link } from "react-router-dom"; 3 - import { useEffect, useRef, useMemo } from "react"; 2 + import { Link, useParams } from "react-router-dom"; 3 + import { useEffect, useMemo, useRef } from "react"; 4 4 import type { ProfileQuery as ProfileQueryType } from "./__generated__/ProfileQuery.graphql"; 5 5 import type { Profile_plays$key } from "./__generated__/Profile_plays.graphql"; 6 6 import TrackItem from "./TrackItem"; ··· 33 33 ...ScrobbleChart_data 34 34 } 35 35 `, 36 - queryVariables 36 + queryVariables, 37 37 ); 38 38 39 39 const { data, loadNext, hasNext, isLoadingNext } = usePaginationFragment< ··· 48 48 count: { type: "Int", defaultValue: 20 } 49 49 where: { type: "FmTealAlphaFeedPlayWhereInput!" } 50 50 ) { 51 - fmTealAlphaFeedPlays( 51 + fmTealAlphaFeedPlay( 52 52 first: $count 53 53 after: $cursor 54 - sortBy: [{ field: playedTime, direction: desc }] 54 + sortBy: [{ field: playedTime, direction: DESC }] 55 55 where: $where 56 56 ) 57 57 @connection( 58 - key: "Profile_fmTealAlphaFeedPlays" 58 + key: "Profile_fmTealAlphaFeedPlay" 59 59 filters: ["where", "sortBy"] 60 60 ) { 61 61 totalCount ··· 63 63 node { 64 64 ...TrackItem_play 65 65 actorHandle 66 - appBskyActorProfile { 66 + appBskyActorProfileByDid { 67 67 displayName 68 68 description 69 69 avatar { ··· 75 75 } 76 76 } 77 77 `, 78 - queryData 78 + queryData, 79 79 ); 80 80 81 81 const loadMoreRef = useRef<HTMLDivElement>(null); 82 82 83 83 const plays = useMemo( 84 - () => data?.fmTealAlphaFeedPlays?.edges?.map((edge) => edge.node).filter((n) => n != null) || [], 85 - [data?.fmTealAlphaFeedPlays?.edges] 84 + () => 85 + data?.fmTealAlphaFeedPlay?.edges?.map((edge) => edge.node).filter((n) => 86 + n != null 87 + ) || [], 88 + [data?.fmTealAlphaFeedPlay?.edges], 86 89 ); 87 - const profile = plays?.[0]?.appBskyActorProfile; 90 + const profile = plays?.[0]?.appBskyActorProfileByDid; 88 91 89 92 useEffect(() => { 90 93 window.scrollTo(0, 0); ··· 99 102 loadNext(20); 100 103 } 101 104 }, 102 - { threshold: 0.1 } 105 + { threshold: 0.1 }, 103 106 ); 104 107 105 108 observer.observe(loadMoreRef.current); ··· 142 145 </div> 143 146 144 147 <div className="mb-8"> 145 - <h2 className="text-sm font-medium uppercase tracking-wider text-zinc-400 mb-2">Recent Tracks</h2> 148 + <h2 className="text-sm font-medium uppercase tracking-wider text-zinc-400 mb-2"> 149 + Recent Tracks 150 + </h2> 146 151 <p className="text-xs text-zinc-500 uppercase tracking-wider"> 147 - {(data?.fmTealAlphaFeedPlays?.totalCount ?? 0).toLocaleString()} scrobbles 152 + {(data?.fmTealAlphaFeedPlay?.totalCount ?? 0).toLocaleString()}{" "} 153 + scrobbles 148 154 </p> 149 155 </div> 150 156 151 157 <div className="space-y-1"> 152 - {plays && plays.length > 0 ? ( 153 - plays.map((play, index) => <TrackItem key={index} play={play} />) 154 - ) : ( 155 - <p className="text-zinc-600 text-center py-8 text-xs uppercase tracking-wider"> 156 - No tracks found for this user 157 - </p> 158 - )} 158 + {plays && plays.length > 0 159 + ? ( 160 + plays.map((play, index) => <TrackItem key={index} play={play} />) 161 + ) 162 + : ( 163 + <p className="text-zinc-600 text-center py-8 text-xs uppercase tracking-wider"> 164 + No tracks found for this user 165 + </p> 166 + )} 159 167 </div> 160 168 161 169 {hasNext && ( 162 170 <div ref={loadMoreRef} className="py-12 text-center"> 163 - {isLoadingNext ? ( 164 - <p className="text-xs text-zinc-600 uppercase tracking-wider">Loading...</p> 165 - ) : ( 166 - <p className="text-xs text-zinc-700 uppercase tracking-wider">·</p> 167 - )} 171 + {isLoadingNext 172 + ? ( 173 + <p className="text-xs text-zinc-600 uppercase tracking-wider"> 174 + Loading... 175 + </p> 176 + ) 177 + : ( 178 + <p className="text-xs text-zinc-700 uppercase tracking-wider"> 179 + · 180 + </p> 181 + )} 168 182 </div> 169 183 )} 170 184 </div>
+23 -21
src/ScrobbleChart.tsx
··· 10 10 const data = useFragment( 11 11 graphql` 12 12 fragment ScrobbleChart_data on Query { 13 - chartData: fmTealAlphaFeedPlaysAggregated( 14 - groupBy: [{ field: playedTime, interval: day }] 13 + chartData: fmTealAlphaFeedPlayAggregated( 14 + groupBy: [{ field: playedTime, interval: DAY }] 15 15 where: $chartWhere 16 16 limit: 90 17 17 ) { ··· 20 20 } 21 21 } 22 22 `, 23 - queryRef 23 + queryRef, 24 24 ); 25 25 26 26 const chartData = useMemo(() => { ··· 29 29 // Convert aggregated data to chart format 30 30 const aggregated = data.chartData.map((item) => { 31 31 // playedTime comes back as '2025-08-03 00:00:00', extract just the date part 32 - const date = item.playedTime ? item.playedTime.split(' ')[0] : ""; 32 + const date = item.playedTime ? item.playedTime.split(" ")[0] : ""; 33 33 return { 34 34 date, 35 35 count: item.count, ··· 71 71 // Generate points for the line 72 72 const points = chartData.map((d, i) => { 73 73 const x = padding.left + (i / (chartData.length - 1)) * chartWidth; 74 - const y = padding.top + chartHeight - ((d.count - minCount) / range) * chartHeight; 74 + const y = padding.top + chartHeight - 75 + ((d.count - minCount) / range) * chartHeight; 75 76 return `${x},${y}`; 76 77 }).join(" "); 77 78 ··· 80 81 `${padding.left},${padding.top + chartHeight}`, 81 82 ...chartData.map((d, i) => { 82 83 const x = padding.left + (i / (chartData.length - 1)) * chartWidth; 83 - const y = padding.top + chartHeight - ((d.count - minCount) / range) * chartHeight; 84 + const y = padding.top + chartHeight - 85 + ((d.count - minCount) / range) * chartHeight; 84 86 return `${x},${y}`; 85 87 }), 86 88 `${padding.left + chartWidth},${padding.top + chartHeight}`, ··· 92 94 className="w-full h-full" 93 95 preserveAspectRatio="none" 94 96 > 95 - {/* Area fill */} 96 - <polygon 97 - points={areaPoints} 98 - fill="rgb(139 92 246 / 0.1)" 99 - stroke="none" 100 - /> 97 + {/* Area fill */} 98 + <polygon 99 + points={areaPoints} 100 + fill="rgb(139 92 246 / 0.1)" 101 + stroke="none" 102 + /> 101 103 102 - {/* Line */} 103 - <polyline 104 - points={points} 105 - fill="none" 106 - stroke="rgb(139 92 246)" 107 - strokeWidth="1.5" 108 - strokeLinecap="round" 109 - strokeLinejoin="round" 110 - /> 104 + {/* Line */} 105 + <polyline 106 + points={points} 107 + fill="none" 108 + stroke="rgb(139 92 246)" 109 + strokeWidth="1.5" 110 + strokeLinecap="round" 111 + strokeLinejoin="round" 112 + /> 111 113 </svg> 112 114 ); 113 115 }
+4 -4
src/TopAlbums.tsx
··· 12 12 const data = useLazyLoadQuery<TopAlbumsQuery>( 13 13 graphql` 14 14 query TopAlbumsQuery($where: FmTealAlphaFeedPlayWhereInput) { 15 - fmTealAlphaFeedPlaysAggregated( 15 + fmTealAlphaFeedPlayAggregated( 16 16 groupBy: [{ field: releaseMbId }, { field: releaseName }, { field: artists }] 17 - orderBy: { count: desc } 17 + orderBy: { count: DESC } 18 18 limit: 100 19 19 where: $where 20 20 ) { ··· 26 26 } 27 27 `, 28 28 queryVariables, 29 - { fetchKey: period || "all", fetchPolicy: "store-or-network" } 29 + { fetchKey: period || "all", fetchPolicy: "store-or-network" }, 30 30 ); 31 31 32 - const albums = [...(data.fmTealAlphaFeedPlaysAggregated || [])]; 32 + const albums = [...(data.fmTealAlphaFeedPlayAggregated || [])]; 33 33 34 34 // Deduplicate by release name, keeping the one with highest count 35 35 // Prefer entries with artist data
+3 -3
src/TopTracks.tsx
··· 12 12 const data = useLazyLoadQuery<TopTracksQuery>( 13 13 graphql` 14 14 query TopTracksQuery($where: FmTealAlphaFeedPlayWhereInput) { 15 - fmTealAlphaFeedPlaysAggregated( 15 + fmTealAlphaFeedPlayAggregated( 16 16 groupBy: [{ field: trackName }, { field: releaseMbId }, { field: artists }] 17 - orderBy: { count: desc } 17 + orderBy: { count: DESC } 18 18 limit: 50 19 19 where: $where 20 20 ) { ··· 29 29 { fetchKey: period || "all", fetchPolicy: "store-or-network" }, 30 30 ); 31 31 32 - const tracks = data.fmTealAlphaFeedPlaysAggregated || []; 32 + const tracks = data.fmTealAlphaFeedPlayAggregated || []; 33 33 const maxCount = tracks.length > 0 ? tracks[0].count : 0; 34 34 35 35 return (
+5 -7
src/TrackItem.tsx
··· 13 13 fragment TrackItem_play on FmTealAlphaFeedPlay { 14 14 trackName 15 15 playedTime 16 - artists { 17 - artistName 18 - artistMbId 19 - } 16 + artists 20 17 releaseName 21 18 releaseMbId 22 19 actorHandle 23 20 musicServiceBaseDomain 24 - appBskyActorProfile { 21 + appBskyActorProfileByDid { 25 22 displayName 26 23 } 27 24 } ··· 55 52 )} 56 53 </h3> 57 54 <p className="text-xs text-zinc-500 truncate"> 58 - {data.artists?.map((a) => a?.artistName).join(", ") || 59 - "Unknown Artist"} 55 + {Array.isArray(data.artists) 56 + ? data.artists.map((a: { artistName: string }) => a.artistName).join(", ") 57 + : data.artists || "Unknown Artist"} 60 58 </p> 61 59 </div> 62 60
+12 -39
src/__generated__/AppPaginationQuery.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<4144e88e9b03430408917b25e498a033>> 2 + * @generated SignedSource<<c45bdaea334f402a012edc7b022378d5>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 51 51 "name": "sortBy", 52 52 "value": [ 53 53 { 54 - "direction": "desc", 54 + "direction": "DESC", 55 55 "field": "playedTime" 56 56 } 57 57 ] 58 58 } 59 - ], 60 - v2 = { 61 - "alias": null, 62 - "args": null, 63 - "kind": "ScalarField", 64 - "name": "id", 65 - "storageKey": null 66 - }; 59 + ]; 67 60 return { 68 61 "fragment": { 69 62 "argumentDefinitions": (v0/*: any*/), ··· 102 95 "args": (v1/*: any*/), 103 96 "concreteType": "FmTealAlphaFeedPlayConnection", 104 97 "kind": "LinkedField", 105 - "name": "fmTealAlphaFeedPlays", 98 + "name": "fmTealAlphaFeedPlay", 106 99 "plural": false, 107 100 "selections": [ 108 101 { ··· 145 138 { 146 139 "alias": null, 147 140 "args": null, 148 - "concreteType": "FmTealAlphaFeedDefsArtist", 149 - "kind": "LinkedField", 141 + "kind": "ScalarField", 150 142 "name": "artists", 151 - "plural": true, 152 - "selections": [ 153 - { 154 - "alias": null, 155 - "args": null, 156 - "kind": "ScalarField", 157 - "name": "artistName", 158 - "storageKey": null 159 - }, 160 - { 161 - "alias": null, 162 - "args": null, 163 - "kind": "ScalarField", 164 - "name": "artistMbId", 165 - "storageKey": null 166 - } 167 - ], 168 143 "storageKey": null 169 144 }, 170 145 { ··· 200 175 "args": null, 201 176 "concreteType": "AppBskyActorProfile", 202 177 "kind": "LinkedField", 203 - "name": "appBskyActorProfile", 178 + "name": "appBskyActorProfileByDid", 204 179 "plural": false, 205 180 "selections": [ 206 181 { ··· 209 184 "kind": "ScalarField", 210 185 "name": "displayName", 211 186 "storageKey": null 212 - }, 213 - (v2/*: any*/) 187 + } 214 188 ], 215 189 "storageKey": null 216 190 }, 217 - (v2/*: any*/), 218 191 { 219 192 "alias": null, 220 193 "args": null, ··· 270 243 "sortBy" 271 244 ], 272 245 "handle": "connection", 273 - "key": "App_fmTealAlphaFeedPlays", 246 + "key": "App_fmTealAlphaFeedPlay", 274 247 "kind": "LinkedHandle", 275 - "name": "fmTealAlphaFeedPlays" 248 + "name": "fmTealAlphaFeedPlay" 276 249 } 277 250 ] 278 251 }, 279 252 "params": { 280 - "cacheID": "d41913a8ba0cde3255c03b34e36f4baf", 253 + "cacheID": "64e4647c8da02ce7d37088b8ed78c6a8", 281 254 "id": null, 282 255 "metadata": {}, 283 256 "name": "AppPaginationQuery", 284 257 "operationKind": "query", 285 - "text": "query AppPaginationQuery(\n $count: Int = 20\n $cursor: String\n) {\n ...App_plays_1G22uz\n}\n\nfragment App_plays_1G22uz on Query {\n fmTealAlphaFeedPlays(first: $count, after: $cursor, sortBy: [{field: playedTime, direction: desc}]) {\n totalCount\n edges {\n node {\n playedTime\n ...TrackItem_play\n id\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists {\n artistName\n artistMbId\n }\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfile {\n displayName\n id\n }\n}\n" 258 + "text": "query AppPaginationQuery(\n $count: Int = 20\n $cursor: String\n) {\n ...App_plays_1G22uz\n}\n\nfragment App_plays_1G22uz on Query {\n fmTealAlphaFeedPlay(first: $count, after: $cursor, sortBy: [{field: playedTime, direction: DESC}]) {\n totalCount\n edges {\n node {\n playedTime\n ...TrackItem_play\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfileByDid {\n displayName\n }\n}\n" 286 259 } 287 260 }; 288 261 })(); 289 262 290 - (node as any).hash = "1e73fa97ccff20071e5a3fba0f00b48c"; 263 + (node as any).hash = "b793d066128b9e7d52d3209bd3e14afe"; 291 264 292 265 export default node;
+34 -81
src/__generated__/AppQuery.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<4eadb1b67651fecb72943df792f91938>> 2 + * @generated SignedSource<<6fa660d4747cd5269f2ca3ac9e251447>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 11 11 import { ConcreteRequest } from 'relay-runtime'; 12 12 import { FragmentRefs } from "relay-runtime"; 13 13 export type FmTealAlphaFeedPlayWhereInput = { 14 - actorHandle?: StringFilter | null | undefined; 15 - and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 16 - artistMbIds?: StringFilter | null | undefined; 17 - artistNames?: StringFilter | null | undefined; 18 - artists?: StringFilter | null | undefined; 19 - cid?: StringFilter | null | undefined; 20 - collection?: StringFilter | null | undefined; 21 - did?: StringFilter | null | undefined; 22 - duration?: IntFilter | null | undefined; 23 - indexedAt?: DateTimeFilter | null | undefined; 24 - isrc?: StringFilter | null | undefined; 25 - json?: StringFilter | null | undefined; 26 - musicServiceBaseDomain?: StringFilter | null | undefined; 27 - or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 28 - originUrl?: StringFilter | null | undefined; 29 - playedTime?: StringFilter | null | undefined; 30 - recordingMbId?: StringFilter | null | undefined; 31 - releaseMbId?: StringFilter | null | undefined; 32 - releaseName?: StringFilter | null | undefined; 33 - submissionClientAgent?: StringFilter | null | undefined; 34 - trackMbId?: StringFilter | null | undefined; 35 - trackName?: StringFilter | null | undefined; 36 - uri?: StringFilter | null | undefined; 37 - }; 38 - export type DateTimeFilter = { 39 - eq?: string | null | undefined; 40 - gt?: string | null | undefined; 41 - gte?: string | null | undefined; 42 - lt?: string | null | undefined; 43 - lte?: string | null | undefined; 14 + actorHandle?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 15 + and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 16 + cid?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 17 + collection?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 18 + did?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 19 + duration?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 20 + indexedAt?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 21 + isrc?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 22 + musicServiceBaseDomain?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 23 + or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 24 + originUrl?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 25 + playedTime?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 26 + recordingMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 27 + releaseMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 28 + releaseName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 29 + submissionClientAgent?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 30 + trackMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 31 + trackName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 32 + uri?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 44 33 }; 45 - export type StringFilter = { 34 + export type FmTealAlphaFeedPlayFieldCondition = { 46 35 contains?: string | null | undefined; 47 36 eq?: string | null | undefined; 48 - fuzzy?: string | null | undefined; 49 37 gt?: string | null | undefined; 50 38 gte?: string | null | undefined; 51 - in?: ReadonlyArray<string | null | undefined> | null | undefined; 39 + in?: ReadonlyArray<string> | null | undefined; 52 40 lt?: string | null | undefined; 53 41 lte?: string | null | undefined; 54 42 }; 55 - export type IntFilter = { 56 - eq?: number | null | undefined; 57 - gt?: number | null | undefined; 58 - gte?: number | null | undefined; 59 - in?: ReadonlyArray<number | null | undefined> | null | undefined; 60 - lt?: number | null | undefined; 61 - lte?: number | null | undefined; 62 - }; 63 43 export type AppQuery$variables = { 64 44 chartWhere: FmTealAlphaFeedPlayWhereInput; 65 45 }; ··· 90 70 "name": "sortBy", 91 71 "value": [ 92 72 { 93 - "direction": "desc", 73 + "direction": "DESC", 94 74 "field": "playedTime" 95 75 } 96 76 ] ··· 101 81 "args": null, 102 82 "kind": "ScalarField", 103 83 "name": "playedTime", 104 - "storageKey": null 105 - }, 106 - v3 = { 107 - "alias": null, 108 - "args": null, 109 - "kind": "ScalarField", 110 - "name": "id", 111 84 "storageKey": null 112 85 }; 113 86 return { ··· 142 115 "args": (v1/*: any*/), 143 116 "concreteType": "FmTealAlphaFeedPlayConnection", 144 117 "kind": "LinkedField", 145 - "name": "fmTealAlphaFeedPlays", 118 + "name": "fmTealAlphaFeedPlay", 146 119 "plural": false, 147 120 "selections": [ 148 121 { ··· 179 152 { 180 153 "alias": null, 181 154 "args": null, 182 - "concreteType": "FmTealAlphaFeedDefsArtist", 183 - "kind": "LinkedField", 155 + "kind": "ScalarField", 184 156 "name": "artists", 185 - "plural": true, 186 - "selections": [ 187 - { 188 - "alias": null, 189 - "args": null, 190 - "kind": "ScalarField", 191 - "name": "artistName", 192 - "storageKey": null 193 - }, 194 - { 195 - "alias": null, 196 - "args": null, 197 - "kind": "ScalarField", 198 - "name": "artistMbId", 199 - "storageKey": null 200 - } 201 - ], 202 157 "storageKey": null 203 158 }, 204 159 { ··· 234 189 "args": null, 235 190 "concreteType": "AppBskyActorProfile", 236 191 "kind": "LinkedField", 237 - "name": "appBskyActorProfile", 192 + "name": "appBskyActorProfileByDid", 238 193 "plural": false, 239 194 "selections": [ 240 195 { ··· 243 198 "kind": "ScalarField", 244 199 "name": "displayName", 245 200 "storageKey": null 246 - }, 247 - (v3/*: any*/) 201 + } 248 202 ], 249 203 "storageKey": null 250 204 }, 251 - (v3/*: any*/), 252 205 { 253 206 "alias": null, 254 207 "args": null, ··· 295 248 "storageKey": null 296 249 } 297 250 ], 298 - "storageKey": "fmTealAlphaFeedPlays(first:20,sortBy:[{\"direction\":\"desc\",\"field\":\"playedTime\"}])" 251 + "storageKey": "fmTealAlphaFeedPlay(first:20,sortBy:[{\"direction\":\"DESC\",\"field\":\"playedTime\"}])" 299 252 }, 300 253 { 301 254 "alias": null, ··· 304 257 "sortBy" 305 258 ], 306 259 "handle": "connection", 307 - "key": "App_fmTealAlphaFeedPlays", 260 + "key": "App_fmTealAlphaFeedPlay", 308 261 "kind": "LinkedHandle", 309 - "name": "fmTealAlphaFeedPlays" 262 + "name": "fmTealAlphaFeedPlay" 310 263 }, 311 264 { 312 265 "alias": "chartData", ··· 317 270 "value": [ 318 271 { 319 272 "field": "playedTime", 320 - "interval": "day" 273 + "interval": "DAY" 321 274 } 322 275 ] 323 276 }, ··· 334 287 ], 335 288 "concreteType": "FmTealAlphaFeedPlayAggregated", 336 289 "kind": "LinkedField", 337 - "name": "fmTealAlphaFeedPlaysAggregated", 290 + "name": "fmTealAlphaFeedPlayAggregated", 338 291 "plural": true, 339 292 "selections": [ 340 293 (v2/*: any*/), ··· 351 304 ] 352 305 }, 353 306 "params": { 354 - "cacheID": "ab3827e5716f65074a802ddb36f66d2b", 307 + "cacheID": "3620b802448dd92e20f1ee8b7fd51980", 355 308 "id": null, 356 309 "metadata": {}, 357 310 "name": "AppQuery", 358 311 "operationKind": "query", 359 - "text": "query AppQuery(\n $chartWhere: FmTealAlphaFeedPlayWhereInput!\n) {\n ...App_plays\n ...ScrobbleChart_data\n}\n\nfragment App_plays on Query {\n fmTealAlphaFeedPlays(first: 20, sortBy: [{field: playedTime, direction: desc}]) {\n totalCount\n edges {\n node {\n playedTime\n ...TrackItem_play\n id\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment ScrobbleChart_data on Query {\n chartData: fmTealAlphaFeedPlaysAggregated(groupBy: [{field: playedTime, interval: day}], where: $chartWhere, limit: 90) {\n playedTime\n count\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists {\n artistName\n artistMbId\n }\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfile {\n displayName\n id\n }\n}\n" 312 + "text": "query AppQuery(\n $chartWhere: FmTealAlphaFeedPlayWhereInput!\n) {\n ...App_plays\n ...ScrobbleChart_data\n}\n\nfragment App_plays on Query {\n fmTealAlphaFeedPlay(first: 20, sortBy: [{field: playedTime, direction: DESC}]) {\n totalCount\n edges {\n node {\n playedTime\n ...TrackItem_play\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment ScrobbleChart_data on Query {\n chartData: fmTealAlphaFeedPlayAggregated(groupBy: [{field: playedTime, interval: DAY}], where: $chartWhere, limit: 90) {\n playedTime\n count\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfileByDid {\n displayName\n }\n}\n" 360 313 } 361 314 }; 362 315 })();
+8 -35
src/__generated__/AppSubscription.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<f0666e46fa4693a3d7869f9de0266bab>> 2 + * @generated SignedSource<<c4198cc44967175302aceaf063070457>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 14 14 export type AppSubscription$data = { 15 15 readonly fmTealAlphaFeedPlayCreated: { 16 16 readonly playedTime: string | null | undefined; 17 - readonly uri: string; 17 + readonly uri: string | null | undefined; 18 18 readonly " $fragmentSpreads": FragmentRefs<"TrackItem_play">; 19 19 }; 20 20 }; ··· 36 36 "args": null, 37 37 "kind": "ScalarField", 38 38 "name": "playedTime", 39 - "storageKey": null 40 - }, 41 - v2 = { 42 - "alias": null, 43 - "args": null, 44 - "kind": "ScalarField", 45 - "name": "id", 46 39 "storageKey": null 47 40 }; 48 41 return { ··· 100 93 { 101 94 "alias": null, 102 95 "args": null, 103 - "concreteType": "FmTealAlphaFeedDefsArtist", 104 - "kind": "LinkedField", 96 + "kind": "ScalarField", 105 97 "name": "artists", 106 - "plural": true, 107 - "selections": [ 108 - { 109 - "alias": null, 110 - "args": null, 111 - "kind": "ScalarField", 112 - "name": "artistName", 113 - "storageKey": null 114 - }, 115 - { 116 - "alias": null, 117 - "args": null, 118 - "kind": "ScalarField", 119 - "name": "artistMbId", 120 - "storageKey": null 121 - } 122 - ], 123 98 "storageKey": null 124 99 }, 125 100 { ··· 155 130 "args": null, 156 131 "concreteType": "AppBskyActorProfile", 157 132 "kind": "LinkedField", 158 - "name": "appBskyActorProfile", 133 + "name": "appBskyActorProfileByDid", 159 134 "plural": false, 160 135 "selections": [ 161 136 { ··· 164 139 "kind": "ScalarField", 165 140 "name": "displayName", 166 141 "storageKey": null 167 - }, 168 - (v2/*: any*/) 142 + } 169 143 ], 170 144 "storageKey": null 171 - }, 172 - (v2/*: any*/) 145 + } 173 146 ], 174 147 "storageKey": null 175 148 } 176 149 ] 177 150 }, 178 151 "params": { 179 - "cacheID": "f547109f04ecd8d1a8679dbf0b7f98b4", 152 + "cacheID": "8dfe214f7630ae86042df4676198d298", 180 153 "id": null, 181 154 "metadata": {}, 182 155 "name": "AppSubscription", 183 156 "operationKind": "subscription", 184 - "text": "subscription AppSubscription {\n fmTealAlphaFeedPlayCreated {\n uri\n playedTime\n ...TrackItem_play\n id\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists {\n artistName\n artistMbId\n }\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfile {\n displayName\n id\n }\n}\n" 157 + "text": "subscription AppSubscription {\n fmTealAlphaFeedPlayCreated {\n uri\n playedTime\n ...TrackItem_play\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfileByDid {\n displayName\n }\n}\n" 185 158 } 186 159 }; 187 160 })();
+10 -10
src/__generated__/App_plays.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<ba0bacb4e016f0edbea67013c8694b23>> 2 + * @generated SignedSource<<3266d35506946a9879921e682d9a0b8a>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 11 11 import { ReaderFragment } from 'relay-runtime'; 12 12 import { FragmentRefs } from "relay-runtime"; 13 13 export type App_plays$data = { 14 - readonly fmTealAlphaFeedPlays: { 14 + readonly fmTealAlphaFeedPlay: { 15 15 readonly edges: ReadonlyArray<{ 16 16 readonly node: { 17 17 readonly playedTime: string | null | undefined; 18 18 readonly " $fragmentSpreads": FragmentRefs<"TrackItem_play">; 19 19 }; 20 20 }>; 21 - readonly totalCount: number; 22 - }; 21 + readonly totalCount: number | null | undefined; 22 + } | null | undefined; 23 23 readonly " $fragmentType": "App_plays"; 24 24 }; 25 25 export type App_plays$key = { ··· 31 31 32 32 const node: ReaderFragment = (function(){ 33 33 var v0 = [ 34 - "fmTealAlphaFeedPlays" 34 + "fmTealAlphaFeedPlay" 35 35 ]; 36 36 return { 37 37 "argumentDefinitions": [ ··· 72 72 "name": "App_plays", 73 73 "selections": [ 74 74 { 75 - "alias": "fmTealAlphaFeedPlays", 75 + "alias": "fmTealAlphaFeedPlay", 76 76 "args": [ 77 77 { 78 78 "kind": "Literal", 79 79 "name": "sortBy", 80 80 "value": [ 81 81 { 82 - "direction": "desc", 82 + "direction": "DESC", 83 83 "field": "playedTime" 84 84 } 85 85 ] ··· 87 87 ], 88 88 "concreteType": "FmTealAlphaFeedPlayConnection", 89 89 "kind": "LinkedField", 90 - "name": "__App_fmTealAlphaFeedPlays_connection", 90 + "name": "__App_fmTealAlphaFeedPlay_connection", 91 91 "plural": false, 92 92 "selections": [ 93 93 { ··· 171 171 "storageKey": null 172 172 } 173 173 ], 174 - "storageKey": "__App_fmTealAlphaFeedPlays_connection(sortBy:[{\"direction\":\"desc\",\"field\":\"playedTime\"}])" 174 + "storageKey": "__App_fmTealAlphaFeedPlay_connection(sortBy:[{\"direction\":\"DESC\",\"field\":\"playedTime\"}])" 175 175 } 176 176 ], 177 177 "type": "Query", ··· 179 179 }; 180 180 })(); 181 181 182 - (node as any).hash = "1e73fa97ccff20071e5a3fba0f00b48c"; 182 + (node as any).hash = "b793d066128b9e7d52d3209bd3e14afe"; 183 183 184 184 export default node;
+32 -79
src/__generated__/ProfilePaginationQuery.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<ebf74750639e18cbf2425bae6cf23f69>> 2 + * @generated SignedSource<<e269ae086e67fb50189bc00d0cfa2fba>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 11 11 import { ConcreteRequest } from 'relay-runtime'; 12 12 import { FragmentRefs } from "relay-runtime"; 13 13 export type FmTealAlphaFeedPlayWhereInput = { 14 - actorHandle?: StringFilter | null | undefined; 15 - and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 16 - artistMbIds?: StringFilter | null | undefined; 17 - artistNames?: StringFilter | null | undefined; 18 - artists?: StringFilter | null | undefined; 19 - cid?: StringFilter | null | undefined; 20 - collection?: StringFilter | null | undefined; 21 - did?: StringFilter | null | undefined; 22 - duration?: IntFilter | null | undefined; 23 - indexedAt?: DateTimeFilter | null | undefined; 24 - isrc?: StringFilter | null | undefined; 25 - json?: StringFilter | null | undefined; 26 - musicServiceBaseDomain?: StringFilter | null | undefined; 27 - or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 28 - originUrl?: StringFilter | null | undefined; 29 - playedTime?: StringFilter | null | undefined; 30 - recordingMbId?: StringFilter | null | undefined; 31 - releaseMbId?: StringFilter | null | undefined; 32 - releaseName?: StringFilter | null | undefined; 33 - submissionClientAgent?: StringFilter | null | undefined; 34 - trackMbId?: StringFilter | null | undefined; 35 - trackName?: StringFilter | null | undefined; 36 - uri?: StringFilter | null | undefined; 37 - }; 38 - export type DateTimeFilter = { 39 - eq?: string | null | undefined; 40 - gt?: string | null | undefined; 41 - gte?: string | null | undefined; 42 - lt?: string | null | undefined; 43 - lte?: string | null | undefined; 14 + actorHandle?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 15 + and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 16 + cid?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 17 + collection?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 18 + did?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 19 + duration?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 20 + indexedAt?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 21 + isrc?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 22 + musicServiceBaseDomain?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 23 + or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 24 + originUrl?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 25 + playedTime?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 26 + recordingMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 27 + releaseMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 28 + releaseName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 29 + submissionClientAgent?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 30 + trackMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 31 + trackName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 32 + uri?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 44 33 }; 45 - export type StringFilter = { 34 + export type FmTealAlphaFeedPlayFieldCondition = { 46 35 contains?: string | null | undefined; 47 36 eq?: string | null | undefined; 48 - fuzzy?: string | null | undefined; 49 37 gt?: string | null | undefined; 50 38 gte?: string | null | undefined; 51 - in?: ReadonlyArray<string | null | undefined> | null | undefined; 39 + in?: ReadonlyArray<string> | null | undefined; 52 40 lt?: string | null | undefined; 53 41 lte?: string | null | undefined; 54 42 }; 55 - export type IntFilter = { 56 - eq?: number | null | undefined; 57 - gt?: number | null | undefined; 58 - gte?: number | null | undefined; 59 - in?: ReadonlyArray<number | null | undefined> | null | undefined; 60 - lt?: number | null | undefined; 61 - lte?: number | null | undefined; 62 - }; 63 43 export type ProfilePaginationQuery$variables = { 64 44 count?: number | null | undefined; 65 45 cursor?: string | null | undefined; ··· 112 92 "name": "sortBy", 113 93 "value": [ 114 94 { 115 - "direction": "desc", 95 + "direction": "DESC", 116 96 "field": "playedTime" 117 97 } 118 98 ] 119 99 }, 120 100 (v1/*: any*/) 121 - ], 122 - v3 = { 123 - "alias": null, 124 - "args": null, 125 - "kind": "ScalarField", 126 - "name": "id", 127 - "storageKey": null 128 - }; 101 + ]; 129 102 return { 130 103 "fragment": { 131 104 "argumentDefinitions": (v0/*: any*/), ··· 165 138 "args": (v2/*: any*/), 166 139 "concreteType": "FmTealAlphaFeedPlayConnection", 167 140 "kind": "LinkedField", 168 - "name": "fmTealAlphaFeedPlays", 141 + "name": "fmTealAlphaFeedPlay", 169 142 "plural": false, 170 143 "selections": [ 171 144 { ··· 208 181 { 209 182 "alias": null, 210 183 "args": null, 211 - "concreteType": "FmTealAlphaFeedDefsArtist", 212 - "kind": "LinkedField", 184 + "kind": "ScalarField", 213 185 "name": "artists", 214 - "plural": true, 215 - "selections": [ 216 - { 217 - "alias": null, 218 - "args": null, 219 - "kind": "ScalarField", 220 - "name": "artistName", 221 - "storageKey": null 222 - }, 223 - { 224 - "alias": null, 225 - "args": null, 226 - "kind": "ScalarField", 227 - "name": "artistMbId", 228 - "storageKey": null 229 - } 230 - ], 231 186 "storageKey": null 232 187 }, 233 188 { ··· 263 218 "args": null, 264 219 "concreteType": "AppBskyActorProfile", 265 220 "kind": "LinkedField", 266 - "name": "appBskyActorProfile", 221 + "name": "appBskyActorProfileByDid", 267 222 "plural": false, 268 223 "selections": [ 269 224 { ··· 273 228 "name": "displayName", 274 229 "storageKey": null 275 230 }, 276 - (v3/*: any*/), 277 231 { 278 232 "alias": null, 279 233 "args": null, ··· 308 262 ], 309 263 "storageKey": null 310 264 }, 311 - (v3/*: any*/), 312 265 { 313 266 "alias": null, 314 267 "args": null, ··· 365 318 "sortBy" 366 319 ], 367 320 "handle": "connection", 368 - "key": "Profile_fmTealAlphaFeedPlays", 321 + "key": "Profile_fmTealAlphaFeedPlay", 369 322 "kind": "LinkedHandle", 370 - "name": "fmTealAlphaFeedPlays" 323 + "name": "fmTealAlphaFeedPlay" 371 324 } 372 325 ] 373 326 }, 374 327 "params": { 375 - "cacheID": "776562076929c2efa168256be3868659", 328 + "cacheID": "71567c0f3de4624c411f4821789aaae9", 376 329 "id": null, 377 330 "metadata": {}, 378 331 "name": "ProfilePaginationQuery", 379 332 "operationKind": "query", 380 - "text": "query ProfilePaginationQuery(\n $count: Int = 20\n $cursor: String\n $where: FmTealAlphaFeedPlayWhereInput!\n) {\n ...Profile_plays_mjR8k\n}\n\nfragment Profile_plays_mjR8k on Query {\n fmTealAlphaFeedPlays(first: $count, after: $cursor, sortBy: [{field: playedTime, direction: desc}], where: $where) {\n totalCount\n edges {\n node {\n ...TrackItem_play\n actorHandle\n appBskyActorProfile {\n displayName\n description\n avatar {\n url(preset: \"avatar\")\n }\n id\n }\n id\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists {\n artistName\n artistMbId\n }\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfile {\n displayName\n id\n }\n}\n" 333 + "text": "query ProfilePaginationQuery(\n $count: Int = 20\n $cursor: String\n $where: FmTealAlphaFeedPlayWhereInput!\n) {\n ...Profile_plays_mjR8k\n}\n\nfragment Profile_plays_mjR8k on Query {\n fmTealAlphaFeedPlay(first: $count, after: $cursor, sortBy: [{field: playedTime, direction: DESC}], where: $where) {\n totalCount\n edges {\n node {\n ...TrackItem_play\n actorHandle\n appBskyActorProfileByDid {\n displayName\n description\n avatar {\n url(preset: \"avatar\")\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfileByDid {\n displayName\n }\n}\n" 381 334 } 382 335 }; 383 336 })(); 384 337 385 - (node as any).hash = "fb9d67e8cd94c4191b9956225ff78bdf"; 338 + (node as any).hash = "06ba557474df22684f61a32da8aec20a"; 386 339 387 340 export default node;
+32 -79
src/__generated__/ProfileQuery.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<0e53ec9fb8aaac689644785adae05957>> 2 + * @generated SignedSource<<d7bc3a763e9feefe1b760612bdc9ef3a>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 11 11 import { ConcreteRequest } from 'relay-runtime'; 12 12 import { FragmentRefs } from "relay-runtime"; 13 13 export type FmTealAlphaFeedPlayWhereInput = { 14 - actorHandle?: StringFilter | null | undefined; 15 - and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 16 - artistMbIds?: StringFilter | null | undefined; 17 - artistNames?: StringFilter | null | undefined; 18 - artists?: StringFilter | null | undefined; 19 - cid?: StringFilter | null | undefined; 20 - collection?: StringFilter | null | undefined; 21 - did?: StringFilter | null | undefined; 22 - duration?: IntFilter | null | undefined; 23 - indexedAt?: DateTimeFilter | null | undefined; 24 - isrc?: StringFilter | null | undefined; 25 - json?: StringFilter | null | undefined; 26 - musicServiceBaseDomain?: StringFilter | null | undefined; 27 - or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 28 - originUrl?: StringFilter | null | undefined; 29 - playedTime?: StringFilter | null | undefined; 30 - recordingMbId?: StringFilter | null | undefined; 31 - releaseMbId?: StringFilter | null | undefined; 32 - releaseName?: StringFilter | null | undefined; 33 - submissionClientAgent?: StringFilter | null | undefined; 34 - trackMbId?: StringFilter | null | undefined; 35 - trackName?: StringFilter | null | undefined; 36 - uri?: StringFilter | null | undefined; 37 - }; 38 - export type DateTimeFilter = { 39 - eq?: string | null | undefined; 40 - gt?: string | null | undefined; 41 - gte?: string | null | undefined; 42 - lt?: string | null | undefined; 43 - lte?: string | null | undefined; 14 + actorHandle?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 15 + and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 16 + cid?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 17 + collection?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 18 + did?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 19 + duration?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 20 + indexedAt?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 21 + isrc?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 22 + musicServiceBaseDomain?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 23 + or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 24 + originUrl?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 25 + playedTime?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 26 + recordingMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 27 + releaseMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 28 + releaseName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 29 + submissionClientAgent?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 30 + trackMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 31 + trackName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 32 + uri?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 44 33 }; 45 - export type StringFilter = { 34 + export type FmTealAlphaFeedPlayFieldCondition = { 46 35 contains?: string | null | undefined; 47 36 eq?: string | null | undefined; 48 - fuzzy?: string | null | undefined; 49 37 gt?: string | null | undefined; 50 38 gte?: string | null | undefined; 51 - in?: ReadonlyArray<string | null | undefined> | null | undefined; 39 + in?: ReadonlyArray<string> | null | undefined; 52 40 lt?: string | null | undefined; 53 41 lte?: string | null | undefined; 54 42 }; 55 - export type IntFilter = { 56 - eq?: number | null | undefined; 57 - gt?: number | null | undefined; 58 - gte?: number | null | undefined; 59 - in?: ReadonlyArray<number | null | undefined> | null | undefined; 60 - lt?: number | null | undefined; 61 - lte?: number | null | undefined; 62 - }; 63 43 export type ProfileQuery$variables = { 64 44 chartWhere: FmTealAlphaFeedPlayWhereInput; 65 45 where: FmTealAlphaFeedPlayWhereInput; ··· 99 79 "name": "sortBy", 100 80 "value": [ 101 81 { 102 - "direction": "desc", 82 + "direction": "DESC", 103 83 "field": "playedTime" 104 84 } 105 85 ] ··· 112 92 "kind": "ScalarField", 113 93 "name": "playedTime", 114 94 "storageKey": null 115 - }, 116 - v5 = { 117 - "alias": null, 118 - "args": null, 119 - "kind": "ScalarField", 120 - "name": "id", 121 - "storageKey": null 122 95 }; 123 96 return { 124 97 "fragment": { ··· 160 133 "args": (v3/*: any*/), 161 134 "concreteType": "FmTealAlphaFeedPlayConnection", 162 135 "kind": "LinkedField", 163 - "name": "fmTealAlphaFeedPlays", 136 + "name": "fmTealAlphaFeedPlay", 164 137 "plural": false, 165 138 "selections": [ 166 139 { ··· 197 170 { 198 171 "alias": null, 199 172 "args": null, 200 - "concreteType": "FmTealAlphaFeedDefsArtist", 201 - "kind": "LinkedField", 173 + "kind": "ScalarField", 202 174 "name": "artists", 203 - "plural": true, 204 - "selections": [ 205 - { 206 - "alias": null, 207 - "args": null, 208 - "kind": "ScalarField", 209 - "name": "artistName", 210 - "storageKey": null 211 - }, 212 - { 213 - "alias": null, 214 - "args": null, 215 - "kind": "ScalarField", 216 - "name": "artistMbId", 217 - "storageKey": null 218 - } 219 - ], 220 175 "storageKey": null 221 176 }, 222 177 { ··· 252 207 "args": null, 253 208 "concreteType": "AppBskyActorProfile", 254 209 "kind": "LinkedField", 255 - "name": "appBskyActorProfile", 210 + "name": "appBskyActorProfileByDid", 256 211 "plural": false, 257 212 "selections": [ 258 213 { ··· 262 217 "name": "displayName", 263 218 "storageKey": null 264 219 }, 265 - (v5/*: any*/), 266 220 { 267 221 "alias": null, 268 222 "args": null, ··· 297 251 ], 298 252 "storageKey": null 299 253 }, 300 - (v5/*: any*/), 301 254 { 302 255 "alias": null, 303 256 "args": null, ··· 354 307 "sortBy" 355 308 ], 356 309 "handle": "connection", 357 - "key": "Profile_fmTealAlphaFeedPlays", 310 + "key": "Profile_fmTealAlphaFeedPlay", 358 311 "kind": "LinkedHandle", 359 - "name": "fmTealAlphaFeedPlays" 312 + "name": "fmTealAlphaFeedPlay" 360 313 }, 361 314 { 362 315 "alias": "chartData", ··· 367 320 "value": [ 368 321 { 369 322 "field": "playedTime", 370 - "interval": "day" 323 + "interval": "DAY" 371 324 } 372 325 ] 373 326 }, ··· 384 337 ], 385 338 "concreteType": "FmTealAlphaFeedPlayAggregated", 386 339 "kind": "LinkedField", 387 - "name": "fmTealAlphaFeedPlaysAggregated", 340 + "name": "fmTealAlphaFeedPlayAggregated", 388 341 "plural": true, 389 342 "selections": [ 390 343 (v4/*: any*/), ··· 401 354 ] 402 355 }, 403 356 "params": { 404 - "cacheID": "6555ddce48917a1e1a522f5b4800192b", 357 + "cacheID": "e246f4fa3d278d1cba09fc7be013172d", 405 358 "id": null, 406 359 "metadata": {}, 407 360 "name": "ProfileQuery", 408 361 "operationKind": "query", 409 - "text": "query ProfileQuery(\n $where: FmTealAlphaFeedPlayWhereInput!\n $chartWhere: FmTealAlphaFeedPlayWhereInput!\n) {\n ...Profile_plays_3FC4Qo\n ...ScrobbleChart_data\n}\n\nfragment Profile_plays_3FC4Qo on Query {\n fmTealAlphaFeedPlays(first: 20, sortBy: [{field: playedTime, direction: desc}], where: $where) {\n totalCount\n edges {\n node {\n ...TrackItem_play\n actorHandle\n appBskyActorProfile {\n displayName\n description\n avatar {\n url(preset: \"avatar\")\n }\n id\n }\n id\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment ScrobbleChart_data on Query {\n chartData: fmTealAlphaFeedPlaysAggregated(groupBy: [{field: playedTime, interval: day}], where: $chartWhere, limit: 90) {\n playedTime\n count\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists {\n artistName\n artistMbId\n }\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfile {\n displayName\n id\n }\n}\n" 362 + "text": "query ProfileQuery(\n $where: FmTealAlphaFeedPlayWhereInput!\n $chartWhere: FmTealAlphaFeedPlayWhereInput!\n) {\n ...Profile_plays_3FC4Qo\n ...ScrobbleChart_data\n}\n\nfragment Profile_plays_3FC4Qo on Query {\n fmTealAlphaFeedPlay(first: 20, sortBy: [{field: playedTime, direction: DESC}], where: $where) {\n totalCount\n edges {\n node {\n ...TrackItem_play\n actorHandle\n appBskyActorProfileByDid {\n displayName\n description\n avatar {\n url(preset: \"avatar\")\n }\n }\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n}\n\nfragment ScrobbleChart_data on Query {\n chartData: fmTealAlphaFeedPlayAggregated(groupBy: [{field: playedTime, interval: DAY}], where: $chartWhere, limit: 90) {\n playedTime\n count\n }\n}\n\nfragment TrackItem_play on FmTealAlphaFeedPlay {\n trackName\n playedTime\n artists\n releaseName\n releaseMbId\n actorHandle\n musicServiceBaseDomain\n appBskyActorProfileByDid {\n displayName\n }\n}\n" 410 363 } 411 364 }; 412 365 })();
+11 -11
src/__generated__/Profile_plays.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<9b9347661ace6bcbeb677e53e4b5feec>> 2 + * @generated SignedSource<<debe921c118f11f1685c3407b690bcf8>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 11 11 import { ReaderFragment } from 'relay-runtime'; 12 12 import { FragmentRefs } from "relay-runtime"; 13 13 export type Profile_plays$data = { 14 - readonly fmTealAlphaFeedPlays: { 14 + readonly fmTealAlphaFeedPlay: { 15 15 readonly edges: ReadonlyArray<{ 16 16 readonly node: { 17 17 readonly actorHandle: string | null | undefined; 18 - readonly appBskyActorProfile: { 18 + readonly appBskyActorProfileByDid: { 19 19 readonly avatar: { 20 20 readonly url: string; 21 21 } | null | undefined; ··· 25 25 readonly " $fragmentSpreads": FragmentRefs<"TrackItem_play">; 26 26 }; 27 27 }>; 28 - readonly totalCount: number; 29 - }; 28 + readonly totalCount: number | null | undefined; 29 + } | null | undefined; 30 30 readonly " $fragmentType": "Profile_plays"; 31 31 }; 32 32 export type Profile_plays$key = { ··· 38 38 39 39 const node: ReaderFragment = (function(){ 40 40 var v0 = [ 41 - "fmTealAlphaFeedPlays" 41 + "fmTealAlphaFeedPlay" 42 42 ]; 43 43 return { 44 44 "argumentDefinitions": [ ··· 84 84 "name": "Profile_plays", 85 85 "selections": [ 86 86 { 87 - "alias": "fmTealAlphaFeedPlays", 87 + "alias": "fmTealAlphaFeedPlay", 88 88 "args": [ 89 89 { 90 90 "kind": "Literal", 91 91 "name": "sortBy", 92 92 "value": [ 93 93 { 94 - "direction": "desc", 94 + "direction": "DESC", 95 95 "field": "playedTime" 96 96 } 97 97 ] ··· 104 104 ], 105 105 "concreteType": "FmTealAlphaFeedPlayConnection", 106 106 "kind": "LinkedField", 107 - "name": "__Profile_fmTealAlphaFeedPlays_connection", 107 + "name": "__Profile_fmTealAlphaFeedPlay_connection", 108 108 "plural": false, 109 109 "selections": [ 110 110 { ··· 147 147 "args": null, 148 148 "concreteType": "AppBskyActorProfile", 149 149 "kind": "LinkedField", 150 - "name": "appBskyActorProfile", 150 + "name": "appBskyActorProfileByDid", 151 151 "plural": false, 152 152 "selections": [ 153 153 { ··· 245 245 }; 246 246 })(); 247 247 248 - (node as any).hash = "fb9d67e8cd94c4191b9956225ff78bdf"; 248 + (node as any).hash = "06ba557474df22684f61a32da8aec20a"; 249 249 250 250 export default node;
+6 -6
src/__generated__/ScrobbleChart_data.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<7b446f8950ffde63fb0e7748bb596e66>> 2 + * @generated SignedSource<<7e2392afa490a7b1da46656aa250f70b>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 13 13 export type ScrobbleChart_data$data = { 14 14 readonly chartData: ReadonlyArray<{ 15 15 readonly count: number; 16 - readonly playedTime: any | null | undefined; 17 - }>; 16 + readonly playedTime: string | null | undefined; 17 + }> | null | undefined; 18 18 readonly " $fragmentType": "ScrobbleChart_data"; 19 19 }; 20 20 export type ScrobbleChart_data$key = { ··· 42 42 "value": [ 43 43 { 44 44 "field": "playedTime", 45 - "interval": "day" 45 + "interval": "DAY" 46 46 } 47 47 ] 48 48 }, ··· 59 59 ], 60 60 "concreteType": "FmTealAlphaFeedPlayAggregated", 61 61 "kind": "LinkedField", 62 - "name": "fmTealAlphaFeedPlaysAggregated", 62 + "name": "fmTealAlphaFeedPlayAggregated", 63 63 "plural": true, 64 64 "selections": [ 65 65 { ··· 84 84 "abstractKey": null 85 85 }; 86 86 87 - (node as any).hash = "6d8ebfa533779947a0b3cd703929b5ba"; 87 + (node as any).hash = "acb96f5268c9520f77c672a7ea3a7454"; 88 88 89 89 export default node;
+32 -52
src/__generated__/TopAlbumsQuery.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<5b4069c82e72c33b75aaff1d16f1421f>> 2 + * @generated SignedSource<<8d07fc631e364271a41ea2bd1ab069bb>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 10 10 11 11 import { ConcreteRequest } from 'relay-runtime'; 12 12 export type FmTealAlphaFeedPlayWhereInput = { 13 - actorHandle?: StringFilter | null | undefined; 14 - and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 15 - artistMbIds?: StringFilter | null | undefined; 16 - artistNames?: StringFilter | null | undefined; 17 - artists?: StringFilter | null | undefined; 18 - cid?: StringFilter | null | undefined; 19 - collection?: StringFilter | null | undefined; 20 - did?: StringFilter | null | undefined; 21 - duration?: IntFilter | null | undefined; 22 - indexedAt?: DateTimeFilter | null | undefined; 23 - isrc?: StringFilter | null | undefined; 24 - json?: StringFilter | null | undefined; 25 - musicServiceBaseDomain?: StringFilter | null | undefined; 26 - or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 27 - originUrl?: StringFilter | null | undefined; 28 - playedTime?: StringFilter | null | undefined; 29 - recordingMbId?: StringFilter | null | undefined; 30 - releaseMbId?: StringFilter | null | undefined; 31 - releaseName?: StringFilter | null | undefined; 32 - submissionClientAgent?: StringFilter | null | undefined; 33 - trackMbId?: StringFilter | null | undefined; 34 - trackName?: StringFilter | null | undefined; 35 - uri?: StringFilter | null | undefined; 36 - }; 37 - export type DateTimeFilter = { 38 - eq?: string | null | undefined; 39 - gt?: string | null | undefined; 40 - gte?: string | null | undefined; 41 - lt?: string | null | undefined; 42 - lte?: string | null | undefined; 13 + actorHandle?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 14 + and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 15 + cid?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 16 + collection?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 17 + did?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 18 + duration?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 19 + indexedAt?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 20 + isrc?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 21 + musicServiceBaseDomain?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 22 + or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 23 + originUrl?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 24 + playedTime?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 25 + recordingMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 26 + releaseMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 27 + releaseName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 28 + submissionClientAgent?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 29 + trackMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 30 + trackName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 31 + uri?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 43 32 }; 44 - export type StringFilter = { 33 + export type FmTealAlphaFeedPlayFieldCondition = { 45 34 contains?: string | null | undefined; 46 35 eq?: string | null | undefined; 47 - fuzzy?: string | null | undefined; 48 36 gt?: string | null | undefined; 49 37 gte?: string | null | undefined; 50 - in?: ReadonlyArray<string | null | undefined> | null | undefined; 38 + in?: ReadonlyArray<string> | null | undefined; 51 39 lt?: string | null | undefined; 52 40 lte?: string | null | undefined; 53 41 }; 54 - export type IntFilter = { 55 - eq?: number | null | undefined; 56 - gt?: number | null | undefined; 57 - gte?: number | null | undefined; 58 - in?: ReadonlyArray<number | null | undefined> | null | undefined; 59 - lt?: number | null | undefined; 60 - lte?: number | null | undefined; 61 - }; 62 42 export type TopAlbumsQuery$variables = { 63 43 where?: FmTealAlphaFeedPlayWhereInput | null | undefined; 64 44 }; 65 45 export type TopAlbumsQuery$data = { 66 - readonly fmTealAlphaFeedPlaysAggregated: ReadonlyArray<{ 67 - readonly artists: any | null | undefined; 46 + readonly fmTealAlphaFeedPlayAggregated: ReadonlyArray<{ 47 + readonly artists: string | null | undefined; 68 48 readonly count: number; 69 - readonly releaseMbId: any | null | undefined; 70 - readonly releaseName: any | null | undefined; 71 - }>; 49 + readonly releaseMbId: string | null | undefined; 50 + readonly releaseName: string | null | undefined; 51 + }> | null | undefined; 72 52 }; 73 53 export type TopAlbumsQuery = { 74 54 response: TopAlbumsQuery$data; ··· 111 91 "kind": "Literal", 112 92 "name": "orderBy", 113 93 "value": { 114 - "count": "desc" 94 + "count": "DESC" 115 95 } 116 96 }, 117 97 { ··· 122 102 ], 123 103 "concreteType": "FmTealAlphaFeedPlayAggregated", 124 104 "kind": "LinkedField", 125 - "name": "fmTealAlphaFeedPlaysAggregated", 105 + "name": "fmTealAlphaFeedPlayAggregated", 126 106 "plural": true, 127 107 "selections": [ 128 108 { ··· 175 155 "selections": (v1/*: any*/) 176 156 }, 177 157 "params": { 178 - "cacheID": "4bc742f9cab572a86f4956ae1325e650", 158 + "cacheID": "6b742b6a57c908748af1780da995e31c", 179 159 "id": null, 180 160 "metadata": {}, 181 161 "name": "TopAlbumsQuery", 182 162 "operationKind": "query", 183 - "text": "query TopAlbumsQuery(\n $where: FmTealAlphaFeedPlayWhereInput\n) {\n fmTealAlphaFeedPlaysAggregated(groupBy: [{field: releaseMbId}, {field: releaseName}, {field: artists}], orderBy: {count: desc}, limit: 100, where: $where) {\n releaseMbId\n releaseName\n artists\n count\n }\n}\n" 163 + "text": "query TopAlbumsQuery(\n $where: FmTealAlphaFeedPlayWhereInput\n) {\n fmTealAlphaFeedPlayAggregated(groupBy: [{field: releaseMbId}, {field: releaseName}, {field: artists}], orderBy: {count: DESC}, limit: 100, where: $where) {\n releaseMbId\n releaseName\n artists\n count\n }\n}\n" 184 164 } 185 165 }; 186 166 })(); 187 167 188 - (node as any).hash = "c916cfe287c6837e7b40f0712b123f12"; 168 + (node as any).hash = "13fd8a47c19eeb4f327f0d6d869b73cd"; 189 169 190 170 export default node;
+32 -52
src/__generated__/TopTracksQuery.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<28bfcfbaf324e20bbfc524afcc9ed549>> 2 + * @generated SignedSource<<3d375bb2f6549eb84b9399717743b845>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 10 10 11 11 import { ConcreteRequest } from 'relay-runtime'; 12 12 export type FmTealAlphaFeedPlayWhereInput = { 13 - actorHandle?: StringFilter | null | undefined; 14 - and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 15 - artistMbIds?: StringFilter | null | undefined; 16 - artistNames?: StringFilter | null | undefined; 17 - artists?: StringFilter | null | undefined; 18 - cid?: StringFilter | null | undefined; 19 - collection?: StringFilter | null | undefined; 20 - did?: StringFilter | null | undefined; 21 - duration?: IntFilter | null | undefined; 22 - indexedAt?: DateTimeFilter | null | undefined; 23 - isrc?: StringFilter | null | undefined; 24 - json?: StringFilter | null | undefined; 25 - musicServiceBaseDomain?: StringFilter | null | undefined; 26 - or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput | null | undefined> | null | undefined; 27 - originUrl?: StringFilter | null | undefined; 28 - playedTime?: StringFilter | null | undefined; 29 - recordingMbId?: StringFilter | null | undefined; 30 - releaseMbId?: StringFilter | null | undefined; 31 - releaseName?: StringFilter | null | undefined; 32 - submissionClientAgent?: StringFilter | null | undefined; 33 - trackMbId?: StringFilter | null | undefined; 34 - trackName?: StringFilter | null | undefined; 35 - uri?: StringFilter | null | undefined; 36 - }; 37 - export type DateTimeFilter = { 38 - eq?: string | null | undefined; 39 - gt?: string | null | undefined; 40 - gte?: string | null | undefined; 41 - lt?: string | null | undefined; 42 - lte?: string | null | undefined; 13 + actorHandle?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 14 + and?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 15 + cid?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 16 + collection?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 17 + did?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 18 + duration?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 19 + indexedAt?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 20 + isrc?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 21 + musicServiceBaseDomain?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 22 + or?: ReadonlyArray<FmTealAlphaFeedPlayWhereInput> | null | undefined; 23 + originUrl?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 24 + playedTime?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 25 + recordingMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 26 + releaseMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 27 + releaseName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 28 + submissionClientAgent?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 29 + trackMbId?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 30 + trackName?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 31 + uri?: FmTealAlphaFeedPlayFieldCondition | null | undefined; 43 32 }; 44 - export type StringFilter = { 33 + export type FmTealAlphaFeedPlayFieldCondition = { 45 34 contains?: string | null | undefined; 46 35 eq?: string | null | undefined; 47 - fuzzy?: string | null | undefined; 48 36 gt?: string | null | undefined; 49 37 gte?: string | null | undefined; 50 - in?: ReadonlyArray<string | null | undefined> | null | undefined; 38 + in?: ReadonlyArray<string> | null | undefined; 51 39 lt?: string | null | undefined; 52 40 lte?: string | null | undefined; 53 41 }; 54 - export type IntFilter = { 55 - eq?: number | null | undefined; 56 - gt?: number | null | undefined; 57 - gte?: number | null | undefined; 58 - in?: ReadonlyArray<number | null | undefined> | null | undefined; 59 - lt?: number | null | undefined; 60 - lte?: number | null | undefined; 61 - }; 62 42 export type TopTracksQuery$variables = { 63 43 where?: FmTealAlphaFeedPlayWhereInput | null | undefined; 64 44 }; 65 45 export type TopTracksQuery$data = { 66 - readonly fmTealAlphaFeedPlaysAggregated: ReadonlyArray<{ 67 - readonly artists: any | null | undefined; 46 + readonly fmTealAlphaFeedPlayAggregated: ReadonlyArray<{ 47 + readonly artists: string | null | undefined; 68 48 readonly count: number; 69 - readonly releaseMbId: any | null | undefined; 70 - readonly trackName: any | null | undefined; 71 - }>; 49 + readonly releaseMbId: string | null | undefined; 50 + readonly trackName: string | null | undefined; 51 + }> | null | undefined; 72 52 }; 73 53 export type TopTracksQuery = { 74 54 response: TopTracksQuery$data; ··· 111 91 "kind": "Literal", 112 92 "name": "orderBy", 113 93 "value": { 114 - "count": "desc" 94 + "count": "DESC" 115 95 } 116 96 }, 117 97 { ··· 122 102 ], 123 103 "concreteType": "FmTealAlphaFeedPlayAggregated", 124 104 "kind": "LinkedField", 125 - "name": "fmTealAlphaFeedPlaysAggregated", 105 + "name": "fmTealAlphaFeedPlayAggregated", 126 106 "plural": true, 127 107 "selections": [ 128 108 { ··· 175 155 "selections": (v1/*: any*/) 176 156 }, 177 157 "params": { 178 - "cacheID": "d889d685b64fb19d468954bb3fb7ff7c", 158 + "cacheID": "bc9ed2b6c355b3a8fedb84cb713fa8de", 179 159 "id": null, 180 160 "metadata": {}, 181 161 "name": "TopTracksQuery", 182 162 "operationKind": "query", 183 - "text": "query TopTracksQuery(\n $where: FmTealAlphaFeedPlayWhereInput\n) {\n fmTealAlphaFeedPlaysAggregated(groupBy: [{field: trackName}, {field: releaseMbId}, {field: artists}], orderBy: {count: desc}, limit: 50, where: $where) {\n trackName\n releaseMbId\n artists\n count\n }\n}\n" 163 + "text": "query TopTracksQuery(\n $where: FmTealAlphaFeedPlayWhereInput\n) {\n fmTealAlphaFeedPlayAggregated(groupBy: [{field: trackName}, {field: releaseMbId}, {field: artists}], orderBy: {count: DESC}, limit: 50, where: $where) {\n trackName\n releaseMbId\n artists\n count\n }\n}\n" 184 164 } 185 165 }; 186 166 })(); 187 167 188 - (node as any).hash = "4b62eaeaf8a935abc28e77c8cd2907d1"; 168 + (node as any).hash = "d2aadd883f60f6f31f8d466dc9653cd8"; 189 169 190 170 export default node;
+7 -28
src/__generated__/TrackItem_play.graphql.ts
··· 1 1 /** 2 - * @generated SignedSource<<b5b4d3bdca427eb13381e978bf98d7b9>> 2 + * @generated SignedSource<<2ac2423fc2223016d85ad3440952732c>> 3 3 * @lightSyntaxTransform 4 4 * @nogrep 5 5 */ ··· 12 12 import { FragmentRefs } from "relay-runtime"; 13 13 export type TrackItem_play$data = { 14 14 readonly actorHandle: string | null | undefined; 15 - readonly appBskyActorProfile: { 15 + readonly appBskyActorProfileByDid: { 16 16 readonly displayName: string | null | undefined; 17 17 } | null | undefined; 18 - readonly artists: ReadonlyArray<{ 19 - readonly artistMbId: string | null | undefined; 20 - readonly artistName: string | null | undefined; 21 - } | null | undefined> | null | undefined; 18 + readonly artists: string | null | undefined; 22 19 readonly musicServiceBaseDomain: string | null | undefined; 23 20 readonly playedTime: string | null | undefined; 24 21 readonly releaseMbId: string | null | undefined; 25 22 readonly releaseName: string | null | undefined; 26 - readonly trackName: string; 23 + readonly trackName: string | null | undefined; 27 24 readonly " $fragmentType": "TrackItem_play"; 28 25 }; 29 26 export type TrackItem_play$key = { ··· 54 51 { 55 52 "alias": null, 56 53 "args": null, 57 - "concreteType": "FmTealAlphaFeedDefsArtist", 58 - "kind": "LinkedField", 54 + "kind": "ScalarField", 59 55 "name": "artists", 60 - "plural": true, 61 - "selections": [ 62 - { 63 - "alias": null, 64 - "args": null, 65 - "kind": "ScalarField", 66 - "name": "artistName", 67 - "storageKey": null 68 - }, 69 - { 70 - "alias": null, 71 - "args": null, 72 - "kind": "ScalarField", 73 - "name": "artistMbId", 74 - "storageKey": null 75 - } 76 - ], 77 56 "storageKey": null 78 57 }, 79 58 { ··· 109 88 "args": null, 110 89 "concreteType": "AppBskyActorProfile", 111 90 "kind": "LinkedField", 112 - "name": "appBskyActorProfile", 91 + "name": "appBskyActorProfileByDid", 113 92 "plural": false, 114 93 "selections": [ 115 94 { ··· 127 106 "abstractKey": null 128 107 }; 129 108 130 - (node as any).hash = "9a70dada54e50e27bdd19183f1b16e35"; 109 + (node as any).hash = "6c80a7f51708b5def457b01bd5fae190"; 131 110 132 111 export default node;
+8 -9
src/main.tsx
··· 1 1 import { StrictMode, Suspense } from "react"; 2 2 import { createRoot } from "react-dom/client"; 3 - import { BrowserRouter, Routes, Route } from "react-router-dom"; 3 + import { BrowserRouter, Route, Routes } from "react-router-dom"; 4 4 import "./index.css"; 5 5 import App from "./App.tsx"; 6 6 import Profile from "./Profile.tsx"; ··· 10 10 import { RelayEnvironmentProvider } from "react-relay"; 11 11 import { 12 12 Environment, 13 + type FetchFunction, 14 + type GraphQLResponse, 13 15 Network, 14 - type FetchFunction, 15 16 Observable, 16 17 type SubscribeFunction, 17 - type GraphQLResponse, 18 18 } from "relay-runtime"; 19 19 import { createClient } from "graphql-ws"; 20 20 21 21 const HTTP_ENDPOINT = 22 - "https://api.slices.network/graphql?slice=at://did:plc:fpruhuo22xkm5o7ttr2ktxdo/network.slices.slice/3m257yljpbg2a"; 22 + "https://quickslice-production-d668.up.railway.app/graphql"; 23 23 24 - const WS_ENDPOINT = 25 - "wss://api.slices.network/graphql/ws?slice=at://did:plc:fpruhuo22xkm5o7ttr2ktxdo/network.slices.slice/3m257yljpbg2a"; 24 + const WS_ENDPOINT = "wss://quickslice-production-d668.up.railway.app/graphql"; 26 25 27 26 const fetchGraphQL: FetchFunction = async (request, variables) => { 28 27 const resp = await fetch(HTTP_ENDPOINT, { ··· 78 77 sink.error(error); 79 78 } else if (error instanceof CloseEvent) { 80 79 sink.error( 81 - new Error(`WebSocket closed: ${error.code} ${error.reason}`) 80 + new Error(`WebSocket closed: ${error.code} ${error.reason}`), 82 81 ); 83 82 } else { 84 83 sink.error(new Error(JSON.stringify(error))); 85 84 } 86 85 }, 87 86 complete: () => sink.complete(), 88 - } 87 + }, 89 88 ); 90 89 }); 91 90 }; ··· 110 109 </Suspense> 111 110 </RelayEnvironmentProvider> 112 111 </BrowserRouter> 113 - </StrictMode> 112 + </StrictMode>, 114 113 );