@autonomys/auto-dag-data 0.8.2

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 (153) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +167 -0
  3. package/dist/cid/index.d.ts +9 -0
  4. package/dist/cid/index.d.ts.map +1 -0
  5. package/dist/cid/index.js +20 -0
  6. package/dist/compression/index.d.ts +7 -0
  7. package/dist/compression/index.d.ts.map +1 -0
  8. package/dist/compression/index.js +106 -0
  9. package/dist/compression/types.d.ts +9 -0
  10. package/dist/compression/types.d.ts.map +1 -0
  11. package/dist/compression/types.js +1 -0
  12. package/dist/encryption/index.d.ts +8 -0
  13. package/dist/encryption/index.d.ts.map +1 -0
  14. package/dist/encryption/index.js +121 -0
  15. package/dist/encryption/types.d.ts +5 -0
  16. package/dist/encryption/types.d.ts.map +1 -0
  17. package/dist/encryption/types.js +1 -0
  18. package/dist/index.d.ts +6 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +5 -0
  21. package/dist/ipld/blockstore/base.d.ts +9 -0
  22. package/dist/ipld/blockstore/base.d.ts.map +1 -0
  23. package/dist/ipld/blockstore/base.js +1 -0
  24. package/dist/ipld/blockstore/index.d.ts +3 -0
  25. package/dist/ipld/blockstore/index.d.ts.map +1 -0
  26. package/dist/ipld/blockstore/index.js +2 -0
  27. package/dist/ipld/blockstore/memory.d.ts +13 -0
  28. package/dist/ipld/blockstore/memory.d.ts.map +1 -0
  29. package/dist/ipld/blockstore/memory.js +57 -0
  30. package/dist/ipld/builders.d.ts +12 -0
  31. package/dist/ipld/builders.d.ts.map +1 -0
  32. package/dist/ipld/builders.js +13 -0
  33. package/dist/ipld/chunker.d.ts +30 -0
  34. package/dist/ipld/chunker.d.ts.map +1 -0
  35. package/dist/ipld/chunker.js +219 -0
  36. package/dist/ipld/index.d.ts +5 -0
  37. package/dist/ipld/index.d.ts.map +1 -0
  38. package/dist/ipld/index.js +4 -0
  39. package/dist/ipld/nodes.d.ts +15 -0
  40. package/dist/ipld/nodes.d.ts.map +1 -0
  41. package/dist/ipld/nodes.js +92 -0
  42. package/dist/ipld/utils.d.ts +8 -0
  43. package/dist/ipld/utils.d.ts.map +1 -0
  44. package/dist/ipld/utils.js +50 -0
  45. package/dist/metadata/index.d.ts +3 -0
  46. package/dist/metadata/index.d.ts.map +1 -0
  47. package/dist/metadata/index.js +2 -0
  48. package/dist/metadata/offchain/base.d.ts +4 -0
  49. package/dist/metadata/offchain/base.d.ts.map +1 -0
  50. package/dist/metadata/offchain/base.js +1 -0
  51. package/dist/metadata/offchain/file.d.ts +18 -0
  52. package/dist/metadata/offchain/file.d.ts.map +1 -0
  53. package/dist/metadata/offchain/file.js +16 -0
  54. package/dist/metadata/offchain/folder.d.ts +22 -0
  55. package/dist/metadata/offchain/folder.d.ts.map +1 -0
  56. package/dist/metadata/offchain/folder.js +27 -0
  57. package/dist/metadata/offchain/index.d.ts +4 -0
  58. package/dist/metadata/offchain/index.d.ts.map +1 -0
  59. package/dist/metadata/offchain/index.js +3 -0
  60. package/dist/metadata/onchain/index.d.ts +3 -0
  61. package/dist/metadata/onchain/index.d.ts.map +1 -0
  62. package/dist/metadata/onchain/index.js +2 -0
  63. package/dist/metadata/onchain/protobuf/OnchainMetadata.d.ts +69 -0
  64. package/dist/metadata/onchain/protobuf/OnchainMetadata.d.ts.map +1 -0
  65. package/dist/metadata/onchain/protobuf/OnchainMetadata.js +322 -0
  66. package/dist/metadata/onchain/utils.d.ts +4 -0
  67. package/dist/metadata/onchain/utils.d.ts.map +1 -0
  68. package/dist/metadata/onchain/utils.js +12 -0
  69. package/dist/src/cid/index.d.ts +9 -0
  70. package/dist/src/cid/index.d.ts.map +1 -0
  71. package/dist/src/cid/index.js +20 -0
  72. package/dist/src/index.d.ts +4 -0
  73. package/dist/src/index.d.ts.map +1 -0
  74. package/dist/src/index.js +3 -0
  75. package/dist/src/ipld/builders.d.ts +11 -0
  76. package/dist/src/ipld/builders.d.ts.map +1 -0
  77. package/dist/src/ipld/builders.js +13 -0
  78. package/dist/src/ipld/chunker.d.ts +22 -0
  79. package/dist/src/ipld/chunker.d.ts.map +1 -0
  80. package/dist/src/ipld/chunker.js +144 -0
  81. package/dist/src/ipld/index.d.ts +4 -0
  82. package/dist/src/ipld/index.d.ts.map +1 -0
  83. package/dist/src/ipld/index.js +3 -0
  84. package/dist/src/ipld/nodes.d.ts +15 -0
  85. package/dist/src/ipld/nodes.d.ts.map +1 -0
  86. package/dist/src/ipld/nodes.js +89 -0
  87. package/dist/src/ipld/utils.d.ts +5 -0
  88. package/dist/src/ipld/utils.d.ts.map +1 -0
  89. package/dist/src/ipld/utils.js +51 -0
  90. package/dist/src/metadata/index.d.ts +3 -0
  91. package/dist/src/metadata/index.d.ts.map +1 -0
  92. package/dist/src/metadata/index.js +2 -0
  93. package/dist/src/metadata/offchain/base.d.ts +4 -0
  94. package/dist/src/metadata/offchain/base.d.ts.map +1 -0
  95. package/dist/src/metadata/offchain/base.js +1 -0
  96. package/dist/src/metadata/offchain/file.d.ts +16 -0
  97. package/dist/src/metadata/offchain/file.d.ts.map +1 -0
  98. package/dist/src/metadata/offchain/file.js +19 -0
  99. package/dist/src/metadata/offchain/folder.d.ts +17 -0
  100. package/dist/src/metadata/offchain/folder.d.ts.map +1 -0
  101. package/dist/src/metadata/offchain/folder.js +10 -0
  102. package/dist/src/metadata/offchain/index.d.ts +4 -0
  103. package/dist/src/metadata/offchain/index.d.ts.map +1 -0
  104. package/dist/src/metadata/offchain/index.js +3 -0
  105. package/dist/src/metadata/onchain/index.d.ts +3 -0
  106. package/dist/src/metadata/onchain/index.d.ts.map +1 -0
  107. package/dist/src/metadata/onchain/index.js +2 -0
  108. package/dist/src/metadata/onchain/protobuf/OnchainMetadata.d.ts +28 -0
  109. package/dist/src/metadata/onchain/protobuf/OnchainMetadata.d.ts.map +1 -0
  110. package/dist/src/metadata/onchain/protobuf/OnchainMetadata.js +112 -0
  111. package/dist/src/metadata/onchain/utils.d.ts +4 -0
  112. package/dist/src/metadata/onchain/utils.d.ts.map +1 -0
  113. package/dist/src/metadata/onchain/utils.js +12 -0
  114. package/dist/utils/async.d.ts +3 -0
  115. package/dist/utils/async.d.ts.map +1 -0
  116. package/dist/utils/async.js +48 -0
  117. package/dist/utils/index.d.ts +2 -0
  118. package/dist/utils/index.d.ts.map +1 -0
  119. package/dist/utils/index.js +1 -0
  120. package/dist/utils/types.d.ts +2 -0
  121. package/dist/utils/types.d.ts.map +1 -0
  122. package/dist/utils/types.js +1 -0
  123. package/jest.config.ts +17 -0
  124. package/package.json +46 -0
  125. package/src/cid/index.ts +26 -0
  126. package/src/compression/index.ts +84 -0
  127. package/src/compression/types.ts +11 -0
  128. package/src/encryption/index.ts +99 -0
  129. package/src/encryption/types.ts +4 -0
  130. package/src/index.ts +5 -0
  131. package/src/ipld/builders.ts +40 -0
  132. package/src/ipld/chunker.ts +245 -0
  133. package/src/ipld/index.ts +4 -0
  134. package/src/ipld/nodes.ts +208 -0
  135. package/src/ipld/utils.ts +21 -0
  136. package/src/metadata/index.ts +2 -0
  137. package/src/metadata/offchain/base.ts +4 -0
  138. package/src/metadata/offchain/file.ts +41 -0
  139. package/src/metadata/offchain/folder.ts +54 -0
  140. package/src/metadata/offchain/index.ts +3 -0
  141. package/src/metadata/onchain/index.ts +2 -0
  142. package/src/metadata/onchain/protobuf/OnchainMetadata.proto +46 -0
  143. package/src/metadata/onchain/protobuf/OnchainMetadata.ts +397 -0
  144. package/src/metadata/onchain/utils.ts +15 -0
  145. package/src/utils/async.ts +20 -0
  146. package/src/utils/index.ts +1 -0
  147. package/src/utils/types.ts +1 -0
  148. package/tests/chunker.spec.ts +294 -0
  149. package/tests/cid.spec.ts +20 -0
  150. package/tests/compression.spec.ts +58 -0
  151. package/tests/encryption.spec.ts +67 -0
  152. package/tests/nodes.spec.ts +74 -0
  153. package/tsconfig.json +14 -0
