@helia/unixfs 0.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.
Files changed (104) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +53 -0
  3. package/dist/index.min.js +3 -0
  4. package/dist/src/commands/add.d.ts +6 -0
  5. package/dist/src/commands/add.d.ts.map +1 -0
  6. package/dist/src/commands/add.js +38 -0
  7. package/dist/src/commands/add.js.map +1 -0
  8. package/dist/src/commands/cat.d.ts +5 -0
  9. package/dist/src/commands/cat.d.ts.map +1 -0
  10. package/dist/src/commands/cat.js +22 -0
  11. package/dist/src/commands/cat.js.map +1 -0
  12. package/dist/src/commands/chmod.d.ts +5 -0
  13. package/dist/src/commands/chmod.d.ts.map +1 -0
  14. package/dist/src/commands/chmod.js +108 -0
  15. package/dist/src/commands/chmod.js.map +1 -0
  16. package/dist/src/commands/cp.d.ts +5 -0
  17. package/dist/src/commands/cp.d.ts.map +1 -0
  18. package/dist/src/commands/cp.js +28 -0
  19. package/dist/src/commands/cp.js.map +1 -0
  20. package/dist/src/commands/ls.d.ts +5 -0
  21. package/dist/src/commands/ls.d.ts.map +1 -0
  22. package/dist/src/commands/ls.js +26 -0
  23. package/dist/src/commands/ls.js.map +1 -0
  24. package/dist/src/commands/mkdir.d.ts +5 -0
  25. package/dist/src/commands/mkdir.d.ts.map +1 -0
  26. package/dist/src/commands/mkdir.js +53 -0
  27. package/dist/src/commands/mkdir.js.map +1 -0
  28. package/dist/src/commands/rm.d.ts +5 -0
  29. package/dist/src/commands/rm.d.ts.map +1 -0
  30. package/dist/src/commands/rm.js +19 -0
  31. package/dist/src/commands/rm.js.map +1 -0
  32. package/dist/src/commands/stat.d.ts +5 -0
  33. package/dist/src/commands/stat.d.ts.map +1 -0
  34. package/dist/src/commands/stat.js +108 -0
  35. package/dist/src/commands/stat.js.map +1 -0
  36. package/dist/src/commands/touch.d.ts +5 -0
  37. package/dist/src/commands/touch.d.ts.map +1 -0
  38. package/dist/src/commands/touch.js +111 -0
  39. package/dist/src/commands/touch.js.map +1 -0
  40. package/dist/src/commands/utils/add-link.d.ts +21 -0
  41. package/dist/src/commands/utils/add-link.d.ts.map +1 -0
  42. package/dist/src/commands/utils/add-link.js +224 -0
  43. package/dist/src/commands/utils/add-link.js.map +1 -0
  44. package/dist/src/commands/utils/cid-to-directory.d.ts +10 -0
  45. package/dist/src/commands/utils/cid-to-directory.d.ts.map +1 -0
  46. package/dist/src/commands/utils/cid-to-directory.js +13 -0
  47. package/dist/src/commands/utils/cid-to-directory.js.map +1 -0
  48. package/dist/src/commands/utils/cid-to-pblink.d.ts +6 -0
  49. package/dist/src/commands/utils/cid-to-pblink.d.ts.map +1 -0
  50. package/dist/src/commands/utils/cid-to-pblink.js +19 -0
  51. package/dist/src/commands/utils/cid-to-pblink.js.map +1 -0
  52. package/dist/src/commands/utils/dir-sharded.d.ts +67 -0
  53. package/dist/src/commands/utils/dir-sharded.d.ts.map +1 -0
  54. package/dist/src/commands/utils/dir-sharded.js +136 -0
  55. package/dist/src/commands/utils/dir-sharded.js.map +1 -0
  56. package/dist/src/commands/utils/errors.d.ts +17 -0
  57. package/dist/src/commands/utils/errors.d.ts.map +1 -0
  58. package/dist/src/commands/utils/errors.js +27 -0
  59. package/dist/src/commands/utils/errors.js.map +1 -0
  60. package/dist/src/commands/utils/hamt-constants.d.ts +4 -0
  61. package/dist/src/commands/utils/hamt-constants.d.ts.map +1 -0
  62. package/dist/src/commands/utils/hamt-constants.js +13 -0
  63. package/dist/src/commands/utils/hamt-constants.js.map +1 -0
  64. package/dist/src/commands/utils/hamt-utils.d.ts +37 -0
  65. package/dist/src/commands/utils/hamt-utils.d.ts.map +1 -0
  66. package/dist/src/commands/utils/hamt-utils.js +202 -0
  67. package/dist/src/commands/utils/hamt-utils.js.map +1 -0
  68. package/dist/src/commands/utils/persist.d.ts +10 -0
  69. package/dist/src/commands/utils/persist.d.ts.map +1 -0
  70. package/dist/src/commands/utils/persist.js +12 -0
  71. package/dist/src/commands/utils/persist.js.map +1 -0
  72. package/dist/src/commands/utils/remove-link.d.ts +11 -0
  73. package/dist/src/commands/utils/remove-link.d.ts.map +1 -0
  74. package/dist/src/commands/utils/remove-link.js +92 -0
  75. package/dist/src/commands/utils/remove-link.js.map +1 -0
  76. package/dist/src/commands/utils/resolve.d.ts +28 -0
  77. package/dist/src/commands/utils/resolve.d.ts.map +1 -0
  78. package/dist/src/commands/utils/resolve.js +85 -0
  79. package/dist/src/commands/utils/resolve.js.map +1 -0
  80. package/dist/src/index.d.ts +97 -0
  81. package/dist/src/index.d.ts.map +1 -0
  82. package/dist/src/index.js +48 -0
  83. package/dist/src/index.js.map +1 -0
  84. package/package.json +166 -0
  85. package/src/commands/add.ts +46 -0
  86. package/src/commands/cat.ts +31 -0
  87. package/src/commands/chmod.ts +133 -0
  88. package/src/commands/cp.ts +41 -0
  89. package/src/commands/ls.ts +36 -0
  90. package/src/commands/mkdir.ts +71 -0
  91. package/src/commands/rm.ts +31 -0
  92. package/src/commands/stat.ts +137 -0
  93. package/src/commands/touch.ts +136 -0
  94. package/src/commands/utils/add-link.ts +319 -0
  95. package/src/commands/utils/cid-to-directory.ts +23 -0
  96. package/src/commands/utils/cid-to-pblink.ts +26 -0
  97. package/src/commands/utils/dir-sharded.ts +219 -0
  98. package/src/commands/utils/errors.ts +31 -0
  99. package/src/commands/utils/hamt-constants.ts +14 -0
  100. package/src/commands/utils/hamt-utils.ts +285 -0
  101. package/src/commands/utils/persist.ts +22 -0
  102. package/src/commands/utils/remove-link.ts +151 -0
  103. package/src/commands/utils/resolve.ts +130 -0
  104. package/src/index.ts +174 -0
