@atproto/bsky 0.0.205 → 0.0.207

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/api/age-assurance/const.d.ts.map +1 -1
  3. package/dist/api/age-assurance/const.js +8 -0
  4. package/dist/api/age-assurance/const.js.map +1 -1
  5. package/dist/api/app/bsky/actor/getProfile.js +1 -1
  6. package/dist/api/app/bsky/actor/getProfile.js.map +1 -1
  7. package/dist/hydration/actor.d.ts +6 -0
  8. package/dist/hydration/actor.d.ts.map +1 -1
  9. package/dist/hydration/actor.js +2 -2
  10. package/dist/hydration/actor.js.map +1 -1
  11. package/dist/hydration/hydrator.d.ts +2 -2
  12. package/dist/hydration/hydrator.d.ts.map +1 -1
  13. package/dist/hydration/hydrator.js +9 -3
  14. package/dist/hydration/hydrator.js.map +1 -1
  15. package/dist/lexicon/lexicons.d.ts +26 -2
  16. package/dist/lexicon/lexicons.d.ts.map +1 -1
  17. package/dist/lexicon/lexicons.js +13 -1
  18. package/dist/lexicon/lexicons.js.map +1 -1
  19. package/dist/lexicon/types/app/bsky/actor/defs.d.ts +2 -0
  20. package/dist/lexicon/types/app/bsky/actor/defs.d.ts.map +1 -1
  21. package/dist/lexicon/types/app/bsky/actor/defs.js.map +1 -1
  22. package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts +2 -0
  23. package/dist/lexicon/types/app/bsky/ageassurance/defs.d.ts.map +1 -1
  24. package/dist/lexicon/types/app/bsky/ageassurance/defs.js.map +1 -1
  25. package/dist/views/index.d.ts.map +1 -1
  26. package/dist/views/index.js +4 -1
  27. package/dist/views/index.js.map +1 -1
  28. package/package.json +6 -6
  29. package/src/api/age-assurance/const.ts +8 -0
  30. package/src/api/app/bsky/actor/getProfile.ts +1 -1
  31. package/src/hydration/actor.ts +12 -2
  32. package/src/hydration/hydrator.ts +10 -3
  33. package/src/lexicon/lexicons.ts +14 -1
  34. package/src/lexicon/types/app/bsky/actor/defs.ts +2 -0
  35. package/src/lexicon/types/app/bsky/ageassurance/defs.ts +2 -0
  36. package/src/views/index.ts +4 -1
  37. package/tests/views/__snapshots__/profile.test.ts.snap +6 -2
  38. package/tests/views/age-assurance-v2.test.ts +2 -0
  39. package/tests/views/profile.test.ts +41 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/bsky",
3
- "version": "0.0.205",
3
+ "version": "0.0.207",
4
4
  "license": "MIT",
5
5
  "description": "Reference implementation of app.bsky App View (Bluesky API)",
