@ethersphere/bee-js 8.3.1 → 9.0.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 (224) hide show
  1. package/README.md +192 -50
  2. package/dist/cjs/bee-dev.js +78 -0
  3. package/dist/cjs/bee.js +341 -417
  4. package/dist/cjs/chunk/bmt.js +15 -32
  5. package/dist/cjs/chunk/cac.js +26 -36
  6. package/dist/cjs/chunk/soc.js +56 -51
  7. package/dist/cjs/feed/identifier.js +3 -28
  8. package/dist/cjs/feed/index.js +95 -44
  9. package/dist/cjs/feed/retrievable.js +11 -22
  10. package/dist/cjs/index.js +17 -1
  11. package/dist/cjs/manifest/manifest.js +369 -0
  12. package/dist/cjs/modules/bytes.js +24 -12
  13. package/dist/cjs/modules/bzz.js +24 -34
  14. package/dist/cjs/modules/chunk.js +13 -7
  15. package/dist/cjs/modules/debug/balance.js +29 -4
  16. package/dist/cjs/modules/debug/chequebook.js +60 -16
  17. package/dist/cjs/modules/debug/connectivity.js +82 -4
  18. package/dist/cjs/modules/debug/settlements.js +22 -2
  19. package/dist/cjs/modules/debug/stake.js +29 -11
  20. package/dist/cjs/modules/debug/stamps.js +88 -7
  21. package/dist/cjs/modules/debug/states.js +25 -3
  22. package/dist/cjs/modules/debug/status.js +45 -47
  23. package/dist/cjs/modules/debug/transactions.js +27 -5
  24. package/dist/cjs/modules/envelope.js +8 -6
  25. package/dist/cjs/modules/feed.js +25 -10
  26. package/dist/cjs/modules/grantee.js +18 -12
  27. package/dist/cjs/modules/gsoc.js +24 -0
  28. package/dist/cjs/modules/pinning.js +13 -2
  29. package/dist/cjs/modules/pss.js +9 -3
  30. package/dist/cjs/modules/soc.js +9 -4
  31. package/dist/cjs/modules/stewardship.js +7 -3
  32. package/dist/cjs/modules/tag.js +35 -3
  33. package/dist/cjs/package.json +1 -0
  34. package/dist/cjs/stamper/stamper.js +43 -0
  35. package/dist/cjs/types/debug.js +16 -1
  36. package/dist/cjs/types/index.js +2 -24
  37. package/dist/cjs/utils/bytes.js +67 -115
  38. package/dist/cjs/utils/chunk-size.js +17 -0
  39. package/dist/cjs/utils/chunk-stream.browser.js +85 -0
  40. package/dist/cjs/utils/chunk-stream.js +84 -0
  41. package/dist/cjs/utils/cid.js +5 -6
  42. package/dist/cjs/utils/collection.browser.js +2 -2
  43. package/dist/cjs/utils/collection.js +3 -2
  44. package/dist/cjs/utils/collection.node.js +0 -2
  45. package/dist/cjs/utils/constants.js +7 -3
  46. package/dist/cjs/utils/data.browser.js +6 -3
  47. package/dist/cjs/utils/data.js +8 -4
  48. package/dist/cjs/utils/duration.js +51 -0
  49. package/dist/cjs/utils/expose.js +11 -40
  50. package/dist/cjs/utils/headers.js +79 -52
  51. package/dist/cjs/utils/http.js +34 -10
  52. package/dist/cjs/utils/mime.js +78 -0
  53. package/dist/cjs/utils/pss.js +3 -4
  54. package/dist/cjs/utils/redundancy.js +18 -14
  55. package/dist/cjs/utils/resource-locator.js +17 -0
  56. package/dist/cjs/utils/size.js +35 -0
  57. package/dist/cjs/utils/stamps.js +67 -51
  58. package/dist/cjs/utils/tar-uploader.browser.js +2 -2
  59. package/dist/cjs/utils/tar-uploader.js +2 -2
  60. package/dist/cjs/utils/tokens.js +144 -0
  61. package/dist/cjs/utils/type.js +142 -350
  62. package/dist/cjs/utils/typed-bytes.js +179 -0
  63. package/dist/cjs/utils/upload-progress.js +2 -0
  64. package/dist/cjs/utils/url.js +0 -4
  65. package/dist/cjs/utils/workaround.js +27 -0
  66. package/dist/index.browser.min.js +1 -2
  67. package/dist/index.browser.min.js.map +1 -1
  68. package/dist/mjs/bee-dev.js +98 -0
  69. package/dist/mjs/bee.js +367 -411
  70. package/dist/mjs/chunk/bmt.js +13 -29
  71. package/dist/mjs/chunk/cac.js +26 -34
  72. package/dist/mjs/chunk/soc.js +57 -53
  73. package/dist/mjs/feed/identifier.js +3 -26
  74. package/dist/mjs/feed/index.js +98 -51
  75. package/dist/mjs/feed/retrievable.js +12 -23
  76. package/dist/mjs/index.js +10 -1
  77. package/dist/mjs/manifest/manifest.js +371 -0
  78. package/dist/mjs/modules/bytes.js +27 -15
  79. package/dist/mjs/modules/bzz.js +25 -32
  80. package/dist/mjs/modules/chunk.js +16 -8
  81. package/dist/mjs/modules/debug/balance.js +61 -4
  82. package/dist/mjs/modules/debug/chequebook.js +116 -16
  83. package/dist/mjs/modules/debug/connectivity.js +144 -3
  84. package/dist/mjs/modules/debug/settlements.js +46 -2
  85. package/dist/mjs/modules/debug/stake.js +69 -11
  86. package/dist/mjs/modules/debug/stamps.js +184 -7
  87. package/dist/mjs/modules/debug/states.js +55 -3
  88. package/dist/mjs/modules/debug/status.js +97 -45
  89. package/dist/mjs/modules/debug/transactions.js +61 -5
  90. package/dist/mjs/modules/envelope.js +11 -9
  91. package/dist/mjs/modules/feed.js +26 -10
  92. package/dist/mjs/modules/grantee.js +35 -13
  93. package/dist/mjs/modules/gsoc.js +16 -0
  94. package/dist/mjs/modules/pinning.js +23 -2
  95. package/dist/mjs/modules/pss.js +10 -4
  96. package/dist/mjs/modules/soc.js +10 -5
  97. package/dist/mjs/modules/stewardship.js +14 -4
  98. package/dist/mjs/modules/tag.js +93 -3
  99. package/dist/mjs/package.json +2 -1
  100. package/dist/mjs/stamper/stamper.js +39 -0
  101. package/dist/mjs/types/debug.js +15 -1
  102. package/dist/mjs/types/index.js +2 -24
  103. package/dist/mjs/utils/bytes.js +63 -104
  104. package/dist/mjs/utils/chunk-size.js +13 -0
  105. package/dist/mjs/utils/chunk-stream.browser.js +85 -0
  106. package/dist/mjs/utils/chunk-stream.js +87 -0
  107. package/dist/mjs/utils/cid.js +5 -6
  108. package/dist/mjs/utils/collection.browser.js +2 -2
  109. package/dist/mjs/utils/collection.js +2 -2
  110. package/dist/mjs/utils/collection.node.js +0 -2
  111. package/dist/mjs/utils/constants.js +6 -2
  112. package/dist/mjs/utils/data.browser.js +9 -3
  113. package/dist/mjs/utils/data.js +12 -4
  114. package/dist/mjs/utils/duration.js +47 -0
  115. package/dist/mjs/utils/expose.js +2 -7
  116. package/dist/mjs/utils/headers.js +73 -48
  117. package/dist/mjs/utils/http.js +33 -11
  118. package/dist/mjs/utils/mime.js +75 -0
  119. package/dist/mjs/utils/pss.js +3 -4
  120. package/dist/mjs/utils/redundancy.js +18 -8
  121. package/dist/mjs/utils/resource-locator.js +13 -0
  122. package/dist/mjs/utils/size.js +31 -0
  123. package/dist/mjs/utils/stamps.js +47 -44
  124. package/dist/mjs/utils/tar-uploader.browser.js +2 -2
  125. package/dist/mjs/utils/tar-uploader.js +2 -2
  126. package/dist/mjs/utils/tokens.js +139 -0
  127. package/dist/mjs/utils/type.js +216 -310
  128. package/dist/mjs/utils/typed-bytes.js +160 -0
  129. package/dist/mjs/utils/upload-progress.js +1 -0
  130. package/dist/mjs/utils/url.js +0 -4
  131. package/dist/mjs/utils/workaround.js +22 -0
  132. package/dist/types/bee-dev.d.ts +5 -0
  133. package/dist/types/bee.d.ts +88 -165
  134. package/dist/types/chunk/bmt.d.ts +2 -2
  135. package/dist/types/chunk/cac.d.ts +7 -24
  136. package/dist/types/chunk/soc.d.ts +15 -15
  137. package/dist/types/feed/identifier.d.ts +2 -4
  138. package/dist/types/feed/index.d.ts +14 -18
  139. package/dist/types/feed/retrievable.d.ts +3 -4
  140. package/dist/types/index.d.ts +28 -1
  141. package/dist/types/manifest/manifest.d.ts +106 -0
  142. package/dist/types/modules/bytes.d.ts +8 -5
  143. package/dist/types/modules/bzz.d.ts +8 -10
  144. package/dist/types/modules/chunk.d.ts +4 -3
  145. package/dist/types/modules/debug/balance.d.ts +3 -2
  146. package/dist/types/modules/debug/chequebook.d.ts +7 -6
  147. package/dist/types/modules/debug/connectivity.d.ts +5 -3
  148. package/dist/types/modules/debug/settlements.d.ts +2 -1
  149. package/dist/types/modules/debug/stake.d.ts +4 -2
  150. package/dist/types/modules/debug/stamps.d.ts +5 -4
  151. package/dist/types/modules/debug/status.d.ts +6 -25
  152. package/dist/types/modules/debug/transactions.d.ts +5 -4
  153. package/dist/types/modules/envelope.d.ts +3 -2
  154. package/dist/types/modules/feed.d.ts +20 -16
  155. package/dist/types/modules/grantee.d.ts +7 -6
  156. package/dist/types/modules/gsoc.d.ts +7 -0
  157. package/dist/types/modules/pinning.d.ts +2 -4
  158. package/dist/types/modules/pss.d.ts +4 -3
  159. package/dist/types/modules/soc.d.ts +3 -2
  160. package/dist/types/modules/stewardship.d.ts +4 -4
  161. package/dist/types/modules/tag.d.ts +2 -1
  162. package/dist/types/stamper/stamper.d.ts +15 -0
  163. package/dist/types/types/debug.d.ts +63 -115
  164. package/dist/types/types/index.d.ts +103 -204
  165. package/dist/types/utils/bytes.d.ts +16 -90
  166. package/dist/types/utils/chunk-size.d.ts +1 -0
  167. package/dist/types/utils/chunk-stream.browser.d.ts +6 -0
  168. package/dist/types/utils/chunk-stream.d.ts +6 -0
  169. package/dist/types/utils/cid.d.ts +3 -2
  170. package/dist/types/utils/collection.browser.d.ts +2 -2
  171. package/dist/types/utils/collection.d.ts +2 -1
  172. package/dist/types/utils/collection.node.d.ts +0 -1
  173. package/dist/types/utils/constants.d.ts +4 -1
  174. package/dist/types/utils/duration.d.ts +17 -0
  175. package/dist/types/utils/error.d.ts +2 -2
  176. package/dist/types/utils/expose.d.ts +2 -7
  177. package/dist/types/utils/headers.d.ts +3 -4
  178. package/dist/types/utils/mime.d.ts +1 -0
  179. package/dist/types/utils/pss.d.ts +2 -2
  180. package/dist/types/utils/resource-locator.d.ts +6 -0
  181. package/dist/types/utils/size.d.ts +16 -0
  182. package/dist/types/utils/stamps.d.ts +27 -33
  183. package/dist/types/utils/tar-uploader.browser.d.ts +3 -4
  184. package/dist/types/utils/tar-uploader.d.ts +3 -4
  185. package/dist/types/utils/tokens.d.ts +77 -0
  186. package/dist/types/utils/type.d.ts +20 -52
  187. package/dist/types/utils/typed-bytes.d.ts +68 -0
  188. package/dist/types/utils/upload-progress.d.ts +4 -0
  189. package/dist/types/utils/workaround.d.ts +2 -0
  190. package/package.json +11 -17
  191. package/dist/cjs/chunk/signer.js +0 -126
  192. package/dist/cjs/chunk/span.js +0 -25
  193. package/dist/cjs/feed/json.js +0 -28
  194. package/dist/cjs/feed/topic.js +0 -25
  195. package/dist/cjs/feed/type.js +0 -15
  196. package/dist/cjs/modules/debug/chunk.js +0 -21
  197. package/dist/cjs/modules/debug/tag.js +0 -19
  198. package/dist/cjs/utils/eth.js +0 -216
  199. package/dist/cjs/utils/hash.js +0 -21
  200. package/dist/cjs/utils/hex.js +0 -150
  201. package/dist/cjs/utils/reference.js +0 -36
  202. package/dist/index.browser.min.js.LICENSE.txt +0 -8
  203. package/dist/mjs/chunk/signer.js +0 -114
  204. package/dist/mjs/chunk/span.js +0 -21
  205. package/dist/mjs/feed/json.js +0 -26
  206. package/dist/mjs/feed/topic.js +0 -19
  207. package/dist/mjs/feed/type.js +0 -10
  208. package/dist/mjs/modules/debug/chunk.js +0 -17
  209. package/dist/mjs/modules/debug/tag.js +0 -15
  210. package/dist/mjs/utils/eth.js +0 -192
  211. package/dist/mjs/utils/hash.js +0 -16
  212. package/dist/mjs/utils/hex.js +0 -135
  213. package/dist/mjs/utils/reference.js +0 -29
  214. package/dist/types/chunk/signer.d.ts +0 -31
  215. package/dist/types/chunk/span.d.ts +0 -10
  216. package/dist/types/feed/json.d.ts +0 -4
  217. package/dist/types/feed/topic.d.ts +0 -3
  218. package/dist/types/feed/type.d.ts +0 -6
  219. package/dist/types/modules/debug/chunk.d.ts +0 -10
  220. package/dist/types/modules/debug/tag.d.ts +0 -8
  221. package/dist/types/utils/eth.d.ts +0 -67
  222. package/dist/types/utils/hash.d.ts +0 -9
  223. package/dist/types/utils/hex.d.ts +0 -86
  224. package/dist/types/utils/reference.d.ts +0 -2
