[READ-ONLY] Mirror of https://github.com/andrioid/n8n-nodes-atproto. atproto node for n8n
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};