@helia/unixfs 0.0.0 → 1.0.0
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/README.md +10 -4
- package/dist/index.min.js +1 -1
- package/dist/src/commands/cat.d.ts +1 -1
- package/dist/src/commands/cat.d.ts.map +1 -1
- package/dist/src/commands/cat.js +1 -1
- package/dist/src/commands/cat.js.map +1 -1
- package/dist/src/commands/chmod.d.ts.map +1 -1
- package/dist/src/commands/chmod.js +12 -7
- package/dist/src/commands/chmod.js.map +1 -1
- package/dist/src/commands/cp.d.ts +1 -1
- package/dist/src/commands/cp.d.ts.map +1 -1
- package/dist/src/commands/cp.js +5 -2
- package/dist/src/commands/cp.js.map +1 -1
- package/dist/src/commands/ls.d.ts +2 -1
- package/dist/src/commands/ls.d.ts.map +1 -1
- package/dist/src/commands/ls.js +1 -1
- package/dist/src/commands/ls.js.map +1 -1
- package/dist/src/commands/mkdir.d.ts.map +1 -1
- package/dist/src/commands/mkdir.js +4 -2
- package/dist/src/commands/mkdir.js.map +1 -1
- package/dist/src/commands/rm.d.ts +1 -1
- package/dist/src/commands/rm.d.ts.map +1 -1
- package/dist/src/commands/rm.js +9 -3
- package/dist/src/commands/rm.js.map +1 -1
- package/dist/src/commands/stat.d.ts +1 -1
- package/dist/src/commands/stat.d.ts.map +1 -1
- package/dist/src/commands/stat.js +19 -15
- package/dist/src/commands/stat.js.map +1 -1
- package/dist/src/commands/touch.d.ts.map +1 -1
- package/dist/src/commands/touch.js +13 -8
- package/dist/src/commands/touch.js.map +1 -1
- package/dist/src/commands/utils/add-link.d.ts +4 -2
- package/dist/src/commands/utils/add-link.d.ts.map +1 -1
- package/dist/src/commands/utils/add-link.js +24 -24
- package/dist/src/commands/utils/add-link.js.map +1 -1
- package/dist/src/commands/utils/cid-to-directory.d.ts +3 -3
- package/dist/src/commands/utils/cid-to-directory.d.ts.map +1 -1
- package/dist/src/commands/utils/cid-to-directory.js +1 -1
- package/dist/src/commands/utils/cid-to-directory.js.map +1 -1
- package/dist/src/commands/utils/cid-to-pblink.d.ts +3 -3
- package/dist/src/commands/utils/cid-to-pblink.d.ts.map +1 -1
- package/dist/src/commands/utils/cid-to-pblink.js.map +1 -1
- package/dist/src/commands/utils/constants.d.ts +2 -0
- package/dist/src/commands/utils/constants.d.ts.map +1 -0
- package/dist/src/commands/utils/constants.js +2 -0
- package/dist/src/commands/utils/constants.js.map +1 -0
- package/dist/src/commands/utils/dir-sharded.d.ts +47 -41
- package/dist/src/commands/utils/dir-sharded.d.ts.map +1 -1
- package/dist/src/commands/utils/dir-sharded.js +99 -15
- package/dist/src/commands/utils/dir-sharded.js.map +1 -1
- package/dist/src/commands/utils/errors.d.ts +22 -6
- package/dist/src/commands/utils/errors.d.ts.map +1 -1
- package/dist/src/commands/utils/errors.js +34 -8
- package/dist/src/commands/utils/errors.js.map +1 -1
- package/dist/src/commands/utils/hamt-constants.d.ts +1 -1
- package/dist/src/commands/utils/hamt-constants.d.ts.map +1 -1
- package/dist/src/commands/utils/hamt-constants.js +1 -1
- package/dist/src/commands/utils/hamt-constants.js.map +1 -1
- package/dist/src/commands/utils/hamt-utils.d.ts +15 -12
- package/dist/src/commands/utils/hamt-utils.d.ts.map +1 -1
- package/dist/src/commands/utils/hamt-utils.js +40 -39
- package/dist/src/commands/utils/hamt-utils.js.map +1 -1
- package/dist/src/commands/utils/is-over-shard-threshold.d.ts +10 -0
- package/dist/src/commands/utils/is-over-shard-threshold.d.ts.map +1 -0
- package/dist/src/commands/utils/is-over-shard-threshold.js +62 -0
- package/dist/src/commands/utils/is-over-shard-threshold.js.map +1 -0
- package/dist/src/commands/utils/persist.d.ts +7 -6
- package/dist/src/commands/utils/persist.d.ts.map +1 -1
- package/dist/src/commands/utils/persist.js +6 -3
- package/dist/src/commands/utils/persist.js.map +1 -1
- package/dist/src/commands/utils/remove-link.d.ts +6 -2
- package/dist/src/commands/utils/remove-link.d.ts.map +1 -1
- package/dist/src/commands/utils/remove-link.js +143 -55
- package/dist/src/commands/utils/remove-link.js.map +1 -1
- package/dist/src/commands/utils/resolve.d.ts +6 -3
- package/dist/src/commands/utils/resolve.d.ts.map +1 -1
- package/dist/src/commands/utils/resolve.js +4 -4
- package/dist/src/commands/utils/resolve.js.map +1 -1
- package/dist/src/index.d.ts +14 -7
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +0 -7
- package/dist/src/index.js.map +1 -1
- package/dist/typedoc-urls.json +14 -0
- package/package.json +8 -7
- package/src/commands/cat.ts +3 -2
- package/src/commands/chmod.ts +12 -7
- package/src/commands/cp.ts +7 -4
- package/src/commands/ls.ts +4 -3
- package/src/commands/mkdir.ts +5 -3
- package/src/commands/rm.ts +9 -5
- package/src/commands/stat.ts +22 -17
- package/src/commands/touch.ts +14 -9
- package/src/commands/utils/add-link.ts +32 -31
- package/src/commands/utils/cid-to-directory.ts +4 -4
- package/src/commands/utils/cid-to-pblink.ts +3 -3
- package/src/commands/utils/constants.ts +2 -0
- package/src/commands/utils/dir-sharded.ts +162 -63
- package/src/commands/utils/errors.ts +42 -8
- package/src/commands/utils/hamt-constants.ts +1 -1
- package/src/commands/utils/hamt-utils.ts +59 -50
- package/src/commands/utils/is-over-shard-threshold.ts +78 -0
- package/src/commands/utils/persist.ts +13 -8
- package/src/commands/utils/remove-link.ts +178 -77
- package/src/commands/utils/resolve.ts +12 -7
- package/src/index.ts +15 -17
- package/dist/src/commands/add.d.ts +0 -6
- package/dist/src/commands/add.d.ts.map +0 -1
- package/dist/src/commands/add.js +0 -38
- package/dist/src/commands/add.js.map +0 -1
- package/src/commands/add.ts +0 -46
package/src/commands/cp.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { Blockstore } from 'ipfs-unixfs-exporter'
|
|
1
|
+
import type { Blockstore } from 'interface-blockstore'
|
|
3
2
|
import type { CID } from 'multiformats/cid'
|
|
4
3
|
import type { CpOptions } from '../index.js'
|
|
5
4
|
import mergeOpts from 'merge-options'
|
|
@@ -7,12 +6,15 @@ import { logger } from '@libp2p/logger'
|
|
|
7
6
|
import { addLink } from './utils/add-link.js'
|
|
8
7
|
import { cidToPBLink } from './utils/cid-to-pblink.js'
|
|
9
8
|
import { cidToDirectory } from './utils/cid-to-directory.js'
|
|
9
|
+
import { SHARD_SPLIT_THRESHOLD_BYTES } from './utils/constants.js'
|
|
10
|
+
import { InvalidParametersError } from './utils/errors.js'
|
|
10
11
|
|
|
11
12
|
const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
|
|
12
13
|
const log = logger('helia:unixfs:cp')
|
|
13
14
|
|
|
14
|
-
const defaultOptions = {
|
|
15
|
-
force: false
|
|
15
|
+
const defaultOptions: CpOptions = {
|
|
16
|
+
force: false,
|
|
17
|
+
shardSplitThresholdBytes: SHARD_SPLIT_THRESHOLD_BYTES
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
export async function cp (source: CID, target: CID, name: string, blockstore: Blockstore, options: Partial<CpOptions> = {}): Promise<CID> {
|
|
@@ -34,6 +36,7 @@ export async function cp (source: CID, target: CID, name: string, blockstore: Bl
|
|
|
34
36
|
|
|
35
37
|
const result = await addLink(directory, pblink, blockstore, {
|
|
36
38
|
allowOverwriting: opts.force,
|
|
39
|
+
cidVersion: target.version,
|
|
37
40
|
...opts
|
|
38
41
|
})
|
|
39
42
|
|
package/src/commands/ls.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Blockstore, exporter, UnixFSEntry } from 'ipfs-unixfs-exporter'
|
|
1
|
+
import { exporter, UnixFSEntry } from 'ipfs-unixfs-exporter'
|
|
3
2
|
import type { CID } from 'multiformats/cid'
|
|
4
3
|
import type { LsOptions } from '../index.js'
|
|
5
4
|
import { resolve } from './utils/resolve.js'
|
|
6
5
|
import mergeOpts from 'merge-options'
|
|
6
|
+
import type { Blockstore } from 'interface-blockstore'
|
|
7
|
+
import { NoContentError, NotADirectoryError } from './utils/errors.js'
|
|
7
8
|
|
|
8
9
|
const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
|
|
9
10
|
|
|
10
|
-
const defaultOptions = {
|
|
11
|
+
const defaultOptions: LsOptions = {
|
|
11
12
|
|
|
12
13
|
}
|
|
13
14
|
|
package/src/commands/mkdir.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { InvalidParametersError, NotADirectoryError } from '@helia/interface/errors'
|
|
2
1
|
import { CID } from 'multiformats/cid'
|
|
3
2
|
import mergeOpts from 'merge-options'
|
|
4
3
|
import { logger } from '@libp2p/logger'
|
|
@@ -11,13 +10,16 @@ import { sha256 } from 'multiformats/hashes/sha2'
|
|
|
11
10
|
import { exporter } from 'ipfs-unixfs-exporter'
|
|
12
11
|
import { cidToDirectory } from './utils/cid-to-directory.js'
|
|
13
12
|
import { cidToPBLink } from './utils/cid-to-pblink.js'
|
|
13
|
+
import { SHARD_SPLIT_THRESHOLD_BYTES } from './utils/constants.js'
|
|
14
|
+
import { InvalidParametersError, NotADirectoryError } from './utils/errors.js'
|
|
14
15
|
|
|
15
16
|
const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
|
|
16
17
|
const log = logger('helia:unixfs:mkdir')
|
|
17
18
|
|
|
18
|
-
const defaultOptions = {
|
|
19
|
+
const defaultOptions: MkdirOptions = {
|
|
19
20
|
cidVersion: 1,
|
|
20
|
-
force: false
|
|
21
|
+
force: false,
|
|
22
|
+
shardSplitThresholdBytes: SHARD_SPLIT_THRESHOLD_BYTES
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
export async function mkdir (parentCid: CID, dirname: string, blockstore: Blockstore, options: Partial<MkdirOptions> = {}): Promise<CID> {
|
package/src/commands/rm.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { Blockstore } from 'ipfs-unixfs-exporter'
|
|
1
|
+
import type { Blockstore } from 'interface-blockstore'
|
|
3
2
|
import type { CID } from 'multiformats/cid'
|
|
4
3
|
import type { RmOptions } from '../index.js'
|
|
5
4
|
import mergeOpts from 'merge-options'
|
|
6
5
|
import { logger } from '@libp2p/logger'
|
|
7
6
|
import { removeLink } from './utils/remove-link.js'
|
|
8
7
|
import { cidToDirectory } from './utils/cid-to-directory.js'
|
|
8
|
+
import { SHARD_SPLIT_THRESHOLD_BYTES } from './utils/constants.js'
|
|
9
|
+
import { InvalidParametersError } from './utils/errors.js'
|
|
9
10
|
|
|
10
11
|
const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
|
|
11
12
|
const log = logger('helia:unixfs:rm')
|
|
12
13
|
|
|
13
|
-
const defaultOptions = {
|
|
14
|
-
|
|
14
|
+
const defaultOptions: RmOptions = {
|
|
15
|
+
shardSplitThresholdBytes: SHARD_SPLIT_THRESHOLD_BYTES
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export async function rm (target: CID, name: string, blockstore: Blockstore, options: Partial<RmOptions> = {}): Promise<CID> {
|
|
@@ -25,7 +26,10 @@ export async function rm (target: CID, name: string, blockstore: Blockstore, opt
|
|
|
25
26
|
|
|
26
27
|
log('Removing %s from %c', name, target)
|
|
27
28
|
|
|
28
|
-
const result = await removeLink(directory, name, blockstore,
|
|
29
|
+
const result = await removeLink(directory, name, blockstore, {
|
|
30
|
+
...opts,
|
|
31
|
+
cidVersion: target.version
|
|
32
|
+
})
|
|
29
33
|
|
|
30
34
|
return result.cid
|
|
31
35
|
}
|
package/src/commands/stat.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { exporter } from 'ipfs-unixfs-exporter'
|
|
2
2
|
import type { CID } from 'multiformats/cid'
|
|
3
3
|
import type { StatOptions, UnixFSStats } from '../index.js'
|
|
4
4
|
import mergeOpts from 'merge-options'
|
|
@@ -10,11 +10,12 @@ import type { AbortOptions } from '@libp2p/interfaces'
|
|
|
10
10
|
import type { Mtime } from 'ipfs-unixfs'
|
|
11
11
|
import { resolve } from './utils/resolve.js'
|
|
12
12
|
import * as raw from 'multiformats/codecs/raw'
|
|
13
|
+
import type { Blockstore } from 'interface-blockstore'
|
|
13
14
|
|
|
14
15
|
const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
|
|
15
16
|
const log = logger('helia:unixfs:stat')
|
|
16
17
|
|
|
17
|
-
const defaultOptions = {
|
|
18
|
+
const defaultOptions: StatOptions = {
|
|
18
19
|
|
|
19
20
|
}
|
|
20
21
|
|
|
@@ -30,43 +31,46 @@ export async function stat (cid: CID, blockstore: Blockstore, options: Partial<S
|
|
|
30
31
|
throw new NotUnixFSError()
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
let fileSize:
|
|
34
|
-
let dagSize:
|
|
35
|
-
let localFileSize:
|
|
36
|
-
let localDagSize:
|
|
34
|
+
let fileSize: bigint = 0n
|
|
35
|
+
let dagSize: bigint = 0n
|
|
36
|
+
let localFileSize: bigint = 0n
|
|
37
|
+
let localDagSize: bigint = 0n
|
|
37
38
|
let blocks: number = 0
|
|
38
39
|
let mode: number | undefined
|
|
39
40
|
let mtime: Mtime | undefined
|
|
40
41
|
const type = result.type
|
|
42
|
+
let unixfs: UnixFS | undefined
|
|
41
43
|
|
|
42
44
|
if (result.type === 'raw') {
|
|
43
|
-
fileSize = result.node.byteLength
|
|
44
|
-
dagSize = result.node.byteLength
|
|
45
|
-
localFileSize = result.node.byteLength
|
|
46
|
-
localDagSize = result.node.byteLength
|
|
45
|
+
fileSize = BigInt(result.node.byteLength)
|
|
46
|
+
dagSize = BigInt(result.node.byteLength)
|
|
47
|
+
localFileSize = BigInt(result.node.byteLength)
|
|
48
|
+
localDagSize = BigInt(result.node.byteLength)
|
|
47
49
|
blocks = 1
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
if (result.type === 'directory') {
|
|
51
|
-
fileSize =
|
|
52
|
-
dagSize = result.unixfs.marshal().byteLength
|
|
53
|
-
localFileSize =
|
|
53
|
+
fileSize = 0n
|
|
54
|
+
dagSize = BigInt(result.unixfs.marshal().byteLength)
|
|
55
|
+
localFileSize = 0n
|
|
54
56
|
localDagSize = dagSize
|
|
55
57
|
blocks = 1
|
|
56
58
|
mode = result.unixfs.mode
|
|
57
59
|
mtime = result.unixfs.mtime
|
|
60
|
+
unixfs = result.unixfs
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
if (result.type === 'file') {
|
|
61
64
|
const results = await inspectDag(resolved.cid, blockstore, opts)
|
|
62
65
|
|
|
63
66
|
fileSize = result.unixfs.fileSize()
|
|
64
|
-
dagSize = (result.node.Data?.byteLength ?? 0) + result.node.Links.reduce((acc, curr) => acc + (curr.Tsize ?? 0), 0)
|
|
65
|
-
localFileSize = results.localFileSize
|
|
66
|
-
localDagSize = results.localDagSize
|
|
67
|
+
dagSize = BigInt((result.node.Data?.byteLength ?? 0) + result.node.Links.reduce((acc, curr) => acc + (curr.Tsize ?? 0), 0))
|
|
68
|
+
localFileSize = BigInt(results.localFileSize)
|
|
69
|
+
localDagSize = BigInt(results.localDagSize)
|
|
67
70
|
blocks = results.blocks
|
|
68
71
|
mode = result.unixfs.mode
|
|
69
72
|
mtime = result.unixfs.mtime
|
|
73
|
+
unixfs = result.unixfs
|
|
70
74
|
}
|
|
71
75
|
|
|
72
76
|
return {
|
|
@@ -78,7 +82,8 @@ export async function stat (cid: CID, blockstore: Blockstore, options: Partial<S
|
|
|
78
82
|
localFileSize,
|
|
79
83
|
localDagSize,
|
|
80
84
|
blocks,
|
|
81
|
-
type
|
|
85
|
+
type,
|
|
86
|
+
unixfs
|
|
82
87
|
}
|
|
83
88
|
}
|
|
84
89
|
|
package/src/commands/touch.ts
CHANGED
|
@@ -15,19 +15,21 @@ import last from 'it-last'
|
|
|
15
15
|
import { sha256 } from 'multiformats/hashes/sha2'
|
|
16
16
|
import { resolve, updatePathCids } from './utils/resolve.js'
|
|
17
17
|
import * as raw from 'multiformats/codecs/raw'
|
|
18
|
+
import { SHARD_SPLIT_THRESHOLD_BYTES } from './utils/constants.js'
|
|
18
19
|
|
|
19
20
|
const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
|
|
20
21
|
const log = logger('helia:unixfs:touch')
|
|
21
22
|
|
|
22
|
-
const defaultOptions = {
|
|
23
|
-
recursive: false
|
|
23
|
+
const defaultOptions: TouchOptions = {
|
|
24
|
+
recursive: false,
|
|
25
|
+
shardSplitThresholdBytes: SHARD_SPLIT_THRESHOLD_BYTES
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
export async function touch (cid: CID, blockstore: Blockstore, options: Partial<TouchOptions> = {}): Promise<CID> {
|
|
27
29
|
const opts: TouchOptions = mergeOptions(defaultOptions, options)
|
|
28
30
|
const resolved = await resolve(cid, opts.path, blockstore, opts)
|
|
29
31
|
const mtime = opts.mtime ?? {
|
|
30
|
-
secs: Date.now() / 1000,
|
|
32
|
+
secs: BigInt(Math.round(Date.now() / 1000)),
|
|
31
33
|
nsecs: 0
|
|
32
34
|
}
|
|
33
35
|
|
|
@@ -69,23 +71,26 @@ export async function touch (cid: CID, blockstore: Blockstore, options: Partial<
|
|
|
69
71
|
(source) => importer(source, blockstore, {
|
|
70
72
|
...opts,
|
|
71
73
|
pin: false,
|
|
72
|
-
dagBuilder: async function * (source, block
|
|
74
|
+
dagBuilder: async function * (source, block) {
|
|
73
75
|
for await (const entry of source) {
|
|
74
76
|
yield async function () {
|
|
75
77
|
// @ts-expect-error cannot derive type
|
|
76
78
|
const node: PBNode = entry.content
|
|
77
79
|
|
|
78
80
|
const buf = dagPB.encode(node)
|
|
79
|
-
const
|
|
81
|
+
const updatedCid = await persist(buf, block, {
|
|
82
|
+
...opts,
|
|
83
|
+
cidVersion: cid.version
|
|
84
|
+
})
|
|
80
85
|
|
|
81
86
|
if (node.Data == null) {
|
|
82
|
-
throw new InvalidPBNodeError(`${
|
|
87
|
+
throw new InvalidPBNodeError(`${updatedCid} had no data`)
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
const unixfs = UnixFS.unmarshal(node.Data)
|
|
86
91
|
|
|
87
92
|
return {
|
|
88
|
-
cid,
|
|
93
|
+
cid: updatedCid,
|
|
89
94
|
size: buf.length,
|
|
90
95
|
path: entry.path,
|
|
91
96
|
unixfs
|
|
@@ -101,7 +106,7 @@ export async function touch (cid: CID, blockstore: Blockstore, options: Partial<
|
|
|
101
106
|
throw new UnknownError(`Could not chmod ${resolved.cid.toString()}`)
|
|
102
107
|
}
|
|
103
108
|
|
|
104
|
-
return await updatePathCids(root.cid, resolved, blockstore,
|
|
109
|
+
return await updatePathCids(root.cid, resolved, blockstore, opts)
|
|
105
110
|
}
|
|
106
111
|
|
|
107
112
|
const block = await blockstore.get(resolved.cid)
|
|
@@ -132,5 +137,5 @@ export async function touch (cid: CID, blockstore: Blockstore, options: Partial<
|
|
|
132
137
|
|
|
133
138
|
await blockstore.put(updatedCid, updatedBlock)
|
|
134
139
|
|
|
135
|
-
return await updatePathCids(updatedCid, resolved, blockstore,
|
|
140
|
+
return await updatePathCids(updatedCid, resolved, blockstore, opts)
|
|
136
141
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as dagPB from '@ipld/dag-pb'
|
|
2
|
-
import { CID } from 'multiformats/cid'
|
|
2
|
+
import { CID, Version } from 'multiformats/cid'
|
|
3
3
|
import { logger } from '@libp2p/logger'
|
|
4
4
|
import { UnixFS } from 'ipfs-unixfs'
|
|
5
5
|
import { DirSharded } from './dir-sharded.js'
|
|
@@ -12,15 +12,15 @@ import {
|
|
|
12
12
|
addLinksToHamtBucket
|
|
13
13
|
} from './hamt-utils.js'
|
|
14
14
|
import last from 'it-last'
|
|
15
|
-
import type { Blockstore } from 'ipfs-unixfs-exporter'
|
|
16
15
|
import type { PBNode, PBLink } from '@ipld/dag-pb/interface'
|
|
17
16
|
import { sha256 } from 'multiformats/hashes/sha2'
|
|
18
17
|
import type { Bucket } from 'hamt-sharding'
|
|
19
|
-
import { AlreadyExistsError, InvalidPBNodeError } from './errors.js'
|
|
20
|
-
import { InvalidParametersError } from '@helia/interface/errors'
|
|
18
|
+
import { AlreadyExistsError, InvalidParametersError, InvalidPBNodeError } from './errors.js'
|
|
21
19
|
import type { ImportResult } from 'ipfs-unixfs-importer'
|
|
22
20
|
import type { AbortOptions } from '@libp2p/interfaces'
|
|
23
21
|
import type { Directory } from './cid-to-directory.js'
|
|
22
|
+
import type { Blockstore } from 'interface-blockstore'
|
|
23
|
+
import { isOverShardThreshold } from './is-over-shard-threshold.js'
|
|
24
24
|
|
|
25
25
|
const log = logger('helia:unixfs:components:utils:add-link')
|
|
26
26
|
|
|
@@ -32,6 +32,8 @@ export interface AddLinkResult {
|
|
|
32
32
|
|
|
33
33
|
export interface AddLinkOptions extends AbortOptions {
|
|
34
34
|
allowOverwriting: boolean
|
|
35
|
+
shardSplitThresholdBytes: number
|
|
36
|
+
cidVersion: Version
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
export async function addLink (parent: Directory, child: Required<PBLink>, blockstore: Blockstore, options: AddLinkOptions): Promise<AddLinkResult> {
|
|
@@ -39,19 +41,6 @@ export async function addLink (parent: Directory, child: Required<PBLink>, block
|
|
|
39
41
|
throw new InvalidParametersError('Invalid parent passed to addLink')
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
// FIXME: this should work on block size not number of links
|
|
43
|
-
if (parent.node.Links.length >= 1000) {
|
|
44
|
-
log('converting directory to sharded directory')
|
|
45
|
-
|
|
46
|
-
const result = await convertToShardedDirectory(parent, blockstore)
|
|
47
|
-
parent.cid = result.cid
|
|
48
|
-
parent.node = dagPB.decode(await blockstore.get(result.cid))
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (parent.node.Data == null) {
|
|
52
|
-
throw new InvalidParametersError('Invalid parent passed to addLink')
|
|
53
|
-
}
|
|
54
|
-
|
|
55
44
|
const meta = UnixFS.unmarshal(parent.node.Data)
|
|
56
45
|
|
|
57
46
|
if (meta.type === 'hamt-sharded-directory') {
|
|
@@ -62,7 +51,17 @@ export async function addLink (parent: Directory, child: Required<PBLink>, block
|
|
|
62
51
|
|
|
63
52
|
log(`adding ${child.Name} (${child.Hash}) to regular directory`)
|
|
64
53
|
|
|
65
|
-
|
|
54
|
+
const result = await addToDirectory(parent, child, blockstore, options)
|
|
55
|
+
|
|
56
|
+
if (await isOverShardThreshold(result.node, blockstore, options.shardSplitThresholdBytes)) {
|
|
57
|
+
log('converting directory to sharded directory')
|
|
58
|
+
|
|
59
|
+
const converted = await convertToShardedDirectory(result, blockstore)
|
|
60
|
+
result.cid = converted.cid
|
|
61
|
+
result.node = dagPB.decode(await blockstore.get(converted.cid))
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return result
|
|
66
65
|
}
|
|
67
66
|
|
|
68
67
|
const convertToShardedDirectory = async (parent: Directory, blockstore: Blockstore): Promise<ImportResult> => {
|
|
@@ -74,11 +73,12 @@ const convertToShardedDirectory = async (parent: Directory, blockstore: Blocksto
|
|
|
74
73
|
|
|
75
74
|
const result = await createShard(blockstore, parent.node.Links.map(link => ({
|
|
76
75
|
name: (link.Name ?? ''),
|
|
77
|
-
size: link.Tsize ?? 0,
|
|
76
|
+
size: BigInt(link.Tsize ?? 0),
|
|
78
77
|
cid: link.Hash
|
|
79
78
|
})), {
|
|
80
79
|
mode: unixfs.mode,
|
|
81
|
-
mtime: unixfs.mtime
|
|
80
|
+
mtime: unixfs.mtime,
|
|
81
|
+
cidVersion: parent.cid.version
|
|
82
82
|
})
|
|
83
83
|
|
|
84
84
|
log(`Converted directory to sharded directory ${result.cid}`)
|
|
@@ -112,7 +112,7 @@ const addToDirectory = async (parent: Directory, child: PBLink, blockstore: Bloc
|
|
|
112
112
|
const secs = Math.floor(ms / 1000)
|
|
113
113
|
|
|
114
114
|
node.mtime = {
|
|
115
|
-
secs,
|
|
115
|
+
secs: BigInt(secs),
|
|
116
116
|
nsecs: (ms - (secs * 1000)) * 1000
|
|
117
117
|
}
|
|
118
118
|
|
|
@@ -154,13 +154,7 @@ const addToShardedDirectory = async (parent: Directory, child: Required<PBLink>,
|
|
|
154
154
|
|
|
155
155
|
// we have written out the shard, but only one sub-shard will have been written so replace it in the original shard
|
|
156
156
|
const parentLinks = parent.node.Links.filter((link) => {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (matches && !options.allowOverwriting) {
|
|
160
|
-
throw new AlreadyExistsError()
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return !matches
|
|
157
|
+
return (link.Name ?? '').substring(0, 2) !== path[0].prefix
|
|
164
158
|
})
|
|
165
159
|
|
|
166
160
|
const newLink = node.Links
|
|
@@ -172,7 +166,10 @@ const addToShardedDirectory = async (parent: Directory, child: Required<PBLink>,
|
|
|
172
166
|
|
|
173
167
|
parentLinks.push(newLink)
|
|
174
168
|
|
|
175
|
-
return await updateHamtDirectory(
|
|
169
|
+
return await updateHamtDirectory({
|
|
170
|
+
Data: parent.node.Data,
|
|
171
|
+
Links: parentLinks
|
|
172
|
+
}, blockstore, path[0].bucket, options)
|
|
176
173
|
}
|
|
177
174
|
|
|
178
175
|
const addFileToShardedDirectory = async (parent: Directory, child: Required<PBLink>, blockstore: Blockstore, options: AddLinkOptions): Promise<{ shard: DirSharded, path: BucketPath[] }> => {
|
|
@@ -202,7 +199,7 @@ const addFileToShardedDirectory = async (parent: Directory, child: Required<PBLi
|
|
|
202
199
|
if (node.mtime != null) {
|
|
203
200
|
// update mtime if previously set
|
|
204
201
|
shard.mtime = {
|
|
205
|
-
secs: Math.round(Date.now() / 1000)
|
|
202
|
+
secs: BigInt(Math.round(Date.now() / 1000))
|
|
206
203
|
}
|
|
207
204
|
}
|
|
208
205
|
|
|
@@ -233,6 +230,10 @@ const addFileToShardedDirectory = async (parent: Directory, child: Required<PBLi
|
|
|
233
230
|
}
|
|
234
231
|
|
|
235
232
|
if (link.Name === `${segment.prefix}${child.Name}`) {
|
|
233
|
+
if (!options.allowOverwriting) {
|
|
234
|
+
throw new AlreadyExistsError()
|
|
235
|
+
}
|
|
236
|
+
|
|
236
237
|
// file already existed, file will be added to the current bucket
|
|
237
238
|
log(`Link ${segment.prefix}${child.Name} will be replaced`)
|
|
238
239
|
index = path.length
|
|
@@ -279,7 +280,7 @@ const addFileToShardedDirectory = async (parent: Directory, child: Required<PBLi
|
|
|
279
280
|
|
|
280
281
|
// finally add the new file into the shard
|
|
281
282
|
await shard._bucket.put(child.Name, {
|
|
282
|
-
size: child.Tsize,
|
|
283
|
+
size: BigInt(child.Tsize),
|
|
283
284
|
cid: child.Hash
|
|
284
285
|
})
|
|
285
286
|
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Blockstore, exporter } from 'ipfs-unixfs-exporter'
|
|
1
|
+
import { exporter, ExporterOptions } from 'ipfs-unixfs-exporter'
|
|
3
2
|
import type { CID } from 'multiformats/cid'
|
|
4
3
|
import type { PBNode } from '@ipld/dag-pb'
|
|
5
|
-
import type {
|
|
4
|
+
import type { Blockstore } from 'interface-blockstore'
|
|
5
|
+
import { NotADirectoryError } from './errors.js'
|
|
6
6
|
|
|
7
7
|
export interface Directory {
|
|
8
8
|
cid: CID
|
|
9
9
|
node: PBNode
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export async function cidToDirectory (cid: CID, blockstore: Blockstore, options:
|
|
12
|
+
export async function cidToDirectory (cid: CID, blockstore: Blockstore, options: ExporterOptions = {}): Promise<Directory> {
|
|
13
13
|
const entry = await exporter(cid, blockstore, options)
|
|
14
14
|
|
|
15
15
|
if (entry.type !== 'directory') {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { exporter, ExporterOptions } from 'ipfs-unixfs-exporter'
|
|
2
2
|
import type { CID } from 'multiformats/cid'
|
|
3
3
|
import { NotUnixFSError } from './errors.js'
|
|
4
4
|
import * as dagPb from '@ipld/dag-pb'
|
|
5
5
|
import type { PBNode, PBLink } from '@ipld/dag-pb'
|
|
6
|
-
import type {
|
|
6
|
+
import type { Blockstore } from 'interface-blockstore'
|
|
7
7
|
|
|
8
|
-
export async function cidToPBLink (cid: CID, name: string, blockstore: Blockstore, options?:
|
|
8
|
+
export async function cidToPBLink (cid: CID, name: string, blockstore: Blockstore, options?: ExporterOptions): Promise<Required<PBLink>> {
|
|
9
9
|
const sourceEntry = await exporter(cid, blockstore, options)
|
|
10
10
|
|
|
11
11
|
if (sourceEntry.type !== 'directory' && sourceEntry.type !== 'file' && sourceEntry.type !== 'raw') {
|