@helia/interop 3.0.1 → 4.0.0-e554493

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 (133) hide show
  1. package/.aegir.js +46 -0
  2. package/README.md +11 -0
  3. package/dist/src/bin.d.ts +3 -0
  4. package/dist/src/bin.d.ts.map +1 -0
  5. package/dist/src/bin.js +20 -0
  6. package/dist/src/bin.js.map +1 -0
  7. package/dist/src/car.spec.d.ts +2 -0
  8. package/dist/src/car.spec.d.ts.map +1 -0
  9. package/dist/src/car.spec.js +77 -0
  10. package/dist/src/car.spec.js.map +1 -0
  11. package/dist/src/dag-cbor.spec.d.ts +2 -0
  12. package/dist/src/dag-cbor.spec.d.ts.map +1 -0
  13. package/dist/src/dag-cbor.spec.js +49 -0
  14. package/dist/src/dag-cbor.spec.js.map +1 -0
  15. package/dist/src/dag-json.spec.d.ts +2 -0
  16. package/dist/src/dag-json.spec.d.ts.map +1 -0
  17. package/dist/src/dag-json.spec.js +49 -0
  18. package/dist/src/dag-json.spec.js.map +1 -0
  19. package/dist/src/fixtures/connect.d.ts +7 -0
  20. package/dist/src/fixtures/connect.d.ts.map +1 -0
  21. package/dist/src/fixtures/connect.js +17 -0
  22. package/dist/src/fixtures/connect.js.map +1 -0
  23. package/dist/src/fixtures/create-helia-http.d.ts +4 -0
  24. package/dist/src/fixtures/create-helia-http.d.ts.map +1 -0
  25. package/dist/src/fixtures/create-helia-http.js +7 -0
  26. package/dist/src/fixtures/create-helia-http.js.map +1 -0
  27. package/dist/src/fixtures/create-helia.browser.d.ts +6 -0
  28. package/dist/src/fixtures/create-helia.browser.d.ts.map +1 -0
  29. package/dist/src/fixtures/create-helia.browser.js +56 -0
  30. package/dist/src/fixtures/create-helia.browser.js.map +1 -0
  31. package/dist/src/fixtures/create-helia.d.ts +6 -0
  32. package/dist/src/fixtures/create-helia.d.ts.map +1 -0
  33. package/dist/src/fixtures/create-helia.js +46 -0
  34. package/dist/src/fixtures/create-helia.js.map +1 -0
  35. package/dist/src/fixtures/create-kubo.browser.d.ts +3 -0
  36. package/dist/src/fixtures/create-kubo.browser.d.ts.map +1 -0
  37. package/dist/src/fixtures/create-kubo.browser.js +30 -0
  38. package/dist/src/fixtures/create-kubo.browser.js.map +1 -0
  39. package/dist/src/fixtures/create-kubo.d.ts +3 -0
  40. package/dist/src/fixtures/create-kubo.d.ts.map +1 -0
  41. package/dist/src/fixtures/create-kubo.js +32 -0
  42. package/dist/src/fixtures/create-kubo.js.map +1 -0
  43. package/dist/src/fixtures/create-peer-ids.d.ts +14 -0
  44. package/dist/src/fixtures/create-peer-ids.d.ts.map +1 -0
  45. package/dist/src/fixtures/create-peer-ids.js +37 -0
  46. package/dist/src/fixtures/create-peer-ids.js.map +1 -0
  47. package/dist/src/fixtures/key-types.d.ts +3 -0
  48. package/dist/src/fixtures/key-types.d.ts.map +1 -0
  49. package/dist/src/fixtures/key-types.js +6 -0
  50. package/dist/src/fixtures/key-types.js.map +1 -0
  51. package/dist/src/fixtures/memory-car.d.ts +7 -0
  52. package/dist/src/fixtures/memory-car.d.ts.map +1 -0
  53. package/dist/src/fixtures/memory-car.js +26 -0
  54. package/dist/src/fixtures/memory-car.js.map +1 -0
  55. package/dist/src/fixtures/wait-for.d.ts +7 -0
  56. package/dist/src/fixtures/wait-for.d.ts.map +1 -0
  57. package/dist/src/fixtures/wait-for.js +17 -0
  58. package/dist/src/fixtures/wait-for.js.map +1 -0
  59. package/dist/src/helia-blockstore.spec.d.ts +2 -0
  60. package/dist/src/helia-blockstore.spec.d.ts.map +1 -0
  61. package/dist/src/helia-blockstore.spec.js +48 -0
  62. package/dist/src/helia-blockstore.spec.js.map +1 -0
  63. package/dist/src/helia-hashes.spec.d.ts +2 -0
  64. package/dist/src/helia-hashes.spec.d.ts.map +1 -0
  65. package/dist/src/helia-hashes.spec.js +50 -0
  66. package/dist/src/helia-hashes.spec.js.map +1 -0
  67. package/dist/src/helia-pins.spec.d.ts +2 -0
  68. package/dist/src/helia-pins.spec.d.ts.map +1 -0
  69. package/dist/src/helia-pins.spec.js +48 -0
  70. package/dist/src/helia-pins.spec.js.map +1 -0
  71. package/dist/src/index.d.ts +12 -0
  72. package/dist/src/index.d.ts.map +1 -1
  73. package/dist/src/index.js +12 -0
  74. package/dist/src/index.js.map +1 -1
  75. package/dist/src/ipns-http.spec.d.ts +2 -0
  76. package/dist/src/ipns-http.spec.d.ts.map +1 -0
  77. package/dist/src/ipns-http.spec.js +55 -0
  78. package/dist/src/ipns-http.spec.js.map +1 -0
  79. package/dist/src/ipns-pubsub.spec.d.ts +2 -0
  80. package/dist/src/ipns-pubsub.spec.d.ts.map +1 -0
  81. package/dist/src/ipns-pubsub.spec.js +151 -0
  82. package/dist/src/ipns-pubsub.spec.js.map +1 -0
  83. package/dist/src/ipns.spec.d.ts +2 -0
  84. package/dist/src/ipns.spec.d.ts.map +1 -0
  85. package/dist/src/ipns.spec.js +146 -0
  86. package/dist/src/ipns.spec.js.map +1 -0
  87. package/dist/src/json.spec.d.ts +2 -0
  88. package/dist/src/json.spec.d.ts.map +1 -0
  89. package/dist/src/json.spec.js +49 -0
  90. package/dist/src/json.spec.js.map +1 -0
  91. package/dist/src/mfs.spec.d.ts +2 -0
  92. package/dist/src/mfs.spec.d.ts.map +1 -0
  93. package/dist/src/mfs.spec.js +85 -0
  94. package/dist/src/mfs.spec.js.map +1 -0
  95. package/dist/src/strings.spec.d.ts +2 -0
  96. package/dist/src/strings.spec.d.ts.map +1 -0
  97. package/dist/src/strings.spec.js +51 -0
  98. package/dist/src/strings.spec.js.map +1 -0
  99. package/dist/src/unixfs-bitswap.spec.d.ts +2 -0
  100. package/dist/src/unixfs-bitswap.spec.d.ts.map +1 -0
  101. package/dist/src/unixfs-bitswap.spec.js +65 -0
  102. package/dist/src/unixfs-bitswap.spec.js.map +1 -0
  103. package/dist/src/unixfs-files.spec.d.ts +2 -0
  104. package/dist/src/unixfs-files.spec.d.ts.map +1 -0
  105. package/dist/src/unixfs-files.spec.js +69 -0
  106. package/dist/src/unixfs-files.spec.js.map +1 -0
  107. package/package.json +33 -20
  108. package/src/bin.ts +25 -0
  109. package/src/car.spec.ts +102 -0
  110. package/src/dag-cbor.spec.ts +65 -0
  111. package/src/dag-json.spec.ts +65 -0
  112. package/src/fixtures/connect.ts +19 -0
  113. package/src/fixtures/create-helia-http.ts +8 -0
  114. package/src/fixtures/create-helia.browser.ts +68 -0
  115. package/src/fixtures/create-helia.ts +55 -0
  116. package/src/fixtures/create-kubo.browser.ts +30 -0
  117. package/src/fixtures/create-kubo.ts +32 -0
  118. package/src/fixtures/create-peer-ids.ts +46 -0
  119. package/src/fixtures/key-types.ts +7 -0
  120. package/src/fixtures/memory-car.ts +33 -0
  121. package/src/fixtures/wait-for.ts +26 -0
  122. package/src/helia-blockstore.spec.ts +59 -0
  123. package/src/helia-hashes.spec.ts +61 -0
  124. package/src/helia-pins.spec.ts +64 -0
  125. package/src/index.ts +13 -0
  126. package/src/ipns-http.spec.ts +68 -0
  127. package/src/ipns-pubsub.spec.ts +187 -0
  128. package/src/ipns.spec.ts +183 -0
  129. package/src/json.spec.ts +65 -0
  130. package/src/mfs.spec.ts +105 -0
  131. package/src/strings.spec.ts +67 -0
  132. package/src/unixfs-bitswap.spec.ts +86 -0
  133. package/src/unixfs-files.spec.ts +89 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helia/interop",
