@helia/interop 3.0.1-19bf9ce → 3.0.1-4836d52

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.
@@ -0,0 +1,4 @@
1
+ import { type HeliaHTTPInit } from '@helia/http';
2
+ import type { Helia } from '@helia/interface';
3
+ export declare function createHeliaHTTP(init?: Partial<HeliaHTTPInit>): Promise<Helia>;
4
+ //# sourceMappingURL=create-helia-http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-helia-http.d.ts","sourceRoot":"","sources":["../../../src/fixtures/create-helia-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAChF,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAE7C,wBAAsB,eAAe,CAAE,IAAI,GAAE,OAAO,CAAC,aAAa,CAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAIxF"}
@@ -0,0 +1,7 @@
1
+ import { createHeliaHTTP as createHelia } from '@helia/http';
2
+ export async function createHeliaHTTP(init = {}) {
3
+ return createHelia({
4
+ ...init
5
+ });
6
+ }
7
+ //# sourceMappingURL=create-helia-http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-helia-http.js","sourceRoot":"","sources":["../../../src/fixtures/create-helia-http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,IAAI,WAAW,EAAsB,MAAM,aAAa,CAAA;AAGhF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAE,OAA+B,EAAE;IACtE,OAAO,WAAW,CAAC;QACjB,GAAG,IAAI;KACR,CAAC,CAAA;AACJ,CAAC"}
@@ -1 +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,CAiB3D"}
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"}
@@ -11,7 +11,16 @@ export async function createKuboNode() {
11
11
  Swarm: [
12
12
  '/ip4/0.0.0.0/tcp/0',
13
13
  '/ip4/0.0.0.0/tcp/0/ws'
14
- ]
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
+ }
15
24
  }
16
25
  }
17
26
  },
@@ -1 +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;iBACF;aACF;SACF;QACD,IAAI,EAAE,CAAC,4BAA4B,EAAE,yBAAyB,CAAC;KAChE,CAAC,CAAA;AACJ,CAAC"}
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"}
@@ -1 +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,CAiB3D"}
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"}
@@ -13,7 +13,16 @@ export async function createKuboNode() {
13
13
  Swarm: [
14
14
  '/ip4/0.0.0.0/tcp/4001',
15
15
  '/ip4/0.0.0.0/tcp/4002/ws'
16
- ]
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
+ }
17
26
  }
18
27
  }
19
28
  },