@@ -0,0 +1,371 @@
1
+ import { Binary, MerkleTree, Optional, Uint8ArrayReader } from 'cafe-utility';
2
+ import { NULL_ADDRESS } from "../index.js";
3
+ import { Reference } from "../utils/typed-bytes.js";
4
+ const ENCODER = new TextEncoder();
5
+ const DECODER = new TextDecoder();
6
+ const TYPE_VALUE = 2;
7
+ const TYPE_EDGE = 4;
8
+ const TYPE_WITH_PATH_SEPARATOR = 8;
9
+ const TYPE_WITH_METADATA = 16;
10
+ const PATH_SEPARATOR = new Uint8Array([47]);
11
+ const VERSION_02_HASH_HEX = '5768b3b6a7db56d21d1abff40d41cebfc83448fed8d7e9b06ec0d3b073f28f7b';
12
+ const VERSION_02_HASH = Binary.hexToUint8Array(VERSION_02_HASH_HEX);
13
+ export class Fork {
14
+ constructor(prefix, node) {
15
+ this.prefix = prefix;
16
+ this.node = node;
17
+ }
18
+ static split(a, b) {
19
+ const commonPart = Binary.commonPrefix(a.prefix, b.prefix);
20
+ const node = new MantarayNode({
21
+ path: commonPart
22
+ });
23
+ const newAFork = new Fork(a.prefix.slice(commonPart.length), a.node);
24
+ const newBFork = new Fork(b.prefix.slice(commonPart.length), b.node);
25
+ a.node.path = a.prefix.slice(commonPart.length);
26
+ b.node.path = b.prefix.slice(commonPart.length);
27
+ a.prefix = a.prefix.slice(commonPart.length);
28
+ b.prefix = b.prefix.slice(commonPart.length);
29
+ node.forks.set(newAFork.prefix[0], newAFork);
30
+ node.forks.set(newBFork.prefix[0], newBFork);
31
+ newAFork.node.parent = node;
32
+ newBFork.node.parent = node;
33
+ return new Fork(commonPart, node);
34
+ }
35
+ marshal() {
36
+ if (!this.node.selfAddress) {
37
+ throw Error('Fork#marshal node.selfAddress is not set');
38
+ }
39
+ const data = [];
40
+ data.push(new Uint8Array([this.node.determineType()]));
41
+ data.push(Binary.numberToUint8(this.prefix.length));
42
+ data.push(this.prefix);
43
+ if (this.prefix.length < 30) {
44
+ data.push(new Uint8Array(30 - this.prefix.length));
45
+ }
46
+ data.push(this.node.selfAddress);
47
+ if (this.node.metadata) {
48
+ const metadataBytes = Binary.padEndToMultiple(new Uint8Array([0x00, 0x00, ...ENCODER.encode(JSON.stringify(this.node.metadata))]), 32, 0x0a);
49
+ const metadataLengthBytes = Binary.numberToUint16(metadataBytes.length - 2, 'BE');
50
+ metadataBytes.set(metadataLengthBytes, 0);
51
+ data.push(metadataBytes);
52
+ }
53
+ return Binary.concatBytes(...data);
54
+ }
55
+ static unmarshal(reader) {
56
+ const type = Binary.uint8ToNumber(reader.read(1));
57
+ const prefixLength = Binary.uint8ToNumber(reader.read(1));
58
+ const prefix = reader.read(prefixLength);
59
+ reader.read(30 - prefixLength);
60
+ const targetAddress = reader.read(32);
61
+ let metadata = undefined;
62
+ if (isType(type, TYPE_WITH_METADATA)) {
63
+ const metadataLength = Binary.uint16ToNumber(reader.read(2), 'BE');
64
+ metadata = JSON.parse(DECODER.decode(reader.read(metadataLength)));
65
+ }
66
+ return new Fork(prefix, new MantarayNode({
67
+ targetAddress,
68
+ metadata,
69
+ path: prefix
70
+ }));
71
+ }
72
+ }
73
+ export class MantarayNode {
74
+ constructor(options) {
75
+ this.obfuscationKey = new Uint8Array(32);
76
+ this.selfAddress = null;
77
+ this.targetAddress = new Uint8Array(32);
78
+ this.metadata = null;
79
+ this.path = new Uint8Array(0);
80
+ this.forks = new Map();
81
+ this.parent = null;
82
+ if (options?.targetAddress) {
83
+ this.targetAddress = options.targetAddress;
84
+ }
85
+ if (options?.selfAddress) {
86
+ this.selfAddress = options.selfAddress;
87
+ }
88
+ if (options?.metadata) {
89
+ this.metadata = options.metadata;
90
+ }
91
+ if (options?.obfuscationKey) {
92
+ this.obfuscationKey = options.obfuscationKey;
93
+ }
94
+ if (options?.path) {
95
+ this.path = options.path;
96
+ }
97
+ if (options?.parent) {
98
+ this.parent = options.parent;
99
+ }
100
+ }
101
+ get fullPath() {
102
+ return Binary.concatBytes(this.parent?.fullPath ?? new Uint8Array(0), this.path);
103
+ }
104
+ get fullPathString() {
105
+ return DECODER.decode(this.fullPath);
106
+ }
107
+ /**
108
+ * Returns the metadata at the `/` path to access idiomatic properties.
109
+ */
110
+ getRootMetadata() {
111
+ const node = this.find('/');
112
+ if (node && node.metadata) {
113
+ return Optional.of(node.metadata);
114
+ }
115
+ return Optional.empty();
116
+ }
117
+ /**
118
+ * Returns the `swarm-index-document` and `swarm-error-document` metadata values.
119
+ */
120
+ getDocsMetadata() {
121
+ const node = this.find('/');
122
+ if (!node || !node.metadata) {
123
+ return {
124
+ indexDocument: null,
125
+ errorDocument: null
126
+ };
127
+ }
128
+ return {
129
+ indexDocument: node.metadata['website-index-document'] ?? null,
130
+ errorDocument: node.metadata['website-error-document'] ?? null
131
+ };
132
+ }
133
+ /**
134
+ * Attempts to resolve the manifest as a feed, returning the latest update.
135
+ */
136
+ async resolveFeed(bee, requestOptions) {
137
+ const node = this.find('/');
138
+ if (!node || !node.metadata) {
139
+ return Optional.empty();
140
+ }
141
+ const owner = node.metadata['swarm-feed-owner'];
142
+ const topic = node.metadata['swarm-feed-topic'];
143
+ if (!owner || !topic) {
144
+ return Optional.empty();
145
+ }
146
+ return Optional.of(await bee.fetchLatestFeedUpdate(topic, owner, requestOptions));
147
+ }
148
+ /**
149
+ * Gets the binary representation of the node.
150
+ */
151
+ async marshal() {
152
+ for (const fork of this.forks.values()) {
153
+ if (!fork.node.selfAddress) {
154
+ fork.node.selfAddress = (await fork.node.calculateSelfAddress()).toUint8Array();
155
+ }
156
+ }
157
+ const header = new Uint8Array(32);
158
+ header.set(VERSION_02_HASH, 0);
159
+ header.set(Binary.equals(this.targetAddress, NULL_ADDRESS) && Binary.equals(this.path, new Uint8Array([47])) ? Binary.numberToUint8(0) : Binary.numberToUint8(this.targetAddress.length), 31);
160
+ const forkBitmap = new Uint8Array(32);
161
+ for (const fork of this.forks.keys()) {
162
+ Binary.setBit(forkBitmap, fork, 1, 'LE');
163
+ }
164
+ const forks = [];
165
+ for (let i = 0; i < 256; i++) {
166
+ if (Binary.getBit(forkBitmap, i, 'LE')) {
167
+ forks.push(this.forks.get(i).marshal());
168
+ }
169
+ }
170
+ const data = Binary.xorCypher(Binary.concatBytes(header, Binary.equals(this.targetAddress, NULL_ADDRESS) && Binary.equals(this.path, new Uint8Array([47])) ? new Uint8Array(0) : this.targetAddress, forkBitmap, ...forks), this.obfuscationKey);
171
+ return Binary.concatBytes(this.obfuscationKey, data);
172
+ }
173
+ /**
174
+ * Downloads and unmarshals a MantarayNode from the given reference.
175
+ *
176
+ * Do not forget calling `loadRecursively` on the returned node to load the entire tree.
177
+ */
178
+ static async unmarshal(bee, reference, options, requestOptions) {
179
+ const data = (await bee.downloadData(reference, options, requestOptions)).toUint8Array();
180
+ return this.unmarshalFromData(data);
181
+ }
182
+ /**
183
+ * Unmarshals a MantarayNode from the given data.
184
+ *
185
+ * Do not forget calling `loadRecursively` on the returned node to load the entire tree.
186
+ */
187
+ static unmarshalFromData(data) {
188
+ const obfuscationKey = data.subarray(0, 32);
189
+ const decrypted = Binary.xorCypher(data.subarray(32), obfuscationKey);
190
+ const reader = new Uint8ArrayReader(decrypted);
191
+ const versionHash = reader.read(31);
192
+ if (!Binary.equals(versionHash, VERSION_02_HASH.slice(0, 31))) {
193
+ throw new Error('MantarayNode#unmarshal invalid version hash');
194
+ }
195
+ const targetAddressLength = Binary.uint8ToNumber(reader.read(1));
196
+ const targetAddress = targetAddressLength === 0 ? NULL_ADDRESS : reader.read(targetAddressLength);
197
+ const node = new MantarayNode({
198
+ targetAddress,
199
+ obfuscationKey
200
+ });
201
+ const forkBitmap = reader.read(32);
202
+ for (let i = 0; i < 256; i++) {
203
+ if (Binary.getBit(forkBitmap, i, 'LE')) {
204
+ const newFork = Fork.unmarshal(reader);
205
+ node.forks.set(i, newFork);
206
+ newFork.node.parent = node;
207
+ }
208
+ }
209
+ return node;
210
+ }
211
+ /**
212
+ * Adds a fork to the node.
213
+ */
214
+ addFork(path, reference, metadata) {
215
+ this.selfAddress = null;
216
+ path = path instanceof Uint8Array ? path : ENCODER.encode(path);
217
+ // TODO: this should not be ignored
218
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
219
+ let tip = this;
220
+ while (path.length) {
221
+ const prefix = path.slice(0, 30);
222
+ path = path.slice(30);
223
+ const isLast = path.length === 0;
224
+ const [bestMatch, matchedPath] = tip.findClosest(prefix);
225
+ const remainingPath = prefix.slice(matchedPath.length);
226
+ if (matchedPath.length) {
227
+ tip = bestMatch;
228
+ }
229
+ if (!remainingPath.length) {
230
+ continue;
231
+ }
232
+ const newFork = new Fork(remainingPath, new MantarayNode({
233
+ targetAddress: isLast ? new Reference(reference).toUint8Array() : undefined,
234
+ metadata: isLast ? metadata : undefined,
235
+ path: remainingPath
236
+ }));
237
+ const existing = bestMatch.forks.get(remainingPath[0]);
238
+ if (existing) {
239
+ const fork = Fork.split(newFork, existing);
240
+ tip.forks.set(remainingPath[0], fork);
241
+ fork.node.parent = tip;
242
+ tip.selfAddress = null;
243
+ tip = newFork.node;
244
+ } else {
245
+ tip.forks.set(remainingPath[0], newFork);
246
+ newFork.node.parent = tip;
247
+ tip.selfAddress = null;
248
+ tip = newFork.node;
249
+ }
250
+ }
251
+ }
252
+ /**
253
+ * Removes a fork from the node.
254
+ */
255
+ removeFork(path) {
256
+ this.selfAddress = null;
257
+ path = path instanceof Uint8Array ? path : ENCODER.encode(path);
258
+ if (path.length === 0) {
259
+ throw Error('MantarayNode#removeFork [path] parameter cannot be empty');
260
+ }
261
+ const match = this.find(path);
262
+ if (!match) {
263
+ throw Error('MantarayNode#removeFork fork not found');
264
+ }
265
+ const [parent, matchedPath] = this.findClosest(path.slice(0, path.length - 1));
266
+ parent.forks.delete(path.slice(matchedPath.length)[0]);
267
+ for (const fork of match.forks.values()) {
268
+ parent.addFork(Binary.concatBytes(match.path, fork.prefix), fork.node.targetAddress, fork.node.metadata);
269
+ }
270
+ }
271
+ /**
272
+ * Calculates the self address of the node.
273
+ */
274
+ async calculateSelfAddress() {
275
+ if (this.selfAddress) {
276
+ return new Reference(this.selfAddress);
277
+ }
278
+ return new Reference((await MerkleTree.root(await this.marshal())).hash());
279
+ }
280
+ /**
281
+ * Saves the node and its children recursively.
282
+ */
283
+ async saveRecursively(bee, postageBatchId, options, requestOptions) {
284
+ for (const fork of this.forks.values()) {
285
+ await fork.node.saveRecursively(bee, postageBatchId, options, requestOptions);
286
+ }
287
+ const result = await bee.uploadData(postageBatchId, await this.marshal(), options, requestOptions);
288
+ this.selfAddress = result.reference.toUint8Array();
289
+ return result;
290
+ }
291
+ /**
292
+ * Loads the node and its children recursively.
293
+ */
294
+ async loadRecursively(bee, options, requestOptions) {
295
+ for (const fork of this.forks.values()) {
296
+ const node = await MantarayNode.unmarshal(bee, fork.node.targetAddress, options, requestOptions);
297
+ fork.node.targetAddress = node.targetAddress;
298
+ fork.node.forks = node.forks;
299
+ fork.node.path = fork.prefix;
300
+ fork.node.parent = this;
301
+ await fork.node.loadRecursively(bee, options, requestOptions);
302
+ }
303
+ }
304
+ /**
305
+ * Finds a node in the tree by its path.
306
+ */
307
+ find(path) {
308
+ const [closest, match] = this.findClosest(path);
309
+ return match.length === path.length ? closest : null;
310
+ }
311
+ /**
312
+ * Finds the closest node in the tree to the given path.
313
+ */
314
+ findClosest(path, current = new Uint8Array()) {
315
+ path = path instanceof Uint8Array ? path : ENCODER.encode(path);
316
+ if (path.length === 0) {
317
+ return [this, current];
318
+ }
319
+ const fork = this.forks.get(path[0]);
320
+ if (fork && Binary.commonPrefix(fork.prefix, path).length === fork.prefix.length) {
321
+ return fork.node.findClosest(path.slice(fork.prefix.length), Binary.concatBytes(current, fork.prefix));
322
+ }
323
+ return [this, current];
324
+ }
325
+ /**
326
+ * Returns an array of all nodes in the tree which have a target address set.
327
+ *
328
+ * Must be called after `loadRecursively`.
329
+ */
330
+ collect(nodes = []) {
331
+ for (const fork of this.forks.values()) {
332
+ if (!Binary.equals(fork.node.targetAddress, NULL_ADDRESS)) {
333
+ nodes.push(fork.node);
334
+ }
335
+ fork.node.collect(nodes);
336
+ }
337
+ return nodes;
338
+ }
339
+ /**
340
+ * Returns a path:reference map of all nodes in the tree which have a target address set.
341
+ *
342
+ * Must be called after `loadRecursively`.
343
+ */
344
+ collectAndMap() {
345
+ const nodes = this.collect();
346
+ const result = {};
347
+ for (const node of nodes) {
348
+ result[node.fullPathString] = new Reference(node.targetAddress).toHex();
349
+ }
350
+ return result;
351
+ }
352
+ determineType() {
353
+ let type = 0;
354
+ if (!Binary.equals(this.targetAddress, NULL_ADDRESS) || Binary.equals(this.path, PATH_SEPARATOR)) {
355
+ type |= TYPE_VALUE;
356
+ }
357
+ if (this.forks.size > 0) {
358
+ type |= TYPE_EDGE;
359
+ }
360
+ if (Binary.indexOf(this.path, PATH_SEPARATOR) !== -1 && !Binary.equals(this.path, PATH_SEPARATOR)) {
361
+ type |= TYPE_WITH_PATH_SEPARATOR;
362
+ }
363
+ if (this.metadata) {
364
+ type |= TYPE_WITH_METADATA;
365
+ }
366
+ return type;
367
+ }
368
+ }
369
+ function isType(value, type) {
370
+ return (value & type) === type;
371
+ }
@@ -1,7 +1,9 @@
1
- import { wrapBytesWithHelpers } from "../utils/bytes.js";
2
- import { extractDownloadHeaders, extractRedundantUploadHeaders } from "../utils/headers.js";
1
+ import { Optional, Types } from 'cafe-utility';
2
+ import { Bytes } from "../utils/bytes.js";
3
+ import { prepareRequestHeaders } from "../utils/headers.js";
3
4
  import { http } from "../utils/http.js";
