prototypey.org - atproto lexicon typescript toolkit - mirror https://github.com/tylersayshi/prototypey
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

add bsky tests and fix primitives

Tyler f94f49c0 2ba30c5d

+1587 -3
+7 -3
lib.ts
··· 90 90 description?: string; 91 91 } 92 92 93 - interface UnionOptions { 93 + interface UnionOptions extends LexiconItemCommonOptions { 94 94 closed?: boolean; 95 95 } 96 96 ··· 224 224 ): { type: "token"; description: Description } { 225 225 return { type: "token", description }; 226 226 }, 227 - ref<Ref extends string>(ref: Ref): { type: "ref"; ref: Ref } { 227 + ref<Ref extends string>( 228 + ref: Ref, 229 + options?: LexiconItemCommonOptions 230 + ): LexiconItemCommonOptions & { type: "ref"; ref: Ref } { 228 231 return { 229 232 type: "ref", 230 233 ref, 231 - }; 234 + ...options, 235 + } as LexiconItemCommonOptions & { type: "ref"; ref: Ref }; 232 236 }, 233 237 union<const Refs extends readonly string[], Options extends UnionOptions>( 234 238 refs: Refs,
+864
tests/bsky-actor.test.ts
··· 1 + import { assertEquals } from "@std/assert"; 2 + import { lx } from "../lib.ts"; 3 + 4 + Deno.test("app.bsky.actor.defs - profileViewBasic", () => { 5 + const profileViewBasic = lx.object({ 6 + did: lx.string({ required: true, format: "did" }), 7 + handle: lx.string({ required: true, format: "handle" }), 8 + displayName: lx.string({ maxGraphemes: 64, maxLength: 640 }), 9 + pronouns: lx.string(), 10 + avatar: lx.string({ format: "uri" }), 11 + associated: lx.ref("#profileAssociated"), 12 + viewer: lx.ref("#viewerState"), 13 + labels: lx.array(lx.ref("com.atproto.label.defs#label")), 14 + createdAt: lx.string({ format: "datetime" }), 15 + verification: lx.ref("#verificationState"), 16 + status: lx.ref("#statusView"), 17 + }); 18 + 19 + assertEquals(profileViewBasic, { 20 + type: "object", 21 + properties: { 22 + did: { type: "string", required: true, format: "did" }, 23 + handle: { type: "string", required: true, format: "handle" }, 24 + displayName: { type: "string", maxGraphemes: 64, maxLength: 640 }, 25 + pronouns: { type: "string" }, 26 + avatar: { type: "string", format: "uri" }, 27 + associated: { type: "ref", ref: "#profileAssociated" }, 28 + viewer: { type: "ref", ref: "#viewerState" }, 29 + labels: { 30 + type: "array", 31 + items: { type: "ref", ref: "com.atproto.label.defs#label" }, 32 + }, 33 + createdAt: { type: "string", format: "datetime" }, 34 + verification: { type: "ref", ref: "#verificationState" }, 35 + status: { type: "ref", ref: "#statusView" }, 36 + }, 37 + required: ["did", "handle"], 38 + }); 39 + }); 40 + 41 + Deno.test("app.bsky.actor.defs - profileView", () => { 42 + const profileView = lx.object({ 43 + did: lx.string({ required: true, format: "did" }), 44 + handle: lx.string({ required: true, format: "handle" }), 45 + displayName: lx.string({ maxGraphemes: 64, maxLength: 640 }), 46 + pronouns: lx.string(), 47 + description: lx.string({ maxGraphemes: 256, maxLength: 2560 }), 48 + avatar: lx.string({ format: "uri" }), 49 + associated: lx.ref("#profileAssociated"), 50 + indexedAt: lx.string({ format: "datetime" }), 51 + createdAt: lx.string({ format: "datetime" }), 52 + viewer: lx.ref("#viewerState"), 53 + labels: lx.array(lx.ref("com.atproto.label.defs#label")), 54 + verification: lx.ref("#verificationState"), 55 + status: lx.ref("#statusView"), 56 + }); 57 + 58 + assertEquals(profileView, { 59 + type: "object", 60 + properties: { 61 + did: { type: "string", required: true, format: "did" }, 62 + handle: { type: "string", required: true, format: "handle" }, 63 + displayName: { type: "string", maxGraphemes: 64, maxLength: 640 }, 64 + pronouns: { type: "string" }, 65 + description: { type: "string", maxGraphemes: 256, maxLength: 2560 }, 66 + avatar: { type: "string", format: "uri" }, 67 + associated: { type: "ref", ref: "#profileAssociated" }, 68 + indexedAt: { type: "string", format: "datetime" }, 69 + createdAt: { type: "string", format: "datetime" }, 70 + viewer: { type: "ref", ref: "#viewerState" }, 71 + labels: { 72 + type: "array", 73 + items: { type: "ref", ref: "com.atproto.label.defs#label" }, 74 + }, 75 + verification: { type: "ref", ref: "#verificationState" }, 76 + status: { type: "ref", ref: "#statusView" }, 77 + }, 78 + required: ["did", "handle"], 79 + }); 80 + }); 81 + 82 + Deno.test("app.bsky.actor.defs - profileViewDetailed", () => { 83 + const profileViewDetailed = lx.object({ 84 + did: lx.string({ required: true, format: "did" }), 85 + handle: lx.string({ required: true, format: "handle" }), 86 + displayName: lx.string({ maxGraphemes: 64, maxLength: 640 }), 87 + description: lx.string({ maxGraphemes: 256, maxLength: 2560 }), 88 + pronouns: lx.string(), 89 + website: lx.string({ format: "uri" }), 90 + avatar: lx.string({ format: "uri" }), 91 + banner: lx.string({ format: "uri" }), 92 + followersCount: lx.integer(), 93 + followsCount: lx.integer(), 94 + postsCount: lx.integer(), 95 + associated: lx.ref("#profileAssociated"), 96 + joinedViaStarterPack: lx.ref("app.bsky.graph.defs#starterPackViewBasic"), 97 + indexedAt: lx.string({ format: "datetime" }), 98 + createdAt: lx.string({ format: "datetime" }), 99 + viewer: lx.ref("#viewerState"), 100 + labels: lx.array(lx.ref("com.atproto.label.defs#label")), 101 + pinnedPost: lx.ref("com.atproto.repo.strongRef"), 102 + verification: lx.ref("#verificationState"), 103 + status: lx.ref("#statusView"), 104 + }); 105 + 106 + assertEquals(profileViewDetailed, { 107 + type: "object", 108 + properties: { 109 + did: { type: "string", required: true, format: "did" }, 110 + handle: { type: "string", required: true, format: "handle" }, 111 + displayName: { type: "string", maxGraphemes: 64, maxLength: 640 }, 112 + description: { type: "string", maxGraphemes: 256, maxLength: 2560 }, 113 + pronouns: { type: "string" }, 114 + website: { type: "string", format: "uri" }, 115 + avatar: { type: "string", format: "uri" }, 116 + banner: { type: "string", format: "uri" }, 117 + followersCount: { type: "integer" }, 118 + followsCount: { type: "integer" }, 119 + postsCount: { type: "integer" }, 120 + associated: { type: "ref", ref: "#profileAssociated" }, 121 + joinedViaStarterPack: { 122 + type: "ref", 123 + ref: "app.bsky.graph.defs#starterPackViewBasic", 124 + }, 125 + indexedAt: { type: "string", format: "datetime" }, 126 + createdAt: { type: "string", format: "datetime" }, 127 + viewer: { type: "ref", ref: "#viewerState" }, 128 + labels: { 129 + type: "array", 130 + items: { type: "ref", ref: "com.atproto.label.defs#label" }, 131 + }, 132 + pinnedPost: { type: "ref", ref: "com.atproto.repo.strongRef" }, 133 + verification: { type: "ref", ref: "#verificationState" }, 134 + status: { type: "ref", ref: "#statusView" }, 135 + }, 136 + required: ["did", "handle"], 137 + }); 138 + }); 139 + 140 + Deno.test("app.bsky.actor.defs - profileAssociated", () => { 141 + const profileAssociated = lx.object({ 142 + lists: lx.integer(), 143 + feedgens: lx.integer(), 144 + starterPacks: lx.integer(), 145 + labeler: lx.boolean(), 146 + chat: lx.ref("#profileAssociatedChat"), 147 + activitySubscription: lx.ref("#profileAssociatedActivitySubscription"), 148 + }); 149 + 150 + assertEquals(profileAssociated, { 151 + type: "object", 152 + properties: { 153 + lists: { type: "integer" }, 154 + feedgens: { type: "integer" }, 155 + starterPacks: { type: "integer" }, 156 + labeler: { type: "boolean" }, 157 + chat: { type: "ref", ref: "#profileAssociatedChat" }, 158 + activitySubscription: { 159 + type: "ref", 160 + ref: "#profileAssociatedActivitySubscription", 161 + }, 162 + }, 163 + }); 164 + }); 165 + 166 + Deno.test("app.bsky.actor.defs - profileAssociatedChat", () => { 167 + const profileAssociatedChat = lx.object({ 168 + allowIncoming: lx.string({ 169 + required: true, 170 + knownValues: ["all", "none", "following"], 171 + }), 172 + }); 173 + 174 + assertEquals(profileAssociatedChat, { 175 + type: "object", 176 + properties: { 177 + allowIncoming: { 178 + type: "string", 179 + required: true, 180 + knownValues: ["all", "none", "following"], 181 + }, 182 + }, 183 + required: ["allowIncoming"], 184 + }); 185 + }); 186 + 187 + Deno.test("app.bsky.actor.defs - profileAssociatedActivitySubscription", () => { 188 + const profileAssociatedActivitySubscription = lx.object({ 189 + allowSubscriptions: lx.string({ 190 + required: true, 191 + knownValues: ["followers", "mutuals", "none"], 192 + }), 193 + }); 194 + 195 + assertEquals(profileAssociatedActivitySubscription, { 196 + type: "object", 197 + properties: { 198 + allowSubscriptions: { 199 + type: "string", 200 + required: true, 201 + knownValues: ["followers", "mutuals", "none"], 202 + }, 203 + }, 204 + required: ["allowSubscriptions"], 205 + }); 206 + }); 207 + 208 + Deno.test("app.bsky.actor.defs - viewerState", () => { 209 + const viewerState = lx.object({ 210 + muted: lx.boolean(), 211 + mutedByList: lx.ref("app.bsky.graph.defs#listViewBasic"), 212 + blockedBy: lx.boolean(), 213 + blocking: lx.string({ format: "at-uri" }), 214 + blockingByList: lx.ref("app.bsky.graph.defs#listViewBasic"), 215 + following: lx.string({ format: "at-uri" }), 216 + followedBy: lx.string({ format: "at-uri" }), 217 + knownFollowers: lx.ref("#knownFollowers"), 218 + activitySubscription: lx.ref( 219 + "app.bsky.notification.defs#activitySubscription" 220 + ), 221 + }); 222 + 223 + assertEquals(viewerState, { 224 + type: "object", 225 + properties: { 226 + muted: { type: "boolean" }, 227 + mutedByList: { type: "ref", ref: "app.bsky.graph.defs#listViewBasic" }, 228 + blockedBy: { type: "boolean" }, 229 + blocking: { type: "string", format: "at-uri" }, 230 + blockingByList: { type: "ref", ref: "app.bsky.graph.defs#listViewBasic" }, 231 + following: { type: "string", format: "at-uri" }, 232 + followedBy: { type: "string", format: "at-uri" }, 233 + knownFollowers: { type: "ref", ref: "#knownFollowers" }, 234 + activitySubscription: { 235 + type: "ref", 236 + ref: "app.bsky.notification.defs#activitySubscription", 237 + }, 238 + }, 239 + }); 240 + }); 241 + 242 + Deno.test("app.bsky.actor.defs - knownFollowers", () => { 243 + const knownFollowers = lx.object({ 244 + count: lx.integer({ required: true }), 245 + followers: lx.array(lx.ref("#profileViewBasic"), { 246 + required: true, 247 + minLength: 0, 248 + maxLength: 5, 249 + }), 250 + }); 251 + 252 + assertEquals(knownFollowers, { 253 + type: "object", 254 + properties: { 255 + count: { type: "integer", required: true }, 256 + followers: { 257 + type: "array", 258 + items: { type: "ref", ref: "#profileViewBasic" }, 259 + required: true, 260 + minLength: 0, 261 + maxLength: 5, 262 + }, 263 + }, 264 + required: ["count", "followers"], 265 + }); 266 + }); 267 + 268 + Deno.test("app.bsky.actor.defs - verificationState", () => { 269 + const verificationState = lx.object({ 270 + verifications: lx.array(lx.ref("#verificationView"), { required: true }), 271 + verifiedStatus: lx.string({ 272 + required: true, 273 + knownValues: ["valid", "invalid", "none"], 274 + }), 275 + trustedVerifierStatus: lx.string({ 276 + required: true, 277 + knownValues: ["valid", "invalid", "none"], 278 + }), 279 + }); 280 + 281 + assertEquals(verificationState, { 282 + type: "object", 283 + properties: { 284 + verifications: { 285 + type: "array", 286 + items: { type: "ref", ref: "#verificationView" }, 287 + required: true, 288 + }, 289 + verifiedStatus: { 290 + type: "string", 291 + required: true, 292 + knownValues: ["valid", "invalid", "none"], 293 + }, 294 + trustedVerifierStatus: { 295 + type: "string", 296 + required: true, 297 + knownValues: ["valid", "invalid", "none"], 298 + }, 299 + }, 300 + required: ["verifications", "verifiedStatus", "trustedVerifierStatus"], 301 + }); 302 + }); 303 + 304 + Deno.test("app.bsky.actor.defs - verificationView", () => { 305 + const verificationView = lx.object({ 306 + issuer: lx.string({ required: true, format: "did" }), 307 + uri: lx.string({ required: true, format: "at-uri" }), 308 + isValid: lx.boolean({ required: true }), 309 + createdAt: lx.string({ required: true, format: "datetime" }), 310 + }); 311 + 312 + assertEquals(verificationView, { 313 + type: "object", 314 + properties: { 315 + issuer: { type: "string", required: true, format: "did" }, 316 + uri: { type: "string", required: true, format: "at-uri" }, 317 + isValid: { type: "boolean", required: true }, 318 + createdAt: { type: "string", required: true, format: "datetime" }, 319 + }, 320 + required: ["issuer", "uri", "isValid", "createdAt"], 321 + }); 322 + }); 323 + 324 + Deno.test("app.bsky.actor.defs - preferences", () => { 325 + const preferences = lx.array( 326 + lx.union([ 327 + "#adultContentPref", 328 + "#contentLabelPref", 329 + "#savedFeedsPref", 330 + "#savedFeedsPrefV2", 331 + "#personalDetailsPref", 332 + "#feedViewPref", 333 + "#threadViewPref", 334 + "#interestsPref", 335 + "#mutedWordsPref", 336 + "#hiddenPostsPref", 337 + "#bskyAppStatePref", 338 + "#labelersPref", 339 + "#postInteractionSettingsPref", 340 + "#verificationPrefs", 341 + ]) 342 + ); 343 + 344 + assertEquals(preferences, { 345 + type: "array", 346 + items: { 347 + type: "union", 348 + refs: [ 349 + "#adultContentPref", 350 + "#contentLabelPref", 351 + "#savedFeedsPref", 352 + "#savedFeedsPrefV2", 353 + "#personalDetailsPref", 354 + "#feedViewPref", 355 + "#threadViewPref", 356 + "#interestsPref", 357 + "#mutedWordsPref", 358 + "#hiddenPostsPref", 359 + "#bskyAppStatePref", 360 + "#labelersPref", 361 + "#postInteractionSettingsPref", 362 + "#verificationPrefs", 363 + ], 364 + }, 365 + }); 366 + }); 367 + 368 + Deno.test("app.bsky.actor.defs - adultContentPref", () => { 369 + const adultContentPref = lx.object({ 370 + enabled: lx.boolean({ required: true, default: false }), 371 + }); 372 + 373 + assertEquals(adultContentPref, { 374 + type: "object", 375 + properties: { 376 + enabled: { type: "boolean", required: true, default: false }, 377 + }, 378 + required: ["enabled"], 379 + }); 380 + }); 381 + 382 + Deno.test("app.bsky.actor.defs - contentLabelPref", () => { 383 + const contentLabelPref = lx.object({ 384 + labelerDid: lx.string({ format: "did" }), 385 + label: lx.string({ required: true }), 386 + visibility: lx.string({ 387 + required: true, 388 + knownValues: ["ignore", "show", "warn", "hide"], 389 + }), 390 + }); 391 + 392 + assertEquals(contentLabelPref, { 393 + type: "object", 394 + properties: { 395 + labelerDid: { type: "string", format: "did" }, 396 + label: { type: "string", required: true }, 397 + visibility: { 398 + type: "string", 399 + required: true, 400 + knownValues: ["ignore", "show", "warn", "hide"], 401 + }, 402 + }, 403 + required: ["label", "visibility"], 404 + }); 405 + }); 406 + 407 + Deno.test("app.bsky.actor.defs - savedFeed", () => { 408 + const savedFeed = lx.object({ 409 + id: lx.string({ required: true }), 410 + type: lx.string({ required: true, knownValues: ["feed", "list", "timeline"] }), 411 + value: lx.string({ required: true }), 412 + pinned: lx.boolean({ required: true }), 413 + }); 414 + 415 + assertEquals(savedFeed, { 416 + type: "object", 417 + properties: { 418 + id: { type: "string", required: true }, 419 + type: { 420 + type: "string", 421 + required: true, 422 + knownValues: ["feed", "list", "timeline"], 423 + }, 424 + value: { type: "string", required: true }, 425 + pinned: { type: "boolean", required: true }, 426 + }, 427 + required: ["id", "type", "value", "pinned"], 428 + }); 429 + }); 430 + 431 + Deno.test("app.bsky.actor.defs - savedFeedsPrefV2", () => { 432 + const savedFeedsPrefV2 = lx.object({ 433 + items: lx.array(lx.ref("app.bsky.actor.defs#savedFeed"), { 434 + required: true, 435 + }), 436 + }); 437 + 438 + assertEquals(savedFeedsPrefV2, { 439 + type: "object", 440 + properties: { 441 + items: { 442 + type: "array", 443 + items: { type: "ref", ref: "app.bsky.actor.defs#savedFeed" }, 444 + required: true, 445 + }, 446 + }, 447 + required: ["items"], 448 + }); 449 + }); 450 + 451 + Deno.test("app.bsky.actor.defs - savedFeedsPref", () => { 452 + const savedFeedsPref = lx.object({ 453 + pinned: lx.array(lx.string({ format: "at-uri" }), { required: true }), 454 + saved: lx.array(lx.string({ format: "at-uri" }), { required: true }), 455 + timelineIndex: lx.integer(), 456 + }); 457 + 458 + assertEquals(savedFeedsPref, { 459 + type: "object", 460 + properties: { 461 + pinned: { 462 + type: "array", 463 + items: { type: "string", format: "at-uri" }, 464 + required: true, 465 + }, 466 + saved: { 467 + type: "array", 468 + items: { type: "string", format: "at-uri" }, 469 + required: true, 470 + }, 471 + timelineIndex: { type: "integer" }, 472 + }, 473 + required: ["pinned", "saved"], 474 + }); 475 + }); 476 + 477 + Deno.test("app.bsky.actor.defs - personalDetailsPref", () => { 478 + const personalDetailsPref = lx.object({ 479 + birthDate: lx.string({ format: "datetime" }), 480 + }); 481 + 482 + assertEquals(personalDetailsPref, { 483 + type: "object", 484 + properties: { 485 + birthDate: { type: "string", format: "datetime" }, 486 + }, 487 + }); 488 + }); 489 + 490 + Deno.test("app.bsky.actor.defs - feedViewPref", () => { 491 + const feedViewPref = lx.object({ 492 + feed: lx.string({ required: true }), 493 + hideReplies: lx.boolean(), 494 + hideRepliesByUnfollowed: lx.boolean({ default: true }), 495 + hideRepliesByLikeCount: lx.integer(), 496 + hideReposts: lx.boolean(), 497 + hideQuotePosts: lx.boolean(), 498 + }); 499 + 500 + assertEquals(feedViewPref, { 501 + type: "object", 502 + properties: { 503 + feed: { type: "string", required: true }, 504 + hideReplies: { type: "boolean" }, 505 + hideRepliesByUnfollowed: { type: "boolean", default: true }, 506 + hideRepliesByLikeCount: { type: "integer" }, 507 + hideReposts: { type: "boolean" }, 508 + hideQuotePosts: { type: "boolean" }, 509 + }, 510 + required: ["feed"], 511 + }); 512 + }); 513 + 514 + Deno.test("app.bsky.actor.defs - threadViewPref", () => { 515 + const threadViewPref = lx.object({ 516 + sort: lx.string({ 517 + knownValues: ["oldest", "newest", "most-likes", "random", "hotness"], 518 + }), 519 + prioritizeFollowedUsers: lx.boolean(), 520 + }); 521 + 522 + assertEquals(threadViewPref, { 523 + type: "object", 524 + properties: { 525 + sort: { 526 + type: "string", 527 + knownValues: ["oldest", "newest", "most-likes", "random", "hotness"], 528 + }, 529 + prioritizeFollowedUsers: { type: "boolean" }, 530 + }, 531 + }); 532 + }); 533 + 534 + Deno.test("app.bsky.actor.defs - interestsPref", () => { 535 + const interestsPref = lx.object({ 536 + tags: lx.array(lx.string({ maxLength: 640, maxGraphemes: 64 }), { 537 + required: true, 538 + maxLength: 100, 539 + }), 540 + }); 541 + 542 + assertEquals(interestsPref, { 543 + type: "object", 544 + properties: { 545 + tags: { 546 + type: "array", 547 + items: { type: "string", maxLength: 640, maxGraphemes: 64 }, 548 + required: true, 549 + maxLength: 100, 550 + }, 551 + }, 552 + required: ["tags"], 553 + }); 554 + }); 555 + 556 + Deno.test("app.bsky.actor.defs - mutedWordTarget", () => { 557 + const mutedWordTarget = lx.string({ 558 + knownValues: ["content", "tag"], 559 + maxLength: 640, 560 + maxGraphemes: 64, 561 + }); 562 + 563 + assertEquals(mutedWordTarget, { 564 + type: "string", 565 + knownValues: ["content", "tag"], 566 + maxLength: 640, 567 + maxGraphemes: 64, 568 + }); 569 + }); 570 + 571 + Deno.test("app.bsky.actor.defs - mutedWord", () => { 572 + const mutedWord = lx.object({ 573 + id: lx.string(), 574 + value: lx.string({ required: true, maxLength: 10000, maxGraphemes: 1000 }), 575 + targets: lx.array(lx.ref("app.bsky.actor.defs#mutedWordTarget"), { 576 + required: true, 577 + }), 578 + actorTarget: lx.string({ 579 + knownValues: ["all", "exclude-following"], 580 + default: "all", 581 + }), 582 + expiresAt: lx.string({ format: "datetime" }), 583 + }); 584 + 585 + assertEquals(mutedWord, { 586 + type: "object", 587 + properties: { 588 + id: { type: "string" }, 589 + value: { 590 + type: "string", 591 + required: true, 592 + maxLength: 10000, 593 + maxGraphemes: 1000, 594 + }, 595 + targets: { 596 + type: "array", 597 + items: { type: "ref", ref: "app.bsky.actor.defs#mutedWordTarget" }, 598 + required: true, 599 + }, 600 + actorTarget: { 601 + type: "string", 602 + knownValues: ["all", "exclude-following"], 603 + default: "all", 604 + }, 605 + expiresAt: { type: "string", format: "datetime" }, 606 + }, 607 + required: ["value", "targets"], 608 + }); 609 + }); 610 + 611 + Deno.test("app.bsky.actor.defs - mutedWordsPref", () => { 612 + const mutedWordsPref = lx.object({ 613 + items: lx.array(lx.ref("app.bsky.actor.defs#mutedWord"), { 614 + required: true, 615 + }), 616 + }); 617 + 618 + assertEquals(mutedWordsPref, { 619 + type: "object", 620 + properties: { 621 + items: { 622 + type: "array", 623 + items: { type: "ref", ref: "app.bsky.actor.defs#mutedWord" }, 624 + required: true, 625 + }, 626 + }, 627 + required: ["items"], 628 + }); 629 + }); 630 + 631 + Deno.test("app.bsky.actor.defs - hiddenPostsPref", () => { 632 + const hiddenPostsPref = lx.object({ 633 + items: lx.array(lx.string({ format: "at-uri" }), { required: true }), 634 + }); 635 + 636 + assertEquals(hiddenPostsPref, { 637 + type: "object", 638 + properties: { 639 + items: { 640 + type: "array", 641 + items: { type: "string", format: "at-uri" }, 642 + required: true, 643 + }, 644 + }, 645 + required: ["items"], 646 + }); 647 + }); 648 + 649 + Deno.test("app.bsky.actor.defs - labelersPref", () => { 650 + const labelersPref = lx.object({ 651 + labelers: lx.array(lx.ref("#labelerPrefItem"), { required: true }), 652 + }); 653 + 654 + assertEquals(labelersPref, { 655 + type: "object", 656 + properties: { 657 + labelers: { 658 + type: "array", 659 + items: { type: "ref", ref: "#labelerPrefItem" }, 660 + required: true, 661 + }, 662 + }, 663 + required: ["labelers"], 664 + }); 665 + }); 666 + 667 + Deno.test("app.bsky.actor.defs - labelerPrefItem", () => { 668 + const labelerPrefItem = lx.object({ 669 + did: lx.string({ required: true, format: "did" }), 670 + }); 671 + 672 + assertEquals(labelerPrefItem, { 673 + type: "object", 674 + properties: { 675 + did: { type: "string", required: true, format: "did" }, 676 + }, 677 + required: ["did"], 678 + }); 679 + }); 680 + 681 + Deno.test("app.bsky.actor.defs - bskyAppStatePref", () => { 682 + const bskyAppStatePref = lx.object({ 683 + activeProgressGuide: lx.ref("#bskyAppProgressGuide"), 684 + queuedNudges: lx.array(lx.string({ maxLength: 100 }), { maxLength: 1000 }), 685 + nuxs: lx.array(lx.ref("app.bsky.actor.defs#nux"), { maxLength: 100 }), 686 + }); 687 + 688 + assertEquals(bskyAppStatePref, { 689 + type: "object", 690 + properties: { 691 + activeProgressGuide: { type: "ref", ref: "#bskyAppProgressGuide" }, 692 + queuedNudges: { 693 + type: "array", 694 + items: { type: "string", maxLength: 100 }, 695 + maxLength: 1000, 696 + }, 697 + nuxs: { 698 + type: "array", 699 + items: { type: "ref", ref: "app.bsky.actor.defs#nux" }, 700 + maxLength: 100, 701 + }, 702 + }, 703 + }); 704 + }); 705 + 706 + Deno.test("app.bsky.actor.defs - bskyAppProgressGuide", () => { 707 + const bskyAppProgressGuide = lx.object({ 708 + guide: lx.string({ required: true, maxLength: 100 }), 709 + }); 710 + 711 + assertEquals(bskyAppProgressGuide, { 712 + type: "object", 713 + properties: { 714 + guide: { type: "string", required: true, maxLength: 100 }, 715 + }, 716 + required: ["guide"], 717 + }); 718 + }); 719 + 720 + Deno.test("app.bsky.actor.defs - nux", () => { 721 + const nux = lx.object({ 722 + id: lx.string({ required: true, maxLength: 100 }), 723 + completed: lx.boolean({ required: true, default: false }), 724 + data: lx.string({ maxLength: 3000, maxGraphemes: 300 }), 725 + expiresAt: lx.string({ format: "datetime" }), 726 + }); 727 + 728 + assertEquals(nux, { 729 + type: "object", 730 + properties: { 731 + id: { type: "string", required: true, maxLength: 100 }, 732 + completed: { type: "boolean", required: true, default: false }, 733 + data: { type: "string", maxLength: 3000, maxGraphemes: 300 }, 734 + expiresAt: { type: "string", format: "datetime" }, 735 + }, 736 + required: ["id", "completed"], 737 + }); 738 + }); 739 + 740 + Deno.test("app.bsky.actor.defs - verificationPrefs", () => { 741 + const verificationPrefs = lx.object({ 742 + hideBadges: lx.boolean({ default: false }), 743 + }); 744 + 745 + assertEquals(verificationPrefs, { 746 + type: "object", 747 + properties: { 748 + hideBadges: { type: "boolean", default: false }, 749 + }, 750 + }); 751 + }); 752 + 753 + Deno.test("app.bsky.actor.defs - postInteractionSettingsPref", () => { 754 + const postInteractionSettingsPref = lx.object({ 755 + threadgateAllowRules: lx.array( 756 + lx.union([ 757 + "app.bsky.feed.threadgate#mentionRule", 758 + "app.bsky.feed.threadgate#followerRule", 759 + "app.bsky.feed.threadgate#followingRule", 760 + "app.bsky.feed.threadgate#listRule", 761 + ]), 762 + { maxLength: 5 } 763 + ), 764 + postgateEmbeddingRules: lx.array( 765 + lx.union(["app.bsky.feed.postgate#disableRule"]), 766 + { maxLength: 5 } 767 + ), 768 + }); 769 + 770 + assertEquals(postInteractionSettingsPref, { 771 + type: "object", 772 + properties: { 773 + threadgateAllowRules: { 774 + type: "array", 775 + items: { 776 + type: "union", 777 + refs: [ 778 + "app.bsky.feed.threadgate#mentionRule", 779 + "app.bsky.feed.threadgate#followerRule", 780 + "app.bsky.feed.threadgate#followingRule", 781 + "app.bsky.feed.threadgate#listRule", 782 + ], 783 + }, 784 + maxLength: 5, 785 + }, 786 + postgateEmbeddingRules: { 787 + type: "array", 788 + items: { 789 + type: "union", 790 + refs: ["app.bsky.feed.postgate#disableRule"], 791 + }, 792 + maxLength: 5, 793 + }, 794 + }, 795 + }); 796 + }); 797 + 798 + Deno.test("app.bsky.actor.defs - statusView", () => { 799 + const statusView = lx.object({ 800 + status: lx.string({ 801 + required: true, 802 + knownValues: ["app.bsky.actor.status#live"], 803 + }), 804 + record: lx.unknown({ required: true }), 805 + embed: lx.union(["app.bsky.embed.external#view"]), 806 + expiresAt: lx.string({ format: "datetime" }), 807 + isActive: lx.boolean(), 808 + }); 809 + 810 + assertEquals(statusView, { 811 + type: "object", 812 + properties: { 813 + status: { 814 + type: "string", 815 + required: true, 816 + knownValues: ["app.bsky.actor.status#live"], 817 + }, 818 + record: { type: "unknown", required: true }, 819 + embed: { 820 + type: "union", 821 + refs: ["app.bsky.embed.external#view"], 822 + }, 823 + expiresAt: { type: "string", format: "datetime" }, 824 + isActive: { type: "boolean" }, 825 + }, 826 + required: ["status", "record"], 827 + }); 828 + }); 829 + 830 + Deno.test("app.bsky.actor.defs - full namespace", () => { 831 + const actorDefs = lx.namespace("app.bsky.actor.defs", { 832 + profileViewBasic: lx.object({ 833 + did: lx.string({ required: true, format: "did" }), 834 + handle: lx.string({ required: true, format: "handle" }), 835 + displayName: lx.string({ maxGraphemes: 64, maxLength: 640 }), 836 + pronouns: lx.string(), 837 + avatar: lx.string({ format: "uri" }), 838 + associated: lx.ref("#profileAssociated"), 839 + viewer: lx.ref("#viewerState"), 840 + labels: lx.array(lx.ref("com.atproto.label.defs#label")), 841 + createdAt: lx.string({ format: "datetime" }), 842 + verification: lx.ref("#verificationState"), 843 + status: lx.ref("#statusView"), 844 + }), 845 + viewerState: lx.object({ 846 + muted: lx.boolean(), 847 + mutedByList: lx.ref("app.bsky.graph.defs#listViewBasic"), 848 + blockedBy: lx.boolean(), 849 + blocking: lx.string({ format: "at-uri" }), 850 + blockingByList: lx.ref("app.bsky.graph.defs#listViewBasic"), 851 + following: lx.string({ format: "at-uri" }), 852 + followedBy: lx.string({ format: "at-uri" }), 853 + knownFollowers: lx.ref("#knownFollowers"), 854 + activitySubscription: lx.ref( 855 + "app.bsky.notification.defs#activitySubscription" 856 + ), 857 + }), 858 + }); 859 + 860 + assertEquals(actorDefs.lexicon, 1); 861 + assertEquals(actorDefs.id, "app.bsky.actor.defs"); 862 + assertEquals(actorDefs.defs.profileViewBasic.type, "object"); 863 + assertEquals(actorDefs.defs.viewerState.type, "object"); 864 + });
+681
tests/bsky-feed.test.ts
··· 1 + import { assertEquals } from "@std/assert"; 2 + import { lx } from "../lib.ts"; 3 + 4 + Deno.test("app.bsky.feed.defs - postView", () => { 5 + const postView = lx.object({ 6 + uri: lx.string({ required: true, format: "at-uri" }), 7 + cid: lx.string({ required: true, format: "cid" }), 8 + author: lx.ref("app.bsky.actor.defs#profileViewBasic", { required: true }), 9 + record: lx.unknown({ required: true }), 10 + embed: lx.union([ 11 + "app.bsky.embed.images#view", 12 + "app.bsky.embed.video#view", 13 + "app.bsky.embed.external#view", 14 + "app.bsky.embed.record#view", 15 + "app.bsky.embed.recordWithMedia#view", 16 + ]), 17 + bookmarkCount: lx.integer(), 18 + replyCount: lx.integer(), 19 + repostCount: lx.integer(), 20 + likeCount: lx.integer(), 21 + quoteCount: lx.integer(), 22 + indexedAt: lx.string({ required: true, format: "datetime" }), 23 + viewer: lx.ref("#viewerState"), 24 + labels: lx.array(lx.ref("com.atproto.label.defs#label")), 25 + threadgate: lx.ref("#threadgateView"), 26 + }); 27 + 28 + assertEquals(postView, { 29 + type: "object", 30 + properties: { 31 + uri: { type: "string", required: true, format: "at-uri" }, 32 + cid: { type: "string", required: true, format: "cid" }, 33 + author: { 34 + type: "ref", 35 + ref: "app.bsky.actor.defs#profileViewBasic", 36 + required: true, 37 + }, 38 + record: { type: "unknown", required: true }, 39 + embed: { 40 + type: "union", 41 + refs: [ 42 + "app.bsky.embed.images#view", 43 + "app.bsky.embed.video#view", 44 + "app.bsky.embed.external#view", 45 + "app.bsky.embed.record#view", 46 + "app.bsky.embed.recordWithMedia#view", 47 + ], 48 + }, 49 + bookmarkCount: { type: "integer" }, 50 + replyCount: { type: "integer" }, 51 + repostCount: { type: "integer" }, 52 + likeCount: { type: "integer" }, 53 + quoteCount: { type: "integer" }, 54 + indexedAt: { type: "string", required: true, format: "datetime" }, 55 + viewer: { type: "ref", ref: "#viewerState" }, 56 + labels: { 57 + type: "array", 58 + items: { type: "ref", ref: "com.atproto.label.defs#label" }, 59 + }, 60 + threadgate: { type: "ref", ref: "#threadgateView" }, 61 + }, 62 + required: ["uri", "cid", "author", "record", "indexedAt"], 63 + }); 64 + }); 65 + 66 + Deno.test("app.bsky.feed.defs - viewerState", () => { 67 + const viewerState = lx.object({ 68 + repost: lx.string({ format: "at-uri" }), 69 + like: lx.string({ format: "at-uri" }), 70 + bookmarked: lx.boolean(), 71 + threadMuted: lx.boolean(), 72 + replyDisabled: lx.boolean(), 73 + embeddingDisabled: lx.boolean(), 74 + pinned: lx.boolean(), 75 + }); 76 + 77 + assertEquals(viewerState, { 78 + type: "object", 79 + properties: { 80 + repost: { type: "string", format: "at-uri" }, 81 + like: { type: "string", format: "at-uri" }, 82 + bookmarked: { type: "boolean" }, 83 + threadMuted: { type: "boolean" }, 84 + replyDisabled: { type: "boolean" }, 85 + embeddingDisabled: { type: "boolean" }, 86 + pinned: { type: "boolean" }, 87 + }, 88 + }); 89 + }); 90 + 91 + Deno.test("app.bsky.feed.defs - threadContext", () => { 92 + const threadContext = lx.object({ 93 + rootAuthorLike: lx.string({ format: "at-uri" }), 94 + }); 95 + 96 + assertEquals(threadContext, { 97 + type: "object", 98 + properties: { 99 + rootAuthorLike: { type: "string", format: "at-uri" }, 100 + }, 101 + }); 102 + }); 103 + 104 + Deno.test("app.bsky.feed.defs - feedViewPost", () => { 105 + const feedViewPost = lx.object({ 106 + post: lx.ref("#postView", { required: true }), 107 + reply: lx.ref("#replyRef"), 108 + reason: lx.union(["#reasonRepost", "#reasonPin"]), 109 + feedContext: lx.string({ maxLength: 2000 }), 110 + reqId: lx.string({ maxLength: 100 }), 111 + }); 112 + 113 + assertEquals(feedViewPost, { 114 + type: "object", 115 + properties: { 116 + post: { type: "ref", ref: "#postView", required: true }, 117 + reply: { type: "ref", ref: "#replyRef" }, 118 + reason: { 119 + type: "union", 120 + refs: ["#reasonRepost", "#reasonPin"], 121 + }, 122 + feedContext: { type: "string", maxLength: 2000 }, 123 + reqId: { type: "string", maxLength: 100 }, 124 + }, 125 + required: ["post"], 126 + }); 127 + }); 128 + 129 + Deno.test("app.bsky.feed.defs - replyRef", () => { 130 + const replyRef = lx.object({ 131 + root: lx.union(["#postView", "#notFoundPost", "#blockedPost"], { 132 + required: true, 133 + }), 134 + parent: lx.union(["#postView", "#notFoundPost", "#blockedPost"], { 135 + required: true, 136 + }), 137 + grandparentAuthor: lx.ref("app.bsky.actor.defs#profileViewBasic"), 138 + }); 139 + 140 + assertEquals(replyRef, { 141 + type: "object", 142 + properties: { 143 + root: { 144 + type: "union", 145 + refs: ["#postView", "#notFoundPost", "#blockedPost"], 146 + required: true, 147 + }, 148 + parent: { 149 + type: "union", 150 + refs: ["#postView", "#notFoundPost", "#blockedPost"], 151 + required: true, 152 + }, 153 + grandparentAuthor: { 154 + type: "ref", 155 + ref: "app.bsky.actor.defs#profileViewBasic", 156 + }, 157 + }, 158 + required: ["root", "parent"], 159 + }); 160 + }); 161 + 162 + Deno.test("app.bsky.feed.defs - reasonRepost", () => { 163 + const reasonRepost = lx.object({ 164 + by: lx.ref("app.bsky.actor.defs#profileViewBasic", { required: true }), 165 + uri: lx.string({ format: "at-uri" }), 166 + cid: lx.string({ format: "cid" }), 167 + indexedAt: lx.string({ required: true, format: "datetime" }), 168 + }); 169 + 170 + assertEquals(reasonRepost, { 171 + type: "object", 172 + properties: { 173 + by: { 174 + type: "ref", 175 + ref: "app.bsky.actor.defs#profileViewBasic", 176 + required: true, 177 + }, 178 + uri: { type: "string", format: "at-uri" }, 179 + cid: { type: "string", format: "cid" }, 180 + indexedAt: { type: "string", required: true, format: "datetime" }, 181 + }, 182 + required: ["by", "indexedAt"], 183 + }); 184 + }); 185 + 186 + Deno.test("app.bsky.feed.defs - reasonPin", () => { 187 + const reasonPin = lx.object({}); 188 + 189 + assertEquals(reasonPin, { 190 + type: "object", 191 + properties: {}, 192 + }); 193 + }); 194 + 195 + Deno.test("app.bsky.feed.defs - threadViewPost", () => { 196 + const threadViewPost = lx.object({ 197 + post: lx.ref("#postView", { required: true }), 198 + parent: lx.union(["#threadViewPost", "#notFoundPost", "#blockedPost"]), 199 + replies: lx.array( 200 + lx.union(["#threadViewPost", "#notFoundPost", "#blockedPost"]) 201 + ), 202 + threadContext: lx.ref("#threadContext"), 203 + }); 204 + 205 + assertEquals(threadViewPost, { 206 + type: "object", 207 + properties: { 208 + post: { type: "ref", ref: "#postView", required: true }, 209 + parent: { 210 + type: "union", 211 + refs: ["#threadViewPost", "#notFoundPost", "#blockedPost"], 212 + }, 213 + replies: { 214 + type: "array", 215 + items: { 216 + type: "union", 217 + refs: ["#threadViewPost", "#notFoundPost", "#blockedPost"], 218 + }, 219 + }, 220 + threadContext: { type: "ref", ref: "#threadContext" }, 221 + }, 222 + required: ["post"], 223 + }); 224 + }); 225 + 226 + Deno.test("app.bsky.feed.defs - notFoundPost", () => { 227 + const notFoundPost = lx.object({ 228 + uri: lx.string({ required: true, format: "at-uri" }), 229 + notFound: lx.boolean({ required: true, const: true }), 230 + }); 231 + 232 + assertEquals(notFoundPost, { 233 + type: "object", 234 + properties: { 235 + uri: { type: "string", required: true, format: "at-uri" }, 236 + notFound: { type: "boolean", required: true, const: true }, 237 + }, 238 + required: ["uri", "notFound"], 239 + }); 240 + }); 241 + 242 + Deno.test("app.bsky.feed.defs - blockedPost", () => { 243 + const blockedPost = lx.object({ 244 + uri: lx.string({ required: true, format: "at-uri" }), 245 + blocked: lx.boolean({ required: true, const: true }), 246 + author: lx.ref("#blockedAuthor", { required: true }), 247 + }); 248 + 249 + assertEquals(blockedPost, { 250 + type: "object", 251 + properties: { 252 + uri: { type: "string", required: true, format: "at-uri" }, 253 + blocked: { type: "boolean", required: true, const: true }, 254 + author: { type: "ref", ref: "#blockedAuthor", required: true }, 255 + }, 256 + required: ["uri", "blocked", "author"], 257 + }); 258 + }); 259 + 260 + Deno.test("app.bsky.feed.defs - blockedAuthor", () => { 261 + const blockedAuthor = lx.object({ 262 + did: lx.string({ required: true, format: "did" }), 263 + viewer: lx.ref("app.bsky.actor.defs#viewerState"), 264 + }); 265 + 266 + assertEquals(blockedAuthor, { 267 + type: "object", 268 + properties: { 269 + did: { type: "string", required: true, format: "did" }, 270 + viewer: { type: "ref", ref: "app.bsky.actor.defs#viewerState" }, 271 + }, 272 + required: ["did"], 273 + }); 274 + }); 275 + 276 + Deno.test("app.bsky.feed.defs - generatorView", () => { 277 + const generatorView = lx.object({ 278 + uri: lx.string({ required: true, format: "at-uri" }), 279 + cid: lx.string({ required: true, format: "cid" }), 280 + did: lx.string({ required: true, format: "did" }), 281 + creator: lx.ref("app.bsky.actor.defs#profileView", { required: true }), 282 + displayName: lx.string({ required: true }), 283 + description: lx.string({ maxGraphemes: 300, maxLength: 3000 }), 284 + descriptionFacets: lx.array(lx.ref("app.bsky.richtext.facet")), 285 + avatar: lx.string({ format: "uri" }), 286 + likeCount: lx.integer({ minimum: 0 }), 287 + acceptsInteractions: lx.boolean(), 288 + labels: lx.array(lx.ref("com.atproto.label.defs#label")), 289 + viewer: lx.ref("#generatorViewerState"), 290 + contentMode: lx.string({ 291 + knownValues: [ 292 + "app.bsky.feed.defs#contentModeUnspecified", 293 + "app.bsky.feed.defs#contentModeVideo", 294 + ], 295 + }), 296 + indexedAt: lx.string({ required: true, format: "datetime" }), 297 + }); 298 + 299 + assertEquals(generatorView, { 300 + type: "object", 301 + properties: { 302 + uri: { type: "string", required: true, format: "at-uri" }, 303 + cid: { type: "string", required: true, format: "cid" }, 304 + did: { type: "string", required: true, format: "did" }, 305 + creator: { 306 + type: "ref", 307 + ref: "app.bsky.actor.defs#profileView", 308 + required: true, 309 + }, 310 + displayName: { type: "string", required: true }, 311 + description: { type: "string", maxGraphemes: 300, maxLength: 3000 }, 312 + descriptionFacets: { 313 + type: "array", 314 + items: { type: "ref", ref: "app.bsky.richtext.facet" }, 315 + }, 316 + avatar: { type: "string", format: "uri" }, 317 + likeCount: { type: "integer", minimum: 0 }, 318 + acceptsInteractions: { type: "boolean" }, 319 + labels: { 320 + type: "array", 321 + items: { type: "ref", ref: "com.atproto.label.defs#label" }, 322 + }, 323 + viewer: { type: "ref", ref: "#generatorViewerState" }, 324 + contentMode: { 325 + type: "string", 326 + knownValues: [ 327 + "app.bsky.feed.defs#contentModeUnspecified", 328 + "app.bsky.feed.defs#contentModeVideo", 329 + ], 330 + }, 331 + indexedAt: { type: "string", required: true, format: "datetime" }, 332 + }, 333 + required: ["uri", "cid", "did", "creator", "displayName", "indexedAt"], 334 + }); 335 + }); 336 + 337 + Deno.test("app.bsky.feed.defs - generatorViewerState", () => { 338 + const generatorViewerState = lx.object({ 339 + like: lx.string({ format: "at-uri" }), 340 + }); 341 + 342 + assertEquals(generatorViewerState, { 343 + type: "object", 344 + properties: { 345 + like: { type: "string", format: "at-uri" }, 346 + }, 347 + }); 348 + }); 349 + 350 + Deno.test("app.bsky.feed.defs - skeletonFeedPost", () => { 351 + const skeletonFeedPost = lx.object({ 352 + post: lx.string({ required: true, format: "at-uri" }), 353 + reason: lx.union(["#skeletonReasonRepost", "#skeletonReasonPin"]), 354 + feedContext: lx.string({ maxLength: 2000 }), 355 + }); 356 + 357 + assertEquals(skeletonFeedPost, { 358 + type: "object", 359 + properties: { 360 + post: { type: "string", required: true, format: "at-uri" }, 361 + reason: { 362 + type: "union", 363 + refs: ["#skeletonReasonRepost", "#skeletonReasonPin"], 364 + }, 365 + feedContext: { type: "string", maxLength: 2000 }, 366 + }, 367 + required: ["post"], 368 + }); 369 + }); 370 + 371 + Deno.test("app.bsky.feed.defs - skeletonReasonRepost", () => { 372 + const skeletonReasonRepost = lx.object({ 373 + repost: lx.string({ required: true, format: "at-uri" }), 374 + }); 375 + 376 + assertEquals(skeletonReasonRepost, { 377 + type: "object", 378 + properties: { 379 + repost: { type: "string", required: true, format: "at-uri" }, 380 + }, 381 + required: ["repost"], 382 + }); 383 + }); 384 + 385 + Deno.test("app.bsky.feed.defs - skeletonReasonPin", () => { 386 + const skeletonReasonPin = lx.object({}); 387 + 388 + assertEquals(skeletonReasonPin, { 389 + type: "object", 390 + properties: {}, 391 + }); 392 + }); 393 + 394 + Deno.test("app.bsky.feed.defs - threadgateView", () => { 395 + const threadgateView = lx.object({ 396 + uri: lx.string({ format: "at-uri" }), 397 + cid: lx.string({ format: "cid" }), 398 + record: lx.unknown(), 399 + lists: lx.array(lx.ref("app.bsky.graph.defs#listViewBasic")), 400 + }); 401 + 402 + assertEquals(threadgateView, { 403 + type: "object", 404 + properties: { 405 + uri: { type: "string", format: "at-uri" }, 406 + cid: { type: "string", format: "cid" }, 407 + record: { type: "unknown" }, 408 + lists: { 409 + type: "array", 410 + items: { type: "ref", ref: "app.bsky.graph.defs#listViewBasic" }, 411 + }, 412 + }, 413 + }); 414 + }); 415 + 416 + Deno.test("app.bsky.feed.defs - interaction", () => { 417 + const interaction = lx.object({ 418 + item: lx.string({ format: "at-uri" }), 419 + event: lx.string({ 420 + knownValues: [ 421 + "app.bsky.feed.defs#requestLess", 422 + "app.bsky.feed.defs#requestMore", 423 + "app.bsky.feed.defs#clickthroughItem", 424 + "app.bsky.feed.defs#clickthroughAuthor", 425 + "app.bsky.feed.defs#clickthroughReposter", 426 + "app.bsky.feed.defs#clickthroughEmbed", 427 + "app.bsky.feed.defs#interactionSeen", 428 + "app.bsky.feed.defs#interactionLike", 429 + "app.bsky.feed.defs#interactionRepost", 430 + "app.bsky.feed.defs#interactionReply", 431 + "app.bsky.feed.defs#interactionQuote", 432 + "app.bsky.feed.defs#interactionShare", 433 + ], 434 + }), 435 + feedContext: lx.string({ maxLength: 2000 }), 436 + reqId: lx.string({ maxLength: 100 }), 437 + }); 438 + 439 + assertEquals(interaction, { 440 + type: "object", 441 + properties: { 442 + item: { type: "string", format: "at-uri" }, 443 + event: { 444 + type: "string", 445 + knownValues: [ 446 + "app.bsky.feed.defs#requestLess", 447 + "app.bsky.feed.defs#requestMore", 448 + "app.bsky.feed.defs#clickthroughItem", 449 + "app.bsky.feed.defs#clickthroughAuthor", 450 + "app.bsky.feed.defs#clickthroughReposter", 451 + "app.bsky.feed.defs#clickthroughEmbed", 452 + "app.bsky.feed.defs#interactionSeen", 453 + "app.bsky.feed.defs#interactionLike", 454 + "app.bsky.feed.defs#interactionRepost", 455 + "app.bsky.feed.defs#interactionReply", 456 + "app.bsky.feed.defs#interactionQuote", 457 + "app.bsky.feed.defs#interactionShare", 458 + ], 459 + }, 460 + feedContext: { type: "string", maxLength: 2000 }, 461 + reqId: { type: "string", maxLength: 100 }, 462 + }, 463 + }); 464 + }); 465 + 466 + Deno.test("app.bsky.feed.defs - requestLess token", () => { 467 + const requestLess = lx.token( 468 + "Request that less content like the given feed item be shown in the feed" 469 + ); 470 + 471 + assertEquals(requestLess, { 472 + type: "token", 473 + description: 474 + "Request that less content like the given feed item be shown in the feed", 475 + }); 476 + }); 477 + 478 + Deno.test("app.bsky.feed.defs - requestMore token", () => { 479 + const requestMore = lx.token( 480 + "Request that more content like the given feed item be shown in the feed" 481 + ); 482 + 483 + assertEquals(requestMore, { 484 + type: "token", 485 + description: 486 + "Request that more content like the given feed item be shown in the feed", 487 + }); 488 + }); 489 + 490 + Deno.test("app.bsky.feed.defs - clickthroughItem token", () => { 491 + const clickthroughItem = lx.token("User clicked through to the feed item"); 492 + 493 + assertEquals(clickthroughItem, { 494 + type: "token", 495 + description: "User clicked through to the feed item", 496 + }); 497 + }); 498 + 499 + Deno.test("app.bsky.feed.defs - clickthroughAuthor token", () => { 500 + const clickthroughAuthor = lx.token( 501 + "User clicked through to the author of the feed item" 502 + ); 503 + 504 + assertEquals(clickthroughAuthor, { 505 + type: "token", 506 + description: "User clicked through to the author of the feed item", 507 + }); 508 + }); 509 + 510 + Deno.test("app.bsky.feed.defs - clickthroughReposter token", () => { 511 + const clickthroughReposter = lx.token( 512 + "User clicked through to the reposter of the feed item" 513 + ); 514 + 515 + assertEquals(clickthroughReposter, { 516 + type: "token", 517 + description: "User clicked through to the reposter of the feed item", 518 + }); 519 + }); 520 + 521 + Deno.test("app.bsky.feed.defs - clickthroughEmbed token", () => { 522 + const clickthroughEmbed = lx.token( 523 + "User clicked through to the embedded content of the feed item" 524 + ); 525 + 526 + assertEquals(clickthroughEmbed, { 527 + type: "token", 528 + description: 529 + "User clicked through to the embedded content of the feed item", 530 + }); 531 + }); 532 + 533 + Deno.test("app.bsky.feed.defs - contentModeUnspecified token", () => { 534 + const contentModeUnspecified = lx.token( 535 + "Declares the feed generator returns any types of posts." 536 + ); 537 + 538 + assertEquals(contentModeUnspecified, { 539 + type: "token", 540 + description: "Declares the feed generator returns any types of posts.", 541 + }); 542 + }); 543 + 544 + Deno.test("app.bsky.feed.defs - contentModeVideo token", () => { 545 + const contentModeVideo = lx.token( 546 + "Declares the feed generator returns posts containing app.bsky.embed.video embeds." 547 + ); 548 + 549 + assertEquals(contentModeVideo, { 550 + type: "token", 551 + description: 552 + "Declares the feed generator returns posts containing app.bsky.embed.video embeds.", 553 + }); 554 + }); 555 + 556 + Deno.test("app.bsky.feed.defs - interactionSeen token", () => { 557 + const interactionSeen = lx.token("Feed item was seen by user"); 558 + 559 + assertEquals(interactionSeen, { 560 + type: "token", 561 + description: "Feed item was seen by user", 562 + }); 563 + }); 564 + 565 + Deno.test("app.bsky.feed.defs - interactionLike token", () => { 566 + const interactionLike = lx.token("User liked the feed item"); 567 + 568 + assertEquals(interactionLike, { 569 + type: "token", 570 + description: "User liked the feed item", 571 + }); 572 + }); 573 + 574 + Deno.test("app.bsky.feed.defs - interactionRepost token", () => { 575 + const interactionRepost = lx.token("User reposted the feed item"); 576 + 577 + assertEquals(interactionRepost, { 578 + type: "token", 579 + description: "User reposted the feed item", 580 + }); 581 + }); 582 + 583 + Deno.test("app.bsky.feed.defs - interactionReply token", () => { 584 + const interactionReply = lx.token("User replied to the feed item"); 585 + 586 + assertEquals(interactionReply, { 587 + type: "token", 588 + description: "User replied to the feed item", 589 + }); 590 + }); 591 + 592 + Deno.test("app.bsky.feed.defs - interactionQuote token", () => { 593 + const interactionQuote = lx.token("User quoted the feed item"); 594 + 595 + assertEquals(interactionQuote, { 596 + type: "token", 597 + description: "User quoted the feed item", 598 + }); 599 + }); 600 + 601 + Deno.test("app.bsky.feed.defs - interactionShare token", () => { 602 + const interactionShare = lx.token("User shared the feed item"); 603 + 604 + assertEquals(interactionShare, { 605 + type: "token", 606 + description: "User shared the feed item", 607 + }); 608 + }); 609 + 610 + Deno.test("app.bsky.feed.defs - full namespace", () => { 611 + const feedDefs = lx.namespace("app.bsky.feed.defs", { 612 + postView: lx.object({ 613 + uri: lx.string({ required: true, format: "at-uri" }), 614 + cid: lx.string({ required: true, format: "cid" }), 615 + author: lx.ref("app.bsky.actor.defs#profileViewBasic", { 616 + required: true, 617 + }), 618 + record: lx.unknown({ required: true }), 619 + embed: lx.union([ 620 + "app.bsky.embed.images#view", 621 + "app.bsky.embed.video#view", 622 + "app.bsky.embed.external#view", 623 + "app.bsky.embed.record#view", 624 + "app.bsky.embed.recordWithMedia#view", 625 + ]), 626 + bookmarkCount: lx.integer(), 627 + replyCount: lx.integer(), 628 + repostCount: lx.integer(), 629 + likeCount: lx.integer(), 630 + quoteCount: lx.integer(), 631 + indexedAt: lx.string({ required: true, format: "datetime" }), 632 + viewer: lx.ref("#viewerState"), 633 + labels: lx.array(lx.ref("com.atproto.label.defs#label")), 634 + threadgate: lx.ref("#threadgateView"), 635 + }), 636 + viewerState: lx.object({ 637 + repost: lx.string({ format: "at-uri" }), 638 + like: lx.string({ format: "at-uri" }), 639 + bookmarked: lx.boolean(), 640 + threadMuted: lx.boolean(), 641 + replyDisabled: lx.boolean(), 642 + embeddingDisabled: lx.boolean(), 643 + pinned: lx.boolean(), 644 + }), 645 + requestLess: lx.token( 646 + "Request that less content like the given feed item be shown in the feed" 647 + ), 648 + requestMore: lx.token( 649 + "Request that more content like the given feed item be shown in the feed" 650 + ), 651 + clickthroughItem: lx.token("User clicked through to the feed item"), 652 + clickthroughAuthor: lx.token( 653 + "User clicked through to the author of the feed item" 654 + ), 655 + clickthroughReposter: lx.token( 656 + "User clicked through to the reposter of the feed item" 657 + ), 658 + clickthroughEmbed: lx.token( 659 + "User clicked through to the embedded content of the feed item" 660 + ), 661 + contentModeUnspecified: lx.token( 662 + "Declares the feed generator returns any types of posts." 663 + ), 664 + contentModeVideo: lx.token( 665 + "Declares the feed generator returns posts containing app.bsky.embed.video embeds." 666 + ), 667 + interactionSeen: lx.token("Feed item was seen by user"), 668 + interactionLike: lx.token("User liked the feed item"), 669 + interactionRepost: lx.token("User reposted the feed item"), 670 + interactionReply: lx.token("User replied to the feed item"), 671 + interactionQuote: lx.token("User quoted the feed item"), 672 + interactionShare: lx.token("User shared the feed item"), 673 + }); 674 + 675 + assertEquals(feedDefs.lexicon, 1); 676 + assertEquals(feedDefs.id, "app.bsky.feed.defs"); 677 + assertEquals(feedDefs.defs.postView.type, "object"); 678 + assertEquals(feedDefs.defs.viewerState.type, "object"); 679 + assertEquals(feedDefs.defs.requestLess.type, "token"); 680 + assertEquals(feedDefs.defs.contentModeVideo.type, "token"); 681 + });
+31
tests/primitives.test.ts
··· 218 218 }); 219 219 }); 220 220 221 + Deno.test("lx.ref() with required option", () => { 222 + const result = lx.ref("#profileView", { required: true }); 223 + assertEquals(result, { 224 + type: "ref", 225 + ref: "#profileView", 226 + required: true, 227 + }); 228 + }); 229 + 230 + Deno.test("lx.ref() with nullable option", () => { 231 + const result = lx.ref("#profileView", { nullable: true }); 232 + assertEquals(result, { 233 + type: "ref", 234 + ref: "#profileView", 235 + nullable: true, 236 + }); 237 + }); 238 + 239 + Deno.test("lx.ref() with both required and nullable", () => { 240 + const result = lx.ref("app.bsky.actor.defs#profileView", { 241 + required: true, 242 + nullable: true, 243 + }); 244 + assertEquals(result, { 245 + type: "ref", 246 + ref: "app.bsky.actor.defs#profileView", 247 + required: true, 248 + nullable: true, 249 + }); 250 + }); 251 + 221 252 Deno.test("lx.union() with local refs", () => { 222 253 const result = lx.union(["#reasonRepost", "#reasonPin"]); 223 254 assertEquals(result, {
+4
todo.md
··· 31 31 ## Implementation Status 32 32 33 33 initial implementation of field types returning json definitions is done 34 + 35 + ## todo 36 + 37 + write two new test files, one for bsky actor and another for bsky feed. i want to see these fully implemented and tested in separate files. then wait.