@helia/unixfs 4.0.2 → 4.0.3-325b36f
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/dist/index.min.js +1 -1
- package/dist/src/commands/add.d.ts +7 -6
- package/dist/src/commands/add.d.ts.map +1 -1
- package/dist/src/commands/add.js +35 -13
- package/dist/src/commands/add.js.map +1 -1
- package/dist/src/commands/stat.d.ts +3 -2
- package/dist/src/commands/stat.d.ts.map +1 -1
- package/dist/src/commands/stat.js +125 -63
- package/dist/src/commands/stat.js.map +1 -1
- package/dist/src/commands/utils/add-link.js +4 -4
- package/dist/src/commands/utils/add-link.js.map +1 -1
- package/dist/src/commands/utils/dir-sharded.js +1 -1
- package/dist/src/commands/utils/dir-sharded.js.map +1 -1
- package/dist/src/commands/utils/remove-link.js +1 -1
- package/dist/src/commands/utils/remove-link.js.map +1 -1
- package/dist/src/errors.js +1 -1
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +152 -30
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/unixfs.d.ts +4 -3
- package/dist/src/unixfs.d.ts.map +1 -1
- package/dist/src/unixfs.js.map +1 -1
- package/dist/src/utils/glob-source.d.ts +19 -0
- package/dist/src/utils/glob-source.d.ts.map +1 -1
- package/dist/src/utils/glob-source.js +19 -0
- package/dist/src/utils/glob-source.js.map +1 -1
- package/dist/src/utils/url-source.d.ts +48 -2
- package/dist/src/utils/url-source.d.ts.map +1 -1
- package/dist/src/utils/url-source.js +50 -0
- package/dist/src/utils/url-source.js.map +1 -1
- package/package.json +5 -4
- package/src/commands/add.ts +47 -17
- package/src/commands/stat.ts +149 -73
- package/src/commands/utils/add-link.ts +4 -4
- package/src/commands/utils/dir-sharded.ts +1 -1
- package/src/commands/utils/remove-link.ts +1 -1
- package/src/errors.ts +1 -1
- package/src/index.ts +163 -30
- package/src/unixfs.ts +5 -3
- package/src/utils/glob-source.ts +19 -0
- package/src/utils/url-source.ts +55 -2
- package/dist/typedoc-urls.json +0 -56
package/src/commands/add.ts
CHANGED
|
@@ -1,31 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { importBytes, importByteStream, importer } from 'ipfs-unixfs-importer'
|
|
2
2
|
import { fixedSize } from 'ipfs-unixfs-importer/chunker'
|
|
3
3
|
import { balanced } from 'ipfs-unixfs-importer/layout'
|
|
4
|
+
import first from 'it-first'
|
|
5
|
+
import last from 'it-last'
|
|
6
|
+
import { InvalidParametersError } from '../errors.js'
|
|
7
|
+
import type { FileCandidate, AddOptions, AddFileOptions } from '../index.js'
|
|
4
8
|
import type { PutStore } from '../unixfs.js'
|
|
9
|
+
import type { ByteStream, DirectoryCandidate, ImportCandidateStream, ImportResult } from 'ipfs-unixfs-importer'
|
|
5
10
|
import type { CID } from 'multiformats/cid'
|
|
6
11
|
|
|
7
12
|
/**
|
|
8
13
|
* Default importer settings match Filecoin
|
|
9
14
|
*/
|
|
10
|
-
const defaultImporterSettings:
|
|
15
|
+
const defaultImporterSettings: AddOptions = {
|
|
11
16
|
cidVersion: 1,
|
|
12
17
|
rawLeaves: true,
|
|
13
18
|
layout: balanced({
|
|
14
19
|
maxChildrenPerNode: 1024
|
|
15
20
|
}),
|
|
16
21
|
chunker: fixedSize({
|
|
17
|
-
chunkSize:
|
|
22
|
+
chunkSize: 1_048_576
|
|
18
23
|
})
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
export async function * addAll (source: ImportCandidateStream, blockstore: PutStore, options: Partial<
|
|
26
|
+
export async function * addAll (source: ImportCandidateStream, blockstore: PutStore, options: Partial<AddOptions> = {}): AsyncGenerator<ImportResult, void, unknown> {
|
|
22
27
|
yield * importer(source, blockstore, {
|
|
23
28
|
...defaultImporterSettings,
|
|
24
29
|
...options
|
|
25
30
|
})
|
|
26
31
|
}
|
|
27
32
|
|
|
28
|
-
export async function addBytes (bytes: Uint8Array, blockstore: PutStore, options: Partial<
|
|
33
|
+
export async function addBytes (bytes: Uint8Array, blockstore: PutStore, options: Partial<AddFileOptions> = {}): Promise<CID> {
|
|
29
34
|
const { cid } = await importBytes(bytes, blockstore, {
|
|
30
35
|
...defaultImporterSettings,
|
|
31
36
|
...options
|
|
@@ -34,7 +39,7 @@ export async function addBytes (bytes: Uint8Array, blockstore: PutStore, options
|
|
|
34
39
|
return cid
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
export async function addByteStream (bytes: ByteStream, blockstore: PutStore, options: Partial<
|
|
42
|
+
export async function addByteStream (bytes: ByteStream, blockstore: PutStore, options: Partial<AddFileOptions> = {}): Promise<CID> {
|
|
38
43
|
const { cid } = await importByteStream(bytes, blockstore, {
|
|
39
44
|
...defaultImporterSettings,
|
|
40
45
|
...options
|
|
@@ -43,23 +48,48 @@ export async function addByteStream (bytes: ByteStream, blockstore: PutStore, op
|
|
|
43
48
|
return cid
|
|
44
49
|
}
|
|
45
50
|
|
|
46
|
-
export async function addFile (file: FileCandidate, blockstore: PutStore, options: Partial<
|
|
47
|
-
|
|
51
|
+
export async function addFile (file: FileCandidate, blockstore: PutStore, options: Partial<AddFileOptions> = {}): Promise<CID> {
|
|
52
|
+
if (file.path == null) {
|
|
53
|
+
throw new InvalidParametersError('path is required')
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (file.content == null) {
|
|
57
|
+
throw new InvalidParametersError('content is required')
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const result = await last(addAll([file], blockstore, {
|
|
48
61
|
...defaultImporterSettings,
|
|
49
|
-
...options
|
|
50
|
-
|
|
62
|
+
...options,
|
|
63
|
+
wrapWithDirectory: true
|
|
64
|
+
}))
|
|
51
65
|
|
|
52
|
-
|
|
66
|
+
if (result == null) {
|
|
67
|
+
throw new InvalidParametersError('Nothing imported')
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return result.cid
|
|
53
71
|
}
|
|
54
72
|
|
|
55
|
-
export async function addDirectory (dir: Partial<DirectoryCandidate>, blockstore: PutStore, options: Partial<
|
|
56
|
-
|
|
73
|
+
export async function addDirectory (dir: Partial<DirectoryCandidate>, blockstore: PutStore, options: Partial<AddFileOptions> = {}): Promise<CID> {
|
|
74
|
+
// @ts-expect-error field is not in the types
|
|
75
|
+
if (dir.content != null) {
|
|
76
|
+
throw new InvalidParametersError('Directories cannot have content, use addFile instead')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const ord = dir.path == null ? first : last
|
|
80
|
+
|
|
81
|
+
const result = await ord(addAll([{
|
|
57
82
|
...dir,
|
|
58
83
|
path: dir.path ?? '-'
|
|
59
|
-
}, blockstore, {
|
|
84
|
+
}], blockstore, {
|
|
60
85
|
...defaultImporterSettings,
|
|
61
|
-
...options
|
|
62
|
-
|
|
86
|
+
...options,
|
|
87
|
+
wrapWithDirectory: dir.path != null
|
|
88
|
+
}))
|
|
63
89
|
|
|
64
|
-
|
|
90
|
+
if (result == null) {
|
|
91
|
+
throw new InvalidParametersError('Nothing imported')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return result.cid
|
|
65
95
|
}
|
package/src/commands/stat.ts
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import * as dagPb from '@ipld/dag-pb'
|
|
2
2
|
import { logger } from '@libp2p/logger'
|
|
3
|
+
import { ScalableCuckooFilter } from '@libp2p/utils/filters'
|
|
3
4
|
import { UnixFS } from 'ipfs-unixfs'
|
|
4
|
-
import { exporter } from 'ipfs-unixfs-exporter'
|
|
5
|
+
import { exporter, type RawNode, type UnixFSDirectory, type UnixFSFile } from 'ipfs-unixfs-exporter'
|
|
5
6
|
import mergeOpts from 'merge-options'
|
|
6
7
|
import * as raw from 'multiformats/codecs/raw'
|
|
7
8
|
import { InvalidPBNodeError, NotUnixFSError, UnknownError } from '../errors.js'
|
|
8
9
|
import { resolve } from './utils/resolve.js'
|
|
9
|
-
import type { StatOptions,
|
|
10
|
+
import type { ExtendedStatOptions, ExtendedDirectoryStats, ExtendedFileStats, StatOptions, DirectoryStats, FileStats, RawStats, ExtendedRawStats } from '../index.js'
|
|
10
11
|
import type { GetStore, HasStore } from '../unixfs.js'
|
|
11
|
-
import type {
|
|
12
|
-
import type { Mtime } from 'ipfs-unixfs'
|
|
12
|
+
import type { Filter } from '@libp2p/utils/filters'
|
|
13
13
|
import type { CID } from 'multiformats/cid'
|
|
14
14
|
|
|
15
|
+
// https://github.com/ipfs/specs/blob/main/UNIXFS.md#metadata
|
|
16
|
+
const DEFAULT_DIR_MODE = 0x755
|
|
17
|
+
const DEFAULT_FILE_MODE = 0x644
|
|
18
|
+
|
|
15
19
|
const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
|
|
16
20
|
const log = logger('helia:unixfs:stat')
|
|
17
21
|
|
|
@@ -19,7 +23,9 @@ const defaultOptions: StatOptions = {
|
|
|
19
23
|
|
|
20
24
|
}
|
|
21
25
|
|
|
22
|
-
export async function stat (cid: CID, blockstore: GetStore & HasStore, options
|
|
26
|
+
export async function stat (cid: CID, blockstore: GetStore & HasStore, options?: StatOptions): Promise<FileStats | DirectoryStats | RawStats>
|
|
27
|
+
export async function stat (cid: CID, blockstore: GetStore & HasStore, options?: ExtendedStatOptions): Promise<ExtendedFileStats | ExtendedDirectoryStats | ExtendedRawStats>
|
|
28
|
+
export async function stat (cid: CID, blockstore: GetStore & HasStore, options: Partial<ExtendedStatOptions> = {}): Promise<any> {
|
|
23
29
|
const opts: StatOptions = mergeOptions(defaultOptions, options)
|
|
24
30
|
const resolved = await resolve(cid, options.path, blockstore, opts)
|
|
25
31
|
|
|
@@ -27,116 +33,186 @@ export async function stat (cid: CID, blockstore: GetStore & HasStore, options:
|
|
|
27
33
|
|
|
28
34
|
const result = await exporter(resolved.cid, blockstore, opts)
|
|
29
35
|
|
|
30
|
-
if (result.type
|
|
31
|
-
|
|
36
|
+
if (result.type === 'raw') {
|
|
37
|
+
if (options.extended === true) {
|
|
38
|
+
return createExtendedRawStats(result)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return createRawStats(result)
|
|
42
|
+
} else if (result.type === 'file' || result.type === 'directory') {
|
|
43
|
+
if (options.extended === true) {
|
|
44
|
+
return createExtendedStats(result, blockstore, options.filter ?? new ScalableCuckooFilter({ filterSize: 1024 }), options)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return createStats(result)
|
|
32
48
|
}
|
|
33
49
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
let localFileSize: bigint = 0n
|
|
37
|
-
let localDagSize: bigint = 0n
|
|
38
|
-
let blocks: number = 0
|
|
39
|
-
let mode: number | undefined
|
|
40
|
-
let mtime: Mtime | undefined
|
|
41
|
-
const type = result.type
|
|
42
|
-
let unixfs: UnixFS | undefined
|
|
50
|
+
throw new NotUnixFSError()
|
|
51
|
+
}
|
|
43
52
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
function createStats (entry: UnixFSFile | UnixFSDirectory): FileStats | DirectoryStats {
|
|
54
|
+
return {
|
|
55
|
+
type: entry.type,
|
|
56
|
+
cid: entry.cid,
|
|
57
|
+
unixfs: entry.unixfs,
|
|
58
|
+
mode: entry.unixfs.mode ?? (entry.unixfs.isDirectory() ? DEFAULT_DIR_MODE : DEFAULT_FILE_MODE),
|
|
59
|
+
mtime: entry.unixfs.mtime,
|
|
60
|
+
size: entry.unixfs.fileSize()
|
|
50
61
|
}
|
|
62
|
+
}
|
|
51
63
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
unixfs
|
|
64
|
+
async function createExtendedStats (entry: UnixFSFile | UnixFSDirectory, blockstore: GetStore & HasStore, filter: Filter, options: StatOptions): Promise<ExtendedFileStats | ExtendedDirectoryStats> {
|
|
65
|
+
const stats = await inspectDag(entry.cid, blockstore, false, filter, options)
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
type: entry.type,
|
|
69
|
+
cid: entry.cid,
|
|
70
|
+
unixfs: entry.unixfs,
|
|
71
|
+
size: entry.unixfs.isDirectory() ? stats.dirSize : entry.unixfs.fileSize(),
|
|
72
|
+
mode: entry.unixfs.mode ?? (entry.unixfs.isDirectory() ? DEFAULT_DIR_MODE : DEFAULT_FILE_MODE),
|
|
73
|
+
mtime: entry.unixfs.mtime,
|
|
74
|
+
localSize: stats.localSize,
|
|
75
|
+
dagSize: stats.dagSize,
|
|
76
|
+
deduplicatedDagSize: stats.deduplicatedDagSize,
|
|
77
|
+
blocks: stats.blocks,
|
|
78
|
+
uniqueBlocks: stats.uniqueBlocks
|
|
61
79
|
}
|
|
80
|
+
}
|
|
62
81
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
mode = result.unixfs.mode
|
|
72
|
-
mtime = result.unixfs.mtime
|
|
73
|
-
unixfs = result.unixfs
|
|
82
|
+
function createRawStats (entry: RawNode): RawStats {
|
|
83
|
+
return {
|
|
84
|
+
type: entry.type,
|
|
85
|
+
cid: entry.cid,
|
|
86
|
+
unixfs: undefined,
|
|
87
|
+
mode: DEFAULT_FILE_MODE,
|
|
88
|
+
mtime: undefined,
|
|
89
|
+
size: BigInt(entry.node.byteLength)
|
|
74
90
|
}
|
|
91
|
+
}
|
|
75
92
|
|
|
93
|
+
function createExtendedRawStats (entry: RawNode): ExtendedRawStats {
|
|
76
94
|
return {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
95
|
+
type: entry.type,
|
|
96
|
+
cid: entry.cid,
|
|
97
|
+
unixfs: undefined,
|
|
98
|
+
mode: DEFAULT_FILE_MODE,
|
|
99
|
+
mtime: undefined,
|
|
100
|
+
size: BigInt(entry.node.byteLength),
|
|
101
|
+
localSize: BigInt(entry.node.byteLength),
|
|
102
|
+
dagSize: BigInt(entry.node.byteLength),
|
|
103
|
+
deduplicatedDagSize: BigInt(entry.node.byteLength),
|
|
104
|
+
blocks: 1n,
|
|
105
|
+
uniqueBlocks: 1n
|
|
87
106
|
}
|
|
88
107
|
}
|
|
89
108
|
|
|
90
109
|
interface InspectDagResults {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
110
|
+
dirSize: bigint
|
|
111
|
+
localSize: bigint
|
|
112
|
+
dagSize: bigint
|
|
113
|
+
deduplicatedDagSize: bigint
|
|
114
|
+
blocks: bigint
|
|
115
|
+
uniqueBlocks: bigint
|
|
94
116
|
}
|
|
95
117
|
|
|
96
|
-
async function inspectDag (cid: CID, blockstore: GetStore & HasStore, options:
|
|
97
|
-
const results = {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
118
|
+
async function inspectDag (cid: CID, blockstore: GetStore & HasStore, isFile: boolean, filter: Filter, options: StatOptions): Promise<InspectDagResults> {
|
|
119
|
+
const results: InspectDagResults = {
|
|
120
|
+
dirSize: 0n,
|
|
121
|
+
localSize: 0n,
|
|
122
|
+
dagSize: 0n,
|
|
123
|
+
deduplicatedDagSize: 0n,
|
|
124
|
+
blocks: 0n,
|
|
125
|
+
uniqueBlocks: 0n
|
|
101
126
|
}
|
|
102
127
|
|
|
103
|
-
|
|
128
|
+
try {
|
|
129
|
+
const alreadyTraversed = filter.has(cid.bytes)
|
|
130
|
+
filter.add(cid.bytes)
|
|
131
|
+
|
|
104
132
|
const block = await blockstore.get(cid, options)
|
|
105
133
|
results.blocks++
|
|
106
|
-
results.
|
|
134
|
+
results.dagSize += BigInt(block.byteLength)
|
|
135
|
+
|
|
136
|
+
if (!alreadyTraversed) {
|
|
137
|
+
results.uniqueBlocks++
|
|
138
|
+
results.deduplicatedDagSize += BigInt(block.byteLength)
|
|
139
|
+
}
|
|
107
140
|
|
|
108
141
|
if (cid.code === raw.code) {
|
|
109
|
-
results.
|
|
142
|
+
results.localSize += BigInt(block.byteLength)
|
|
143
|
+
|
|
144
|
+
if (isFile) {
|
|
145
|
+
results.dirSize += BigInt(block.byteLength)
|
|
146
|
+
}
|
|
110
147
|
} else if (cid.code === dagPb.code) {
|
|
111
148
|
const pbNode = dagPb.decode(block)
|
|
112
149
|
|
|
150
|
+
let unixfs: UnixFS | undefined
|
|
151
|
+
|
|
152
|
+
if (pbNode.Data != null) {
|
|
153
|
+
unixfs = UnixFS.unmarshal(pbNode.Data)
|
|
154
|
+
}
|
|
155
|
+
|
|
113
156
|
if (pbNode.Links.length > 0) {
|
|
114
157
|
// intermediate node
|
|
115
158
|
for (const link of pbNode.Links) {
|
|
116
|
-
const linkResult = await inspectDag(link.Hash, blockstore, options)
|
|
159
|
+
const linkResult = await inspectDag(link.Hash, blockstore, linkIsFile(link, unixfs), filter, options)
|
|
117
160
|
|
|
118
|
-
results.
|
|
119
|
-
results.
|
|
161
|
+
results.localSize += linkResult.localSize
|
|
162
|
+
results.dagSize += linkResult.dagSize
|
|
163
|
+
results.deduplicatedDagSize += linkResult.deduplicatedDagSize
|
|
120
164
|
results.blocks += linkResult.blocks
|
|
165
|
+
results.uniqueBlocks += linkResult.uniqueBlocks
|
|
166
|
+
results.dirSize += linkResult.dirSize
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// multi-block file node
|
|
170
|
+
if (isFile && unixfs != null) {
|
|
171
|
+
results.dirSize += unixfs.fileSize()
|
|
121
172
|
}
|
|
122
173
|
} else {
|
|
123
|
-
|
|
124
|
-
if (pbNode.Data == null) {
|
|
174
|
+
if (unixfs == null) {
|
|
125
175
|
throw new InvalidPBNodeError(`PBNode ${cid.toString()} had no data`)
|
|
126
176
|
}
|
|
127
177
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
throw new InvalidPBNodeError(`UnixFS node ${cid.toString()} had no data`)
|
|
178
|
+
// multi-block file leaf node
|
|
179
|
+
if (unixfs.data != null) {
|
|
180
|
+
results.localSize += BigInt(unixfs.data.byteLength ?? 0)
|
|
132
181
|
}
|
|
133
182
|
|
|
134
|
-
|
|
183
|
+
// single-block file node
|
|
184
|
+
if (isFile) {
|
|
185
|
+
results.dirSize += unixfs.fileSize()
|
|
186
|
+
}
|
|
135
187
|
}
|
|
136
188
|
} else {
|
|
137
189
|
throw new UnknownError(`${cid.toString()} was neither DAG_PB nor RAW`)
|
|
138
190
|
}
|
|
191
|
+
} catch (err: any) {
|
|
192
|
+
if (err.name !== 'NotFoundError' || options.offline !== true) {
|
|
193
|
+
throw err
|
|
194
|
+
}
|
|
139
195
|
}
|
|
140
196
|
|
|
141
197
|
return results
|
|
142
198
|
}
|
|
199
|
+
|
|
200
|
+
function linkIsFile (link: dagPb.PBLink, parent?: UnixFS): boolean {
|
|
201
|
+
if (parent == null) {
|
|
202
|
+
return false
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const name = link.Name
|
|
206
|
+
|
|
207
|
+
if (name == null) {
|
|
208
|
+
return false
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (parent.type === 'directory') {
|
|
212
|
+
return true
|
|
213
|
+
} else if (parent.type === 'hamt-sharded-directory' && name.length > 2) {
|
|
214
|
+
return true
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return false
|
|
218
|
+
}
|
|
@@ -165,7 +165,7 @@ const addToShardedDirectory = async (parent: Directory, child: Required<PBLink>,
|
|
|
165
165
|
throw new AlreadyExistsError()
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
log('overwriting %s in
|
|
168
|
+
log('overwriting %s in sub-shard', child.Name)
|
|
169
169
|
finalSegment.node.Links = finalSegment.node.Links.filter(l => l.Name !== linkName)
|
|
170
170
|
finalSegment.node.Links.push({
|
|
171
171
|
Name: linkName,
|
|
@@ -173,10 +173,10 @@ const addToShardedDirectory = async (parent: Directory, child: Required<PBLink>,
|
|
|
173
173
|
Tsize: child.Tsize
|
|
174
174
|
})
|
|
175
175
|
} else if (existingLink.Name?.length === 2) {
|
|
176
|
-
throw new Error('Existing link was
|
|
176
|
+
throw new Error('Existing link was sub-shard?!')
|
|
177
177
|
} else {
|
|
178
178
|
// conflict, add a new HAMT segment
|
|
179
|
-
log('prefix %s already exists, creating new
|
|
179
|
+
log('prefix %s already exists, creating new sub-shard', prefix)
|
|
180
180
|
// find the sibling we are going to replace
|
|
181
181
|
const index = finalSegment.node.Links.findIndex(l => l.Name?.startsWith(prefix))
|
|
182
182
|
const sibling = finalSegment.node.Links.splice(index, 1)[0]
|
|
@@ -186,7 +186,7 @@ const addToShardedDirectory = async (parent: Directory, child: Required<PBLink>,
|
|
|
186
186
|
const wrapped = wrapHash(hamtHashFn)
|
|
187
187
|
const siblingHash = wrapped(uint8ArrayFromString(siblingName))
|
|
188
188
|
|
|
189
|
-
// discard hash bits until we reach the
|
|
189
|
+
// discard hash bits until we reach the sub-shard depth
|
|
190
190
|
for (let i = 0; i < path.length; i++) {
|
|
191
191
|
await siblingHash.take(hamtBucketBits)
|
|
192
192
|
}
|
|
@@ -161,7 +161,7 @@ async function * flush (bucket: Bucket<Dir | InProgressImportResult>, blockstore
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
if (shard == null) {
|
|
164
|
-
throw new Error('Could not flush sharded directory, no
|
|
164
|
+
throw new Error('Could not flush sharded directory, no sub-shard found')
|
|
165
165
|
}
|
|
166
166
|
|
|
167
167
|
links.push({
|
|
@@ -96,7 +96,7 @@ const removeFromShardedDirectory = async (parent: Directory, name: string, block
|
|
|
96
96
|
finalSegment.children.unset(index)
|
|
97
97
|
|
|
98
98
|
if (finalSegment.node.Links.length === 1) {
|
|
99
|
-
// replace the
|
|
99
|
+
// replace the sub-shard with the last remaining file in the parent
|
|
100
100
|
while (true) {
|
|
101
101
|
if (path.length === 1) {
|
|
102
102
|
break
|
package/src/errors.ts
CHANGED
|
@@ -18,7 +18,7 @@ export class NotUnixFSError extends UnixFSError {
|
|
|
18
18
|
|
|
19
19
|
export class InvalidPBNodeError extends UnixFSError {
|
|
20
20
|
constructor (message = 'invalid PBNode') {
|
|
21
|
-
super(message, 'InvalidPBNodeError', '
|
|
21
|
+
super(message, 'InvalidPBNodeError', 'ERR_INVALID_PB_NODE')
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|