@@ -0,0 +1,294 @@
1
+ import { BaseBlockstore, MemoryBlockstore } from 'blockstore-core'
2
+ import { cidOfNode, cidToString } from '../src'
3
+ import {
4
+ processFileToIPLDFormat,
5
+ processFolderToIPLDFormat,
6
+ processMetadataToIPLDFormat,
7
+ } from '../src/ipld/chunker'
8
+ import { createNode, decodeNode, PBNode } from '../src/ipld/utils'
9
+ import { IPLDNodeData, MetadataType, OffchainMetadata } from '../src/metadata'
10
+
11
+ describe('chunker', () => {
12
+ describe('file creation', () => {
13
+ it('create a file dag from a small buffer', async () => {
14
+ const text = 'hello world'
15
+ const size = text.length
16
+ const name = 'test.txt'
17
+ const blockstore = new MemoryBlockstore()
18
+
19
+ await processFileToIPLDFormat(blockstore, bufferToIterable(Buffer.from(text)), size, name)
20
+ const nodes = await nodesFromBlockstore(blockstore)
21
+ expect(nodes.length).toBe(1)
22
+
23
+ const node = nodes[0]
24
+ expect(node).toBeDefined()
25
+ expect(node?.Data).toBeDefined()
26
+ const decoded = IPLDNodeData.decode(node?.Data ?? new Uint8Array())
27
+ expect(decoded.data).toBeDefined()
28
+
29
+ /// Check the metadata
30
+ expect(decoded.name).toBe(name)
31
+ expect(decoded.type).toBe(MetadataType.File)
32
+ expect(Buffer.from(decoded.data ?? '').toString()).toBe(text)
33
+ expect(decoded.linkDepth).toBe(0)
34
+ expect(decoded.size).toBe(text.length)
35
+
36
+ /// Check no links
37
+ expect(node?.Links.length).toBe(0)
38
+ })
39
+
40
+ it('create a file dag from a large buffer', async () => {
41
+ const maxChunkSize = 1000
42
+ const chunkNum = 10
43
+ const chunk = 'h'.repeat(maxChunkSize)
44
+ const text = chunk.repeat(chunkNum)
45
+ const size = text.length
46
+
47
+ const name = 'test.txt'
48
+ /// 1 chunk + root
49
+ const EXPECTED_NODE_COUNT = 2
50
+
51
+ const blockstore = new MemoryBlockstore()
52
+ const headCID = await processFileToIPLDFormat(
53
+ blockstore,
54
+ bufferToIterable(Buffer.from(text)),
55
+ size,
56
+ name,
57
+ {
58
+ maxChunkSize,
59
+ maxLinkPerNode: maxChunkSize / 64,
60
+ },
61
+ )
62
+
63
+ const nodes = await nodesFromBlockstore(blockstore)
64
+ expect(nodes.length).toBe(EXPECTED_NODE_COUNT)
65
+
66
+ const head = decodeNode(await blockstore.get(headCID))
67
+ expect(head?.Data).toBeDefined()
68
+ expect(head).toBeDefined()
69
+ expect(head?.Links.length).toBe(chunkNum)
70
+
71
+ const decoded = IPLDNodeData.decode(head?.Data ?? new Uint8Array())
72
+ expect(decoded.name).toBe(name)
73
+ expect(decoded.type).toBe(MetadataType.File)
74
+ expect(decoded.linkDepth).toBe(1)
75
+ expect(decoded.size).toBe(text.length)
76
+
77
+ nodes.forEach((node) => {
78
+ if (cidToString(cidOfNode(node)) !== cidToString(headCID)) {
79
+ expect(node?.Links.length).toBe(0)
80
+ }
81
+ })
82
+ })
83
+
84
+ it('create a file dag with inlinks', async () => {
85
+ const maxChunkSize = 1000
86
+ const chunkNum = 10
87
+ const chunk = 'h'.repeat(maxChunkSize)
88
+ const name = 'test.txt'
89
+ const text = chunk.repeat(chunkNum)
90
+ const size = text.length
91
+
92
+ /// 1 chunks + 2 inlinks + root
93
+ const EXPECTED_NODE_COUNT = 4
94
+
95
+ const blockstore = new MemoryBlockstore()
96
+ const headCID = await processFileToIPLDFormat(
97
+ blockstore,
98
+ bufferToIterable(Buffer.from(text)),
99
+ size,
100
+ name,
101
+ {
102
+ maxChunkSize,
103
+ maxLinkPerNode: 4,
104
+ },
105
+ )
106
+
107
+ const nodes = await nodesFromBlockstore(blockstore)
108
+ expect(nodes.length).toBe(EXPECTED_NODE_COUNT)
109
+
110
+ let [rootCount, inlinkCount, chunkCount] = [0, 0, 0]
111
+
112
+ nodes.forEach((node) => {
113
+ const decoded = IPLDNodeData.decode(node?.Data ?? new Uint8Array())
114
+ if (decoded.type === MetadataType.File) {
115
+ rootCount++
116
+ } else if (decoded.type === MetadataType.FileInlink) {
117
+ inlinkCount++
118
+ } else if (decoded.type === MetadataType.FileChunk) {
119
+ chunkCount++
120
+ } else {
121
+ throw new Error('Unexpected node type')
122
+ }
123
+ })
124
+
125
+ expect(rootCount).toBe(1)
126
+ expect(inlinkCount).toBe(2)
127
+ expect(chunkCount).toBe(1)
128
+ })
129
+ })
130
+
131
+ describe('folder creation', () => {
132
+ it('create a folder dag from a small buffer', async () => {
133
+ const links = Array.from({ length: 1 }, () =>
134
+ cidOfNode(createNode(Buffer.from(Math.random().toString()))),
135
+ )
136
+ const name = 'folder'
137
+ const size = 1000
138
+ const blockstore = new MemoryBlockstore()
139
+ const headCID = processFolderToIPLDFormat(blockstore, links, name, size, {
140
+ maxLinkPerNode: 4,
141
+ })
142
+
143
+ const nodes = await nodesFromBlockstore(blockstore)
144
+ expect(nodes.length).toBe(1)
145
+ const node = nodes[0]
146
+ expect(node).toBeDefined()
147
+ expect(node?.Data).toBeDefined()
148
+ const decoded = IPLDNodeData.decode(node?.Data ?? new Uint8Array())
149
+ expect(decoded.name).toBe(name)
150
+ expect(decoded.type).toBe(MetadataType.Folder)
151
+ expect(decoded.linkDepth).toBe(0)
152
+ expect(decoded.size).toBe(size)
153
+ })
154
+
155
+ it('create a folder dag with inlinks', async () => {
156
+ const links = Array.from({ length: 10 }, () =>
157
+ cidOfNode(createNode(Buffer.from(Math.random().toString()))),
158
+ )
159
+ const name = 'folder'
160
+ const size = 1000
161
+
162
+ /// 3 inlinks + root
163
+ const EXPECTED_NODE_COUNT = 4
164
+
165
+ const blockstore = new MemoryBlockstore()
166
+ const headCID = processFolderToIPLDFormat(blockstore, links, name, size, {
167
+ maxLinkPerNode: 4,
168
+ })
169
+
170
+ const nodes = await nodesFromBlockstore(blockstore)
171
+ expect(nodes.length).toBe(EXPECTED_NODE_COUNT)
172
+
173
+ let [rootCount, inlinkCount] = [0, 0, 0]
174
+
175
+ nodes.forEach((node) => {
176
+ const decoded = IPLDNodeData.decode(node?.Data ?? new Uint8Array())
177
+ if (decoded.type === MetadataType.Folder) {
178
+ rootCount++
179
+ } else if (decoded.type === MetadataType.FolderInlink) {
180
+ inlinkCount++
181
+ } else {
182
+ throw new Error('Unexpected node type')
183
+ }
184
+ })
185
+
186
+ expect(rootCount).toBe(1)
187
+ expect(inlinkCount).toBe(3)
188
+ })
189
+ })
190
+
191
+ describe('metadata creation', () => {
192
+ it('create a metadata dag from a small buffer', async () => {
193
+ const metadata: OffchainMetadata = {
194
+ type: 'file',
195
+ dataCid: 'test',
196
+ name: 'test',
197
+ mimeType: 'text/plain',
198
+ totalSize: 1000,
199
+ totalChunks: 10,
200
+ chunks: [],
201
+ }
202
+
203
+ const blockstore = new MemoryBlockstore()
204
+ const headCID = await processMetadataToIPLDFormat(blockstore, metadata)
205
+ const nodes = await nodesFromBlockstore(blockstore)
206
+ expect(nodes.length).toBe(1)
207
+ })
208
+
209
+ it('large metadata dag represented into multiple nodes', async () => {
210
+ const metadata: OffchainMetadata = {
211
+ type: 'file',
212
+ dataCid: 'test',
213
+ name: 'test',
214
+ mimeType: 'text/plain'.repeat(100),
215
+ totalSize: 1000,
216
+ totalChunks: 10,
217
+ chunks: [],
218
+ }
219
+
220
+ const blockstore = new MemoryBlockstore()
221
+ const headCID = await processMetadataToIPLDFormat(blockstore, metadata, {
222
+ maxChunkSize: 200,
223
+ maxLinkPerNode: 2,
224
+ })
225
+ const nodes = await nodesFromBlockstore(blockstore)
226
+ expect(nodes.length).toBeGreaterThan(1)
227
+ })
228
+ })
229
+
230
+ describe('asyncronous chunking equivalence', () => {
231
+ it('chunk a small file buffer', async () => {
232
+ const buffer = Buffer.from('hello world')
233
+ const blockstore = new MemoryBlockstore()
234
+ const chunkedBlockstore = new MemoryBlockstore()
235
+ const singleBufferCID = await processFileToIPLDFormat(
236
+ blockstore,
237
+ bufferToIterable(buffer),
238
+ buffer.length,
239
+ 'test.txt',
240
+ )
241
+ const chunkedBufferCID = await processFileToIPLDFormat(
242
+ chunkedBlockstore,
243
+ separateBufferToIterable(buffer, 5),
244
+ buffer.length,
245
+ 'test.txt',
246
+ )
247
+
248
+ expect(singleBufferCID).toEqual(chunkedBufferCID)
249
+ })
250
+
251
+ it('chunk a large file buffer', async () => {
252
+ const buffer = Buffer.from('hello world')
253
+ const blockstore = new MemoryBlockstore()
254
+ const chunkedBlockstore = new MemoryBlockstore()
255
+ const singleBufferCID = await processFileToIPLDFormat(
256
+ blockstore,
257
+ bufferToIterable(buffer),
258
+ buffer.length,
259
+ 'test.txt',
260
+ )
261
+ const chunkedBufferCID = await processFileToIPLDFormat(
262
+ chunkedBlockstore,
263
+ separateBufferToIterable(buffer, 5),
264
+ buffer.length,
265
+ 'test.txt',
266
+ )
267
+
268
+ expect(singleBufferCID).toEqual(chunkedBufferCID)
269
+ })
270
+ })
271
+ })
272
+
273
+ const bufferToIterable = (buffer: Buffer): AsyncIterable<Buffer> => {
274
+ return (async function* () {
275
+ yield buffer
276
+ })()
277
+ }
278
+
279
+ const separateBufferToIterable = (buffer: Buffer, chunkSize: number): AsyncIterable<Buffer> => {
280
+ return (async function* () {
281
+ while (buffer.length > 0) {
282
+ yield buffer.subarray(0, chunkSize)
283
+ buffer = buffer.subarray(chunkSize)
284
+ }
285
+ })()
286
+ }
287
+
288
+ const nodesFromBlockstore = async (blockstore: BaseBlockstore): Promise<PBNode[]> => {
289
+ const nodes: PBNode[] = []
290
+ for await (const pair of blockstore.getAll()) {
291
+ nodes.push(decodeNode(pair.block))
292
+ }
293
+ return nodes
294
+ }
@@ -0,0 +1,20 @@
1
+ import { CID } from 'multiformats'
2
+ import { cidOfNode, cidToString, stringToCid } from '../src/cid/index.js'
3
+ import { createNode } from '../src/ipld/index.js'
4
+
5
+ const randomCIDString = cidOfNode(createNode(new Uint8Array([]), [])).toString()
6
+
7
+ describe('CID', () => {
8
+ it('should generate a valid CID from a node', () => {
9
+ const node = createNode(new Uint8Array([1, 2, 3]), [])
10
+ const cid = cidOfNode(node).toString()
11
+ expect(cid).toBeDefined()
12
+ expect(cidToString(stringToCid(cid))).toEqual(cid)
13
+ })
14
+
15
+ it('should convert CID string back to CID object', () => {
16
+ const cidObject = stringToCid(randomCIDString)
17
+ expect(cidObject).toBeInstanceOf(CID)
18
+ expect(cidToString(cidObject)).toEqual(randomCIDString)
19
+ })
20
+ })
@@ -0,0 +1,58 @@
1
+ import { compressFile, COMPRESSION_CHUNK_SIZE, CompressionAlgorithm, decompressFile } from '../src'
2
+
3
+ describe('compression', () => {
4
+ it('compresses and decompresses a file with default options', async () => {
5
+ const file = Buffer.from('hello'.repeat(1000))
6
+
7
+ const compressed = compressFile(
8
+ (async function* () {
9
+ yield file
10
+ })(),
11
+ {
12
+ algorithm: CompressionAlgorithm.ZLIB,
13
+ level: 9,
14
+ },
15
+ )
16
+
17
+ const decompressed = decompressFile(compressed, {
18
+ algorithm: CompressionAlgorithm.ZLIB,
19
+ level: 9,
20
+ })
21
+
22
+ let decompressedBuffer = Buffer.alloc(0)
23
+ for await (const chunk of decompressed) {
24
+ decompressedBuffer = Buffer.concat([decompressedBuffer, chunk])
25
+ }
26
+
27
+ expect(decompressedBuffer.toString()).toBe(file.toString())
28
+ })
29
+
30
+ it('compresses and decompresses a file with custom chunk size', async () => {
31
+ const file = Buffer.from('hello'.repeat(1000))
32
+ const chunkSize = 100
33
+
34
+ const compressed = compressFile(
35
+ (async function* () {
36
+ yield file
37
+ })(),
38
+ {
39
+ algorithm: CompressionAlgorithm.ZLIB,
40
+ level: 9,
41
+ chunkSize,
42
+ },
43
+ )
44
+
45
+ const decompressed = decompressFile(compressed, {
46
+ algorithm: CompressionAlgorithm.ZLIB,
47
+ level: 9,
48
+ chunkSize,
49
+ })
50
+
51
+ let decompressedBuffer = Buffer.alloc(0)
52
+ for await (const chunk of decompressed) {
53
+ decompressedBuffer = Buffer.concat([decompressedBuffer, chunk])
54
+ }
55
+
56
+ expect(decompressedBuffer.toString()).toBe(file.toString())
57
+ })
58
+ })
@@ -0,0 +1,67 @@
1
+ import { decryptFile, encryptFile, EncryptionAlgorithm } from '../src'
2
+
3
+ describe('encryption', () => {
4
+ it('encrypts and decrypts a file with default chunk size', async () => {
5
+ const chunk = 'hello'
6
+ const file = Buffer.from(chunk.repeat(1000))
7
+ const password = 'password'
8
+ const salt = 'salt'
9
+
10
+ const encrypted = encryptFile(
11
+ (async function* () {
12
+ yield file
13
+ })(),
14
+ password,
15
+ {
16
+ algorithm: EncryptionAlgorithm.AES_256_GCM,
17
+ },
18
+ )
19
+
20
+ const decrypted = decryptFile(encrypted, password, {
21
+ algorithm: EncryptionAlgorithm.AES_256_GCM,
22
+ })
23
+
24
+ let decryptedBuffer = Buffer.alloc(0)
25
+ for await (const chunk of decrypted) {
26
+ decryptedBuffer = Buffer.concat([decryptedBuffer, chunk])
27
+ }
28
+
29
+ expect(decryptedBuffer.toString()).toBe(file.toString())
30
+ })
31
+
32
+ it('encrypts and decrypts a file with custom chunk size', async () => {
33
+ const chunk = 'hello'
34
+ const file = Buffer.from(chunk.repeat(1000))
35
+ const password = 'password'
36
+ const salt = 'salt'
37
+ const IV_SIZE = 16
38
+ const TAG_SIZE = 16
39
+
40
+ const encryptingSize = 100
41
+
42
+ const encrypted = encryptFile(
43
+ (async function* () {
44
+ yield file
45
+ })(),
46
+ password,
47
+ {
48
+ algorithm: EncryptionAlgorithm.AES_256_GCM,
49
+ chunkSize: encryptingSize,
50
+ },
51
+ )
52
+
53
+ const decryptingSize = encryptingSize + IV_SIZE + TAG_SIZE
54
+
55
+ const decrypted = decryptFile(encrypted, password, {
56
+ algorithm: EncryptionAlgorithm.AES_256_GCM,
57
+ chunkSize: decryptingSize,
58
+ })
59
+
60
+ let decryptedBuffer = Buffer.alloc(0)
61
+ for await (const chunk of decrypted) {
62
+ decryptedBuffer = Buffer.concat([decryptedBuffer, chunk])
63
+ }
64
+
65
+ expect(decryptedBuffer.toString()).toBe(file.toString())
66
+ })
67
+ })
@@ -0,0 +1,74 @@
1
+ import {
2
+ cidOfNode,
3
+ createChunkedFileIpldNode,
4
+ createFileChunkIpldNode,
5
+ createSingleFileIpldNode,
6
+ } from '../src/index.js'
7
+ import { createNode } from '../src/ipld/index.js'
8
+ import { IPLDNodeData, MetadataType } from '../src/metadata/onchain/protobuf/OnchainMetadata.js'
9
+
10
+ describe('node creation', () => {
11
+ describe('files nodes', () => {
12
+ it('single file node | correctly params setup', () => {
13
+ const filename = 'test.txt'
14
+ const buffer = Buffer.from('hello world')
15
+ const node = createSingleFileIpldNode(buffer, filename)
16
+ const decoded = IPLDNodeData.decode(node.Data ?? new Uint8Array())
17
+ expect(decoded.name).toBe(filename)
18
+ expect(decoded.size).toBe(buffer.length)
19
+ expect(Buffer.from(decoded.data ?? '').toString()).toBe(buffer.toString())
20
+ })
21
+
22
+ it('single file root node | no name', () => {
23
+ const buffer = Buffer.from('hello world')
24
+ const node = createSingleFileIpldNode(buffer)
25
+ const decoded = IPLDNodeData.decode(node.Data ?? new Uint8Array())
26
+ expect(decoded.type).toBe(MetadataType.File)
27
+ expect(decoded.name).toBeUndefined()
28
+ expect(decoded.size).toBe(buffer.length)
29
+ expect(Buffer.from(decoded.data ?? '').toString()).toBe(buffer.toString())
30
+ })
31
+
32
+ it('chunked file root node | correctly params setup', () => {
33
+ const links = Array.from({ length: 10 }, () =>
34
+ cidOfNode(createNode(Buffer.from(Math.random().toString()))),
35
+ )
36
+ const size = 1000
37
+ const linkDepth = 1
38
+ const filename = 'test.txt'
39
+ const node = createChunkedFileIpldNode(links, size, linkDepth, filename)
40
+
41
+ const decoded = IPLDNodeData.decode(node.Data ?? new Uint8Array())
42
+ expect(decoded.type).toBe(MetadataType.File)
43
+ expect(decoded.name).toBe(filename)
44
+ expect(decoded.size).toBe(size)
45
+ expect(decoded.linkDepth).toBe(linkDepth)
46
+ })
47
+
48
+ it('chunked file root node | no name', () => {
49
+ const links = Array.from({ length: 10 }, () =>
50
+ cidOfNode(createNode(Buffer.from(Math.random().toString()))),
51
+ )
52
+ const size = 1000
53
+ const linkDepth = 1
54
+ const node = createChunkedFileIpldNode(links, size, linkDepth)
55
+
56
+ const decoded = IPLDNodeData.decode(node.Data ?? new Uint8Array())
57
+ expect(decoded.type).toBe(MetadataType.File)
58
+ expect(decoded.name).toBeUndefined()
59
+ expect(decoded.size).toBe(size)
60
+ expect(decoded.linkDepth).toBe(linkDepth)
61
+ })
62
+
63
+ it('file chunk node | correctly params setup', () => {
64
+ const buffer = Buffer.from('hello world')
65
+ const node = createFileChunkIpldNode(buffer)
66
+
67
+ const decoded = IPLDNodeData.decode(node.Data ?? new Uint8Array())
68
+ expect(decoded.type).toBe(MetadataType.FileChunk)
69
+ expect(decoded.name).toBeUndefined()
70
+ expect(decoded.size).toBe(buffer.length)
71
+ expect(decoded.linkDepth).toBe(0)
72
+ })
73
+ })
74
+ })
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src/",
6
+ "moduleResolution": "NodeNext",
7
+ "module": "NodeNext",
8
+ "forceConsistentCasingInFileNames": true,
9
+ "skipLibCheck": true,
10
+ "stripInternal": true,
11
+ "resolveJsonModule": true
12
+ },
13
+ "include": ["src"]
14
+ }