@atproto/bsky 0.0.237 → 0.0.238
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/api/com/atproto/repo/getRecord.js +2 -2
- package/dist/api/com/atproto/repo/getRecord.js.map +1 -1
- package/dist/hydration/hydrator.d.ts.map +1 -1
- package/dist/hydration/hydrator.js +3 -2
- package/dist/hydration/hydrator.js.map +1 -1
- package/dist/hydration/label.d.ts +1 -1
- package/dist/hydration/label.d.ts.map +1 -1
- package/dist/hydration/label.js +4 -4
- package/dist/hydration/label.js.map +1 -1
- package/dist/lexicons/app/bsky/actor/profile.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/actor/status.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/draft/defs.defs.d.ts +22 -0
- package/dist/lexicons/app/bsky/draft/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/draft/defs.defs.js +11 -0
- package/dist/lexicons/app/bsky/draft/defs.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/gallery.d.ts +3 -0
- package/dist/lexicons/app/bsky/embed/gallery.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/embed/gallery.defs.d.ts +130 -0
- package/dist/lexicons/app/bsky/embed/gallery.defs.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/embed/gallery.defs.js +47 -0
- package/dist/lexicons/app/bsky/embed/gallery.defs.js.map +1 -0
- package/dist/lexicons/app/bsky/embed/gallery.js +6 -0
- package/dist/lexicons/app/bsky/embed/gallery.js.map +1 -0
- package/dist/lexicons/app/bsky/embed/record.defs.d.ts +2 -1
- package/dist/lexicons/app/bsky/embed/record.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/record.defs.js +2 -0
- package/dist/lexicons/app/bsky/embed/record.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/recordWithMedia.defs.d.ts +13 -12
- package/dist/lexicons/app/bsky/embed/recordWithMedia.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/recordWithMedia.defs.js +3 -0
- package/dist/lexicons/app/bsky/embed/recordWithMedia.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed.d.ts +1 -0
- package/dist/lexicons/app/bsky/embed.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed.js +1 -0
- package/dist/lexicons/app/bsky/embed.js.map +1 -1
- package/dist/lexicons/app/bsky/feed/defs.defs.d.ts +2 -1
- package/dist/lexicons/app/bsky/feed/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/feed/defs.defs.js +2 -0
- package/dist/lexicons/app/bsky/feed/defs.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/feed/generator.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/feed/like.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/feed/post.defs.d.ts +12 -11
- package/dist/lexicons/app/bsky/feed/post.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/feed/post.defs.js +2 -0
- package/dist/lexicons/app/bsky/feed/post.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/feed/postgate.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/feed/repost.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/feed/threadgate.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/graph/block.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/graph/follow.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/graph/list.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/graph/listblock.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/graph/listitem.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/graph/starterpack.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/graph/verification.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/labeler/service.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/notification/declaration.defs.d.ts.map +1 -1
- package/dist/lexicons/chat/bsky/actor/declaration.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/lexicon/schema.defs.d.ts.map +1 -1
- package/dist/lexicons/com/germnetwork/declaration.defs.d.ts.map +1 -1
- package/dist/lexicons/site/standard/document.defs.d.ts.map +1 -1
- package/dist/lexicons/site/standard/graph/recommend.defs.d.ts.map +1 -1
- package/dist/lexicons/site/standard/graph/subscription.defs.d.ts.map +1 -1
- package/dist/lexicons/site/standard/publication.defs.d.ts.map +1 -1
- package/dist/lexicons/site/standard/theme/basic.defs.d.ts.map +1 -1
- package/dist/views/index.d.ts +4 -1
- package/dist/views/index.d.ts.map +1 -1
- package/dist/views/index.js +39 -5
- package/dist/views/index.js.map +1 -1
- package/dist/views/types.d.ts +8 -2
- package/dist/views/types.d.ts.map +1 -1
- package/dist/views/types.js +2 -0
- package/dist/views/types.js.map +1 -1
- package/package.json +7 -7
- package/src/api/com/atproto/repo/getRecord.ts +2 -2
- package/src/hydration/hydrator.ts +3 -6
- package/src/hydration/label.ts +3 -3
- package/src/views/index.ts +61 -11
- package/src/views/types.ts +9 -0
- package/tests/views/__snapshots__/posts.test.ts.snap +251 -0
- package/tests/views/drafts.test.ts +105 -0
- package/tests/views/posts.test.ts +134 -0
- package/tsconfig.build.tsbuildinfo +1 -1
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
vi,
|
|
9
9
|
} from 'vitest'
|
|
10
10
|
import {
|
|
11
|
+
$Typed,
|
|
11
12
|
AppBskyDraftCreateDraft,
|
|
12
13
|
AppBskyDraftDefs,
|
|
13
14
|
AppBskyDraftGetDrafts,
|
|
@@ -302,6 +303,110 @@ describe('appview drafts views', () => {
|
|
|
302
303
|
expect(paginated.at(-1)?.id).toBe(full.at(-1)?.id)
|
|
303
304
|
})
|
|
304
305
|
})
|
|
306
|
+
|
|
307
|
+
describe('gallery embed', () => {
|
|
308
|
+
const galleryItem = (
|
|
309
|
+
i: number,
|
|
310
|
+
): $Typed<AppBskyDraftDefs.DraftEmbedImage> => ({
|
|
311
|
+
$type: 'app.bsky.draft.defs#draftEmbedImage',
|
|
312
|
+
localRef: { path: `/local/img-${i}.jpg` },
|
|
313
|
+
alt: `image ${i}`,
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
const galleryDraft = (size: number): AppBskyDraftDefs.Draft => ({
|
|
317
|
+
posts: [
|
|
318
|
+
{
|
|
319
|
+
text: 'gallery draft',
|
|
320
|
+
embedGallery: {
|
|
321
|
+
items: Array.from({ length: size }, (_, i) => galleryItem(i)),
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
],
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
it('round-trips a draft with embedGallery', async () => {
|
|
328
|
+
await create(alice, galleryDraft(3))
|
|
329
|
+
const { data } = await get(alice)
|
|
330
|
+
expect(data.drafts).toHaveLength(1)
|
|
331
|
+
|
|
332
|
+
const post = data.drafts[0].draft.posts[0]
|
|
333
|
+
expect(post.embedGallery?.items).toHaveLength(3)
|
|
334
|
+
post.embedGallery?.items.forEach((item, i) => {
|
|
335
|
+
expect(item.$type).toBe('app.bsky.draft.defs#draftEmbedImage')
|
|
336
|
+
if (AppBskyDraftDefs.isDraftEmbedImage(item)) {
|
|
337
|
+
expect(item.localRef.path).toBe(`/local/img-${i}.jpg`)
|
|
338
|
+
expect(item.alt).toBe(`image ${i}`)
|
|
339
|
+
}
|
|
340
|
+
})
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
it('updates a draft to add a gallery', async () => {
|
|
344
|
+
await create(alice, { posts: [{ text: 'text only' }] })
|
|
345
|
+
const { data: before } = await get(alice)
|
|
346
|
+
expect(before.drafts).toHaveLength(1)
|
|
347
|
+
expect(before.drafts[0].draft.posts[0].embedGallery).toBeUndefined()
|
|
348
|
+
|
|
349
|
+
const draftId = before.drafts[0].id
|
|
350
|
+
await update(alice, {
|
|
351
|
+
id: draftId,
|
|
352
|
+
draft: galleryDraft(2),
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
const { data: after } = await get(alice)
|
|
356
|
+
expect(after.drafts).toHaveLength(1)
|
|
357
|
+
expect(after.drafts[0].id).toBe(draftId)
|
|
358
|
+
expect(after.drafts[0].draft.posts[0].embedGallery?.items).toHaveLength(2)
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
it('updates a draft to change gallery items', async () => {
|
|
362
|
+
await create(alice, galleryDraft(2))
|
|
363
|
+
const { data: before } = await get(alice)
|
|
364
|
+
expect(before.drafts[0].draft.posts[0].embedGallery?.items).toHaveLength(
|
|
365
|
+
2,
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
const draftId = before.drafts[0].id
|
|
369
|
+
await update(alice, {
|
|
370
|
+
id: draftId,
|
|
371
|
+
draft: galleryDraft(5),
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
const { data: after } = await get(alice)
|
|
375
|
+
const post = after.drafts[0].draft.posts[0]
|
|
376
|
+
expect(post.embedGallery?.items).toHaveLength(5)
|
|
377
|
+
// Confirm full replacement (new items 0..4, not appended onto old 0..1).
|
|
378
|
+
post.embedGallery?.items.forEach((item, i) => {
|
|
379
|
+
if (AppBskyDraftDefs.isDraftEmbedImage(item)) {
|
|
380
|
+
expect(item.localRef.path).toBe(`/local/img-${i}.jpg`)
|
|
381
|
+
}
|
|
382
|
+
})
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
it('rejects embedGallery.items exceeding maxLength=20', async () => {
|
|
386
|
+
await expect(create(alice, galleryDraft(21))).rejects.toThrow()
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
it('rejects gallery items without $type', async () => {
|
|
390
|
+
const badDraft = {
|
|
391
|
+
posts: [
|
|
392
|
+
{
|
|
393
|
+
text: 'gallery without $type',
|
|
394
|
+
embedGallery: {
|
|
395
|
+
items: [
|
|
396
|
+
// Union members must be $type-tagged. Cast away types so the
|
|
397
|
+
// request reaches the server, where lex validation rejects it.
|
|
398
|
+
{
|
|
399
|
+
localRef: { path: '/local/untagged.jpg' },
|
|
400
|
+
alt: 'untagged',
|
|
401
|
+
} as unknown as $Typed<AppBskyDraftDefs.DraftEmbedImage>,
|
|
402
|
+
],
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
],
|
|
406
|
+
}
|
|
407
|
+
await expect(create(alice, badDraft)).rejects.toThrow()
|
|
408
|
+
})
|
|
409
|
+
})
|
|
305
410
|
})
|
|
306
411
|
|
|
307
412
|
const clearDrafts = async (db: Database) => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
|
|
2
2
|
import {
|
|
3
|
+
AppBskyEmbedGallery,
|
|
3
4
|
AppBskyEmbedRecord,
|
|
4
5
|
AppBskyEmbedRecordWithMedia,
|
|
5
6
|
AppBskyEmbedVideo,
|
|
@@ -291,4 +292,137 @@ describe('pds posts views', () => {
|
|
|
291
292
|
expect(data.posts.length).toBe(1)
|
|
292
293
|
expect(forSnapshot(data.posts[0])).toMatchSnapshot()
|
|
293
294
|
})
|
|
295
|
+
|
|
296
|
+
it('embeds gallery.', async () => {
|
|
297
|
+
const img1 = await sc.uploadFile(
|
|
298
|
+
sc.dids.alice,
|
|
299
|
+
'../dev-env/assets/key-landscape-small.jpg',
|
|
300
|
+
'image/jpeg',
|
|
301
|
+
)
|
|
302
|
+
const img2 = await sc.uploadFile(
|
|
303
|
+
sc.dids.alice,
|
|
304
|
+
'../dev-env/assets/key-portrait-small.jpg',
|
|
305
|
+
'image/jpeg',
|
|
306
|
+
)
|
|
307
|
+
const { uri } = await pdsAgent.api.app.bsky.feed.post.create(
|
|
308
|
+
{ repo: sc.dids.alice },
|
|
309
|
+
{
|
|
310
|
+
text: 'gallery',
|
|
311
|
+
createdAt: new Date().toISOString(),
|
|
312
|
+
embed: {
|
|
313
|
+
$type: 'app.bsky.embed.gallery',
|
|
314
|
+
items: [
|
|
315
|
+
{
|
|
316
|
+
$type: 'app.bsky.embed.gallery#image',
|
|
317
|
+
image: img1.image,
|
|
318
|
+
alt: 'landscape',
|
|
319
|
+
aspectRatio: { width: 4, height: 3 },
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
$type: 'app.bsky.embed.gallery#image',
|
|
323
|
+
image: img2.image,
|
|
324
|
+
alt: 'portrait',
|
|
325
|
+
aspectRatio: { width: 3, height: 4 },
|
|
326
|
+
},
|
|
327
|
+
],
|
|
328
|
+
} satisfies AppBskyEmbedGallery.Main,
|
|
329
|
+
},
|
|
330
|
+
sc.getHeaders(sc.dids.alice),
|
|
331
|
+
)
|
|
332
|
+
await network.processAll()
|
|
333
|
+
const { data } = await agent.app.bsky.feed.getPosts({ uris: [uri] })
|
|
334
|
+
expect(data.posts.length).toBe(1)
|
|
335
|
+
expect(forSnapshot(data.posts[0])).toMatchSnapshot()
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
it('embeds gallery with record.', async () => {
|
|
339
|
+
const img = await sc.uploadFile(
|
|
340
|
+
sc.dids.alice,
|
|
341
|
+
'../dev-env/assets/key-landscape-small.jpg',
|
|
342
|
+
'image/jpeg',
|
|
343
|
+
)
|
|
344
|
+
const embedRecord = await pdsAgent.api.app.bsky.feed.post.create(
|
|
345
|
+
{ repo: sc.dids.alice },
|
|
346
|
+
{
|
|
347
|
+
text: 'embedded',
|
|
348
|
+
createdAt: new Date().toISOString(),
|
|
349
|
+
},
|
|
350
|
+
sc.getHeaders(sc.dids.alice),
|
|
351
|
+
)
|
|
352
|
+
const { uri } = await pdsAgent.api.app.bsky.feed.post.create(
|
|
353
|
+
{ repo: sc.dids.alice },
|
|
354
|
+
{
|
|
355
|
+
text: 'gallery + record',
|
|
356
|
+
createdAt: new Date().toISOString(),
|
|
357
|
+
embed: {
|
|
358
|
+
$type: 'app.bsky.embed.recordWithMedia',
|
|
359
|
+
record: {
|
|
360
|
+
record: {
|
|
361
|
+
uri: embedRecord.uri,
|
|
362
|
+
cid: embedRecord.cid,
|
|
363
|
+
},
|
|
364
|
+
} satisfies AppBskyEmbedRecord.Main,
|
|
365
|
+
media: {
|
|
366
|
+
$type: 'app.bsky.embed.gallery',
|
|
367
|
+
items: [
|
|
368
|
+
{
|
|
369
|
+
$type: 'app.bsky.embed.gallery#image',
|
|
370
|
+
image: img.image,
|
|
371
|
+
alt: 'landscape',
|
|
372
|
+
aspectRatio: { width: 4, height: 3 },
|
|
373
|
+
},
|
|
374
|
+
],
|
|
375
|
+
} satisfies AppBskyEmbedGallery.Main,
|
|
376
|
+
} satisfies AppBskyEmbedRecordWithMedia.Main,
|
|
377
|
+
},
|
|
378
|
+
sc.getHeaders(sc.dids.alice),
|
|
379
|
+
)
|
|
380
|
+
await network.processAll()
|
|
381
|
+
const { data } = await agent.app.bsky.feed.getPosts({ uris: [uri] })
|
|
382
|
+
expect(data.posts.length).toBe(1)
|
|
383
|
+
expect(forSnapshot(data.posts[0])).toMatchSnapshot()
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
it('truncates gallery view to soft limit of 10 items.', async () => {
|
|
387
|
+
const img = await sc.uploadFile(
|
|
388
|
+
sc.dids.alice,
|
|
389
|
+
'../dev-env/assets/key-landscape-small.jpg',
|
|
390
|
+
'image/jpeg',
|
|
391
|
+
)
|
|
392
|
+
const items: AppBskyEmbedGallery.Main['items'] = Array.from(
|
|
393
|
+
{ length: 11 },
|
|
394
|
+
(_, i) => ({
|
|
395
|
+
$type: 'app.bsky.embed.gallery#image',
|
|
396
|
+
image: img.image,
|
|
397
|
+
alt: `item ${i}`,
|
|
398
|
+
aspectRatio: { width: 4, height: 3 },
|
|
399
|
+
}),
|
|
400
|
+
)
|
|
401
|
+
const { uri } = await pdsAgent.api.app.bsky.feed.post.create(
|
|
402
|
+
{ repo: sc.dids.alice },
|
|
403
|
+
{
|
|
404
|
+
text: 'oversize gallery',
|
|
405
|
+
createdAt: new Date().toISOString(),
|
|
406
|
+
embed: {
|
|
407
|
+
$type: 'app.bsky.embed.gallery',
|
|
408
|
+
items,
|
|
409
|
+
} satisfies AppBskyEmbedGallery.Main,
|
|
410
|
+
},
|
|
411
|
+
sc.getHeaders(sc.dids.alice),
|
|
412
|
+
)
|
|
413
|
+
await network.processAll()
|
|
414
|
+
const { data } = await agent.app.bsky.feed.getPosts({ uris: [uri] })
|
|
415
|
+
expect(data.posts.length).toBe(1)
|
|
416
|
+
const embed = data.posts[0].embed
|
|
417
|
+
if (!embed || !AppBskyEmbedGallery.isView(embed)) {
|
|
418
|
+
throw new Error('expected gallery view')
|
|
419
|
+
}
|
|
420
|
+
expect(embed.items).toHaveLength(10)
|
|
421
|
+
// Verify the AppView keeps the head of the items list (not the tail).
|
|
422
|
+
embed.items.forEach((item, i) => {
|
|
423
|
+
if (AppBskyEmbedGallery.isViewImage(item)) {
|
|
424
|
+
expect(item.alt).toBe(`item ${i}`)
|
|
425
|
+
}
|
|
426
|
+
})
|
|
427
|
+
})
|
|
294
428
|
})
|