@atproto/pds 0.4.100 → 0.4.102

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 (89) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/actor-store/repo/transactor.d.ts +5 -5
  3. package/dist/actor-store/repo/transactor.d.ts.map +1 -1
  4. package/dist/actor-store/repo/transactor.js +38 -18
  5. package/dist/actor-store/repo/transactor.js.map +1 -1
  6. package/dist/actor-store/repo/util.d.ts +5 -0
  7. package/dist/actor-store/repo/util.d.ts.map +1 -0
  8. package/dist/actor-store/repo/util.js +25 -0
  9. package/dist/actor-store/repo/util.js.map +1 -0
  10. package/dist/api/com/atproto/repo/applyWrites.js +1 -1
  11. package/dist/api/com/atproto/repo/applyWrites.js.map +1 -1
  12. package/dist/api/com/atproto/repo/createRecord.d.ts.map +1 -1
  13. package/dist/api/com/atproto/repo/createRecord.js +3 -3
  14. package/dist/api/com/atproto/repo/createRecord.js.map +1 -1
  15. package/dist/api/com/atproto/repo/deleteRecord.js +1 -1
  16. package/dist/api/com/atproto/repo/deleteRecord.js.map +1 -1
  17. package/dist/api/com/atproto/repo/putRecord.d.ts.map +1 -1
  18. package/dist/api/com/atproto/repo/putRecord.js +1 -1
  19. package/dist/api/com/atproto/repo/putRecord.js.map +1 -1
  20. package/dist/api/com/atproto/server/activateAccount.d.ts.map +1 -1
  21. package/dist/api/com/atproto/server/activateAccount.js +4 -1
  22. package/dist/api/com/atproto/server/activateAccount.js.map +1 -1
  23. package/dist/api/com/atproto/server/createAccount.js +1 -1
  24. package/dist/api/com/atproto/server/createAccount.js.map +1 -1
  25. package/dist/index.d.ts +1 -1
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/lexicon/index.d.ts +2 -0
  28. package/dist/lexicon/index.d.ts.map +1 -1
  29. package/dist/lexicon/index.js +4 -0
  30. package/dist/lexicon/index.js.map +1 -1
  31. package/dist/lexicon/lexicons.d.ts +166 -32
  32. package/dist/lexicon/lexicons.d.ts.map +1 -1
  33. package/dist/lexicon/lexicons.js +105 -15
  34. package/dist/lexicon/lexicons.js.map +1 -1
  35. package/dist/lexicon/types/chat/bsky/convo/updateAllRead.d.ts +40 -0
  36. package/dist/lexicon/types/chat/bsky/convo/updateAllRead.d.ts.map +1 -0
  37. package/dist/lexicon/types/chat/bsky/convo/updateAllRead.js +7 -0
  38. package/dist/lexicon/types/chat/bsky/convo/updateAllRead.js.map +1 -0
  39. package/dist/lexicon/types/com/atproto/sync/getRepoStatus.d.ts +1 -1
  40. package/dist/lexicon/types/com/atproto/sync/getRepoStatus.d.ts.map +1 -1
  41. package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts +1 -1
  42. package/dist/lexicon/types/com/atproto/sync/listRepos.d.ts.map +1 -1
  43. package/dist/lexicon/types/com/atproto/sync/listRepos.js.map +1 -1
  44. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.d.ts +25 -7
  45. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.d.ts.map +1 -1
  46. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.js +9 -0
  47. package/dist/lexicon/types/com/atproto/sync/subscribeRepos.js.map +1 -1
  48. package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts +2 -2
  49. package/dist/lexicon/types/tools/ozone/moderation/defs.d.ts.map +1 -1
  50. package/dist/repo/types.d.ts +12 -1
  51. package/dist/repo/types.d.ts.map +1 -1
  52. package/dist/repo/types.js.map +1 -1
  53. package/dist/scripts/rebuild-repo.d.ts.map +1 -1
  54. package/dist/scripts/rebuild-repo.js +4 -1
  55. package/dist/scripts/rebuild-repo.js.map +1 -1
  56. package/dist/sequencer/events.d.ts +22 -16
  57. package/dist/sequencer/events.d.ts.map +1 -1
  58. package/dist/sequencer/events.js +31 -39
  59. package/dist/sequencer/events.js.map +1 -1
  60. package/dist/sequencer/sequencer.d.ts +2 -3
  61. package/dist/sequencer/sequencer.d.ts.map +1 -1
  62. package/dist/sequencer/sequencer.js +2 -2
  63. package/dist/sequencer/sequencer.js.map +1 -1
  64. package/package.json +6 -6
  65. package/src/actor-store/repo/transactor.ts +47 -21
  66. package/src/actor-store/repo/util.ts +22 -0
  67. package/src/api/com/atproto/repo/applyWrites.ts +1 -1
  68. package/src/api/com/atproto/repo/createRecord.ts +28 -31
  69. package/src/api/com/atproto/repo/deleteRecord.ts +1 -1
  70. package/src/api/com/atproto/repo/putRecord.ts +3 -3
  71. package/src/api/com/atproto/server/activateAccount.ts +4 -1
  72. package/src/api/com/atproto/server/createAccount.ts +1 -1
  73. package/src/index.ts +1 -1
  74. package/src/lexicon/index.ts +12 -0
  75. package/src/lexicon/lexicons.ts +114 -16
  76. package/src/lexicon/types/chat/bsky/convo/updateAllRead.ts +53 -0
  77. package/src/lexicon/types/com/atproto/sync/getRepoStatus.ts +8 -1
  78. package/src/lexicon/types/com/atproto/sync/listRepos.ts +8 -1
  79. package/src/lexicon/types/com/atproto/sync/subscribeRepos.ts +41 -6
  80. package/src/lexicon/types/tools/ozone/moderation/defs.ts +2 -2
  81. package/src/repo/types.ts +14 -1
  82. package/src/scripts/rebuild-repo.ts +4 -1
  83. package/src/sequencer/events.ts +35 -49
  84. package/src/sequencer/sequencer.ts +3 -5
  85. package/tests/crud.test.ts +1 -1
  86. package/tests/sequencer.test.ts +1 -5
  87. package/tests/sync/invertible-ops.test.ts +104 -0
  88. package/tsconfig.build.tsbuildinfo +1 -1
  89. package/tsconfig.tests.tsbuildinfo +1 -1