4
- import { makeTagUid } from "../utils/type.js";
5
+ import { makeTagUid, prepareDownloadOptions } from "../utils/type.js";
6
+ import { Reference } from "../utils/typed-bytes.js";
5
7
  const endpoint = 'bytes';
6
8
  /**
7
9
  * Upload data to a Bee node
@@ -19,13 +21,16 @@ export async function upload(requestOptions, data, postageBatchId, options) {
19
21
  data,
20
22
  headers: {
21
23
  'content-type': 'application/octet-stream',
22
- ...extractRedundantUploadHeaders(postageBatchId, options)
24
+ ...prepareRequestHeaders(postageBatchId, options)
23
25
  }
24
26
  });
27
+ const body = Types.asObject(response.data, {
28
+ name: 'response.data'
29
+ });
25
30
  return {
26
- reference: response.data.reference,
31
+ reference: new Reference(Types.asHexString(body.reference)),
27
32
  tagUid: response.headers['swarm-tag'] ? makeTagUid(response.headers['swarm-tag']) : undefined,
28
- historyAddress: response.headers['swarm-act-history-address'] || ''
33
+ historyAddress: response.headers['swarm-act-history-address'] ? Optional.of(new Reference(response.headers['swarm-act-history-address'])) : Optional.empty()
29
34
  };
30
35
  }
31
36
  /**
@@ -34,9 +39,10 @@ export async function upload(requestOptions, data, postageBatchId, options) {
34
39
  * @param requestOptions Options for making requests
35
40
  * @param hash Bee content reference
36
41
  */