6
6
  "keywords": [
@@ -52,17 +52,17 @@
52
52
  "undici": "^6.19.8",
53
53
  "zod": "3.23.8",
54
54
  "@atproto-labs/fetch-node": "0.2.0",
55
- "@atproto/api": "^0.18.10",
56
55
  "@atproto/common": "^0.5.6",
57
- "@atproto/crypto": "^0.4.5",
56
+ "@atproto/api": "^0.18.12",
58
57
  "@atproto-labs/xrpc-utils": "0.0.24",
58
+ "@atproto/crypto": "^0.4.5",
59
59
  "@atproto/did": "^0.2.4",
60
60
  "@atproto/identity": "^0.4.10",
61
61
  "@atproto/lexicon": "^0.6.0",
62
+ "@atproto/repo": "^0.8.12",
62
63
  "@atproto/sync": "^0.1.39",
63
64
  "@atproto/syntax": "^0.4.2",
64
- "@atproto/xrpc-server": "^0.10.7",
65
- "@atproto/repo": "^0.8.12"
65
+ "@atproto/xrpc-server": "^0.10.7"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@bufbuild/buf": "^1.28.1",
@@ -78,7 +78,7 @@
78
78
  "jest": "^28.1.2",
79
79
  "ts-node": "^10.8.2",
80
80
  "typescript": "^5.6.3",
81
- "@atproto/api": "^0.18.10",
81
+ "@atproto/api": "^0.18.12",
82
82
  "@atproto/lex-cli": "^0.9.8",
83
83
  "@atproto/pds": "^0.4.202",
84
84
  "@atproto/xrpc": "^0.7.7"
@@ -16,6 +16,7 @@ export const AGE_ASSURANCE_CONFIG: AppBskyAgeassuranceDefs.Config = {
16
16
  {
17
17
  countryCode: 'GB',
18
18
  regionCode: undefined,
19
+ minAccessAge: 13,
19
20
  rules: [
20
21
  {
21
22
  $type: ids.IfAssuredOverAge,
@@ -36,6 +37,7 @@ export const AGE_ASSURANCE_CONFIG: AppBskyAgeassuranceDefs.Config = {
36
37
  {
37
38
  countryCode: 'AU',
38
39
  regionCode: undefined,
40
+ minAccessAge: 16,
39
41
  rules: [
40
42
  {
41
43
  $type: ids.IfAccountNewerThan,
@@ -66,6 +68,7 @@ export const AGE_ASSURANCE_CONFIG: AppBskyAgeassuranceDefs.Config = {
66
68
  {
67
69
  countryCode: 'US',
68
70
  regionCode: 'SD',
71
+ minAccessAge: 13,
69
72
  rules: [
70
73
  {
71
74
  $type: ids.IfAssuredOverAge,
@@ -86,6 +89,7 @@ export const AGE_ASSURANCE_CONFIG: AppBskyAgeassuranceDefs.Config = {
86
89
  {
87
90
  countryCode: 'US',
88
91
  regionCode: 'WY',
92
+ minAccessAge: 13,
89
93
  rules: [
90
94
  {
91
95
  $type: ids.IfAssuredOverAge,
@@ -106,6 +110,7 @@ export const AGE_ASSURANCE_CONFIG: AppBskyAgeassuranceDefs.Config = {
106
110
  {
107
111
  countryCode: 'US',
108
112
  regionCode: 'OH',
113
+ minAccessAge: 13,
109
114
  rules: [
110
115
  {
111
116
  $type: ids.IfAssuredOverAge,
@@ -126,6 +131,7 @@ export const AGE_ASSURANCE_CONFIG: AppBskyAgeassuranceDefs.Config = {
126
131
  {
127
132
  countryCode: 'US',
128
133
  regionCode: 'MS',
134
+ minAccessAge: 18,
129
135
  rules: [
130
136
  {
131
137
  $type: ids.IfAssuredOverAge,
@@ -141,6 +147,7 @@ export const AGE_ASSURANCE_CONFIG: AppBskyAgeassuranceDefs.Config = {
141
147
  {
142
148
  countryCode: 'US',
143
149
  regionCode: 'VA',
150
+ minAccessAge: 16,
144
151
  rules: [
145
152
  {
146
153
  $type: ids.IfAssuredOverAge,
@@ -161,6 +168,7 @@ export const AGE_ASSURANCE_CONFIG: AppBskyAgeassuranceDefs.Config = {
161
168
  {
162
169
  countryCode: 'US',
163
170
  regionCode: 'TN',
171
+ minAccessAge: 18,
164
172
  rules: [
165
173
  {
166
174
  $type: ids.IfAssuredOverAge,
@@ -61,7 +61,7 @@ const hydration = async (input: {
61
61
  return ctx.hydrator.hydrateProfilesDetailed(
62
62
  [skeleton.did],
63
63
  params.hydrateCtx.copy({
64
- includeActorTakedowns: true,
64
+ overrideIncludeTakedownsForActor: true,
65
65
  }),
66
66
  )
67
67
  }
@@ -160,10 +160,20 @@ export class ActorHydrator {
160
160
  dids: string[],
161
161
  opts: {
162
162
  includeTakedowns?: boolean
163
+ /**
164
+ * The raw `HydrationCtx.includeTakedowns` value, independent of any
165
+ * special casing that may apply to `includeTakedowns` within this
166
+ * method.
167
+ */
168
+ includeTakedownsBase?: boolean
163
169
  skipCacheForDids?: string[]
164
170
  } = {},
165
171
  ): Promise<Actors> {
166
- const { includeTakedowns = false, skipCacheForDids } = opts
172
+ const {
173
+ includeTakedowns = false,
174
+ skipCacheForDids,
175
+ includeTakedownsBase = false,
176
+ } = opts
167
177
  if (!dids.length) return new HydrationMap<Actor>()
168
178
  const res = await this.dataplane.getActors({ dids, skipCacheForDids })
169
179
  return dids.reduce((acc, did, i) => {
@@ -184,7 +194,7 @@ export class ActorHydrator {
184
194
  : undefined
185
195
 
186
196
  const status = actor.statusRecord
187
- ? parseRecord<StatusRecord>(actor.statusRecord, includeTakedowns)
197
+ ? parseRecord<StatusRecord>(actor.statusRecord, includeTakedownsBase)
188
198
  : undefined
189
199
 
190
200
  const verifications = mapDefined(
@@ -80,7 +80,7 @@ export class HydrateCtx {
80
80
  labelers = this.vals.labelers
81
81
  viewer = this.vals.viewer !== null ? serviceRefToDid(this.vals.viewer) : null
82
82
  includeTakedowns = this.vals.includeTakedowns
83
- includeActorTakedowns = this.vals.includeActorTakedowns
83
+ overrideIncludeTakedownsForActor = this.vals.overrideIncludeTakedownsForActor
84
84
  include3pBlocks = this.vals.include3pBlocks
85
85
  includeDebugField = this.vals.includeDebugField
86
86
  featureGates: CheckedFeatureGatesMap = this.vals.featureGates || new Map()
@@ -99,7 +99,7 @@ export type HydrateCtxVals = {
99
99
  labelers: ParsedLabelers
100
100
  viewer: string | null
101
101
  includeTakedowns?: boolean
102
- includeActorTakedowns?: boolean
102
+ overrideIncludeTakedownsForActor?: boolean
103
103
  include3pBlocks?: boolean
104
104
  includeDebugField?: boolean
105
105
  featureGates?: CheckedFeatureGatesMap
@@ -228,10 +228,17 @@ export class Hydrator {
228
228
  dids: string[],
229
229
  ctx: HydrateCtx,
230
230
  ): Promise<HydrationState> {
231
- const includeTakedowns = ctx.includeTakedowns || ctx.includeActorTakedowns
231
+ /**
232
+ * Special case here, we want to include takedowns in special cases, like
233
+ * `getProfile`, since we throw client-facing errors later in the pipeline.
234
+ */
235
+ const includeTakedowns =
236
+ ctx.includeTakedowns || ctx.overrideIncludeTakedownsForActor
237
+ const includeTakedownsBase = ctx.includeTakedowns
232
238
  const [actors, labels, profileViewersState] = await Promise.all([
233
239
  this.actor.getActors(dids, {
234
240
  includeTakedowns,
241
+ includeTakedownsBase,
235
242
  skipCacheForDids: ctx.skipCacheForViewer,
236
243
  }),
237
244
  this.label.getLabelsForSubjects(labelSubjectsForDid(dids), ctx.labelers),
@@ -812,6 +812,14 @@ export const schemaDict = {
812
812
  type: 'object',
813
813
  required: ['status', 'record'],
814
814
  properties: {
815
+ uri: {
816
+ type: 'string',
817
+ format: 'at-uri',
818
+ },
819
+ cid: {
820
+ type: 'string',
821
+ format: 'cid',
822
+ },
815
823
  status: {
816
824
  type: 'string',
817
825
  description: 'The status for the account.',
@@ -1345,7 +1353,7 @@ export const schemaDict = {
1345
1353
  configRegion: {
1346
1354
  type: 'object',
1347
1355
  description: 'The Age Assurance configuration for a specific region.',
1348
- required: ['countryCode', 'rules'],
1356
+ required: ['countryCode', 'minAccessAge', 'rules'],
1349
1357
  properties: {
1350
1358
  countryCode: {
1351
1359
  type: 'string',
@@ -1357,6 +1365,11 @@ export const schemaDict = {
1357
1365
  description:
1358
1366
  'The ISO 3166-2 region code this configuration applies to. If omitted, the configuration applies to the entire country.',
1359
1367
  },
1368
+ minAccessAge: {
1369
+ type: 'integer',
1370
+ description:
1371
+ 'The minimum age (as a whole integer) required to use Bluesky in this region.',
1372
+ },
1360
1373
  rules: {
1361
1374
  type: 'array',
1362
1375
  description:
@@ -652,6 +652,8 @@ export function validatePostInteractionSettingsPref<V>(v: V) {
652
652
 
653
653
  export interface StatusView {
654
654
  $type?: 'app.bsky.actor.defs#statusView'
655
+ uri?: string
656
+ cid?: string
655
657
  /** The status for the account. */
656
658
  status: 'app.bsky.actor.status#live' | (string & {})
657
659
  record: { [_ in string]: unknown }
@@ -83,6 +83,8 @@ export interface ConfigRegion {
83
83
  countryCode: string
84
84
  /** The ISO 3166-2 region code this configuration applies to. If omitted, the configuration applies to the entire country. */
85
85
  regionCode?: string
86
+ /** The minimum age (as a whole integer) required to use Bluesky in this region. */
87
+ minAccessAge: number
86
88
  /** The ordered list of Age Assurance rules that apply to this region. Rules should be applied in order, and the first matching rule determines the access level granted. The rules array should always include a default rule as the last item. */
87
89
  rules: (
88
90
  | $Typed<ConfigRegionRuleDefault>
@@ -545,7 +545,8 @@ export class Views {
545
545
  if (!actor?.status) return
546
546
 
547
547
  const { status } = actor
548
- const { record, sortedAt } = status
548
+ const { record, sortedAt, cid } = status
549
+ const uri = AtUri.make(did, ids.AppBskyActorStatus, 'self').toString()
549
550
 
550
551
  const minDuration = 5 * MINUTE
551
552
  const maxDuration = 4 * HOUR
@@ -564,6 +565,8 @@ export class Views {
564
565
  const isActive = expiresAtMs ? expiresAtMs > Date.now() : undefined
565
566
 
566
567
  return {
568
+ uri,
569
+ cid,
567
570
  record: record,
568
571
  status: record.status,
569
572
  embed: isExternalEmbed(record.embed)
@@ -703,6 +703,7 @@ Object {
703
703
 
704
704
  exports[`pds profile views status returns active status when within the duration 1`] = `
705
705
  Object {
706
+ "cid": "cids(0)",
706
707
  "embed": Object {
707
708
  "$type": "app.bsky.embed.external#view",
708
709
  "external": Object {
@@ -728,11 +729,13 @@ Object {
728
729
  "status": "app.bsky.actor.status#live",
729
730
  },
730
731
  "status": "app.bsky.actor.status#live",
732
+ "uri": "record(0)",
731
733
  }
732
734
  `;
733
735
 
734
736
  exports[`pds profile views status when outside the duration returns inactive status 1`] = `
735
737
  Object {
738
+ "cid": "cids(0)",
736
739
  "embed": Object {
737
740
  "$type": "app.bsky.embed.external#view",
738
741
  "external": Object {
@@ -741,11 +744,11 @@ Object {
741
744
  "uri": "https://example.com",
742
745
  },
743
746
  },
744
- "expiresAt": "2021-01-01T01:10:00.000Z",
747
+ "expiresAt": "1970-01-01T00:00:00.000Z",
745
748
  "isActive": false,
746
749
  "record": Object {
747
750
  "$type": "app.bsky.actor.status",
748
- "createdAt": "2021-01-01T01:00:00.000Z",
751
+ "createdAt": "1970-01-01T00:00:00.000Z",
749
752
  "durationMinutes": 10,
750
753
  "embed": Object {
751
754
  "$type": "app.bsky.embed.external",
@@ -758,5 +761,6 @@ Object {
758
761
  "status": "app.bsky.actor.status#live",
759
762
  },
760
763
  "status": "app.bsky.actor.status#live",
764
+ "uri": "record(0)",
761
765
  }
762
766
  `;
@@ -33,6 +33,7 @@ jest.mock('../../dist/api/age-assurance/const.js', () => {
33
33
  {
34
34
  countryCode: 'AA',
35
35
  regionCode: undefined,
36
+ minAccessAge: 13,
36
37
  rules: [
37
38
  {
38
39
  $type: ruleIds.IfAssuredOverAge,
@@ -48,6 +49,7 @@ jest.mock('../../dist/api/age-assurance/const.js', () => {
48
49
  {
49
50
  countryCode: 'BB',
50
51
  regionCode: undefined,
52
+ minAccessAge: 13,
51
53
  rules: [
52
54
  {
53
55
  $type: ruleIds.IfAssuredOverAge,
@@ -490,7 +490,47 @@ describe('pds profile views', () => {
490
490
  )
491
491
 
492
492
  // Doesn't need `forSnapshot` because the dates are already mocked.
493
- expect(data.status).toMatchSnapshot()
493
+ expect(forSnapshot(data.status)).toMatchSnapshot()
494
+ })
495
+ })
496
+
497
+ describe('when taken down', () => {
498
+ it('it does not return the live status', async () => {
499
+ const res = await sc.agent.com.atproto.repo.putRecord(
500
+ {
501
+ repo: alice,
502
+ collection: ids.AppBskyActorStatus,
503
+ rkey: 'self',
504
+ record: {
505
+ status: 'app.bsky.actor.status#live',
506
+ embed,
507
+ durationMinutes: 10,
508
+ createdAt: new Date().toISOString(),
509
+ },
510
+ },
511
+ {
512
+ headers: sc.getHeaders(alice),
513
+ encoding: 'application/json',
514
+ },
515
+ )
516
+ await network.processAll()
517
+
518
+ await network.bsky.ctx.dataplane.takedownRecord({
519
+ recordUri: res.data.uri,
520
+ })
521
+ await network.processAll()
522
+
523
+ const { data } = await agent.api.app.bsky.actor.getProfile(
524
+ { actor: alice },
525
+ {
526
+ headers: await network.serviceHeaders(
527
+ alice,
528
+ ids.AppBskyActorGetProfile,
529
+ ),
530
+ },
531
+ )
532
+
533
+ expect(forSnapshot(data.status)).toBeUndefined()
494
534
  })
495
535
  })
496
536
  })