@helia/verified-fetch-interop 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 (45) hide show
  1. package/LICENSE +4 -0
  2. package/README.md +58 -0
  3. package/dist/index.min.js +3 -0
  4. package/dist/src/fixtures/create-kubo.browser.d.ts +3 -0
  5. package/dist/src/fixtures/create-kubo.browser.d.ts.map +1 -0
  6. package/dist/src/fixtures/create-kubo.browser.js +30 -0
  7. package/dist/src/fixtures/create-kubo.browser.js.map +1 -0
  8. package/dist/src/fixtures/create-kubo.d.ts +3 -0
  9. package/dist/src/fixtures/create-kubo.d.ts.map +1 -0
  10. package/dist/src/fixtures/create-kubo.js +32 -0
  11. package/dist/src/fixtures/create-kubo.js.map +1 -0
  12. package/dist/src/fixtures/load-fixture-data.d.ts +3 -0
  13. package/dist/src/fixtures/load-fixture-data.d.ts.map +1 -0
  14. package/dist/src/fixtures/load-fixture-data.js +8 -0
  15. package/dist/src/fixtures/load-fixture-data.js.map +1 -0
  16. package/dist/src/index.d.ts +14 -0
  17. package/dist/src/index.d.ts.map +1 -0
  18. package/dist/src/index.js +14 -0
  19. package/dist/src/index.js.map +1 -0
  20. package/dist/src/json.spec.d.ts +2 -0
  21. package/dist/src/json.spec.d.ts.map +1 -0
  22. package/dist/src/json.spec.js +43 -0
  23. package/dist/src/json.spec.js.map +1 -0
  24. package/dist/src/unixfs-dir.spec.d.ts +2 -0
  25. package/dist/src/unixfs-dir.spec.d.ts.map +1 -0
  26. package/dist/src/unixfs-dir.spec.js +81 -0
  27. package/dist/src/unixfs-dir.spec.js.map +1 -0
  28. package/dist/src/websites.spec.d.ts +2 -0
  29. package/dist/src/websites.spec.d.ts.map +1 -0
  30. package/dist/src/websites.spec.js +76 -0
  31. package/dist/src/websites.spec.js.map +1 -0
  32. package/package.json +69 -0
  33. package/src/bin.ts +25 -0
  34. package/src/fixtures/create-kubo.browser.ts +30 -0
  35. package/src/fixtures/create-kubo.ts +32 -0
  36. package/src/fixtures/data/QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr-tokens.uniswap.org-2024-01-18.car +0 -0
  37. package/src/fixtures/data/QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR-xkcd-Barrel-part-1.car +0 -0
  38. package/src/fixtures/data/QmbxpRxwKXxnJQjnPqm1kzDJSJ8YgkLxH23mcZURwPHjGv-helia-identify-website.car +0 -0
  39. package/src/fixtures/data/QmeiDMLtPUS3RT2xAcUwsNyZz169wPke2q7im9vZpVLSYw-fake-blog.libp2p.io.car +0 -0
  40. package/src/fixtures/data/bafybeidbclfqleg2uojchspzd4bob56dqetqjsj27gy2cq3klkkgxtpn4i-single-layer-hamt-with-multi-block-files.car +0 -0
  41. package/src/fixtures/load-fixture-data.ts +9 -0
  42. package/src/index.ts +14 -0
  43. package/src/json.spec.ts +47 -0
  44. package/src/unixfs-dir.spec.ts +94 -0
  45. package/src/websites.spec.ts +85 -0