3
- "version": "3.0.1",
3
+ "version": "4.0.0-e554493",
4
4
  "description": "Interop tests for Helia",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/ipfs/helia/tree/main/packages/interop#readme",
@@ -11,16 +11,24 @@
11
11
  "bugs": {
12
12
  "url": "https://github.com/ipfs/helia/issues"
13
13
  },
14
+ "publishConfig": {
15
+ "access": "public",
16
+ "provenance": true
17
+ },
14
18
  "keywords": [
15
19
  "IPFS"
16
20
  ],
21
+ "bin": {
22
+ "helia-interop": "./dist/src/bin.js"
23
+ },
17
24
  "type": "module",
18
25
  "types": "./dist/src/index.d.ts",
19
26
  "files": [
20
27
  "src",
21
28
  "dist",
22
29
  "!dist/test",
23
- "!**/*.tsbuildinfo"
30
+ "!**/*.tsbuildinfo",
31
+ ".aegir.js"
24
32
  ],
25
33
  "exports": {
26
34
  ".": {
@@ -48,28 +56,31 @@
48
56
  "test:node": "aegir test -t node --cov",
49
57
  "test:electron-main": "aegir test -t electron-main"
50
58
  },
51
- "devDependencies": {
52
- "@helia/block-brokers": "~1.0.0",
53
- "@helia/car": "^2.0.1",
54
- "@helia/dag-cbor": "^2.0.1",
55
- "@helia/dag-json": "^2.0.1",
56
- "@helia/interface": "^3.0.1",
57
- "@helia/ipns": "^4.0.0",
58
- "@helia/json": "^2.0.1",
59
- "@helia/mfs": "^2.0.1",
60
- "@helia/strings": "^2.0.1",
61
- "@helia/unixfs": "^2.0.1",
59
+ "dependencies": {
60
+ "@chainsafe/libp2p-gossipsub": "^11.1.0",
61
+ "@helia/block-brokers": "2.0.0-e554493",
62
+ "@helia/car": "3.0.0-e554493",
63
+ "@helia/dag-cbor": "3.0.0-e554493",
64
+ "@helia/dag-json": "3.0.0-e554493",
65
+ "@helia/http": "1.0.0-e554493",
66
+ "@helia/interface": "4.0.0-e554493",
67
+ "@helia/ipns": "5.0.0-e554493",
68
+ "@helia/json": "3.0.0-e554493",
69
+ "@helia/mfs": "3.0.0-e554493",
70
+ "@helia/routers": "1.0.0-e554493",
71
+ "@helia/strings": "3.0.0-e554493",
72
+ "@helia/unixfs": "3.0.0-e554493",
62
73
  "@ipld/car": "^5.2.5",
63
74
  "@ipld/dag-cbor": "^9.0.7",
64
75
  "@libp2p/interface": "^1.1.1",
65
76
  "@libp2p/kad-dht": "^12.0.2",
66
- "@libp2p/keychain": "^4.0.5",
67
- "@libp2p/peer-id": "^4.0.3",
77
+ "@libp2p/keychain": "^4.0.7",
78
+ "@libp2p/peer-id": "^4.0.5",
68
79
  "@libp2p/peer-id-factory": "^4.0.3",
69
- "@libp2p/websockets": "^8.0.1",
80
+ "@libp2p/websockets": "^8.0.10",
70
81
  "@multiformats/sha3": "^3.0.0",
71
82
  "aegir": "^42.1.0",
72
- "helia": "^3.0.1",
83
+ "helia": "4.0.0-e554493",
73
84
  "ipfs-core-types": "^0.14.1",
74
85
  "ipfs-unixfs-importer": "^15.2.3",
75
86
  "ipfsd-ctl": "^13.0.0",
@@ -78,16 +89,18 @@
78
89
  "it-last": "^3.0.4",
79
90
  "it-map": "^3.0.5",
80
91
  "it-to-buffer": "^4.0.2",
81
- "kubo": "^0.25.0",
92
+ "kubo": "^0.26.0",
82
93
  "kubo-rpc-client": "^3.0.1",
94
+ "libp2p": "^1.2.0",
83
95
  "multiformats": "^13.0.0",
84
96
  "p-defer": "^4.0.0",
85
97
  "uint8arrays": "^5.0.1",
86
98
  "wherearewe": "^2.0.1"
87
99
  },
88
100
  "browser": {
89
- "./dist/test/fixtures/create-helia.js": "./dist/test/fixtures/create-helia.browser.js",
90
- "./dist/test/fixtures/create-kubo.js": "./dist/test/fixtures/create-kubo.browser.js",
101
+ "./dist/src/fixtures/create-helia.js": "./dist/src/fixtures/create-helia.browser.js",
102
+ "./dist/src/fixtures/create-kubo.js": "./dist/src/fixtures/create-kubo.browser.js",
103
+ "./dist/src/bin.js": "./dist/src/index.js",
91
104
  "kubo": false
92
105
  }
93
106
  }
package/src/bin.ts ADDED
@@ -0,0 +1,25 @@
1
+ #! /usr/bin/env node
2
+ /* eslint-disable no-console */
3
+
4
+ import { spawn } from 'node:child_process'
5
+ import { dirname, resolve } from 'path'
6
+ import { fileURLToPath } from 'url'
7
+
8
+ // aegir should be run from `node_modules/@helia/interop`
9
+ const cwd = resolve(dirname(fileURLToPath(import.meta.url)), '../../')
10
+
11
+ const test = spawn('npx', ['aegir', 'test'], {
12
+ cwd
13
+ })
14
+
15
+ test.stdout.on('data', (data) => {
16
+ process.stdout.write(data)
17
+ })
18
+
19
+ test.stderr.on('data', (data) => {
20
+ process.stderr.write(data)
21
+ })
22
+
23
+ test.on('close', (code) => {
24
+ process.exit(code ?? 0)
25
+ })
@@ -0,0 +1,102 @@
1
+ /* eslint-env mocha */
2
+
3
+ import { car } from '@helia/car'
4
+ import { type UnixFS, unixfs } from '@helia/unixfs'
5
+ import { CarReader } from '@ipld/car'
6
+ import { expect } from 'aegir/chai'
7
+ import drain from 'it-drain'
8
+ import toBuffer from 'it-to-buffer'
9
+ import { CID } from 'multiformats/cid'
10
+ import { createHeliaNode } from './fixtures/create-helia.js'
11
+ import { createKuboNode } from './fixtures/create-kubo.js'
12
+ import { memoryCarWriter } from './fixtures/memory-car.js'
13
+ import type { Car } from '@helia/car'
14
+ import type { HeliaLibp2p } from 'helia'
15
+ import type { FileCandidate } from 'ipfs-unixfs-importer'
16
+ import type { Controller } from 'ipfsd-ctl'
17
+
18
+ describe('@helia/car', () => {
19
+ let helia: HeliaLibp2p
20
+ let c: Car
21
+ let u: UnixFS
22
+ let kubo: Controller
23
+
24
+ beforeEach(async () => {
25
+ helia = await createHeliaNode()
26
+ c = car(helia)
27
+ u = unixfs(helia)
28
+ kubo = await createKuboNode()
29
+
30
+ // connect helia to kubo
31
+ await helia.libp2p.dial(kubo.peer.addresses)
32
+ })
33
+
34
+ afterEach(async () => {
35
+ if (helia != null) {
36
+ await helia.stop()
37
+ }
38
+
39
+ if (kubo != null) {
40
+ await kubo.stop()
41
+ }
42
+ })
43
+
44
+ it('should export a car from Helia, import and read the contents from kubo', async () => {
45
+ const chunkSize = 1024 * 1024
46
+ const size = chunkSize * 10
47
+ const input: Uint8Array[] = []
48
+
49
+ const candidate: FileCandidate = {
50
+ content: (async function * () {
51
+ for (let i = 0; i < size; i += chunkSize) {
52
+ const buf = new Uint8Array(chunkSize)
53
+ input.push(buf)
54
+
55
+ yield buf
56
+ }
57
+ }())
58
+ }
59
+
60
+ const cid = await u.addFile(candidate)
61
+ const writer = memoryCarWriter(cid)
62
+ await c.export(cid, writer)
63
+
64
+ const buf = await writer.bytes()
65
+
66
+ await drain(kubo.api.dag.import([buf]))
67
+
68
+ const output: Uint8Array[] = []
69
+
70
+ for await (const b of kubo.api.cat(cid)) {
71
+ output.push(b)
72
+ }
73
+
74
+ expect(toBuffer(output)).to.equalBytes(toBuffer(input))
75
+ })
76
+
77
+ it('should export a car from kubo, import and read the contents from Helia', async () => {
78
+ const chunkSize = 1024 * 1024
79
+ const size = chunkSize * 10
80
+ const input: Uint8Array[] = []
81
+
82
+ const candidate: FileCandidate = {
83
+ content: (async function * () {
84
+ for (let i = 0; i < size; i += chunkSize) {
85
+ const buf = new Uint8Array(chunkSize)
86
+ input.push(buf)
87
+
88
+ yield buf
89
+ }
90
+ }())
91
+ }
92
+
93
+ const { cid } = await kubo.api.add(candidate.content)
94
+ const bytes = await toBuffer(kubo.api.dag.export(cid))
95
+
96
+ const reader = await CarReader.fromBytes(bytes)
97
+
98
+ await c.import(reader)
99
+
100
+ expect(await toBuffer(u.cat(CID.parse(cid.toString())))).to.equalBytes(toBuffer(input))
101
+ })
102
+ })
@@ -0,0 +1,65 @@
1
+ /* eslint-env mocha */
2
+
3
+ import { dagCbor, type DAGCBOR, type AddOptions } from '@helia/dag-cbor'
4
+ import * as codec from '@ipld/dag-cbor'
5
+ import { expect } from 'aegir/chai'
6
+ import { CID } from 'multiformats/cid'
7
+ import { createHeliaNode } from './fixtures/create-helia.js'
8
+ import { createKuboNode } from './fixtures/create-kubo.js'
9
+ import type { HeliaLibp2p } from 'helia'
10
+ import type { PutOptions as KuboAddOptions } from 'ipfs-core-types/src/block/index.js'
11
+ import type { Controller } from 'ipfsd-ctl'
12
+
13
+ describe('@helia/dag-cbor', () => {
14
+ let helia: HeliaLibp2p
15
+ let d: DAGCBOR
16
+ let kubo: Controller
17
+
18
+ async function expectSameCid (data: () => any, heliaOpts: Partial<AddOptions> = {}, kuboOpts: KuboAddOptions = {}): Promise<void> {
19
+ const heliaCid = await d.add(data(), heliaOpts)
20
+ const kuboCid = await kubo.api.dag.put(data(), kuboOpts)
21
+
22
+ expect(heliaCid.toString()).to.equal(kuboCid.toString())
23
+ }
24
+
25
+ beforeEach(async () => {
26
+ helia = await createHeliaNode()
27
+ d = dagCbor(helia)
28
+ kubo = await createKuboNode()
29
+
30
+ await helia.libp2p.dial((await (kubo.api.id())).addresses)
31
+ })
32
+
33
+ afterEach(async () => {
34
+ if (helia != null) {
35
+ await helia.stop()
36
+ }
37
+
38
+ if (kubo != null) {
39
+ await kubo.stop()
40
+ }
41
+ })
42
+
43
+ it('should create the same CID for a string', async () => {
44
+ const candidate = (): any => ({ hello: 'world' })
45
+
46
+ await expectSameCid(candidate)
47
+ })
48
+
49
+ it('should add to helia and fetch from kubo', async () => {
50
+ const input = { hello: 'world' }
51
+ const cid = await d.add(input)
52
+ const block = await kubo.api.block.get(cid)
53
+ const output = codec.decode(block)
54
+
55
+ expect(output).to.deep.equal(input)
56
+ })
57
+
58
+ it('should add to kubo and fetch from helia', async () => {
59
+ const input = { hello: 'world' }
60
+ const cid = await kubo.api.block.put(codec.encode(input))
61
+ const output = await d.get(CID.parse(cid.toString()))
62
+
63
+ expect(output).to.deep.equal(input)
64
+ })
65
+ })
@@ -0,0 +1,65 @@
1
+ /* eslint-env mocha */
2
+
3
+ import { dagJson, type DAGJSON, type AddOptions } from '@helia/dag-json'
4
+ import { expect } from 'aegir/chai'
5
+ import { CID } from 'multiformats/cid'
6
+ import * as codec from 'multiformats/codecs/json'
7
+ import { createHeliaNode } from './fixtures/create-helia.js'
8
+ import { createKuboNode } from './fixtures/create-kubo.js'
9
+ import type { HeliaLibp2p } from 'helia'
10
+ import type { PutOptions as KuboAddOptions } from 'ipfs-core-types/src/block/index.js'
11
+ import type { Controller } from 'ipfsd-ctl'
12
+
13
+ describe('@helia/dag-json', () => {
14
+ let helia: HeliaLibp2p
15
+ let d: DAGJSON
16
+ let kubo: Controller
17
+
18
+ async function expectSameCid (data: () => any, heliaOpts: Partial<AddOptions> = {}, kuboOpts: KuboAddOptions = { format: 'dag-json' }): Promise<void> {
19
+ const heliaCid = await d.add(data(), heliaOpts)
20
+ const kuboCid = await kubo.api.block.put(codec.encode(data()), kuboOpts)
21
+
22
+ expect(heliaCid.toString()).to.equal(kuboCid.toString())
23
+ }
24
+
25
+ beforeEach(async () => {
26
+ helia = await createHeliaNode()
27
+ d = dagJson(helia)
28
+ kubo = await createKuboNode()
29
+
30
+ await helia.libp2p.dial((await (kubo.api.id())).addresses)
31
+ })
32
+
33
+ afterEach(async () => {
34
+ if (helia != null) {
35
+ await helia.stop()
36
+ }
37
+
38
+ if (kubo != null) {
39
+ await kubo.stop()
40
+ }
41
+ })
42
+
43
+ it('should create the same CID for a string', async () => {
44
+ const candidate = (): any => ({ hello: 'world' })
45
+
46
+ await expectSameCid(candidate)
47
+ })
48
+
49
+ it('should add to helia and fetch from kubo', async () => {
50
+ const input = { hello: 'world' }
51
+ const cid = await d.add(input)
52
+ const block = await kubo.api.block.get(cid)
53
+ const output = codec.decode(block)
54
+
55
+ expect(output).to.deep.equal(input)
56
+ })
57
+
58
+ it('should add to kubo and fetch from helia', async () => {
59
+ const input = { hello: 'world' }
60
+ const cid = await kubo.api.block.put(codec.encode(input))
61
+ const output = await d.get(CID.parse(cid.toString()))
62
+
63
+ expect(output).to.deep.equal(input)
64
+ })
65
+ })
@@ -0,0 +1,19 @@
1
+ import { expect } from 'aegir/chai'
2
+ import type { HeliaLibp2p } from 'helia'
3
+ import type { Controller } from 'ipfsd-ctl'
4
+
5
+ /**
6
+ * Connect the two nodes by dialing a protocol stream
7
+ */
8
+ export async function connect (helia: HeliaLibp2p<any>, kubo: Controller, protocol: string): Promise<void> {
9
+ let connected = false
10
+ for (const addr of kubo.peer.addresses) {
11
+ try {
12
+ await helia.libp2p.dialProtocol(addr, protocol)
13
+ connected = true
14
+ break
15
+ } catch { }
16
+ }
17
+
18
+ expect(connected).to.be.true('could not connect Helia to Kubo')
19
+ }
@@ -0,0 +1,8 @@
1
+ import { createHeliaHTTP as createHelia, type HeliaHTTPInit } from '@helia/http'
2
+ import type { Helia } from '@helia/interface'
3
+
4
+ export async function createHeliaHTTP (init: Partial<HeliaHTTPInit> = {}): Promise<Helia> {
5
+ return createHelia({
6
+ ...init
7
+ })
8
+ }
@@ -0,0 +1,68 @@
1
+ import { bitswap } from '@helia/block-brokers'
2
+ import { ipnsValidator, ipnsSelector } from '@helia/ipns'
3
+ import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
4
+ import { webSockets } from '@libp2p/websockets'
5
+ import { all } from '@libp2p/websockets/filters'
6
+ import { sha3512 } from '@multiformats/sha3'
7
+ import { createHelia, libp2pDefaults } from 'helia'
8
+ import type { Libp2p } from '@libp2p/interface'
9
+ import type { DefaultLibp2pServices, HeliaLibp2p } from 'helia'
10
+ import type { Libp2pOptions } from 'libp2p'
11
+
12
+ export async function createHeliaNode (): Promise<HeliaLibp2p<Libp2p<DefaultLibp2pServices>>>
13
+ export async function createHeliaNode <Services extends Record<string, unknown>> (libp2pOptions: Libp2pOptions<Services>): Promise<HeliaLibp2p<Libp2p<Services & DefaultLibp2pServices>>>
14
+ export async function createHeliaNode (libp2pOptions?: Libp2pOptions): Promise<HeliaLibp2p<Libp2p<DefaultLibp2pServices>>> {
15
+ const defaults = libp2pDefaults()
16
+
17
+ // allow dialing insecure WebSockets
18
+ defaults.transports?.pop()
19
+ defaults.transports = [
20
+ ...(defaults.transports ?? []),
21
+ webSockets({
22
+ filter: all
23
+ })
24
+ ]
25
+
26
+ // allow dialing loopback
27
+ defaults.connectionGater = {
28
+ denyDialMultiaddr: () => false
29
+ }
30
+
31
+ // use LAN DHT
32
+ defaults.services = {
33
+ ...(defaults.services ?? {}),
34
+ ...(libp2pOptions?.services ?? {}),
35
+ dht: kadDHT({
36
+ validators: {
37
+ ipns: ipnsValidator
38
+ },
39
+ selectors: {
40
+ ipns: ipnsSelector
41
+ },
42
+ // skips waiting for the initial self-query to find peers
43
+ allowQueryWithZeroPeers: true,
44
+
45
+ protocol: '/ipfs/lan/kad/1.0.0',
46
+ peerInfoMapper: removePublicAddressesMapper,
47
+ clientMode: false
48
+ })
49
+ }
50
+
51
+ // remove bootstrappers
52
+ defaults.peerDiscovery = []
53
+
54
+ // remove services that are not used in tests
55
+ delete defaults.services.autoNAT
56
+ delete defaults.services.dcutr
57
+ delete defaults.services.delegatedRouting
58
+
59
+ return createHelia<Libp2p<DefaultLibp2pServices>>({
60
+ blockBrokers: [
61
+ bitswap()
62
+ ],
63
+ libp2p: defaults,
64
+ hashers: [
65
+ sha3512
66
+ ]
67
+ })
68
+ }
@@ -0,0 +1,55 @@
1
+ import { bitswap } from '@helia/block-brokers'
2
+ import { ipnsValidator, ipnsSelector } from '@helia/ipns'
3
+ import { kadDHT, removePublicAddressesMapper } from '@libp2p/kad-dht'
4
+ import { sha3512 } from '@multiformats/sha3'
5
+ import { createHelia, libp2pDefaults } from 'helia'
6
+ import type { Libp2p } from '@libp2p/interface'
7
+ import type { DefaultLibp2pServices, HeliaLibp2p } from 'helia'
8
+ import type { Libp2pOptions } from 'libp2p'
9
+
10
+ export async function createHeliaNode (): Promise<HeliaLibp2p<Libp2p<DefaultLibp2pServices>>>
11
+ export async function createHeliaNode <Services extends Record<string, unknown>> (libp2pOptions: Libp2pOptions<Services>): Promise<HeliaLibp2p<Libp2p<Services & DefaultLibp2pServices>>>
12
+ export async function createHeliaNode (libp2pOptions?: Libp2pOptions): Promise<HeliaLibp2p<Libp2p<DefaultLibp2pServices>>> {
13
+ const defaults = libp2pDefaults()
14
+ defaults.addresses = {
15
+ listen: [
16
+ '/ip4/0.0.0.0/tcp/0'
17
+ ]
18
+ }
19
+ defaults.services = {
20
+ ...(defaults.services ?? {}),
21
+ ...(libp2pOptions?.services ?? {}),
22
+ dht: kadDHT({
23
+ validators: {
24
+ ipns: ipnsValidator
25
+ },
26
+ selectors: {
27
+ ipns: ipnsSelector
28
+ },
29
+ // skips waiting for the initial self-query to find peers
30
+ allowQueryWithZeroPeers: true,
31
+
32
+ protocol: '/ipfs/lan/kad/1.0.0',
33
+ peerInfoMapper: removePublicAddressesMapper,
34
+ clientMode: false
35
+ })
36
+ }
37
+
38
+ // remove bootstrappers, mdns, etc
39
+ defaults.peerDiscovery = []
40
+
41
+ // remove services that are not used in tests
42
+ delete defaults.services.autoNAT
43
+ delete defaults.services.dcutr
44
+ delete defaults.services.delegatedRouting
45
+
46
+ return createHelia<Libp2p<DefaultLibp2pServices>>({
47
+ blockBrokers: [
48
+ bitswap()
49
+ ],
50
+ libp2p: defaults,
51
+ hashers: [
52
+ sha3512
53
+ ]
54
+ })
55
+ }
@@ -0,0 +1,30 @@
1
+ import { type Controller, createController } from 'ipfsd-ctl'
2
+ import * as kuboRpcClient from 'kubo-rpc-client'
3
+
4
+ export async function createKuboNode (): Promise<Controller> {
5
+ return createController({
6
+ kuboRpcModule: kuboRpcClient,
7
+ test: true,
8
+ endpoint: process.env.IPFSD_SERVER,
9
+ ipfsOptions: {
10
+ config: {
11
+ Addresses: {
12
+ Swarm: [
13
+ '/ip4/0.0.0.0/tcp/0',
14
+ '/ip4/0.0.0.0/tcp/0/ws'
15
+ ],
16
+ Gateway: '/ip4/127.0.0.1/tcp/8180'
17
+ },
18
+ Gateway: {
19
+ NoFetch: true,
20
+ ExposeRoutingAPI: true,
21
+ HTTPHeaders: {
22
+ 'Access-Control-Allow-Origin': ['*'],
23
+ 'Access-Control-Allow-Methods': ['GET', 'POST', 'PUT', 'OPTIONS']
24
+ }
25
+ }
26
+ }
27
+ },
28
+ args: ['--enable-pubsub-experiment', '--enable-namesys-pubsub']
29
+ })
30
+ }
@@ -0,0 +1,32 @@
1
+ /* eslint-disable @typescript-eslint/ban-ts-comment,@typescript-eslint/prefer-ts-expect-error */
2
+ import { createController, type Controller } from 'ipfsd-ctl'
3
+ import { path as kuboPath } from 'kubo'
4
+ import * as kuboRpcClient from 'kubo-rpc-client'
5
+
6
+ export async function createKuboNode (): Promise<Controller> {
7
+ return createController({
8
+ kuboRpcModule: kuboRpcClient,
9
+ ipfsBin: kuboPath(),
10
+ test: true,
11
+ ipfsOptions: {
12
+ config: {
13
+ Addresses: {
14
+ Swarm: [
15
+ '/ip4/0.0.0.0/tcp/4001',
16
+ '/ip4/0.0.0.0/tcp/4002/ws'
17
+ ],
18
+ Gateway: '/ip4/127.0.0.1/tcp/8180'
19
+ },
20
+ Gateway: {
21
+ NoFetch: true,
22
+ ExposeRoutingAPI: true,
23
+ HTTPHeaders: {
24
+ 'Access-Control-Allow-Origin': ['*'],
25
+ 'Access-Control-Allow-Methods': ['GET', 'POST', 'PUT', 'OPTIONS']
26
+ }
27
+ }
28
+ }
29
+ },
30
+ args: ['--enable-pubsub-experiment', '--enable-namesys-pubsub']
31
+ })
32
+ }
@@ -0,0 +1,46 @@
1
+ import all from 'it-all'
2
+ import map from 'it-map'
3
+ import { sha256 } from 'multiformats/hashes/sha2'
4
+ import { compare as uint8ArrayCompare } from 'uint8arrays/compare'
5
+ import { xor as uint8ArrayXor } from 'uint8arrays/xor'
6
+ import type { PeerId } from '@libp2p/interface'
7
+
8
+ /**
9
+ * Sort peers by distance to the KadID of the passed buffer
10
+ */
11
+ export async function sortClosestPeers (buf: Uint8Array, peers: PeerId[]): Promise<PeerId[]> {
12
+ const kadId = await convertBuffer(buf)
13
+
14
+ const distances = await all(
15
+ map(peers, async (peer) => {
16
+ const id = await convertPeerId(peer)
17
+
18
+ return {
19
+ peer,
20
+ distance: uint8ArrayXor(id, kadId)
21
+ }
22
+ })
23
+ )
24
+
25
+ return distances
26
+ .sort((a, b) => {
27
+ return uint8ArrayCompare(a.distance, b.distance)
28
+ })
29
+ .map((d) => d.peer)
30
+ }
31
+
32
+ /**
33
+ * Creates a DHT ID by hashing a Peer ID
34
+ */
35
+ export async function convertPeerId (peerId: PeerId): Promise<Uint8Array> {
36
+ return convertBuffer(peerId.toBytes())
37
+ }
38
+
39
+ /**
40
+ * Creates a DHT ID by hashing a given Uint8Array
41
+ */
42
+ export async function convertBuffer (buf: Uint8Array): Promise<Uint8Array> {
43
+ const multihash = await sha256.digest(buf)
44
+
45
+ return multihash.digest
46
+ }
@@ -0,0 +1,7 @@
1
+ import type { PeerIdType } from '@libp2p/interface'
2
+
3
+ export const keyTypes: PeerIdType[] = [
4
+ 'Ed25519',
5
+ 'secp256k1',
6
+ 'RSA'
7
+ ]
@@ -0,0 +1,33 @@
1
+ import { CarWriter } from '@ipld/car'
2
+ import toBuffer from 'it-to-buffer'
3
+ import defer from 'p-defer'
4
+ import type { CID } from 'multiformats/cid'
5
+
6
+ export interface MemoryCar extends Pick<CarWriter, 'put' | 'close'> {
7
+ bytes(): Promise<Uint8Array>
8
+ }
9
+
10
+ export function memoryCarWriter (root: CID | CID[]): MemoryCar {
11
+ const deferred = defer<Uint8Array>()
12
+ const { writer, out } = CarWriter.create(Array.isArray(root) ? root : [root])
13
+
14
+ Promise.resolve()
15
+ .then(async () => {
16
+ deferred.resolve(await toBuffer(out))
17
+ })
18
+ .catch(err => {
19
+ deferred.reject(err)
20
+ })
21
+
22
+ return {
23
+ async put (block: { cid: CID, bytes: Uint8Array }): Promise<void> {
24
+ await writer.put(block)
25
+ },
26
+ async close (): Promise<void> {
27
+ await writer.close()
28
+ },
29
+ async bytes (): Promise<Uint8Array> {
30
+ return deferred.promise
31
+ }
32
+ }
33
+ }