@@ -3517,7 +3517,14 @@ export const schemaDict = {
3517
3517
  type: 'string',
3518
3518
  description:
3519
3519
  'If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.',
3520
- knownValues: ['takendown', 'suspended', 'deactivated'],
3520
+ knownValues: [
3521
+ 'takendown',
3522
+ 'suspended',
3523
+ 'deleted',
3524
+ 'deactivated',
3525
+ 'desynchronized',
3526
+ 'throttled',
3527
+ ],
3521
3528
  },
3522
3529
  rev: {
3523
3530
  type: 'string',
@@ -3671,7 +3678,14 @@ export const schemaDict = {
3671
3678
  type: 'string',
3672
3679
  description:
3673
3680
  'If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted.',
3674
- knownValues: ['takendown', 'suspended', 'deactivated'],
3681
+ knownValues: [
3682
+ 'takendown',
3683
+ 'suspended',
3684
+ 'deleted',
3685
+ 'deactivated',
3686
+ 'desynchronized',
3687
+ 'throttled',
3688
+ ],
3675
3689
  },
3676
3690
  },
3677
3691
  },
@@ -3810,6 +3824,7 @@ export const schemaDict = {
3810
3824
  type: 'union',
3811
3825
  refs: [
3812
3826
  'lex:com.atproto.sync.subscribeRepos#commit',
3827
+ 'lex:com.atproto.sync.subscribeRepos#sync',
3813
3828
  'lex:com.atproto.sync.subscribeRepos#identity',
3814
3829
  'lex:com.atproto.sync.subscribeRepos#account',
3815
3830
  'lex:com.atproto.sync.subscribeRepos#handle',
@@ -3847,7 +3862,7 @@ export const schemaDict = {
3847
3862
  'blobs',
3848
3863
  'time',
3849
3864
  ],
3850
- nullable: ['prev', 'since'],
3865
+ nullable: ['since'],
3851
3866
  properties: {
3852
3867
  seq: {
3853
3868
  type: 'integer',
@@ -3860,22 +3875,18 @@ export const schemaDict = {
3860
3875
  tooBig: {
3861
3876
  type: 'boolean',
3862
3877
  description:
3863
- 'Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data.',
3878
+ 'DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data.',
3864
3879
  },
3865
3880
  repo: {
3866
3881
  type: 'string',
3867
3882
  format: 'did',
3868
- description: 'The repo this event comes from.',
3883
+ description:
3884
+ "The repo this event comes from. Note that all other message types name this field 'did'.",
3869
3885
  },
3870
3886
  commit: {
3871
3887
  type: 'cid-link',
3872
3888
  description: 'Repo commit object CID.',
3873
3889
  },
3874
- prev: {
3875
- type: 'cid-link',
3876
- description:
3877
- 'DEPRECATED -- unused. WARNING -- nullable and optional; stick with optional to ensure golang interoperability.',
3878
- },
3879
3890
  rev: {
3880
3891
  type: 'string',
3881
3892
  format: 'tid',
@@ -3891,8 +3902,8 @@ export const schemaDict = {
3891
3902
  blocks: {
3892
3903
  type: 'bytes',
3893
3904
  description:
3894
- 'CAR file containing relevant blocks, as a diff since the previous repo state.',
3895
- maxLength: 1000000,
3905
+ "CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list.",
3906
+ maxLength: 2000000,
3896
3907
  },
3897
3908
  ops: {
3898
3909
  type: 'array',
@@ -3909,9 +3920,49 @@ export const schemaDict = {
3909
3920
  items: {
3910
3921
  type: 'cid-link',
3911
3922
  description:
3912
- 'List of new blobs (by CID) referenced by records in this commit.',
3923
+ 'DEPRECATED -- will soon always be empty. List of new blobs (by CID) referenced by records in this commit.',
3913
3924
  },
3914
3925
  },
3926
+ prevData: {
3927
+ type: 'cid-link',
3928
+ description:
3929
+ "The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose.",
3930
+ },
3931
+ time: {
3932
+ type: 'string',
3933
+ format: 'datetime',
3934
+ description:
3935
+ 'Timestamp of when this message was originally broadcast.',
3936
+ },
3937
+ },
3938
+ },
3939
+ sync: {
3940
+ type: 'object',
3941
+ description:
3942
+ 'Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository.',
3943
+ required: ['seq', 'did', 'blocks', 'rev', 'time'],
3944
+ properties: {
3945
+ seq: {
3946
+ type: 'integer',
3947
+ description: 'The stream sequence number of this message.',
3948
+ },
3949
+ did: {
3950
+ type: 'string',
3951
+ format: 'did',
3952
+ description:
3953
+ 'The account this repo event corresponds to. Must match that in the commit object.',
3954
+ },
3955
+ blocks: {
3956
+ type: 'bytes',
3957
+ description:
3958
+ "CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'.",
3959
+ maxLength: 10000,
3960
+ },
3961
+ rev: {
3962
+ type: 'string',
3963
+ description:
3964
+ 'The rev of the commit. This value must match that in the commit object.',
3965
+ },
3915
3966
  time: {
3916
3967
  type: 'string',
3917
3968
  format: 'datetime',
@@ -3971,7 +4022,14 @@ export const schemaDict = {
3971
4022
  type: 'string',
3972
4023
  description:
3973
4024
  'If active=false, this optional field indicates a reason for why the account is not active.',
3974
- knownValues: ['takendown', 'suspended', 'deleted', 'deactivated'],
4025
+ knownValues: [
4026
+ 'takendown',
4027
+ 'suspended',
4028
+ 'deleted',
4029
+ 'deactivated',
4030
+ 'desynchronized',
4031
+ 'throttled',
4032
+ ],
3975
4033
  },
3976
4034
  },
3977
4035
  },
@@ -4068,6 +4126,11 @@ export const schemaDict = {
4068
4126
  description:
4069
4127
  'For creates and updates, the new record CID. For deletions, null.',
4070
4128
  },
4129
+ prev: {
4130
+ type: 'cid-link',
4131
+ description:
4132
+ 'For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined.',
4133
+ },
4071
4134
  },
4072
4135
  },
4073
4136
  },
@@ -10979,6 +11042,40 @@ export const schemaDict = {
10979
11042
  },
10980
11043
  },
10981
11044
  },
11045
+ ChatBskyConvoUpdateAllRead: {
11046
+ lexicon: 1,
11047
+ id: 'chat.bsky.convo.updateAllRead',
11048
+ defs: {
11049
+ main: {
11050
+ type: 'procedure',
11051
+ input: {
11052
+ encoding: 'application/json',
11053
+ schema: {
11054
+ type: 'object',
11055
+ properties: {
11056
+ status: {
11057
+ type: 'string',
11058
+ knownValues: ['request', 'accepted'],
11059
+ },
11060
+ },
11061
+ },
11062
+ },
11063
+ output: {
11064
+ encoding: 'application/json',
11065
+ schema: {
11066
+ type: 'object',
11067
+ required: ['updatedCount'],
11068
+ properties: {
11069
+ updatedCount: {
11070
+ description: 'The count of updated convos.',
11071
+ type: 'integer',
11072
+ },
11073
+ },
11074
+ },
11075
+ },
11076
+ },
11077
+ },
11078
+ },
10982
11079
  ChatBskyConvoUpdateRead: {
10983
11080
  lexicon: 1,
10984
11081
  id: 'chat.bsky.convo.updateRead',
@@ -11777,8 +11874,8 @@ export const schemaDict = {
11777
11874
  },
11778
11875
  modEventComment: {
11779
11876
  type: 'object',
11780
- description: 'Add a comment to a subject',
11781
- required: ['comment'],
11877
+ description:
11878
+ 'Add a comment to a subject. An empty comment will clear any previously set sticky comment.',
11782
11879
  properties: {
11783
11880
  comment: {
11784
11881
  type: 'string',
@@ -14445,6 +14542,7 @@ export const ids = {
14445
14542
  ChatBskyConvoSendMessage: 'chat.bsky.convo.sendMessage',
14446
14543
  ChatBskyConvoSendMessageBatch: 'chat.bsky.convo.sendMessageBatch',
14447
14544
  ChatBskyConvoUnmuteConvo: 'chat.bsky.convo.unmuteConvo',
14545
+ ChatBskyConvoUpdateAllRead: 'chat.bsky.convo.updateAllRead',
14448
14546
  ChatBskyConvoUpdateRead: 'chat.bsky.convo.updateRead',
14449
14547
  ChatBskyModerationGetActorMetadata: 'chat.bsky.moderation.getActorMetadata',
14450
14548
  ChatBskyModerationGetMessageContext: 'chat.bsky.moderation.getMessageContext',
@@ -0,0 +1,53 @@
1
+ /**
2
+ * GENERATED CODE - DO NOT MODIFY
3
+ */
4
+ import express from 'express'
5
+ import { ValidationResult, BlobRef } from '@atproto/lexicon'
6
+ import { CID } from 'multiformats/cid'
7
+ import { validate as _validate } from '../../../../lexicons'
8
+ import { $Typed, is$typed as _is$typed, OmitKey } from '../../../../util'
9
+ import { HandlerAuth, HandlerPipeThrough } from '@atproto/xrpc-server'
10
+
11
+ const is$typed = _is$typed,
12
+ validate = _validate
13
+ const id = 'chat.bsky.convo.updateAllRead'
14
+
15
+ export interface QueryParams {}
16
+
17
+ export interface InputSchema {
18
+ status?: 'request' | 'accepted' | (string & {})
19
+ }
20
+
21
+ export interface OutputSchema {
22
+ /** The count of updated convos. */
23
+ updatedCount: number
24
+ }
25
+
26
+ export interface HandlerInput {
27
+ encoding: 'application/json'
28
+ body: InputSchema
29
+ }
30
+
31
+ export interface HandlerSuccess {
32
+ encoding: 'application/json'
33
+ body: OutputSchema
34
+ headers?: { [key: string]: string }
35
+ }
36
+
37
+ export interface HandlerError {
38
+ status: number
39
+ message?: string
40
+ }
41
+
42
+ export type HandlerOutput = HandlerError | HandlerSuccess | HandlerPipeThrough
43
+ export type HandlerReqCtx<HA extends HandlerAuth = never> = {
44
+ auth: HA
45
+ params: QueryParams
46
+ input: HandlerInput
47
+ req: express.Request
48
+ res: express.Response
49
+ resetRouteRateLimits: () => Promise<void>
50
+ }
51
+ export type Handler<HA extends HandlerAuth = never> = (
52
+ ctx: HandlerReqCtx<HA>,
53
+ ) => Promise<HandlerOutput> | HandlerOutput
@@ -23,7 +23,14 @@ export interface OutputSchema {
23
23
  did: string
24
24
  active: boolean
25
25
  /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
26
- status?: 'takendown' | 'suspended' | 'deactivated' | (string & {})
26
+ status?:
27
+ | 'takendown'
28
+ | 'suspended'
29
+ | 'deleted'
30
+ | 'deactivated'
31
+ | 'desynchronized'
32
+ | 'throttled'
33
+ | (string & {})
27
34
  /** Optional field, the current rev of the repo, if active=true */
28
35
  rev?: string
29
36
  }
@@ -58,7 +58,14 @@ export interface Repo {
58
58
  rev: string
59
59
  active?: boolean
60
60
  /** If active=false, this optional field indicates a possible reason for why the account is not active. If active=false and no status is supplied, then the host makes no claim for why the repository is no longer being hosted. */
61
- status?: 'takendown' | 'suspended' | 'deactivated' | (string & {})
61
+ status?:
62
+ | 'takendown'
63
+ | 'suspended'
64
+ | 'deleted'
65
+ | 'deactivated'
66
+ | 'desynchronized'
67
+ | 'throttled'
68
+ | (string & {})
62
69
  }
63
70
 
64
71
  const hashRepo = 'repo'
@@ -19,6 +19,7 @@ export interface QueryParams {
19
19
 
20
20
  export type OutputSchema =
21
21
  | $Typed<Commit>
22
+ | $Typed<Sync>
22
23
  | $Typed<Identity>
23
24
  | $Typed<Account>
24
25
  | $Typed<Handle>
@@ -45,22 +46,22 @@ export interface Commit {
45
46
  seq: number
46
47
  /** DEPRECATED -- unused */
47
48
  rebase: boolean
48
- /** Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data. */
49
+ /** DEPRECATED -- replaced by #sync event and data limits. Indicates that this commit contained too many ops, or data size was too large. Consumers will need to make a separate request to get missing data. */
49
50
  tooBig: boolean
50
- /** The repo this event comes from. */
51
+ /** The repo this event comes from. Note that all other message types name this field 'did'. */
51
52
  repo: string
52
53
  /** Repo commit object CID. */
53
54
  commit: CID
54
- /** DEPRECATED -- unused. WARNING -- nullable and optional; stick with optional to ensure golang interoperability. */
55
- prev?: CID | null
56
55
  /** The rev of the emitted commit. Note that this information is also in the commit object included in blocks, unless this is a tooBig event. */
57
56
  rev: string
58
57
  /** The rev of the last emitted commit from this repo (if any). */
59
58
  since: string | null
60
- /** CAR file containing relevant blocks, as a diff since the previous repo state. */
59
+ /** CAR file containing relevant blocks, as a diff since the previous repo state. The commit must be included as a block, and the commit block CID must be the first entry in the CAR header 'roots' list. */
61
60
  blocks: Uint8Array
62
61
  ops: RepoOp[]
63
62
  blobs: CID[]
63
+ /** The root CID of the MST tree for the previous commit from this repo (indicated by the 'since' revision field in this message). Corresponds to the 'data' field in the repo commit object. NOTE: this field is effectively required for the 'inductive' version of firehose. */
64
+ prevData?: CID
64
65
  /** Timestamp of when this message was originally broadcast. */
65
66
  time: string
66
67
  }
@@ -75,6 +76,31 @@ export function validateCommit<V>(v: V) {
75
76
  return validate<Commit & V>(v, id, hashCommit)
76
77
  }
77
78
 
79
+ /** Updates the repo to a new state, without necessarily including that state on the firehose. Used to recover from broken commit streams, data loss incidents, or in situations where upstream host does not know recent state of the repository. */
80
+ export interface Sync {
81
+ $type?: 'com.atproto.sync.subscribeRepos#sync'
82
+ /** The stream sequence number of this message. */
83
+ seq: number
84
+ /** The account this repo event corresponds to. Must match that in the commit object. */
85
+ did: string
86
+ /** CAR file containing the commit, as a block. The CAR header must include the commit block CID as the first 'root'. */
87
+ blocks: Uint8Array
88
+ /** The rev of the commit. This value must match that in the commit object. */
89
+ rev: string
90
+ /** Timestamp of when this message was originally broadcast. */
91
+ time: string
92
+ }
93
+
94
+ const hashSync = 'sync'
95
+
96
+ export function isSync<V>(v: V) {
97
+ return is$typed(v, id, hashSync)
98
+ }
99
+
100
+ export function validateSync<V>(v: V) {
101
+ return validate<Sync & V>(v, id, hashSync)
102
+ }
103
+
78
104
  /** Represents a change to an account's identity. Could be an updated handle, signing key, or pds hosting endpoint. Serves as a prod to all downstream services to refresh their identity cache. */
79
105
  export interface Identity {
80
106
  $type?: 'com.atproto.sync.subscribeRepos#identity'
@@ -104,7 +130,14 @@ export interface Account {
104
130
  /** Indicates that the account has a repository which can be fetched from the host that emitted this event. */
105
131
  active: boolean
106
132
  /** If active=false, this optional field indicates a reason for why the account is not active. */
107
- status?: 'takendown' | 'suspended' | 'deleted' | 'deactivated' | (string & {})
133
+ status?:
134
+ | 'takendown'
135
+ | 'suspended'
136
+ | 'deleted'
137
+ | 'deactivated'
138
+ | 'desynchronized'
139
+ | 'throttled'
140
+ | (string & {})
108
141
  }
109
142
 
110
143
  const hashAccount = 'account'
@@ -196,6 +229,8 @@ export interface RepoOp {
196
229
  path: string
197
230
  /** For creates and updates, the new record CID. For deletions, null. */
198
231
  cid: CID | null
232
+ /** For updates and deletes, the previous record CID (required for inductive firehose). For creations, field should not be defined. */
233
+ prev?: CID
199
234
  }
200
235
 
201
236
  const hashRepoOp = 'repoOp'
@@ -284,10 +284,10 @@ export function validateModEventResolveAppeal<V>(v: V) {
284
284
  return validate<ModEventResolveAppeal & V>(v, id, hashModEventResolveAppeal)
285
285
  }
286
286
 
287
- /** Add a comment to a subject */
287
+ /** Add a comment to a subject. An empty comment will clear any previously set sticky comment. */
288
288
  export interface ModEventComment {
289
289
  $type?: 'tools.ozone.moderation.defs#modEventComment'
290
- comment: string
290
+ comment?: string
291
291
  /** Make the comment persistent on the subject */
292
292
  sticky?: boolean
293
293
  }
package/src/repo/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { CID } from 'multiformats/cid'
2
2
  import { RepoRecord } from '@atproto/lexicon'
3
- import { WriteOpAction } from '@atproto/repo'
3
+ import { CidSet, CommitData, WriteOpAction } from '@atproto/repo'
4
4
  import { AtUri } from '@atproto/syntax'
5
5
 
6
6
  export type ValidationStatus = 'valid' | 'unknown' | undefined
@@ -42,6 +42,19 @@ export type PreparedDelete = {
42
42
  swapCid?: CID | null
43
43
  }
44
44
 
45
+ export type CommitOp = {
46
+ action: 'create' | 'update' | 'delete'
47
+ path: string
48
+ cid: CID | null
49
+ prev?: CID
50
+ }
51
+
52
+ export type CommitDataWithOps = CommitData & {
53
+ ops: CommitOp[]
54
+ blobs: CidSet
55
+ prevData: CID | null
56
+ }
57
+
45
58
  export type PreparedWrite = PreparedCreate | PreparedUpdate | PreparedDelete
46
59
 
47
60
  export class InvalidRecordError extends Error {}
@@ -71,10 +71,13 @@ export const rebuildRepo = async (ctx: AppContext, args: string[]) => {
71
71
  newBlocks,
72
72
  relevantBlocks: newBlocks,
73
73
  removedCids: toDelete,
74
+ ops: [],
75
+ blobs: new CidSet(),
76
+ prevData: null,
74
77
  }
75
78
  })
76
79
  await ctx.accountManager.updateRepoRoot(did, commit.cid, rev)
77
- await ctx.sequencer.sequenceCommit(did, commit, [])
80
+ await ctx.sequencer.sequenceCommit(did, commit)
78
81
  }
79
82
 
80
83
  const promptContinue = async (): Promise<boolean> => {
@@ -1,74 +1,59 @@
1
- import { CID } from 'multiformats/cid'
2
1
  import { z } from 'zod'
3
- import { cborEncode, schema } from '@atproto/common'
4
- import {
5
- BlockMap,
6
- CidSet,
7
- CommitData,
8
- WriteOpAction,
9
- blocksToCarFile,
10
- } from '@atproto/repo'
2
+ import { cborEncode, noUndefinedVals, schema } from '@atproto/common'
3
+ import { BlockMap, blocksToCarFile } from '@atproto/repo'
11
4
  import { AccountStatus } from '../account-manager'
12
- import { PreparedWrite } from '../repo'
5
+ import { CommitDataWithOps } from '../repo'
13
6
  import { RepoSeqInsert } from './db'
14
7
 
15
8
  export const formatSeqCommit = async (
16
9
  did: string,
17
- commitData: CommitData,
18
- writes: PreparedWrite[],
10
+ commitData: CommitDataWithOps,
19
11
  ): Promise<RepoSeqInsert> => {
20
- let tooBig: boolean
21
- const ops: CommitEvtOp[] = []
22
- const blobs = new CidSet()
23
- let carSlice: Uint8Array
24
-
25
12
  const blocksToSend = new BlockMap()
26
13
  blocksToSend.addMap(commitData.newBlocks)
27
14
  blocksToSend.addMap(commitData.relevantBlocks)
28
15
 
29
- // max 200 ops or 1MB of data
30
- if (writes.length > 200 || blocksToSend.byteSize > 1000000) {
31
- tooBig = true
16
+ let evt: CommitEvt
17
+
18
+ // If event is too big (max 200 ops or 1MB of data)
19
+ if (commitData.ops.length > 200 || blocksToSend.byteSize > 1000000) {
32
20
  const justRoot = new BlockMap()
33
21
  const rootBlock = blocksToSend.get(commitData.cid)
34
22
  if (rootBlock) {
35
23
  justRoot.set(commitData.cid, rootBlock)
36
24
  }
37
- carSlice = await blocksToCarFile(commitData.cid, justRoot)
25
+
26
+ evt = {
27
+ rebase: false,
28
+ tooBig: true,
29
+ repo: did,
30
+ commit: commitData.cid,
31
+ rev: commitData.rev,
32
+ since: commitData.since,
33
+ blocks: await blocksToCarFile(commitData.cid, justRoot),
34
+ ops: [],
35
+ blobs: [],
36
+ prevData: commitData.prevData ?? undefined,
37
+ }
38
38
  } else {
39
- tooBig = false
40
- for (const w of writes) {
41
- const path = w.uri.collection + '/' + w.uri.rkey
42
- let cid: CID | null
43
- if (w.action === WriteOpAction.Delete) {
44
- cid = null
45
- } else {
46
- cid = w.cid
47
- w.blobs.forEach((blob) => {
48
- blobs.add(blob.cid)
49
- })
50
- }
51
- ops.push({ action: w.action, path, cid })
39
+ evt = {
40
+ rebase: false,
41
+ tooBig: false,
42
+ repo: did,
43
+ commit: commitData.cid,
44
+ rev: commitData.rev,
45
+ since: commitData.since,
46
+ blocks: await blocksToCarFile(commitData.cid, blocksToSend),
47
+ ops: commitData.ops,
48
+ blobs: commitData.blobs.toList(),
49
+ prevData: commitData.prevData ?? undefined,
52
50
  }
53
- carSlice = await blocksToCarFile(commitData.cid, blocksToSend)
54
51
  }
55
52
 
56
- const evt: CommitEvt = {
57
- rebase: false,
58
- tooBig,
59
- repo: did,
60
- commit: commitData.cid,
61
- prev: commitData.prev,
62
- rev: commitData.rev,
63
- since: commitData.since,
64
- ops,
65
- blocks: carSlice,
66
- blobs: blobs.toList(),
67
- }
68
53
  return {
69
54
  did,
70
55
  eventType: 'append' as const,
71
- event: cborEncode(evt),
56
+ event: cborEncode(noUndefinedVals(evt)),
72
57
  sequencedAt: new Date().toISOString(),
73
58
  }
74
59
  }
@@ -149,6 +134,7 @@ export const commitEvtOp = z.object({
149
134
  ]),
150
135
  path: z.string(),
151
136
  cid: schema.cid.nullable(),
137
+ prev: schema.cid.optional(),
152
138
  })
153
139
  export type CommitEvtOp = z.infer<typeof commitEvtOp>
154
140
 
@@ -157,12 +143,12 @@ export const commitEvt = z.object({
157
143
  tooBig: z.boolean(),
158
144
  repo: z.string(),
159
145
  commit: schema.cid,
160
- prev: schema.cid.nullable(),
161
146
  rev: z.string(),
162
147
  since: z.string().nullable(),
163
148
  blocks: schema.bytes,
164
149
  ops: z.array(commitEvtOp),
165
150
  blobs: z.array(schema.cid),
151
+ prevData: schema.cid.optional(),
166
152
  })
167
153
  export type CommitEvt = z.infer<typeof commitEvt>
168
154
 
@@ -1,11 +1,10 @@
1
1
  import EventEmitter from 'node:events'
2
2
  import TypedEmitter from 'typed-emitter'
3
3
  import { SECOND, cborDecode, wait } from '@atproto/common'
4
- import { CommitData } from '@atproto/repo'
5
4
  import { AccountStatus } from '../account-manager/helpers/account'
6
5
  import { Crawlers } from '../crawlers'
7
6
  import { seqLogger as log } from '../logger'
8
- import { PreparedWrite } from '../repo'
7
+ import { CommitDataWithOps } from '../repo'
9
8
  import {
10
9
  RepoSeqEntry,
11
10
  RepoSeqInsert,
@@ -217,10 +216,9 @@ export class Sequencer extends (EventEmitter as new () => SequencerEmitter) {
217
216
 
218
217
  async sequenceCommit(
219
218
  did: string,
220
- commitData: CommitData,
221
- writes: PreparedWrite[],
219
+ commitData: CommitDataWithOps,
222
220
  ): Promise<number> {
223
- const evt = await formatSeqCommit(did, commitData, writes)
221
+ const evt = await formatSeqCommit(did, commitData)
224
222
  return await this.sequenceEvt(evt)
225
223
  }
226
224
 
@@ -1191,7 +1191,7 @@ describe('crud operations', () => {
1191
1191
  record: {
1192
1192
  text: 'x',
1193
1193
  createdAt: new Date().toISOString(),
1194
- deepObject: createDeepObject(3000),
1194
+ deepObject: createDeepObject(4000),
1195
1195
  },
1196
1196
  }),
1197
1197
  {
@@ -241,11 +241,7 @@ describe('sequencer', () => {
241
241
  (store) => store.repo.formatCommit(writes),
242
242
  )
243
243
 
244
- const repoSeqInsert = await formatSeqCommit(
245
- sc.dids.alice,
246
- writeCommit,
247
- writes,
248
- )
244
+ const repoSeqInsert = await formatSeqCommit(sc.dids.alice, writeCommit)
249
245
 
250
246
  const evt = cborDecode<sequencer.CommitEvt>(repoSeqInsert.event)
251
247
  expect(evt.tooBig).toBe(true)