package/LICENSE ADDED
@@ -0,0 +1,4 @@
1
+ This project is dual licensed under MIT and Apache-2.0.
2
+
3
+ MIT: https://www.opensource.org/licenses/mit
4
+ Apache-2.0: https://www.apache.org/licenses/license-2.0
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ <p align="center">
2
+ <a href="https://github.com/ipfs/helia" title="Helia">
3
+ <img src="https://raw.githubusercontent.com/ipfs/helia/main/assets/helia.png" alt="Helia logo" width="300" />
4
+ </a>
5
+ </p>
6
+
7
+ # @helia/interop
8
+
9
+ [![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech)
10
+ [![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech)
11
+ [![codecov](https://img.shields.io/codecov/c/github/ipfs/helia-verified-fetch.svg?style=flat-square)](https://codecov.io/gh/ipfs/helia-verified-fetch)
12
+ [![CI](https://img.shields.io/github/actions/workflow/status/ipfs/helia-verified-fetch/js-test-and-release.yml?branch=main\&style=flat-square)](https://github.com/ipfs/helia-verified-fetch/actions/workflows/js-test-and-release.yml?query=branch%3Amain)
13
+
14
+ > Interop tests for @helia/verified-fetch
15
+
16
+ # About
17
+
18
+ Runs interop tests between Helia and Kubo.
19
+
20
+ ## Example - Testing a new Kubo release
21
+
22
+ ```console
23
+ $ npm i @helia/interop
24
+ $ KUBO_BINARY=/path/to/kubo helia-interop
25
+ ```
26
+
27
+ # Install
28
+
29
+ ```console
30
+ $ npm i @helia/interop
31
+ ```
32
+
33
+ ## Browser `<script>` tag
34
+
35
+ Loading this module through a script tag will make it's exports available as `HeliaInterop` in the global namespace.
36
+
37
+ ```html
38
+ <script src="https://unpkg.com/@helia/interop/dist/index.min.js"></script>
39
+ ```
40
+
41
+ # License
42
+
43
+ Licensed under either of
44
+
45
+ - Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
46
+ - MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
47
+
48
+ # Contribute
49
+
50
+ Contributions welcome! Please check out [the issues](https://github.com/ipfs/helia-verified-fetch/issues).
51
+
52
+ Also see our [contributing document](https://github.com/ipfs/community/blob/master/CONTRIBUTING_JS.md) for more information on how we work, and about contributing in general.
53
+
54
+ Please be aware that all interactions related to this repo are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md).
55
+
56
+ Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
57
+
58
+ [![](https://cdn.rawgit.com/jbenet/contribute-ipfs-gif/master/img/contribute.gif)](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md)
@@ -0,0 +1,3 @@
1
+ (function (root, factory) {(typeof module === 'object' && module.exports) ? module.exports = factory() : root.HeliaInterop = factory()}(typeof self !== 'undefined' ? self : this, function () {
2
+ "use strict";var HeliaInterop=(()=>{var t=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var d=(o,e,x,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let p of b(e))!c.call(o,p)&&p!==x&&t(o,p,{get:()=>e[p],enumerable:!(r=a(e,p))||r.enumerable});return o};var f=o=>d(t({},"__esModule",{value:!0}),o);var g={};return f(g);})();
3
+ return HeliaInterop}));
@@ -0,0 +1,3 @@
1
+ import { type Controller } from 'ipfsd-ctl';
2
+ export declare function createKuboNode(): Promise<Controller>;
3
+ //# sourceMappingURL=create-kubo.browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-kubo.browser.d.ts","sourceRoot":"","sources":["../../../src/fixtures/create-kubo.browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAoB,MAAM,WAAW,CAAA;AAG7D,wBAAsB,cAAc,IAAK,OAAO,CAAC,UAAU,CAAC,CA0B3D"}
@@ -0,0 +1,30 @@
1
+ import { createController } from 'ipfsd-ctl';
2
+ import * as kuboRpcClient from 'kubo-rpc-client';
3
+ export async function createKuboNode() {
4
+ return createController({
5
+ kuboRpcModule: kuboRpcClient,
6
+ test: true,
7
+ endpoint: process.env.IPFSD_SERVER,
8
+ ipfsOptions: {
9
+ config: {
10
+ Addresses: {
11
+ Swarm: [
12
+ '/ip4/0.0.0.0/tcp/0',
13
+ '/ip4/0.0.0.0/tcp/0/ws'
14
+ ],
15
+ Gateway: '/ip4/127.0.0.1/tcp/8180'
16
+ },
17
+ Gateway: {
18
+ NoFetch: true,
19
+ ExposeRoutingAPI: true,
20
+ HTTPHeaders: {
21
+ 'Access-Control-Allow-Origin': ['*'],
22
+ 'Access-Control-Allow-Methods': ['GET', 'POST', 'PUT', 'OPTIONS']
23
+ }
24
+ }
25
+ }
26
+ },
27
+ args: ['--enable-pubsub-experiment', '--enable-namesys-pubsub']
28
+ });
29
+ }
30
+ //# sourceMappingURL=create-kubo.browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-kubo.browser.js","sourceRoot":"","sources":["../../../src/fixtures/create-kubo.browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAC7D,OAAO,KAAK,aAAa,MAAM,iBAAiB,CAAA;AAEhD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,OAAO,gBAAgB,CAAC;QACtB,aAAa,EAAE,aAAa;QAC5B,IAAI,EAAE,IAAI;QACV,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QAClC,WAAW,EAAE;YACX,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,KAAK,EAAE;wBACL,oBAAoB;wBACpB,uBAAuB;qBACxB;oBACD,OAAO,EAAE,yBAAyB;iBACnC;gBACD,OAAO,EAAE;oBACP,OAAO,EAAE,IAAI;oBACb,gBAAgB,EAAE,IAAI;oBACtB,WAAW,EAAE;wBACX,6BAA6B,EAAE,CAAC,GAAG,CAAC;wBACpC,8BAA8B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC;qBAClE;iBACF;aACF;SACF;QACD,IAAI,EAAE,CAAC,4BAA4B,EAAE,yBAAyB,CAAC;KAChE,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type Controller } from 'ipfsd-ctl';
2
+ export declare function createKuboNode(): Promise<Controller>;
3
+ //# sourceMappingURL=create-kubo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-kubo.d.ts","sourceRoot":"","sources":["../../../src/fixtures/create-kubo.ts"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAA;AAI7D,wBAAsB,cAAc,IAAK,OAAO,CAAC,UAAU,CAAC,CA0B3D"}
@@ -0,0 +1,32 @@
1
+ /* eslint-disable @typescript-eslint/ban-ts-comment,@typescript-eslint/prefer-ts-expect-error */
2
+ import { createController } from 'ipfsd-ctl';
3
+ import { path as kuboPath } from 'kubo';
4
+ import * as kuboRpcClient from 'kubo-rpc-client';
5
+ export async function createKuboNode() {
6
+ return createController({
7
+ kuboRpcModule: kuboRpcClient,
8
+ ipfsBin: kuboPath(),
9
+ test: true,
10
+ ipfsOptions: {
11
+ config: {
12
+ Addresses: {
13
+ Swarm: [
14
+ '/ip4/0.0.0.0/tcp/4001',
15
+ '/ip4/0.0.0.0/tcp/4002/ws'
16
+ ],
17
+ Gateway: '/ip4/127.0.0.1/tcp/8180'
18
+ },
19
+ Gateway: {
20
+ NoFetch: true,
21
+ ExposeRoutingAPI: true,
22
+ HTTPHeaders: {
23
+ 'Access-Control-Allow-Origin': ['*'],
24
+ 'Access-Control-Allow-Methods': ['GET', 'POST', 'PUT', 'OPTIONS']
25
+ }
26
+ }
27
+ }
28
+ },
29
+ args: ['--enable-pubsub-experiment', '--enable-namesys-pubsub']
30
+ });
31
+ }
32
+ //# sourceMappingURL=create-kubo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-kubo.js","sourceRoot":"","sources":["../../../src/fixtures/create-kubo.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,OAAO,EAAE,gBAAgB,EAAmB,MAAM,WAAW,CAAA;AAC7D,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,MAAM,MAAM,CAAA;AACvC,OAAO,KAAK,aAAa,MAAM,iBAAiB,CAAA;AAEhD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,OAAO,gBAAgB,CAAC;QACtB,aAAa,EAAE,aAAa;QAC5B,OAAO,EAAE,QAAQ,EAAE;QACnB,IAAI,EAAE,IAAI;QACV,WAAW,EAAE;YACX,MAAM,EAAE;gBACN,SAAS,EAAE;oBACT,KAAK,EAAE;wBACL,uBAAuB;wBACvB,0BAA0B;qBAC3B;oBACD,OAAO,EAAE,yBAAyB;iBACnC;gBACD,OAAO,EAAE;oBACP,OAAO,EAAE,IAAI;oBACb,gBAAgB,EAAE,IAAI;oBACtB,WAAW,EAAE;wBACX,6BAA6B,EAAE,CAAC,GAAG,CAAC;wBACpC,8BAA8B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC;qBAClE;iBACF;aACF;SACF;QACD,IAAI,EAAE,CAAC,4BAA4B,EAAE,yBAAyB,CAAC;KAChE,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Controller } from 'ipfsd-ctl';
2
+ export declare function loadFixtureDataCar(controller: Controller, path: string): Promise<void>;
3
+ //# sourceMappingURL=load-fixture-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-fixture-data.d.ts","sourceRoot":"","sources":["../../../src/fixtures/load-fixture-data.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AAE3C,wBAAsB,kBAAkB,CAAE,UAAU,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI7F"}
@@ -0,0 +1,8 @@
1
+ import loadFixture from 'aegir/fixtures';
2
+ import drain from 'it-drain';
3
+ export async function loadFixtureDataCar(controller, path) {
4
+ const fixtureData = `src/fixtures/data/${path}`;
5
+ const buf = loadFixture(fixtureData);
6
+ await drain(controller.api.dag.import([buf]));
7
+ }
8
+ //# sourceMappingURL=load-fixture-data.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-fixture-data.js","sourceRoot":"","sources":["../../../src/fixtures/load-fixture-data.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,gBAAgB,CAAA;AACxC,OAAO,KAAK,MAAM,UAAU,CAAA;AAG5B,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAE,UAAsB,EAAE,IAAY;IAC5E,MAAM,WAAW,GAAG,qBAAqB,IAAI,EAAE,CAAA;IAC/C,MAAM,GAAG,GAAG,WAAW,CAAC,WAAW,CAAC,CAAA;IACpC,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;AAC/C,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * Runs interop tests between Helia and Kubo.
5
+ *
6
+ * @example Testing a new Kubo release
7
+ *
8
+ * ```console
9
+ * $ npm i @helia/interop
10
+ * $ KUBO_BINARY=/path/to/kubo helia-interop
11
+ * ```
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAA"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * Runs interop tests between Helia and Kubo.
5
+ *
6
+ * @example Testing a new Kubo release
7
+ *
8
+ * ```console
9
+ * $ npm i @helia/interop
10
+ * $ KUBO_BINARY=/path/to/kubo helia-interop
11
+ * ```
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=json.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.spec.d.ts","sourceRoot":"","sources":["../../src/json.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ /* eslint-env mocha */
2
+ import { createVerifiedFetch } from '@helia/verified-fetch';
3
+ import { expect } from 'aegir/chai';
4
+ import { CID } from 'multiformats/cid';
5
+ import { createKuboNode } from './fixtures/create-kubo.js';
6
+ import { loadFixtureDataCar } from './fixtures/load-fixture-data.js';
7
+ describe('@helia/verified-fetch - json', () => {
8
+ describe('unixfs - multiblock', () => {
9
+ let controller;
10
+ let verifiedFetch;
11
+ before(async () => {
12
+ controller = await createKuboNode();
13
+ await controller.start();
14
+ // As of 2024-01-18, https://cloudflare-ipfs.com/ipns/tokens.uniswap.org resolves to:
15
+ // root: QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr
16
+ // child1: QmNik5N4ryNwzzXYq5hCYKGcRjAf9QtigxtiJh9o8aXXbG // partial JSON
17
+ // child2: QmWNBJX6fZyNTLWNYBHxAHpBctCP43R2zeqV2G8uavqFZn // partial JSON
18
+ await loadFixtureDataCar(controller, 'QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr-tokens.uniswap.org-2024-01-18.car');
19
+ verifiedFetch = await createVerifiedFetch({
20
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
21
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
22
+ });
23
+ });
24
+ after(async () => {
25
+ await controller.stop();
26
+ await verifiedFetch.stop();
27
+ });
28
+ it('handles UnixFS-chunked JSON file', async () => {
29
+ const resp = await verifiedFetch(CID.parse('QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr'));
30
+ expect(resp).to.be.ok();
31
+ const jsonObj = await resp.json();
32
+ expect(jsonObj).to.be.ok();
33
+ expect(jsonObj).to.have.property('name').equal('Uniswap Labs Default');
34
+ expect(jsonObj).to.have.property('timestamp').equal('2023-12-13T18:25:25.830Z');
35
+ expect(jsonObj).to.have.property('version').to.deep.equal({ major: 11, minor: 11, patch: 0 });
36
+ expect(jsonObj).to.have.property('tags');
37
+ expect(jsonObj).to.have.property('logoURI').equal('ipfs://QmNa8mQkrNKp1WEEeGjFezDmDeodkWRevGFN8JCV7b4Xir');
38
+ expect(jsonObj).to.have.property('keywords').to.deep.equal(['uniswap', 'default']);
39
+ expect(jsonObj.tokens).to.be.an('array').of.length(767);
40
+ });
41
+ });
42
+ });
43
+ //# sourceMappingURL=json.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.spec.js","sourceRoot":"","sources":["../../src/json.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=unixfs-dir.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unixfs-dir.spec.d.ts","sourceRoot":"","sources":["../../src/unixfs-dir.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,81 @@
1
+ /* eslint-env mocha */
2
+ import { createVerifiedFetch } from '@helia/verified-fetch';
3
+ import { expect } from 'aegir/chai';
4
+ import { filetypemime } from 'magic-bytes.js';
5
+ import { createKuboNode } from './fixtures/create-kubo.js';
6
+ import { loadFixtureDataCar } from './fixtures/load-fixture-data.js';
7
+ describe('@helia/verified-fetch - unixfs directory', () => {
8
+ let controller;
9
+ let verifiedFetch;
10
+ before(async () => {
11
+ controller = await createKuboNode();
12
+ await controller.start();
13
+ verifiedFetch = await createVerifiedFetch({
14
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
15
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
16
+ });
17
+ });
18
+ after(async () => {
19
+ await controller.stop();
20
+ await verifiedFetch.stop();
21
+ });
22
+ describe('XKCD Barrel Part 1', () => {
23
+ before(async () => {
24
+ // This is the content of https://explore.ipld.io/#/explore/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm/1%20-%20Barrel%20-%20Part%201
25
+ await loadFixtureDataCar(controller, 'QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR-xkcd-Barrel-part-1.car');
26
+ });
27
+ it('fails to load when passed the root', async () => {
28
+ // The spec says we should generate HTML with directory listings, but we don't do that yet, so expect a failure
29
+ const resp = await verifiedFetch('ipfs://QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR');
30
+ expect(resp).to.be.ok();
31
+ expect(resp.status).to.equal(501); // TODO: we should do a directory listing instead
32
+ });
33
+ it('can return a string for unixfs pathed data', async () => {
34
+ const resp = await verifiedFetch('ipfs://QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR/1 - Barrel - Part 1 - alt.txt');
35
+ expect(resp).to.be.ok();
36
+ const text = await resp.text();
37
+ expect(text).to.equal('Don\'t we all.');
38
+ });
39
+ it('can return an image for unixfs pathed data', async () => {
40
+ const resp = await verifiedFetch('ipfs://QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR/1 - Barrel - Part 1.png');
41
+ expect(resp).to.be.ok();
42
+ const imgData = await resp.blob();
43
+ expect(imgData).to.be.ok();
44
+ expect(imgData.size).to.equal(24848);
45
+ });
46
+ });
47
+ describe('content type parser', () => {
48
+ before(async () => {
49
+ await verifiedFetch.stop();
50
+ verifiedFetch = await createVerifiedFetch({
51
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
52
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
53
+ }, {
54
+ contentTypeParser: (bytes) => {
55
+ return filetypemime(bytes)?.[0];
56
+ }
57
+ });
58
+ });
59
+ it('can return an image content-type for unixfs pathed data', async () => {
60
+ const resp = await verifiedFetch('ipfs://QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR/1 - Barrel - Part 1.png');
61
+ // tediously this is actually a jpeg file with a .png extension
62
+ expect(resp.headers.get('content-type')).to.equal('image/jpeg');
63
+ });
64
+ });
65
+ describe('HAMT-sharded directory', () => {
66
+ before(async () => {
67
+ // from https://github.com/ipfs/gateway-conformance/blob/193833b91f2e9b17daf45c84afaeeae61d9d7c7e/fixtures/trustless_gateway_car/single-layer-hamt-with-multi-block-files.car
68
+ await loadFixtureDataCar(controller, 'bafybeidbclfqleg2uojchspzd4bob56dqetqjsj27gy2cq3klkkgxtpn4i-single-layer-hamt-with-multi-block-files.car');
69
+ });
70
+ it('loads path /ipfs/bafybeidbclfqleg2uojchspzd4bob56dqetqjsj27gy2cq3klkkgxtpn4i/685.txt', async () => {
71
+ const resp = await verifiedFetch('ipfs://bafybeidbclfqleg2uojchspzd4bob56dqetqjsj27gy2cq3klkkgxtpn4i/685.txt');
72
+ expect(resp).to.be.ok();
73
+ const text = await resp.text();
74
+ // npx kubo@0.25.0 cat '/ipfs/bafybeidbclfqleg2uojchspzd4bob56dqetqjsj27gy2cq3klkkgxtpn4i/685.txt'
75
+ expect(text).to.equal(`Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc non imperdiet nunc. Proin ac quam ut nibh eleifend aliquet. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Sed ligula dolor, imperdiet sagittis arcu et, semper tincidunt urna. Donec et tempor augue, quis sollicitudin metus. Curabitur semper ullamcorper aliquet. Mauris hendrerit sodales lectus eget fermentum. Proin sollicitudin vestibulum commodo. Vivamus nec lectus eu augue aliquet dignissim nec condimentum justo. In hac habitasse platea dictumst. Mauris vel sem neque.
76
+
77
+ Vivamus finibus, enim at lacinia semper, arcu erat gravida lacus, sit amet gravida magna orci sit amet est. Sed non leo lacus. Nullam viverra ipsum a tincidunt dapibus. Nulla pulvinar ligula sit amet ante ultrices tempus. Proin purus urna, semper sed lobortis quis, gravida vitae ipsum. Aliquam mi urna, pulvinar eu bibendum quis, convallis ac dolor. In gravida justo sed risus ullamcorper, vitae luctus massa hendrerit. Pellentesque habitant amet.`);
78
+ });
79
+ });
80
+ });
81
+ //# sourceMappingURL=unixfs-dir.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unixfs-dir.spec.js","sourceRoot":"","sources":["../../src/unixfs-dir.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=websites.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websites.spec.d.ts","sourceRoot":"","sources":["../../src/websites.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,76 @@
1
+ /* eslint-env mocha */
2
+ import { createVerifiedFetch } from '@helia/verified-fetch';
3
+ import { expect } from 'aegir/chai';
4
+ import { createKuboNode } from './fixtures/create-kubo.js';
5
+ import { loadFixtureDataCar } from './fixtures/load-fixture-data.js';
6
+ describe('@helia/verified-fetch - websites', () => {
7
+ describe('helia-identify.on.fleek.co', () => {
8
+ let controller;
9
+ let verifiedFetch;
10
+ before(async () => {
11
+ controller = await createKuboNode();
12
+ await controller.start();
13
+ // 2024-01-22 CID for _dnslink.helia-identify.on.fleek.co
14
+ await loadFixtureDataCar(controller, 'QmbxpRxwKXxnJQjnPqm1kzDJSJ8YgkLxH23mcZURwPHjGv-helia-identify-website.car');
15
+ verifiedFetch = await createVerifiedFetch({
16
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
17
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
18
+ });
19
+ });
20
+ after(async () => {
21
+ await controller.stop();
22
+ await verifiedFetch.stop();
23
+ });
24
+ it('loads index.html when passed helia-identify.on.fleek.co root CID', async () => {
25
+ const resp = await verifiedFetch('ipfs://QmbxpRxwKXxnJQjnPqm1kzDJSJ8YgkLxH23mcZURwPHjGv');
26
+ expect(resp).to.be.ok();
27
+ const html = await resp.text();
28
+ expect(html).to.be.ok();
29
+ expect(html).to.include('<title>Run Identify on a remote node with Helia</title>');
30
+ });
31
+ it('loads helia-identify.on.fleek.co index.html directly ', async () => {
32
+ const resp = await verifiedFetch('ipfs://QmbxpRxwKXxnJQjnPqm1kzDJSJ8YgkLxH23mcZURwPHjGv/index.html');
33
+ expect(resp).to.be.ok();
34
+ const html = await resp.text();
35
+ expect(html).to.be.ok();
36
+ expect(html).to.include('<title>Run Identify on a remote node with Helia</title>');
37
+ });
38
+ });
39
+ /**
40
+ *
41
+ * Created on 2024-01-23. /ipns/blog.libp2p.io/index.html resolved to QmVZNGy6SPvUbvQCXXaGDdp8kvfJm9MMozjU12dyzH6hKf
42
+ *
43
+ * ```shell
44
+ * mkdir fake-blog.libp2p.io
45
+ * npx kubo@0.25.0 cat '/ipfs/QmVZNGy6SPvUbvQCXXaGDdp8kvfJm9MMozjU12dyzH6hKf' > fake-blog.libp2p.io/index.html
46
+ * npx kubo@0.25.0 add -r fake-blog.libp2p.io
47
+ * npx kubo@0.25.0 dag export QmeiDMLtPUS3RT2xAcUwsNyZz169wPke2q7im9vZpVLSYw > QmeiDMLtPUS3RT2xAcUwsNyZz169wPke2q7im9vZpVLSYw-fake-blog.libp2p.io.car
48
+ * ```
49
+ */
50
+ describe('fake blog.libp2p.io', () => {
51
+ let controller;
52
+ let verifiedFetch;
53
+ before(async () => {
54
+ controller = await createKuboNode();
55
+ await controller.start();
56
+ await loadFixtureDataCar(controller, 'QmeiDMLtPUS3RT2xAcUwsNyZz169wPke2q7im9vZpVLSYw-fake-blog.libp2p.io.car');
57
+ verifiedFetch = await createVerifiedFetch({
58
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
59
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
60
+ });
61
+ });
62
+ after(async () => {
63
+ await controller.stop();
64
+ await verifiedFetch.stop();
65
+ });
66
+ it('loads index.html when passed fake-blog.libp2p.io root CID', async () => {
67
+ const resp = await verifiedFetch('ipfs://QmeiDMLtPUS3RT2xAcUwsNyZz169wPke2q7im9vZpVLSYw');
68
+ expect(resp).to.be.ok();
69
+ const html = await resp.text();
70
+ expect(html).to.be.ok();
71
+ expect(html).to.include('<title>Home | libp2p Blog &#x26; News</title>');
72
+ expect(html).to.include('<link href="https://libp2p.io/" rel="canonical">');
73
+ });
74
+ });
75
+ });
76
+ //# sourceMappingURL=websites.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websites.spec.js","sourceRoot":"","sources":["../../src/websites.spec.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,69 @@
1
+ {
2
+ "name": "@helia/verified-fetch-interop",
3
+ "version": "0.0.0",
4
+ "description": "Interop tests for @helia/verified-fetch",
5
+ "license": "Apache-2.0 OR MIT",
6
+ "homepage": "https://github.com/ipfs/helia-verified-fetch/tree/main/packages/interop#readme",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/ipfs/helia-verified-fetch.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/ipfs/helia-verified-fetch/issues"
13
+ },
14
+ "keywords": [
15
+ "IPFS"
16
+ ],
17
+ "bin": {
18
+ "helia-verified-fetch-interop": "./dist/src/bin.js"
19
+ },
20
+ "type": "module",
21
+ "types": "./dist/src/index.d.ts",
22
+ "files": [
23
+ "src",
24
+ "dist",
25
+ "!dist/test",
26
+ "!**/*.tsbuildinfo"
27
+ ],
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/src/index.d.ts",
31
+ "import": "./dist/src/index.js"
32
+ }
33
+ },
34
+ "eslintConfig": {
35
+ "extends": "ipfs",
36
+ "parserOptions": {
37
+ "project": true,
38
+ "sourceType": "module"
39
+ }
40
+ },
41
+ "scripts": {
42
+ "clean": "aegir clean",
43
+ "lint": "aegir lint",
44
+ "dep-check": "aegir dep-check",
45
+ "doc-check": "aegir doc-check",
46
+ "build": "aegir build",
47
+ "test": "aegir test",
48
+ "test:chrome": "aegir test -t browser --cov",
49
+ "test:chrome-webworker": "aegir test -t webworker",
50
+ "test:firefox": "aegir test -t browser -- --browser firefox",
51
+ "test:firefox-webworker": "aegir test -t webworker -- --browser firefox",
52
+ "test:node": "aegir test -t node --cov",
53
+ "test:electron-main": "aegir test -t electron-main"
54
+ },
55
+ "dependencies": {
56
+ "@helia/verified-fetch": "~0.0.0",
57
+ "aegir": "^42.2.5",
58
+ "ipfsd-ctl": "^13.0.0",
59
+ "it-drain": "^3.0.5",
60
+ "kubo": "^0.26.0",
61
+ "kubo-rpc-client": "^3.0.3",
62
+ "magic-bytes.js": "^1.8.0",
63
+ "multiformats": "^13.1.0"
64
+ },
65
+ "browser": {
66
+ "./dist/src/fixtures/create-kubo.js": "./dist/src/fixtures/create-kubo.browser.js",
67
+ "kubo": false
68
+ }
69
+ }
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 'node:path'
6
+ import { fileURLToPath } from 'node: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,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,9 @@
1
+ import loadFixture from 'aegir/fixtures'
2
+ import drain from 'it-drain'
3
+ import type { Controller } from 'ipfsd-ctl'
4
+
5
+ export async function loadFixtureDataCar (controller: Controller, path: string): Promise<void> {
6
+ const fixtureData = `src/fixtures/data/${path}`
7
+ const buf = loadFixture(fixtureData)
8
+ await drain(controller.api.dag.import([buf]))
9
+ }
package/src/index.ts ADDED
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @packageDocumentation
3
+ *
4
+ * Runs interop tests between @helia/verified-fetch and Kubo.
5
+ *
6
+ * @example Testing a new Kubo release
7
+ *
8
+ * ```console
9
+ * $ npm i @helia/verified-fetch-interop
10
+ * $ KUBO_BINARY=/path/to/kubo helia-verified-fetch-interop
11
+ * ```
12
+ */
13
+
14
+ export {}
@@ -0,0 +1,47 @@
1
+ /* eslint-env mocha */
2
+ import { createVerifiedFetch } from '@helia/verified-fetch'
3
+ import { expect } from 'aegir/chai'
4
+ import { CID } from 'multiformats/cid'
5
+ import { createKuboNode } from './fixtures/create-kubo.js'
6
+ import { loadFixtureDataCar } from './fixtures/load-fixture-data.js'
7
+ import type { Controller } from 'ipfsd-ctl'
8
+
9
+ describe('@helia/verified-fetch - json', () => {
10
+ describe('unixfs - multiblock', () => {
11
+ let controller: Controller<'go'>
12
+ let verifiedFetch: Awaited<ReturnType<typeof createVerifiedFetch>>
13
+
14
+ before(async () => {
15
+ controller = await createKuboNode()
16
+ await controller.start()
17
+ // As of 2024-01-18, https://cloudflare-ipfs.com/ipns/tokens.uniswap.org resolves to:
18
+ // root: QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr
19
+ // child1: QmNik5N4ryNwzzXYq5hCYKGcRjAf9QtigxtiJh9o8aXXbG // partial JSON
20
+ // child2: QmWNBJX6fZyNTLWNYBHxAHpBctCP43R2zeqV2G8uavqFZn // partial JSON
21
+ await loadFixtureDataCar(controller, 'QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr-tokens.uniswap.org-2024-01-18.car')
22
+ verifiedFetch = await createVerifiedFetch({
23
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
24
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
25
+ })
26
+ })
27
+
28
+ after(async () => {
29
+ await controller.stop()
30
+ await verifiedFetch.stop()
31
+ })
32
+
33
+ it('handles UnixFS-chunked JSON file', async () => {
34
+ const resp = await verifiedFetch(CID.parse('QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr'))
35
+ expect(resp).to.be.ok()
36
+ const jsonObj = await resp.json()
37
+ expect(jsonObj).to.be.ok()
38
+ expect(jsonObj).to.have.property('name').equal('Uniswap Labs Default')
39
+ expect(jsonObj).to.have.property('timestamp').equal('2023-12-13T18:25:25.830Z')
40
+ expect(jsonObj).to.have.property('version').to.deep.equal({ major: 11, minor: 11, patch: 0 })
41
+ expect(jsonObj).to.have.property('tags')
42
+ expect(jsonObj).to.have.property('logoURI').equal('ipfs://QmNa8mQkrNKp1WEEeGjFezDmDeodkWRevGFN8JCV7b4Xir')
43
+ expect(jsonObj).to.have.property('keywords').to.deep.equal(['uniswap', 'default'])
44
+ expect(jsonObj.tokens).to.be.an('array').of.length(767)
45
+ })
46
+ })
47
+ })
@@ -0,0 +1,94 @@
1
+ /* eslint-env mocha */
2
+ import { createVerifiedFetch } from '@helia/verified-fetch'
3
+ import { expect } from 'aegir/chai'
4
+ import { filetypemime } from 'magic-bytes.js'
5
+ import { createKuboNode } from './fixtures/create-kubo.js'
6
+ import { loadFixtureDataCar } from './fixtures/load-fixture-data.js'
7
+ import type { VerifiedFetch } from '@helia/verified-fetch'
8
+ import type { Controller } from 'ipfsd-ctl'
9
+
10
+ describe('@helia/verified-fetch - unixfs directory', () => {
11
+ let controller: Controller
12
+ let verifiedFetch: VerifiedFetch
13
+
14
+ before(async () => {
15
+ controller = await createKuboNode()
16
+ await controller.start()
17
+
18
+ verifiedFetch = await createVerifiedFetch({
19
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
20
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
21
+ })
22
+ })
23
+
24
+ after(async () => {
25
+ await controller.stop()
26
+ await verifiedFetch.stop()
27
+ })
28
+
29
+ describe('XKCD Barrel Part 1', () => {
30
+ before(async () => {
31
+ // This is the content of https://explore.ipld.io/#/explore/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm/1%20-%20Barrel%20-%20Part%201
32
+ await loadFixtureDataCar(controller, 'QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR-xkcd-Barrel-part-1.car')
33
+ })
34
+
35
+ it('fails to load when passed the root', async () => {
36
+ // The spec says we should generate HTML with directory listings, but we don't do that yet, so expect a failure
37
+ const resp = await verifiedFetch('ipfs://QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR')
38
+ expect(resp).to.be.ok()
39
+ expect(resp.status).to.equal(501) // TODO: we should do a directory listing instead
40
+ })
41
+
42
+ it('can return a string for unixfs pathed data', async () => {
43
+ const resp = await verifiedFetch('ipfs://QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR/1 - Barrel - Part 1 - alt.txt')
44
+ expect(resp).to.be.ok()
45
+ const text = await resp.text()
46
+ expect(text).to.equal('Don\'t we all.')
47
+ })
48
+
49
+ it('can return an image for unixfs pathed data', async () => {
50
+ const resp = await verifiedFetch('ipfs://QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR/1 - Barrel - Part 1.png')
51
+ expect(resp).to.be.ok()
52
+ const imgData = await resp.blob()
53
+ expect(imgData).to.be.ok()
54
+ expect(imgData.size).to.equal(24848)
55
+ })
56
+ })
57
+
58
+ describe('content type parser', () => {
59
+ before(async () => {
60
+ await verifiedFetch.stop()
61
+ verifiedFetch = await createVerifiedFetch({
62
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
63
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
64
+ }, {
65
+ contentTypeParser: (bytes) => {
66
+ return filetypemime(bytes)?.[0]
67
+ }
68
+ })
69
+ })
70
+
71
+ it('can return an image content-type for unixfs pathed data', async () => {
72
+ const resp = await verifiedFetch('ipfs://QmbQDovX7wRe9ek7u6QXe9zgCXkTzoUSsTFJEkrYV1HrVR/1 - Barrel - Part 1.png')
73
+ // tediously this is actually a jpeg file with a .png extension
74
+ expect(resp.headers.get('content-type')).to.equal('image/jpeg')
75
+ })
76
+ })
77
+
78
+ describe('HAMT-sharded directory', () => {
79
+ before(async () => {
80
+ // from https://github.com/ipfs/gateway-conformance/blob/193833b91f2e9b17daf45c84afaeeae61d9d7c7e/fixtures/trustless_gateway_car/single-layer-hamt-with-multi-block-files.car
81
+ await loadFixtureDataCar(controller, 'bafybeidbclfqleg2uojchspzd4bob56dqetqjsj27gy2cq3klkkgxtpn4i-single-layer-hamt-with-multi-block-files.car')
82
+ })
83
+
84
+ it('loads path /ipfs/bafybeidbclfqleg2uojchspzd4bob56dqetqjsj27gy2cq3klkkgxtpn4i/685.txt', async () => {
85
+ const resp = await verifiedFetch('ipfs://bafybeidbclfqleg2uojchspzd4bob56dqetqjsj27gy2cq3klkkgxtpn4i/685.txt')
86
+ expect(resp).to.be.ok()
87
+ const text = await resp.text()
88
+ // npx kubo@0.25.0 cat '/ipfs/bafybeidbclfqleg2uojchspzd4bob56dqetqjsj27gy2cq3klkkgxtpn4i/685.txt'
89
+ expect(text).to.equal(`Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc non imperdiet nunc. Proin ac quam ut nibh eleifend aliquet. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Sed ligula dolor, imperdiet sagittis arcu et, semper tincidunt urna. Donec et tempor augue, quis sollicitudin metus. Curabitur semper ullamcorper aliquet. Mauris hendrerit sodales lectus eget fermentum. Proin sollicitudin vestibulum commodo. Vivamus nec lectus eu augue aliquet dignissim nec condimentum justo. In hac habitasse platea dictumst. Mauris vel sem neque.
90
+
91
+ Vivamus finibus, enim at lacinia semper, arcu erat gravida lacus, sit amet gravida magna orci sit amet est. Sed non leo lacus. Nullam viverra ipsum a tincidunt dapibus. Nulla pulvinar ligula sit amet ante ultrices tempus. Proin purus urna, semper sed lobortis quis, gravida vitae ipsum. Aliquam mi urna, pulvinar eu bibendum quis, convallis ac dolor. In gravida justo sed risus ullamcorper, vitae luctus massa hendrerit. Pellentesque habitant amet.`)
92
+ })
93
+ })
94
+ })
@@ -0,0 +1,85 @@
1
+ /* eslint-env mocha */
2
+ import { createVerifiedFetch } from '@helia/verified-fetch'
3
+ import { expect } from 'aegir/chai'
4
+ import { createKuboNode } from './fixtures/create-kubo.js'
5
+ import { loadFixtureDataCar } from './fixtures/load-fixture-data.js'
6
+ import type { Controller } from 'ipfsd-ctl'
7
+
8
+ describe('@helia/verified-fetch - websites', () => {
9
+ describe('helia-identify.on.fleek.co', () => {
10
+ let controller: Controller<'go'>
11
+ let verifiedFetch: Awaited<ReturnType<typeof createVerifiedFetch>>
12
+
13
+ before(async () => {
14
+ controller = await createKuboNode()
15
+ await controller.start()
16
+ // 2024-01-22 CID for _dnslink.helia-identify.on.fleek.co
17
+ await loadFixtureDataCar(controller, 'QmbxpRxwKXxnJQjnPqm1kzDJSJ8YgkLxH23mcZURwPHjGv-helia-identify-website.car')
18
+ verifiedFetch = await createVerifiedFetch({
19
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
20
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
21
+ })
22
+ })
23
+
24
+ after(async () => {
25
+ await controller.stop()
26
+ await verifiedFetch.stop()
27
+ })
28
+
29
+ it('loads index.html when passed helia-identify.on.fleek.co root CID', async () => {
30
+ const resp = await verifiedFetch('ipfs://QmbxpRxwKXxnJQjnPqm1kzDJSJ8YgkLxH23mcZURwPHjGv')
31
+ expect(resp).to.be.ok()
32
+ const html = await resp.text()
33
+ expect(html).to.be.ok()
34
+ expect(html).to.include('<title>Run Identify on a remote node with Helia</title>')
35
+ })
36
+
37
+ it('loads helia-identify.on.fleek.co index.html directly ', async () => {
38
+ const resp = await verifiedFetch('ipfs://QmbxpRxwKXxnJQjnPqm1kzDJSJ8YgkLxH23mcZURwPHjGv/index.html')
39
+ expect(resp).to.be.ok()
40
+ const html = await resp.text()
41
+ expect(html).to.be.ok()
42
+ expect(html).to.include('<title>Run Identify on a remote node with Helia</title>')
43
+ })
44
+ })
45
+
46
+ /**
47
+ *
48
+ * Created on 2024-01-23. /ipns/blog.libp2p.io/index.html resolved to QmVZNGy6SPvUbvQCXXaGDdp8kvfJm9MMozjU12dyzH6hKf
49
+ *
50
+ * ```shell
51
+ * mkdir fake-blog.libp2p.io
52
+ * npx kubo@0.25.0 cat '/ipfs/QmVZNGy6SPvUbvQCXXaGDdp8kvfJm9MMozjU12dyzH6hKf' > fake-blog.libp2p.io/index.html
53
+ * npx kubo@0.25.0 add -r fake-blog.libp2p.io
54
+ * npx kubo@0.25.0 dag export QmeiDMLtPUS3RT2xAcUwsNyZz169wPke2q7im9vZpVLSYw > QmeiDMLtPUS3RT2xAcUwsNyZz169wPke2q7im9vZpVLSYw-fake-blog.libp2p.io.car
55
+ * ```
56
+ */
57
+ describe('fake blog.libp2p.io', () => {
58
+ let controller: Controller<'go'>
59
+ let verifiedFetch: Awaited<ReturnType<typeof createVerifiedFetch>>
60
+
61
+ before(async () => {
62
+ controller = await createKuboNode()
63
+ await controller.start()
64
+ await loadFixtureDataCar(controller, 'QmeiDMLtPUS3RT2xAcUwsNyZz169wPke2q7im9vZpVLSYw-fake-blog.libp2p.io.car')
65
+ verifiedFetch = await createVerifiedFetch({
66
+ gateways: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`],
67
+ routers: [`http://${controller.api.gatewayHost}:${controller.api.gatewayPort}`]
68
+ })
69
+ })
70
+
71
+ after(async () => {
72
+ await controller.stop()
73
+ await verifiedFetch.stop()
74
+ })
75
+
76
+ it('loads index.html when passed fake-blog.libp2p.io root CID', async () => {
77
+ const resp = await verifiedFetch('ipfs://QmeiDMLtPUS3RT2xAcUwsNyZz169wPke2q7im9vZpVLSYw')
78
+ expect(resp).to.be.ok()
79
+ const html = await resp.text()
80
+ expect(html).to.be.ok()
81
+ expect(html).to.include('<title>Home | libp2p Blog &#x26; News</title>')
82
+ expect(html).to.include('<link href="https://libp2p.io/" rel="canonical">')
83
+ })
84
+ })
85
+ })