@@ -1 +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;iBACF;aACF;SACF;QACD,IAAI,EAAE,CAAC,4BAA4B,EAAE,yBAAyB,CAAC;KAChE,CAAC,CAAA;AACJ,CAAC"}
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=ipns-http.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipns-http.spec.d.ts","sourceRoot":"","sources":["../../src/ipns-http.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ /* eslint-env mocha */
2
+ import { ipns } from '@helia/ipns';
3
+ import { delegatedHTTPRouting } from '@helia/routers';
4
+ import { peerIdFromString } from '@libp2p/peer-id';
5
+ import { expect } from 'aegir/chai';
6
+ import { isNode } from 'wherearewe';
7
+ import { createHeliaHTTP } from './fixtures/create-helia-http.js';
8
+ import { createKuboNode } from './fixtures/create-kubo.js';
9
+ describe('@helia/ipns - http', () => {
10
+ let helia;
11
+ let kubo;
12
+ let name;
13
+ /**
14
+ * Ensure that for the CID we are going to publish, the resolver has a peer ID that
15
+ * is KAD-closer to the routing key so we can predict the the resolver will receive
16
+ * the DHT record containing the IPNS record
17
+ */
18
+ beforeEach(async () => {
19
+ kubo = await createKuboNode();
20
+ helia = await createHeliaHTTP({
21
+ routers: [
22
+ delegatedHTTPRouting('http://127.0.0.1:8180')
23
+ ]
24
+ });
25
+ name = ipns(helia);
26
+ });
27
+ afterEach(async () => {
28
+ if (helia != null) {
29
+ await helia.stop();
30
+ }
31
+ if (kubo != null) {
32
+ await kubo.stop();
33
+ }
34
+ });
35
+ it('should publish on kubo and resolve on helia', async function () {
36
+ if (!isNode) {
37
+ // https://github.com/protocol/bifrost-community/issues/4#issuecomment-1898417008
38
+ return this.skip();
39
+ }
40
+ const keyName = 'my-ipns-key';
41
+ const { cid } = await kubo.api.add(Uint8Array.from([0, 1, 2, 3, 4]));
42
+ await kubo.api.key.gen(keyName, {
43
+ // @ts-expect-error the types say upper-case E, Kubo errors unless it's a
44
+ // lower case e
45
+ type: 'ed25519'
46
+ });
47
+ const res = await kubo.api.name.publish(cid, {
48
+ key: keyName
49
+ });
50
+ const key = peerIdFromString(res.name);
51
+ const resolvedCid = await name.resolve(key);
52
+ expect(resolvedCid.toString()).to.equal(cid.toString());
53
+ });
54
+ });
55
+ //# sourceMappingURL=ipns-http.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ipns-http.spec.js","sourceRoot":"","sources":["../../src/ipns-http.spec.ts"],"names":[],"mappings":"AAAA,sBAAsB;AAEtB,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAA;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAK1D,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,IAAI,KAAY,CAAA;IAChB,IAAI,IAAgB,CAAA;IACpB,IAAI,IAAU,CAAA;IAEd;;;;OAIG;IACH,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,IAAI,GAAG,MAAM,cAAc,EAAE,CAAA;QAC7B,KAAK,GAAG,MAAM,eAAe,CAAC;YAC5B,OAAO,EAAE;gBACP,oBAAoB,CAAC,uBAAuB,CAAC;aAC9C;SACF,CAAC,CAAA;QACF,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;IACpB,CAAC,CAAC,CAAA;IAEF,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,MAAM,KAAK,CAAC,IAAI,EAAE,CAAA;QACpB,CAAC;QAED,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,IAAI,EAAE,CAAA;QACnB,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6CAA6C,EAAE,KAAK;QACrD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,iFAAiF;YACjF,OAAO,IAAI,CAAC,IAAI,EAAE,CAAA;QACpB,CAAC;QAED,MAAM,OAAO,GAAG,aAAa,CAAA;QAC7B,MAAM,EAAE,GAAG,EAAE,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAEpE,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE;YAC9B,yEAAyE;YACzE,eAAe;YACf,IAAI,EAAE,SAAS;SAChB,CAAC,CAAA;QAEF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE;YAC3C,GAAG,EAAE,OAAO;SACb,CAAC,CAAA;QAEF,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QAEtC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC3C,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helia/interop",
3
- "version": "3.0.1-19bf9ce",
3
+ "version": "3.0.1-4836d52",
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",
@@ -57,15 +57,18 @@
57
57
  "test:electron-main": "aegir test -t electron-main"
58
58
  },
