[READ-ONLY] Mirror of https://github.com/andrioid/n8n-nodes-atproto. atproto node for n8n
0

Configure Feed

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

n8n-nodes-atproto / tests / mockLexicons.ts
11 kB 437 lines
1/** 2 * Mock lexicon documents used in Phase 2 tests. 3 * 4 * These represent real AT Protocol lexicon shapes but use simplified 5 * content to keep tests focused on the mapping logic. 6 */ 7 8/** A realistic `app.bsky.feed.post` lexicon with refs, unions, arrays. */ 9export const APP_BSKY_FEED_POST = { 10 $type: 'com.atproto.lexicon.schema', 11 lexicon: 1, 12 id: 'app.bsky.feed.post', 13 revision: 1, 14 description: 'A post in a Bluesky feed.', 15 defs: { 16 main: { 17 type: 'record', 18 key: 'tid', 19 record: { 20 type: 'object', 21 properties: { 22 text: { 23 type: 'string', 24 maxLength: 3000, 25 description: 'Post text', 26 }, 27 createdAt: { 28 type: 'string', 29 format: 'datetime', 30 description: 'Post creation date', 31 }, 32 facets: { 33 type: 'array', 34 items: { ref: 'app.bsky.richtext.facet' }, 35 }, 36 reply: { 37 type: 'ref', 38 ref: 'app.bsky.feed.post#replyRef', 39 }, 40 embed: { 41 type: 'union', 42 refs: [ 43 'app.bsky.embed.images', 44 'app.bsky.embed.external', 45 'app.bsky.embed.record', 46 'app.bsky.embed.recordWithMedia', 47 ], 48 }, 49 tags: { 50 type: 'array', 51 items: { type: 'string' }, 52 }, 53 langs: { 54 type: 'array', 55 items: { type: 'string' }, 56 }, 57 labels: { 58 type: 'ref', 59 ref: 'com.atproto.label.defs#selfLabels', 60 }, 61 }, 62 required: ['text', 'createdAt'], 63 }, 64 }, 65 replyRef: { 66 type: 'object', 67 required: ['root', 'parent'], 68 properties: { 69 root: { type: 'ref', ref: 'com.atproto.repo.strongRef' }, 70 parent: { type: 'ref', ref: 'com.atproto.repo.strongRef' }, 71 }, 72 }, 73 }, 74}; 75 76/** A lexicon with only primitive types. */ 77export const PRIMITIVE_ONLY = { 78 $type: 'com.atproto.lexicon.schema', 79 lexicon: 1, 80 id: 'io.example.primitive', 81 defs: { 82 main: { 83 type: 'record', 84 key: 'any', 85 record: { 86 type: 'object', 87 properties: { 88 title: { type: 'string', description: 'A title' }, 89 count: { type: 'integer' }, 90 enabled: { type: 'boolean' }, 91 publishedAt: { type: 'string', format: 'datetime' }, 92 url: { type: 'string', format: 'uri' }, 93 blob: { type: 'blob' }, 94 cid: { type: 'cid-link' }, 95 data: { type: 'bytes' }, 96 }, 97 required: ['title', 'count'], 98 }, 99 }, 100 }, 101}; 102 103/** A lexicon that uses query/procedure (not a record) — should fail parse. */ 104export const QUERY_NOT_RECORD = { 105 $type: 'com.atproto.lexicon.schema', 106 lexicon: 1, 107 id: 'com.atproto.repo.getRecord', 108 defs: { 109 main: { 110 type: 'query', 111 parameters: { 112 type: 'params', 113 properties: { 114 repo: { type: 'string' }, 115 collection: { type: 'string' }, 116 rkey: { type: 'string' }, 117 }, 118 required: ['repo', 'collection', 'rkey'], 119 }, 120 }, 121 }, 122}; 123 124/** A lexicon with nested inline objects. */ 125export const INLINE_OBJECT = { 126 $type: 'com.atproto.lexicon.schema', 127 lexicon: 1, 128 id: 'io.example.nested', 129 defs: { 130 main: { 131 type: 'record', 132 key: 'tid', 133 record: { 134 type: 'object', 135 properties: { 136 name: { type: 'string' }, 137 metadata: { 138 type: 'object', 139 properties: { 140 source: { type: 'string' }, 141 version: { type: 'integer' }, 142 }, 143 required: ['source'], 144 }, 145 }, 146 required: ['name'], 147 }, 148 }, 149 }, 150}; 151 152/** 153 * Type-only lexicon (no main record) — defines reusable types only. 154 * Modeled on `site.standard.theme.color`. 155 */ 156export const TYPE_ONLY_COLOR = { 157 $type: 'com.atproto.lexicon.schema', 158 lexicon: 1, 159 id: 'io.example.color', 160 defs: { 161 rgb: { 162 type: 'object', 163 required: ['r', 'g', 'b'], 164 properties: { 165 r: { type: 'integer', minimum: 0, maximum: 255 }, 166 g: { type: 'integer', minimum: 0, maximum: 255 }, 167 b: { type: 'integer', minimum: 0, maximum: 255 }, 168 }, 169 }, 170 rgba: { 171 type: 'object', 172 required: ['r', 'g', 'b', 'a'], 173 properties: { 174 r: { type: 'integer', minimum: 0, maximum: 255 }, 175 g: { type: 'integer', minimum: 0, maximum: 255 }, 176 b: { type: 'integer', minimum: 0, maximum: 255 }, 177 a: { type: 'integer', minimum: 0, maximum: 100 }, 178 }, 179 }, 180 }, 181}; 182 183/** 184 * Record lexicon with single-ref union properties. 185 * Modeled on `site.standard.theme.basic` — each color property is a 186 * single-ref union pointing to `io.example.color#rgb`. 187 */ 188export const SINGLE_REF_UNION = { 189 $type: 'com.atproto.lexicon.schema', 190 lexicon: 1, 191 id: 'io.example.theme', 192 defs: { 193 main: { 194 type: 'record', 195 key: 'tid', 196 record: { 197 type: 'object', 198 properties: { 199 background: { 200 type: 'union', 201 refs: ['io.example.color#rgb'], 202 description: 'Color used for content background.', 203 }, 204 accent: { 205 type: 'union', 206 refs: ['io.example.color#rgb'], 207 description: 'Color used for links.', 208 }, 209 }, 210 required: ['background', 'accent'], 211 }, 212 }, 213 }, 214}; 215 216/** 217 * Record lexicon that references a single-ref union theme via ref. 218 * Modeled on `site.standard.publication` → basicTheme. 219 */ 220export const PUBLICATION_WITH_THEME = { 221 $type: 'com.atproto.lexicon.schema', 222 lexicon: 1, 223 id: 'io.example.publication', 224 defs: { 225 main: { 226 type: 'record', 227 key: 'tid', 228 record: { 229 type: 'object', 230 properties: { 231 name: { 232 type: 'string', 233 description: 'Name of the publication.', 234 }, 235 theme: { 236 type: 'ref', 237 ref: 'io.example.theme', 238 description: 'Theme for the publication.', 239 }, 240 labels: { 241 type: 'union', 242 refs: [ 243 'io.example.label#a', 244 'io.example.label#b', 245 ], 246 description: 'Multi-ref union (should stay as object).', 247 }, 248 }, 249 required: ['name'], 250 }, 251 }, 252 }, 253}; 254 255/** 256 * Lexicon with every constraint type for Phase 5 testing. 257 * 258 * Covers: enum, knownValues, default, const, minimum/maximum, 259 * minLength/maxLength, minGraphemes/maxGraphemes, blob accept/maxSize, 260 * closed union, array length constraints, nullable fields. 261 */ 262export const CONSTRAINED_SCHEMA = { 263 $type: 'com.atproto.lexicon.schema', 264 lexicon: 1, 265 id: 'io.example.constrained', 266 defs: { 267 main: { 268 type: 'record', 269 key: 'tid', 270 record: { 271 type: 'object', 272 properties: { 273 visibility: { 274 type: 'string', 275 enum: ['public', 'private', 'unlisted'], 276 default: 'public', 277 description: 'Post visibility', 278 }, 279 priority: { 280 type: 'integer', 281 enum: [0, 1, 2], 282 description: 'Priority level', 283 }, 284 role: { 285 type: 'string', 286 knownValues: [ 287 'com.example.defs#admin', 288 'com.example.defs#moderator', 289 'com.example.defs#member', 290 'com.example.defs#guest', 291 'com.example.defs#bot', 292 ], 293 description: 'User role', 294 }, 295 bio: { 296 type: 'string', 297 maxLength: 2560, 298 maxGraphemes: 256, 299 description: 'Profile bio', 300 }, 301 displayName: { 302 type: 'string', 303 minLength: 1, 304 maxLength: 640, 305 maxGraphemes: 64, 306 description: 'Display name', 307 }, 308 score: { 309 type: 'integer', 310 minimum: 0, 311 maximum: 100, 312 description: 'Score value', 313 }, 314 version: { 315 type: 'integer', 316 const: 1, 317 description: 'Schema version', 318 }, 319 locked: { 320 type: 'boolean', 321 const: false, 322 description: 'Lock state', 323 }, 324 avatar: { 325 type: 'blob', 326 accept: ['image/png', 'image/jpeg'], 327 maxSize: 1000000, 328 description: 'Profile avatar', 329 }, 330 tags: { 331 type: 'array', 332 items: { type: 'string', maxLength: 640, maxGraphemes: 64 }, 333 minLength: 1, 334 maxLength: 8, 335 description: 'Content tags', 336 }, 337 embed: { 338 type: 'union', 339 closed: true, 340 refs: ['io.example.constrained#imageEmbed', 'io.example.constrained#linkEmbed'], 341 description: 'Embedded content', 342 }, 343 handle: { 344 type: 'string', 345 format: 'handle', 346 description: 'AT Protocol handle', 347 }, 348 website: { 349 type: 'string', 350 format: 'uri', 351 description: 'Website URL', 352 }, 353 atUri: { 354 type: 'string', 355 format: 'at-uri', 356 description: 'AT URI reference', 357 }, 358 unknown: { 359 type: 'unknown', 360 description: 'Arbitrary JSON object', 361 }, 362 nullableField: { 363 type: 'string', 364 description: 'A nullable string', 365 }, 366 }, 367 required: ['visibility', 'score', 'version', 'nullableField'], 368 nullable: ['nullableField'], 369 }, 370 }, 371 imageEmbed: { 372 type: 'object', 373 required: ['url'], 374 properties: { 375 url: { type: 'string', format: 'uri' }, 376 alt: { type: 'string', maxGraphemes: 300 }, 377 }, 378 }, 379 linkEmbed: { 380 type: 'object', 381 required: ['url'], 382 properties: { 383 url: { type: 'string', format: 'uri' }, 384 title: { type: 'string' }, 385 }, 386 }, 387 }, 388}; 389 390/** A lexicon that demonstrates a deeply nested ref chain. */ 391export const DEEPLY_NESTED = { 392 $type: 'com.atproto.lexicon.schema', 393 lexicon: 1, 394 id: 'io.example.deep', 395 defs: { 396 main: { 397 type: 'record', 398 key: 'tid', 399 record: { 400 type: 'object', 401 properties: { 402 level1: { 403 type: 'ref', 404 ref: 'io.example.deep#level1Ref', 405 }, 406 }, 407 required: [], 408 }, 409 }, 410 level1Ref: { 411 type: 'object', 412 properties: { 413 name: { type: 'string' }, 414 level2: { 415 type: 'ref', 416 ref: 'io.example.deep#level2Ref', 417 }, 418 }, 419 }, 420 level2Ref: { 421 type: 'object', 422 properties: { 423 value: { type: 'integer' }, 424 level3: { 425 type: 'ref', 426 ref: 'io.example.deep#level3Ref', 427 }, 428 }, 429 }, 430 level3Ref: { 431 type: 'object', 432 properties: { 433 deep: { type: 'string' }, 434 }, 435 }, 436 }, 437};