@atproto/repo 0.3.6 → 0.3.8

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/src/types.ts CHANGED
@@ -2,6 +2,7 @@ import { z } from 'zod'
2
2
  import { def as commonDef } from '@atproto/common-web'
3
3
  import { schema as common } from '@atproto/common'
4
4
  import { CID } from 'multiformats'
5
+ import * as car from '@ipld/car/api'
5
6
  import BlockMap from './block-map'
6
7
  import { RepoRecord } from '@atproto/lexicon'
7
8
  import CidSet from './cid-set'
@@ -15,7 +16,7 @@ const unsignedCommit = z.object({
15
16
  data: common.cid,
16
17
  rev: z.string(),
17
18
  // `prev` added for backwards compatibility with v2, no requirement of keeping around history
18
- prev: common.cid.nullable().optional(),
19
+ prev: common.cid.nullable(),
19
20
  })
20
21
  export type UnsignedCommit = z.infer<typeof unsignedCommit> & { sig?: never }
21
22
 
@@ -24,7 +25,7 @@ const commit = z.object({
24
25
  version: z.literal(3),
25
26
  data: common.cid,
26
27
  rev: z.string(),
27
- prev: common.cid.nullable().optional(),
28
+ prev: common.cid.nullable(),
28
29
  sig: common.bytes,
29
30
  })
30
31
  export type Commit = z.infer<typeof commit>