59
59
  "dependencies": {
60
- "@helia/block-brokers": "1.0.0-19bf9ce",
61
- "@helia/car": "2.0.1-19bf9ce",
62
- "@helia/dag-cbor": "2.0.1-19bf9ce",
63
- "@helia/dag-json": "2.0.1-19bf9ce",
64
- "@helia/ipns": "4.0.0-19bf9ce",
65
- "@helia/json": "2.0.1-19bf9ce",
66
- "@helia/mfs": "2.0.1-19bf9ce",
67
- "@helia/strings": "2.0.1-19bf9ce",
68
- "@helia/unixfs": "2.0.1-19bf9ce",
60
+ "@helia/block-brokers": "1.0.0-4836d52",
61
+ "@helia/car": "2.0.1-4836d52",
62
+ "@helia/dag-cbor": "2.0.1-4836d52",
63
+ "@helia/dag-json": "2.0.1-4836d52",
64
+ "@helia/http": "0.9.0-4836d52",
65
+ "@helia/interface": "3.0.1-4836d52",
66
+ "@helia/ipns": "4.0.0-4836d52",
67
+ "@helia/json": "2.0.1-4836d52",
68
+ "@helia/mfs": "2.0.1-4836d52",
69
+ "@helia/routers": "0.0.0-4836d52",
70
+ "@helia/strings": "2.0.1-4836d52",
71
+ "@helia/unixfs": "2.0.1-4836d52",
69
72
  "@ipld/car": "^5.2.5",
70
73
  "@ipld/dag-cbor": "^9.0.7",
71
74
  "@libp2p/interface": "^1.1.1",
@@ -75,7 +78,7 @@
75
78
  "@libp2p/websockets": "^8.0.10",
76
79
  "@multiformats/sha3": "^3.0.0",
77
80
  "aegir": "^42.1.0",
78
- "helia": "3.0.1-19bf9ce",
81
+ "helia": "3.0.1-4836d52",
79
82
  "ipfs-core-types": "^0.14.1",
80
83
  "ipfs-unixfs-importer": "^15.2.3",
81
84
  "ipfsd-ctl": "^13.0.0",
@@ -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
+ }
@@ -12,7 +12,16 @@ export async function createKuboNode (): Promise<Controller> {
12
12
  Swarm: [
13
13
  '/ip4/0.0.0.0/tcp/0',
14
14
  '/ip4/0.0.0.0/tcp/0/ws'
15
- ]
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
+ }
16
25
  }
17
26
  }
18
27
  },
@@ -14,7 +14,16 @@ export async function createKuboNode (): Promise<Controller> {
14
14
  Swarm: [
15
15
  '/ip4/0.0.0.0/tcp/4001',
16
16
  '/ip4/0.0.0.0/tcp/4002/ws'
17
- ]
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
+ }
18
27
  }
19
28
  }
20
29
  },
@@ -0,0 +1,68 @@
1
+ /* eslint-env mocha */
2
+
3
+ import { ipns } from '@helia/ipns'
4
+ import { delegatedHTTPRouting } from '@helia/routers'
5
+ import { peerIdFromString } from '@libp2p/peer-id'
6
+ import { expect } from 'aegir/chai'
7
+ import { isNode } from 'wherearewe'
8
+ import { createHeliaHTTP } from './fixtures/create-helia-http.js'
9
+ import { createKuboNode } from './fixtures/create-kubo.js'
10
+ import type { Helia } from '@helia/interface'
11
+ import type { IPNS } from '@helia/ipns'
12
+ import type { Controller } from 'ipfsd-ctl'
13
+
14
+ describe('@helia/ipns - http', () => {
15
+ let helia: Helia
16
+ let kubo: Controller
17
+ let name: IPNS
18
+
19
+ /**
20
+ * Ensure that for the CID we are going to publish, the resolver has a peer ID that
21
+ * is KAD-closer to the routing key so we can predict the the resolver will receive
22
+ * the DHT record containing the IPNS record
23
+ */
24
+ beforeEach(async () => {
25
+ kubo = await createKuboNode()
26
+ helia = await createHeliaHTTP({
27
+ routers: [
28
+ delegatedHTTPRouting('http://127.0.0.1:8180')
29
+ ]
30
+ })
31
+ name = ipns(helia)
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 publish on kubo and resolve on helia', async function () {
45
+ if (!isNode) {
46
+ // https://github.com/protocol/bifrost-community/issues/4#issuecomment-1898417008
47
+ return this.skip()
48
+ }
49
+
50
+ const keyName = 'my-ipns-key'
51
+ const { cid } = await kubo.api.add(Uint8Array.from([0, 1, 2, 3, 4]))
52
+
53
+ await kubo.api.key.gen(keyName, {
54
+ // @ts-expect-error the types say upper-case E, Kubo errors unless it's a
55
+ // lower case e
56
+ type: 'ed25519'
57
+ })
58
+
59
+ const res = await kubo.api.name.publish(cid, {
60
+ key: keyName
61
+ })
62
+
63
+ const key = peerIdFromString(res.name)
64
+
65
+ const resolvedCid = await name.resolve(key)
66
+ expect(resolvedCid.toString()).to.equal(cid.toString())
67
+ })
68
+ })