37
- export async function head(requestOptions, hash) {
42
+ export async function head(requestOptions, reference) {
43
+ reference = new Reference(reference);
38
44
  const response = await http(requestOptions, {
39
- url: `${endpoint}/${hash}`,
45
+ url: `${endpoint}/${reference}`,
40
46
  method: 'head',
41
47
  responseType: 'json'
42
48
  });
@@ -50,13 +56,16 @@ export async function head(requestOptions, hash) {
50
56
  * @param requestOptions Options for making requests
51
57
  * @param hash Bee content reference
52
58
  */
53
- export async function download(requestOptions, hash, options) {
59
+ export async function download(requestOptions, resource, options) {
60
+ if (options) {
61
+ options = prepareDownloadOptions(options);
62
+ }
54
63
  const response = await http(requestOptions, {
55
64
  responseType: 'arraybuffer',
56
- url: `${endpoint}/${hash}`,
57
- headers: extractDownloadHeaders(options)
65
+ url: `${endpoint}/${resource}`,
66
+ headers: prepareRequestHeaders(null, options)
58
67
  });
59
- return wrapBytesWithHelpers(new Uint8Array(response.data));
68
+ return new Bytes(response.data);
60
69
  }
61
70
  /**
62
71
  * Download data as a readable stream
@@ -64,11 +73,14 @@ export async function download(requestOptions, hash, options) {
64
73
  * @param requestOptions Options for making requests
65
74
  * @param hash Bee content reference
66
75
  */
67
- export async function downloadReadable(requestOptions, hash, options) {
76
+ export async function downloadReadable(requestOptions, resource, options) {
77
+ if (options) {
78
+ options = prepareDownloadOptions(options);
79
+ }
68
80
  const response = await http(requestOptions, {
69
81
  responseType: 'stream',
70
- url: `${endpoint}/${hash}`,
71
- headers: extractDownloadHeaders(options)
82
+ url: `${endpoint}/${resource}`,
83
+ headers: prepareRequestHeaders(null, options)
72
84
  });
73
85
  return response.data;
74
86
  }
@@ -1,16 +1,12 @@
1
- import { wrapBytesWithHelpers } from "../utils/bytes.js";
1
+ import { Optional, Types } from 'cafe-utility';
2
+ import { Bytes } from "../utils/bytes.js";
2
3
  import { assertCollection } from "../utils/collection.js";
3
- import { extractDownloadHeaders, extractRedundantUploadHeaders, readFileHeaders } from "../utils/headers.js";
4
+ import { prepareRequestHeaders, readFileHeaders } from "../utils/headers.js";
4
5
  import { http } from "../utils/http.js";
5
6
  import { uploadTar } from "../utils/tar-uploader.js";
6
7
  import { isReadable, makeTagUid } from "../utils/type.js";
8
+ import { Reference } from "../utils/typed-bytes.js";
7
9
  const bzzEndpoint = 'bzz';
8
- function extractFileUploadHeaders(postageBatchId, options) {
9
- const headers = extractRedundantUploadHeaders(postageBatchId, options);
10
- if (options?.size) headers['content-length'] = String(options.size);
11
- if (options?.contentType) headers['content-type'] = options.contentType;
12
- return headers;
13
- }
14
10
  /**
15
11
  * Upload single file
16
12
  *
@@ -31,18 +27,19 @@ export async function uploadFile(requestOptions, data, postageBatchId, name, opt
31
27
  method: 'post',
32
28
  url: bzzEndpoint,
33
29
  data,
34
- headers: {
35
- ...extractFileUploadHeaders(postageBatchId, options)
36
- },
30
+ headers: prepareRequestHeaders(postageBatchId, options),
37
31
  params: {
38
32
  name
39
33
  },
40
34
  responseType: 'json'
41
35
  });
36
+ const body = Types.asObject(response.data, {
37
+ name: 'response.data'
38
+ });
42
39
  return {
43
- reference: response.data.reference,
40
+ reference: new Reference(Types.asHexString(body.reference)),
44
41
  tagUid: response.headers['swarm-tag'] ? makeTagUid(response.headers['swarm-tag']) : undefined,
45
- historyAddress: response.headers['swarm-act-history-address'] || ''
42
+ historyAddress: response.headers['swarm-act-history-address'] ? Optional.of(new Reference(response.headers['swarm-act-history-address'])) : Optional.empty()
46
43
  };
47
44
  }
48
45
  /**
@@ -52,16 +49,16 @@ export async function uploadFile(requestOptions, data, postageBatchId, name, opt
52
49
  * @param hash Bee file or collection hash
53
50
  * @param path If hash is collection then this defines path to a single file in the collection
54
51
  */
55
- export async function downloadFile(requestOptions, hash, path = '', options) {
52
+ export async function downloadFile(requestOptions, resource, path = '', options) {
56
53
  const response = await http(requestOptions, {
57
54
  method: 'GET',
58
55
  responseType: 'arraybuffer',
59
- url: `${bzzEndpoint}/${hash}/${path}`,
60
- headers: extractDownloadHeaders(options)
56
+ url: `${bzzEndpoint}/${resource}/${path}`,
57
+ headers: prepareRequestHeaders(null, options)
61
58
  });
62
59
  const file = {
63
60
  ...readFileHeaders(response.headers),
64
- data: wrapBytesWithHelpers(new Uint8Array(response.data))
61
+ data: new Bytes(response.data)
65
62
  };
66
63
  return file;
67
64
  }
@@ -72,12 +69,13 @@ export async function downloadFile(requestOptions, hash, path = '', options) {
72
69
  * @param hash Bee file or collection hash
73
70
  * @param path If hash is collection then this defines path to a single file in the collection
74
71
  */
75
- export async function downloadFileReadable(requestOptions, hash, path = '', options) {
72
+ export async function downloadFileReadable(requestOptions, reference, path = '', options) {
73
+ reference = new Reference(reference);
76
74
  const response = await http(requestOptions, {
77
75
  method: 'GET',
78
76
  responseType: 'stream',
79
- url: `${bzzEndpoint}/${hash}/${path}`,
80
- headers: extractDownloadHeaders(options)
77
+ url: `${bzzEndpoint}/${reference}/${path}`,
78
+ headers: prepareRequestHeaders(null, options)
81
79
  });
82
80
  const file = {
83
81
  ...readFileHeaders(response.headers),
@@ -85,16 +83,8 @@ export async function downloadFileReadable(requestOptions, hash, path = '', opti
85
83
  };
86
84
  return file;
87
85
  }
88
- export function extractCollectionUploadHeaders(postageBatchId, options) {
89
- const headers = extractRedundantUploadHeaders(postageBatchId, options);
90
- if (options?.indexDocument) {
91
- headers['swarm-index-document'] = options.indexDocument;
92
- }
93
- if (options?.errorDocument) {
94
- headers['swarm-error-document'] = options.errorDocument;
95
- }
96
- return headers;
97
- }
86
+ /*******************************************************************************************************************/
87
+ // Collections
98
88
  /**
99
89
  * Upload collection
100
90
  * @param requestOptions Options for making requests
@@ -105,9 +95,12 @@ export function extractCollectionUploadHeaders(postageBatchId, options) {
105
95
  export async function uploadCollection(requestOptions, collection, postageBatchId, options) {
106
96
  assertCollection(collection);
107
97
  const response = await uploadTar(requestOptions, collection, postageBatchId, options);
98
+ const body = Types.asObject(response.data, {
99
+ name: 'response.data'
100
+ });
108
101
  return {
109
- reference: response.data.reference,
102
+ reference: new Reference(Types.asHexString(body.reference)),
110
103
  tagUid: response.headers['swarm-tag'] ? makeTagUid(response.headers['swarm-tag']) : undefined,
111
- historyAddress: response.headers['swarm-act-history-address'] || ''
104
+ historyAddress: response.headers['swarm-act-history-address'] ? Optional.of(new Reference(response.headers['swarm-act-history-address'])) : Optional.empty()
112
105
  };
113
106
  }
@@ -1,7 +1,8 @@
1
- import { wrapBytesWithHelpers } from "../utils/bytes.js";
2
- import { extractUploadHeaders } from "../utils/headers.js";
1
+ import { Optional, Types } from 'cafe-utility';
2
+ import { prepareRequestHeaders } from "../utils/headers.js";
3
3
  import { http } from "../utils/http.js";
4
4
  import { makeTagUid } from "../utils/type.js";
5
+ import { Reference } from "../utils/typed-bytes.js";
5
6
  const endpoint = 'chunks';
6
7
  /**
7
8
  * Upload chunk to a Bee node
@@ -22,14 +23,19 @@ export async function upload(requestOptions, data, stamp, options) {
22
23
  data,
23
24
  headers: {
24
25
  'content-type': 'application/octet-stream',
25
- ...extractUploadHeaders(stamp, options)
26
+ ...prepareRequestHeaders(stamp, options)
26
27
  },
27
28
  responseType: 'json'
28
29
  });
30
+ const body = Types.asObject(response.data, {
31
+ name: 'response.data'
32
+ });
29
33
  return {
30
- reference: response.data.reference,
34
+ reference: new Reference(Types.asString(body.reference, {
35
+ name: 'reference'
36
+ })),
31
37
  tagUid: response.headers['swarm-tag'] ? makeTagUid(response.headers['swarm-tag']) : undefined,
32
- historyAddress: response.headers['swarm-act-history-address'] || ''
38
+ historyAddress: response.headers['swarm-act-history-address'] ? Optional.of(new Reference(response.headers['swarm-act-history-address'])) : Optional.empty()
33
39
  };
34
40
  }
35
41
  /**
@@ -39,10 +45,12 @@ export async function upload(requestOptions, data, stamp, options) {
39
45
  * @param hash Bee content reference
40
46
  *
41
47
  */
42
- export async function download(requestOptions, hash) {
48
+ export async function download(requestOptions, reference, options) {
49
+ reference = new Reference(reference);
43
50
  const response = await http(requestOptions, {
44
51
  responseType: 'arraybuffer',
45
- url: `${endpoint}/${hash}`
52
+ url: `${endpoint}/${reference}`,
53
+ headers: prepareRequestHeaders(null, options)
46
54
  });
47
- return wrapBytesWithHelpers(new Uint8Array(response.data));
55
+ return new Uint8Array(response.data);
48
56
  }