@@ -0,0 +1,48 @@
1
+ import { add, addStream } from './commands/add.js';
2
+ import { cat } from './commands/cat.js';
3
+ import { mkdir } from './commands/mkdir.js';
4
+ import { cp } from './commands/cp.js';
5
+ import { rm } from './commands/rm.js';
6
+ import { stat } from './commands/stat.js';
7
+ import { touch } from './commands/touch.js';
8
+ import { chmod } from './commands/chmod.js';
9
+ import { ls } from './commands/ls.js';
10
+ class DefaultUnixFS {
11
+ constructor(components) {
12
+ this.components = components;
13
+ }
14
+ async add(source, options = {}) {
15
+ return await add(source, this.components.blockstore, options);
16
+ }
17
+ async *addStream(source, options = {}) {
18
+ yield* addStream(source, this.components.blockstore, options);
19
+ }
20
+ async *cat(cid, options = {}) {
21
+ yield* cat(cid, this.components.blockstore, options);
22
+ }
23
+ async chmod(source, mode, options = {}) {
24
+ return await chmod(source, mode, this.components.blockstore, options);
25
+ }
26
+ async cp(source, target, name, options = {}) {
27
+ return await cp(source, target, name, this.components.blockstore, options);
28
+ }
29
+ async *ls(cid, options = {}) {
30
+ yield* ls(cid, this.components.blockstore, options);
31
+ }
32
+ async mkdir(cid, dirname, options = {}) {
33
+ return await mkdir(cid, dirname, this.components.blockstore, options);
34
+ }
35
+ async rm(cid, path, options = {}) {
36
+ return await rm(cid, path, this.components.blockstore, options);
37
+ }
38
+ async stat(cid, options = {}) {
39
+ return await stat(cid, this.components.blockstore, options);
40
+ }
41
+ async touch(cid, options = {}) {
42
+ return await touch(cid, this.components.blockstore, options);
43
+ }
44
+ }
45
+ export function unixfs(helia) {
46
+ return new DefaultUnixFS(helia);
47
+ }
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,166 @@
1
+ {
2
+ "name": "@helia/unixfs",
3
+ "version": "0.0.0",
4
+ "description": "A Helia-compatible wrapper for UnixFS",
5
+ "license": "Apache-2.0 OR MIT",
6
+ "homepage": "https://github.com/ipfs/helia/tree/master/packages/unixfs#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/ipfs/helia.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/ipfs/helia/issues"
13
+ },
14
+ "keywords": [
15
+ "IPFS"
16
+ ],
17
+ "engines": {
18
+ "node": ">=16.0.0",
19
+ "npm": ">=7.0.0"
20
+ },
21
+ "type": "module",
22
+ "types": "./dist/src/index.d.ts",
23
+ "files": [
24
+ "src",
25
+ "dist",
26
+ "!dist/test",
27
+ "!**/*.tsbuildinfo"
28
+ ],
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/src/index.d.ts",
32
+ "import": "./dist/src/index.js"
33
+ }
34
+ },
35
+ "eslintConfig": {
36
+ "extends": "ipfs",
37
+ "parserOptions": {
38
+ "sourceType": "module"
39
+ }
40
+ },
41
+ "release": {
42
+ "branches": [
43
+ "main"
44
+ ],
45
+ "plugins": [
46
+ [
47
+ "@semantic-release/commit-analyzer",
48
+ {
49
+ "preset": "conventionalcommits",
50
+ "releaseRules": [
51
+ {
52
+ "breaking": true,
53
+ "release": "major"
54
+ },
55
+ {
56
+ "revert": true,
57
+ "release": "patch"
58
+ },
59
+ {
60
+ "type": "feat",
61
+ "release": "minor"
62
+ },
63
+ {
64
+ "type": "fix",
65
+ "release": "patch"
66
+ },
67
+ {
68
+ "type": "docs",
69
+ "release": "patch"
70
+ },
71
+ {
72
+ "type": "test",
73
+ "release": "patch"
74
+ },
75
+ {
76
+ "type": "deps",
77
+ "release": "patch"
78
+ },
79
+ {
80
+ "scope": "no-release",
81
+ "release": false
82
+ }
83
+ ]
84
+ }
85
+ ],
86
+ [
87
+ "@semantic-release/release-notes-generator",
88
+ {
89
+ "preset": "conventionalcommits",
90
+ "presetConfig": {
91
+ "types": [
92
+ {
93
+ "type": "feat",
94
+ "section": "Features"
95
+ },
96
+ {
97
+ "type": "fix",
98
+ "section": "Bug Fixes"
99
+ },
100
+ {
101
+ "type": "chore",
102
+ "section": "Trivial Changes"
103
+ },
104
+ {
105
+ "type": "docs",
106
+ "section": "Documentation"
107
+ },
108
+ {
109
+ "type": "deps",
110
+ "section": "Dependencies"
111
+ },
112
+ {
113
+ "type": "test",
114
+ "section": "Tests"
115
+ }
116
+ ]
117
+ }
118
+ }
119
+ ],
120
+ "@semantic-release/changelog",
121
+ "@semantic-release/npm",
122
+ "@semantic-release/github",
123
+ "@semantic-release/git"
124
+ ]
125
+ },
126
+ "scripts": {
127
+ "clean": "aegir clean",
128
+ "lint": "aegir lint",
129
+ "dep-check": "aegir dep-check",
130
+ "build": "aegir build",
131
+ "docs": "aegir docs",
132
+ "test": "aegir test",
133
+ "test:chrome": "aegir test -t browser --cov",
134
+ "test:chrome-webworker": "aegir test -t webworker",
135
+ "test:firefox": "aegir test -t browser -- --browser firefox",
136
+ "test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
137
+ "test:node": "aegir test -t node --cov",
138
+ "test:electron-main": "aegir test -t electron-main",
139
+ "release": "aegir release"
140
+ },
141
+ "dependencies": {
142
+ "@helia/interface": "next",
143
+ "@ipld/dag-pb": "^4.0.0",
144
+ "@libp2p/interfaces": "^3.3.1",
145
+ "@libp2p/logger": "^2.0.5",
146
+ "@multiformats/murmur3": "^2.1.2",
147
+ "hamt-sharding": "^3.0.2",
148
+ "interface-blockstore": "^4.0.1",
149
+ "ipfs-unixfs": "^9.0.0",
150
+ "ipfs-unixfs-exporter": "^10.0.0",
151
+ "ipfs-unixfs-importer": "^12.0.0",
152
+ "it-last": "^2.0.0",
153
+ "it-pipe": "^2.0.5",
154
+ "merge-options": "^3.0.4",
155
+ "multiformats": "^11.0.1"
156
+ },
157
+ "devDependencies": {
158
+ "aegir": "^38.1.0",
159
+ "blockstore-core": "^3.0.0",
160
+ "delay": "^5.0.0",
161
+ "it-all": "^2.0.0",
162
+ "it-drain": "^2.0.0",
163
+ "it-to-buffer": "^3.0.0",
164
+ "uint8arrays": "^4.0.3"
165
+ }
166
+ }
@@ -0,0 +1,46 @@
1
+ import type { Blockstore } from 'interface-blockstore'
2
+ import { ImportCandidate, importer, ImportResult, UserImporterOptions } from 'ipfs-unixfs-importer'
3
+ import last from 'it-last'
4
+ import type { CID } from 'multiformats/cid'
5
+ import { UnknownError } from './utils/errors.js'
6
+
7
+ function isIterable (obj: any): obj is Iterator<Uint8Array> {
8
+ return obj[Symbol.iterator] != null
9
+ }
10
+
11
+ function isAsyncIterable (obj: any): obj is AsyncIterator<Uint8Array> {
12
+ return obj[Symbol.asyncIterator] != null
13
+ }
14
+
15
+ export async function add (source: Uint8Array | Iterator<Uint8Array> | AsyncIterator<Uint8Array> | ImportCandidate, blockstore: Blockstore, options: UserImporterOptions = {}): Promise<CID> {
16
+ let importCandidate: ImportCandidate
17
+
18
+ if (source instanceof Uint8Array || isIterable(source) || isAsyncIterable(source)) {
19
+ importCandidate = {
20
+ // @ts-expect-error FIXME: work out types
21
+ content: source
22
+ }
23
+ } else {
24
+ importCandidate = source
25
+ }
26
+
27
+ const result = await last(importer(importCandidate, blockstore, {
28
+ cidVersion: 1,
29
+ rawLeaves: true,
30
+ ...options
31
+ }))
32
+
33
+ if (result == null) {
34
+ throw new UnknownError('Could not import')
35
+ }
36
+
37
+ return result.cid
38
+ }
39
+
40
+ export async function * addStream (source: Iterable<ImportCandidate> | AsyncIterable<ImportCandidate>, blockstore: Blockstore, options: UserImporterOptions = {}): AsyncGenerator<ImportResult> {
41
+ yield * importer(source, blockstore, {
42
+ cidVersion: 1,
43
+ rawLeaves: true,
44
+ ...options
45
+ })
46
+ }
@@ -0,0 +1,31 @@
1
+ import { NoContentError, NotAFileError } from '@helia/interface/errors'
2
+ import { Blockstore, exporter } from 'ipfs-unixfs-exporter'
3
+ import type { CID } from 'multiformats/cid'
4
+ import type { CatOptions } from '../index.js'
5
+ import { resolve } from './utils/resolve.js'
6
+ import mergeOpts from 'merge-options'
7
+
8
+ const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
9
+
10
+ const defaultOptions: CatOptions = {
11
+
12
+ }
13
+
14
+ export async function * cat (cid: CID, blockstore: Blockstore, options: Partial<CatOptions> = {}): AsyncIterable<Uint8Array> {
15
+ const opts: CatOptions = mergeOptions(defaultOptions, options)
16
+ const resolved = await resolve(cid, opts.path, blockstore, opts)
17
+ const result = await exporter(resolved.cid, blockstore, opts)
18
+
19
+ if (result.type !== 'file' && result.type !== 'raw') {
20
+ throw new NotAFileError()
21
+ }
22
+
23
+ if (result.content == null) {
24
+ throw new NoContentError()
25
+ }
26
+
27
+ yield * result.content({
28
+ offset: opts.offset,
29
+ length: opts.length
30
+ })
31
+ }
@@ -0,0 +1,133 @@
1
+ import { recursive } from 'ipfs-unixfs-exporter'
2
+ import { CID } from 'multiformats/cid'
3
+ import type { ChmodOptions } from '../index.js'
4
+ import mergeOpts from 'merge-options'
5
+ import { logger } from '@libp2p/logger'
6
+ import { UnixFS } from 'ipfs-unixfs'
7
+ import { pipe } from 'it-pipe'
8
+ import { InvalidPBNodeError, NotUnixFSError, UnknownError } from './utils/errors.js'
9
+ import * as dagPB from '@ipld/dag-pb'
10
+ import type { PBNode, PBLink } from '@ipld/dag-pb'
11
+ import { importer } from 'ipfs-unixfs-importer'
12
+ import { persist } from './utils/persist.js'
13
+ import type { Blockstore } from 'interface-blockstore'
14
+ import last from 'it-last'
15
+ import { sha256 } from 'multiformats/hashes/sha2'
16
+ import { resolve, updatePathCids } from './utils/resolve.js'
17
+ import * as raw from 'multiformats/codecs/raw'
18
+
19
+ const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
20
+ const log = logger('helia:unixfs:chmod')
21
+
22
+ const defaultOptions: ChmodOptions = {
23
+ recursive: false
24
+ }
25
+
26
+ export async function chmod (cid: CID, mode: number, blockstore: Blockstore, options: Partial<ChmodOptions> = {}): Promise<CID> {
27
+ const opts: ChmodOptions = mergeOptions(defaultOptions, options)
28
+ const resolved = await resolve(cid, opts.path, blockstore, options)
29
+
30
+ log('chmod %c %d', resolved.cid, mode)
31
+
32
+ if (opts.recursive) {
33
+ // recursively export from root CID, change perms of each entry then reimport
34
+ // but do not reimport files, only manipulate dag-pb nodes
35
+ const root = await pipe(
36
+ async function * () {
37
+ for await (const entry of recursive(resolved.cid, blockstore)) {
38
+ let metadata: UnixFS
39
+ let links: PBLink[] = []
40
+
41
+ if (entry.type === 'raw') {
42
+ // convert to UnixFS
43
+ metadata = new UnixFS({ type: 'file', data: entry.node })
44
+ } else if (entry.type === 'file' || entry.type === 'directory') {
45
+ metadata = entry.unixfs
46
+ links = entry.node.Links
47
+ } else {
48
+ throw new NotUnixFSError()
49
+ }
50
+
51
+ metadata.mode = mode
52
+
53
+ const node = {
54
+ Data: metadata.marshal(),
55
+ Links: links
56
+ }
57
+
58
+ yield {
59
+ path: entry.path,
60
+ content: node
61
+ }
62
+ }
63
+ },
64
+ // @ts-expect-error we account for the incompatible source type with our custom dag builder below
65
+ (source) => importer(source, blockstore, {
66
+ ...opts,
67
+ pin: false,
68
+ dagBuilder: async function * (source, block, opts) {
69
+ for await (const entry of source) {
70
+ yield async function () {
71
+ // @ts-expect-error cannot derive type
72
+ const node: PBNode = entry.content
73
+
74
+ const buf = dagPB.encode(node)
75
+ const cid = await persist(buf, block, opts)
76
+
77
+ if (node.Data == null) {
78
+ throw new InvalidPBNodeError(`${cid} had no data`)
79
+ }
80
+
81
+ const unixfs = UnixFS.unmarshal(node.Data)
82
+
83
+ return {
84
+ cid,
85
+ size: buf.length,
86
+ path: entry.path,
87
+ unixfs
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }),
93
+ async (nodes) => await last(nodes)
94
+ )
95
+
96
+ if (root == null) {
97
+ throw new UnknownError(`Could not chmod ${resolved.cid.toString()}`)
98
+ }
99
+
100
+ return await updatePathCids(root.cid, resolved, blockstore, options)
101
+ }
102
+
103
+ const block = await blockstore.get(resolved.cid)
104
+ let metadata: UnixFS
105
+ let links: PBLink[] = []
106
+
107
+ if (resolved.cid.code === raw.code) {
108
+ // convert to UnixFS
109
+ metadata = new UnixFS({ type: 'file', data: block })
110
+ } else {
111
+ const node = dagPB.decode(block)
112
+
113
+ if (node.Data == null) {
114
+ throw new InvalidPBNodeError(`${resolved.cid.toString()} had no data`)
115
+ }
116
+
117
+ links = node.Links
118
+ metadata = UnixFS.unmarshal(node.Data)
119
+ }
120
+
121
+ metadata.mode = mode
122
+ const updatedBlock = dagPB.encode({
123
+ Data: metadata.marshal(),
124
+ Links: links
125
+ })
126
+
127
+ const hash = await sha256.digest(updatedBlock)
128
+ const updatedCid = CID.create(resolved.cid.version, dagPB.code, hash)
129
+
130
+ await blockstore.put(updatedCid, updatedBlock)
131
+
132
+ return await updatePathCids(updatedCid, resolved, blockstore, options)
133
+ }
@@ -0,0 +1,41 @@
1
+ import { InvalidParametersError } from '@helia/interface/errors'
2
+ import type { Blockstore } from 'ipfs-unixfs-exporter'
3
+ import type { CID } from 'multiformats/cid'
4
+ import type { CpOptions } from '../index.js'
5
+ import mergeOpts from 'merge-options'
6
+ import { logger } from '@libp2p/logger'
7
+ import { addLink } from './utils/add-link.js'
8
+ import { cidToPBLink } from './utils/cid-to-pblink.js'
9
+ import { cidToDirectory } from './utils/cid-to-directory.js'
10
+
11
+ const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
12
+ const log = logger('helia:unixfs:cp')
13
+
14
+ const defaultOptions = {
15
+ force: false
16
+ }
17
+
18
+ export async function cp (source: CID, target: CID, name: string, blockstore: Blockstore, options: Partial<CpOptions> = {}): Promise<CID> {
19
+ const opts: CpOptions = mergeOptions(defaultOptions, options)
20
+
21
+ if (name.includes('/')) {
22
+ throw new InvalidParametersError('Name must not have slashes')
23
+ }
24
+
25
+ const [
26
+ directory,
27
+ pblink
28
+ ] = await Promise.all([
29
+ cidToDirectory(target, blockstore, opts),
30
+ cidToPBLink(source, name, blockstore, opts)
31
+ ])
32
+
33
+ log('Adding %c as "%s" to %c', source, name, target)
34
+
35
+ const result = await addLink(directory, pblink, blockstore, {
36
+ allowOverwriting: opts.force,
37
+ ...opts
38
+ })
39
+
40
+ return result.cid
41
+ }
@@ -0,0 +1,36 @@
1
+ import { NoContentError, NotADirectoryError } from '@helia/interface/errors'
2
+ import { Blockstore, exporter, UnixFSEntry } from 'ipfs-unixfs-exporter'
3
+ import type { CID } from 'multiformats/cid'
4
+ import type { LsOptions } from '../index.js'
5
+ import { resolve } from './utils/resolve.js'
6
+ import mergeOpts from 'merge-options'
7
+
8
+ const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
9
+
10
+ const defaultOptions = {
11
+
12
+ }
13
+
14
+ export async function * ls (cid: CID, blockstore: Blockstore, options: Partial<LsOptions> = {}): AsyncIterable<UnixFSEntry> {
15
+ const opts: LsOptions = mergeOptions(defaultOptions, options)
16
+ const resolved = await resolve(cid, opts.path, blockstore, opts)
17
+ const result = await exporter(resolved.cid, blockstore)
18
+
19
+ if (result.type === 'file' || result.type === 'raw') {
20
+ yield result
21
+ return
22
+ }
23
+
24
+ if (result.content == null) {
25
+ throw new NoContentError()
26
+ }
27
+
28
+ if (result.type !== 'directory') {
29
+ throw new NotADirectoryError()
30
+ }
31
+
32
+ yield * result.content({
33
+ offset: options.offset,
34
+ length: options.length
35
+ })
36
+ }
@@ -0,0 +1,71 @@
1
+ import { InvalidParametersError, NotADirectoryError } from '@helia/interface/errors'
2
+ import { CID } from 'multiformats/cid'
3
+ import mergeOpts from 'merge-options'
4
+ import { logger } from '@libp2p/logger'
5
+ import type { MkdirOptions } from '../index.js'
6
+ import * as dagPB from '@ipld/dag-pb'
7
+ import { addLink } from './utils/add-link.js'
8
+ import type { Blockstore } from 'interface-blockstore'
9
+ import { UnixFS } from 'ipfs-unixfs'
10
+ import { sha256 } from 'multiformats/hashes/sha2'
11
+ import { exporter } from 'ipfs-unixfs-exporter'
12
+ import { cidToDirectory } from './utils/cid-to-directory.js'
13
+ import { cidToPBLink } from './utils/cid-to-pblink.js'
14
+
15
+ const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
16
+ const log = logger('helia:unixfs:mkdir')
17
+
18
+ const defaultOptions = {
19
+ cidVersion: 1,
20
+ force: false
21
+ }
22
+
23
+ export async function mkdir (parentCid: CID, dirname: string, blockstore: Blockstore, options: Partial<MkdirOptions> = {}): Promise<CID> {
24
+ const opts: MkdirOptions = mergeOptions(defaultOptions, options)
25
+
26
+ if (dirname.includes('/')) {
27
+ throw new InvalidParametersError('Path must not have slashes')
28
+ }
29
+
30
+ const entry = await exporter(parentCid, blockstore, options)
31
+
32
+ if (entry.type !== 'directory') {
33
+ throw new NotADirectoryError(`${parentCid.toString()} was not a UnixFS directory`)
34
+ }
35
+
36
+ log('creating %s', dirname)
37
+
38
+ const metadata = new UnixFS({
39
+ type: 'directory',
40
+ mode: opts.mode,
41
+ mtime: opts.mtime
42
+ })
43
+
44
+ // Persist the new parent PBNode
45
+ const node = {
46
+ Data: metadata.marshal(),
47
+ Links: []
48
+ }
49
+ const buf = dagPB.encode(node)
50
+ const hash = await sha256.digest(buf)
51
+ const emptyDirCid = CID.create(opts.cidVersion, dagPB.code, hash)
52
+
53
+ await blockstore.put(emptyDirCid, buf)
54
+
55
+ const [
56
+ directory,
57
+ pblink
58
+ ] = await Promise.all([
59
+ cidToDirectory(parentCid, blockstore, opts),
60
+ cidToPBLink(emptyDirCid, dirname, blockstore, opts)
61
+ ])
62
+
63
+ log('adding empty dir called %s to %c', dirname, parentCid)
64
+
65
+ const result = await addLink(directory, pblink, blockstore, {
66
+ ...opts,
67
+ allowOverwriting: opts.force
68
+ })
69
+
70
+ return result.cid
71
+ }
@@ -0,0 +1,31 @@
1
+ import { InvalidParametersError } from '@helia/interface/errors'
2
+ import type { Blockstore } from 'ipfs-unixfs-exporter'
3
+ import type { CID } from 'multiformats/cid'
4
+ import type { RmOptions } from '../index.js'
5
+ import mergeOpts from 'merge-options'
6
+ import { logger } from '@libp2p/logger'
7
+ import { removeLink } from './utils/remove-link.js'
8
+ import { cidToDirectory } from './utils/cid-to-directory.js'
9
+
10
+ const mergeOptions = mergeOpts.bind({ ignoreUndefined: true })
11
+ const log = logger('helia:unixfs:rm')
12
+
13
+ const defaultOptions = {
14
+
15
+ }
16
+
17
+ export async function rm (target: CID, name: string, blockstore: Blockstore, options: Partial<RmOptions> = {}): Promise<CID> {
18
+ const opts: RmOptions = mergeOptions(defaultOptions, options)
19
+
20
+ if (name.includes('/')) {
21
+ throw new InvalidParametersError('Name must not have slashes')
22
+ }
23
+
24
+ const directory = await cidToDirectory(target, blockstore, opts)
25
+
26
+ log('Removing %s from %c', name, target)
27
+
28
+ const result = await removeLink(directory, name, blockstore, opts)
29
+
30
+ return result.cid
31
+ }