@@ -95,16 +96,25 @@ export type RecordDeleteOp = {
95
96
 
96
97
  export type RecordWriteOp = RecordCreateOp | RecordUpdateOp | RecordDeleteOp
97
98
 
98
- export type RecordCreateDescript = RecordCreateOp & {
99
+ export type RecordCreateDescript = {
100
+ action: WriteOpAction.Create
101
+ collection: string
102
+ rkey: string
99
103
  cid: CID
100
104
  }
101
105
 
102
- export type RecordUpdateDescript = RecordUpdateOp & {
106
+ export type RecordUpdateDescript = {
107
+ action: WriteOpAction.Update
108
+ collection: string
109
+ rkey: string
103
110
  prev: CID
104
111
  cid: CID
105
112
  }
106
113
 
107
- export type RecordDeleteDescript = RecordDeleteOp & {
114
+ export type RecordDeleteDescript = {
115
+ action: WriteOpAction.Delete
116
+ collection: string
117
+ rkey: string
108
118
  cid: CID
109
119
  }
110
120
 
@@ -163,3 +173,5 @@ export type VerifiedRepo = {
163
173
  creates: RecordCreateDescript[]
164
174
  commit: CommitData
165
175
  }
176
+
177
+ export type CarBlock = car.Block
package/src/util.ts CHANGED
@@ -1,8 +1,8 @@
1
+ import { setImmediate } from 'node:timers/promises'
1
2
  import { CID } from 'multiformats/cid'
2
3
  import * as cbor from '@ipld/dag-cbor'
3
- import { CarReader } from '@ipld/car/reader'
4
+ import { CarBlockIterator } from '@ipld/car'
4
5
  import { BlockWriter, CarWriter } from '@ipld/car/writer'
5
- import { Block as CarBlock } from '@ipld/car/api'
6
6
  import {
7
7
  streamToBuffer,
8
8
  verifyCidForBytes,
@@ -18,6 +18,7 @@ import { ipldToLex, lexToIpld, LexValue, RepoRecord } from '@atproto/lexicon'
18
18
  import * as crypto from '@atproto/crypto'
19
19
  import DataDiff from './data-diff'
20
20
  import {
21
+ CarBlock,
21
22
  Commit,
22
23
  LegacyV2Commit,
23
24
  RecordCreateDescript,
@@ -29,7 +30,6 @@ import {
29
30
  WriteOpAction,
30
31
  } from './types'
31
32
  import BlockMap from './block-map'
32
- import * as parse from './parse'
33
33
  import { Keypair } from '@atproto/crypto'
34
34
  import { Readable } from 'stream'
35
35
 
@@ -88,14 +88,15 @@ export const blocksToCarFile = (
88
88
  return streamToBuffer(carStream)
89
89
  }
90
90
 
91
- export const readCar = async (
92
- bytes: Uint8Array,
91
+ export const carToBlocks = async (
92
+ car: CarBlockIterator,
93
93
  ): Promise<{ roots: CID[]; blocks: BlockMap }> => {
94
- const car = await CarReader.fromBytes(bytes)
95
94
  const roots = await car.getRoots()
96
95
  const blocks = new BlockMap()
97
- for await (const block of verifyIncomingCarBlocks(car.blocks())) {
96
+ for await (const block of verifyIncomingCarBlocks(car)) {
98
97
  blocks.set(block.cid, block.bytes)
98
+ // break up otherwise "synchronous" work in car parsing
99
+ await setImmediate()
99
100
  }
100
101
  return {
101
102
  roots,
@@ -103,6 +104,18 @@ export const readCar = async (
103
104
  }
104
105
  }
105
106
 
107
+ export const readCar = async (
108
+ bytes: Uint8Array,
109
+ ): Promise<{ roots: CID[]; blocks: BlockMap }> => {
110
+ const car = await CarBlockIterator.fromBytes(bytes)
111
+ return carToBlocks(car)
112
+ }
113
+
114
+ export const readCarStream = async (stream: AsyncIterable<Uint8Array>) => {
115
+ const car = await CarBlockIterator.fromIterable(stream)
116
+ return carToBlocks(car)
117
+ }
118
+
106
119
  export const readCarWithRoot = async (
107
120
  bytes: Uint8Array,
108
121
  ): Promise<{ root: CID; blocks: BlockMap }> => {
@@ -119,30 +132,25 @@ export const readCarWithRoot = async (
119
132
 
120
133
  export const diffToWriteDescripts = (
121
134
  diff: DataDiff,
122
- blocks: BlockMap,
123
135
  ): Promise<RecordWriteDescript[]> => {
124
136
  return Promise.all([
125
137
  ...diff.addList().map(async (add) => {
126
138
  const { collection, rkey } = parseDataKey(add.key)
127
- const value = await parse.getAndParseRecord(blocks, add.cid)
128
139
  return {
129
140
  action: WriteOpAction.Create,
130
141
  collection,
131
142
  rkey,
132
143
  cid: add.cid,
133
- record: value.record,
134
144
  } as RecordCreateDescript
135
145
  }),
136
146
  ...diff.updateList().map(async (upd) => {
137
147
  const { collection, rkey } = parseDataKey(upd.key)
138
- const value = await parse.getAndParseRecord(blocks, upd.cid)
139
148
  return {
140
149
  action: WriteOpAction.Update,
141
150
  collection,
142
151
  rkey,
143
152
  cid: upd.cid,
144
153
  prev: upd.prev,
145
- record: value.record,
146
154
  } as RecordUpdateDescript
147
155
  }),
148
156
  ...diff.deleteList().map((del) => {
@@ -4,6 +4,7 @@ import {
4
4
  Repo,
5
5
  RepoContents,
6
6
  RepoVerificationError,
7
+ getAndParseRecord,
7
8
  readCarWithRoot,
8
9
  } from '../src'
9
10
  import { MemoryBlockstore } from '../src/storage'
@@ -47,7 +48,8 @@ describe('Repo Sync', () => {
47
48
  const contentsFromOps: RepoContents = {}
48
49
  for (const write of verified.creates) {
49
50
  contentsFromOps[write.collection] ??= {}
50
- contentsFromOps[write.collection][write.rkey] = write.record
51
+ const parsed = await getAndParseRecord(car.blocks, write.cid)
52
+ contentsFromOps[write.collection][write.rkey] = parsed.record
51
53
  }
52
54
  expect(contentsFromOps).toEqual(repoData)
53
55
  })