@helia/ipns 9.2.0 → 9.2.1-17530ed8

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 (69) hide show
  1. package/README.md +21 -57
  2. package/dist/index.min.js +9 -23
  3. package/dist/index.min.js.map +4 -4
  4. package/dist/src/errors.d.ts +33 -5
  5. package/dist/src/errors.d.ts.map +1 -1
  6. package/dist/src/errors.js +33 -20
  7. package/dist/src/errors.js.map +1 -1
  8. package/dist/src/index.d.ts +62 -99
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/index.js +21 -60
  11. package/dist/src/index.js.map +1 -1
  12. package/dist/src/ipns/publisher.d.ts +5 -9
  13. package/dist/src/ipns/publisher.d.ts.map +1 -1
  14. package/dist/src/ipns/publisher.js +30 -22
  15. package/dist/src/ipns/publisher.js.map +1 -1
  16. package/dist/src/ipns/republisher.d.ts +3 -5
  17. package/dist/src/ipns/republisher.d.ts.map +1 -1
  18. package/dist/src/ipns/republisher.js +18 -9
  19. package/dist/src/ipns/republisher.js.map +1 -1
  20. package/dist/src/ipns/resolver.d.ts +6 -5
  21. package/dist/src/ipns/resolver.d.ts.map +1 -1
  22. package/dist/src/ipns/resolver.js +32 -78
  23. package/dist/src/ipns/resolver.js.map +1 -1
  24. package/dist/src/ipns.d.ts +6 -4
  25. package/dist/src/ipns.d.ts.map +1 -1
  26. package/dist/src/ipns.js +33 -4
  27. package/dist/src/ipns.js.map +1 -1
  28. package/dist/src/pb/ipns.d.ts +62 -0
  29. package/dist/src/pb/ipns.d.ts.map +1 -0
  30. package/dist/src/pb/ipns.js +203 -0
  31. package/dist/src/pb/ipns.js.map +1 -0
  32. package/dist/src/pb/metadata.d.ts +1 -1
  33. package/dist/src/pb/metadata.d.ts.map +1 -1
  34. package/dist/src/records.d.ts +155 -0
  35. package/dist/src/records.d.ts.map +1 -0
  36. package/dist/src/records.js +88 -0
  37. package/dist/src/records.js.map +1 -0
  38. package/dist/src/routing/pubsub.d.ts +3 -0
  39. package/dist/src/routing/pubsub.d.ts.map +1 -1
  40. package/dist/src/routing/pubsub.js +15 -10
  41. package/dist/src/routing/pubsub.js.map +1 -1
  42. package/dist/src/selector.d.ts +14 -0
  43. package/dist/src/selector.d.ts.map +1 -0
  44. package/dist/src/selector.js +47 -0
  45. package/dist/src/selector.js.map +1 -0
  46. package/dist/src/utils.d.ts +29 -2
  47. package/dist/src/utils.d.ts.map +1 -1
  48. package/dist/src/utils.js +308 -0
  49. package/dist/src/utils.js.map +1 -1
  50. package/dist/src/validator.d.ts +18 -0
  51. package/dist/src/validator.d.ts.map +1 -0
  52. package/dist/src/validator.js +58 -0
  53. package/dist/src/validator.js.map +1 -0
  54. package/package.json +32 -28
  55. package/src/errors.ts +40 -25
  56. package/src/index.ts +63 -100
  57. package/src/ipns/publisher.ts +34 -29
  58. package/src/ipns/republisher.ts +24 -13
  59. package/src/ipns/resolver.ts +40 -88
  60. package/src/ipns.ts +44 -7
  61. package/src/pb/ipns.proto +39 -0
  62. package/src/pb/ipns.ts +280 -0
  63. package/src/pb/metadata.ts +1 -1
  64. package/src/records.ts +273 -0
  65. package/src/routing/pubsub.ts +17 -10
  66. package/src/selector.ts +55 -0
  67. package/src/utils.ts +371 -2
  68. package/src/validator.ts +67 -0
  69. package/dist/typedoc-urls.json +0 -51
@@ -0,0 +1,58 @@
1
+ import NanoDate from 'timestamp-nano';
2
+ import { InvalidEmbeddedPublicKeyError, RecordExpiredError, SignatureVerificationError, UnsupportedValidityError } from "./errors.js";
3
+ import { IpnsEntry } from "./pb/ipns.js";
4
+ import { ipnsRecordDataForV2Sig } from "./utils.js";
5
+ /**
6
+ * Validate the given IPNS record against the given routing key.
7
+ *
8
+ * @see https://specs.ipfs.tech/ipns/ipns-record/#routing-record for the binary
9
+ * format of the routing key
10
+ */
11
+ export async function ipnsValidator(record, options) {
12
+ if (record.publicKey == null) {
13
+ throw new InvalidEmbeddedPublicKeyError('The record had no public key associated with it');
14
+ }
15
+ // Validate Signature V2
16
+ let isValid;
17
+ try {
18
+ const dataForSignature = ipnsRecordDataForV2Sig(record.data);
19
+ isValid = await record.publicKey.verify(dataForSignature, record.signatureV2, options);
20
+ }
21
+ catch {
22
+ isValid = false;
23
+ }
24
+ if (!isValid) {
25
+ throw new SignatureVerificationError('Record signature verification failed');
26
+ }
27
+ // Validate according to the validity type
28
+ if (record.validityType === IpnsEntry.ValidityType.EOL) {
29
+ if (NanoDate.fromString(record.validity).toDate().getTime() < Date.now()) {
30
+ throw new RecordExpiredError('record has expired');
31
+ }
32
+ }
33
+ else if (record.validityType != null) {
34
+ throw new UnsupportedValidityError('The validity type is unsupported');
35
+ }
36
+ }
37
+ /**
38
+ * Returns the number of milliseconds until the record expires.
39
+ * If the record is already expired, returns 0.
40
+ *
41
+ * @param record - The IPNS record to validate.
42
+ * @returns The number of milliseconds until the record expires, or 0 if the record is already expired.
43
+ */
44
+ export function validFor(record) {
45
+ if (record.validityType !== IpnsEntry.ValidityType.EOL) {
46
+ throw new UnsupportedValidityError();
47
+ }
48
+ if (record.validity == null) {
49
+ throw new UnsupportedValidityError();
50
+ }
51
+ const validUntil = NanoDate.fromString(record.validity).toDate().getTime();
52
+ const now = Date.now();
53
+ if (validUntil < now) {
54
+ return 0;
55
+ }
56
+ return validUntil - now;
57
+ }
58
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/validator.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAA;AACrC,OAAO,EAAE,6BAA6B,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AACrI,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAInD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAE,MAAkB,EAAE,OAAsB;IAC7E,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,6BAA6B,CAAC,iDAAiD,CAAC,CAAA;IAC5F,CAAC;IAED,wBAAwB;IACxB,IAAI,OAAO,CAAA;IAEX,IAAI,CAAC;QACH,MAAM,gBAAgB,GAAG,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAC5D,OAAO,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IACxF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,KAAK,CAAA;IACjB,CAAC;IAED,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,0BAA0B,CAAC,sCAAsC,CAAC,CAAA;IAC9E,CAAC;IAED,0CAA0C;IAC1C,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;QACvD,IAAI,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YACzE,MAAM,IAAI,kBAAkB,CAAC,oBAAoB,CAAC,CAAA;QACpD,CAAC;IACH,CAAC;SAAM,IAAI,MAAM,CAAC,YAAY,IAAI,IAAI,EAAE,CAAC;QACvC,MAAM,IAAI,wBAAwB,CAAC,kCAAkC,CAAC,CAAA;IACxE,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAE,MAAkB;IAC1C,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC;QACvD,MAAM,IAAI,wBAAwB,EAAE,CAAA;IACtC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,wBAAwB,EAAE,CAAA;IACtC,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,CAAA;IAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAEtB,IAAI,UAAU,GAAG,GAAG,EAAE,CAAC;QACrB,OAAO,CAAC,CAAA;IACV,CAAC;IAED,OAAO,UAAU,GAAG,GAAG,CAAA;AACzB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helia/ipns",
3
- "version": "9.2.0",
3
+ "version": "9.2.1-17530ed8",
4
4
  "description": "An implementation of IPNS for Helia",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/ipfs/helia/tree/main/packages/ipns#readme",
@@ -45,15 +45,18 @@
45
45
  "exports": {
46
46
  ".": {
47
47
  "types": "./dist/src/index.d.ts",
48
- "import": "./dist/src/index.js"
48
+ "import": "./dist/src/index.js",
49
+ "module-sync": "./dist/src/index.js"
49
50
  },
50
51
  "./dns-resolvers": {
51
52
  "types": "./dist/src/dns-resolvers/index.d.ts",
52
- "import": "./dist/src/dns-resolvers/index.js"
53
+ "import": "./dist/src/dns-resolvers/index.js",
54
+ "module-sync": "./dist/src/dns-resolvers/index.js"
53
55
  },
54
56
  "./routing": {
55
57
  "types": "./dist/src/routing/index.d.ts",
56
- "import": "./dist/src/routing/index.js"
58
+ "import": "./dist/src/routing/index.js",
59
+ "module-sync": "./dist/src/routing/index.js"
57
60
  }
58
61
  },
59
62
  "scripts": {
@@ -63,7 +66,7 @@
63
66
  "doc-check": "aegir doc-check",
64
67
  "build": "aegir build",
65
68
  "docs": "aegir docs",
66
- "generate": "protons ./src/pb/metadata.proto",
69
+ "generate": "protons ./src/pb/*.proto",
67
70
  "test": "aegir test",
68
71
  "test:chrome": "aegir test -t browser --cov",
69
72
  "test:chrome-webworker": "aegir test -t webworker",
@@ -73,34 +76,35 @@
73
76
  "test:electron-main": "aegir test -t electron-main"
74
77
  },
75
78
  "dependencies": {
76
- "@helia/interface": "^6.2.0",
77
- "@libp2p/crypto": "^5.1.7",
78
- "@libp2p/fetch": "^4.1.0",
79
- "@libp2p/interface": "^3.2.0",
80
- "@libp2p/kad-dht": "^16.1.0",
81
- "@libp2p/keychain": "^6.0.5",
82
- "@libp2p/logger": "^6.0.5",
83
- "@libp2p/peer-collections": "^7.0.14",
84
- "@libp2p/utils": "^7.0.5",
79
+ "@helia/interface": "6.2.1-17530ed8",
80
+ "@libp2p/fetch": "^4.1.6",
81
+ "@libp2p/interface": "^3.2.3",
82
+ "@libp2p/kad-dht": "^16.3.2",
83
+ "@libp2p/logger": "^6.2.8",
84
+ "@libp2p/peer-collections": "^7.0.21",
85
+ "@libp2p/utils": "^7.2.2",
86
+ "abort-error": "^1.0.2",
85
87
  "any-signal": "^4.2.0",
88
+ "cborg": "^5.1.1",
86
89
  "delay": "^7.0.0",
87
- "interface-datastore": "^9.0.2",
88
- "ipns": "^10.1.2",
89
- "multiformats": "^13.4.1",
90
- "progress-events": "^1.0.1",
91
- "protons-runtime": "^6.0.1",
90
+ "interface-datastore": "^10.0.1",
91
+ "multiformats": "^14.0.0",
92
+ "progress-events": "^1.1.0",
93
+ "protons-runtime": "^7.0.0",
92
94
  "race-signal": "^2.0.0",
93
- "uint8arraylist": "^2.4.8",
94
- "uint8arrays": "^5.1.0"
95
+ "timestamp-nano": "^1.0.1",
96
+ "uint8arraylist": "^3.0.2",
97
+ "uint8arrays": "^6.1.1"
95
98
  },
96
99
  "devDependencies": {
97
- "@libp2p/crypto": "^5.1.12",
98
- "@libp2p/peer-id": "^6.0.6",
99
- "aegir": "^47.0.22",
100
- "datastore-core": "^11.0.2",
101
- "it-drain": "^3.0.10",
102
- "protons": "^8.1.1",
103
- "sinon": "^21.0.0",
100
+ "@ipshipyard/crypto": "^1.1.0",
101
+ "@ipshipyard/keychain": "^1.0.2",
102
+ "aegir": "^48.0.11",
103
+ "datastore-core": "^12.0.1",
104
+ "it-drain": "^3.0.12",
105
+ "it-last": "^3.0.11",
106
+ "protons": "^9.0.1",
107
+ "sinon": "^22.0.0",
104
108
  "sinon-ts": "^2.0.0"
105
109
  },
106
110
  "browser": {
package/src/errors.ts CHANGED
@@ -1,49 +1,64 @@
1
1
  export class RecordsFailedValidationError extends Error {
2
2
  static name = 'RecordsFailedValidationError'
3
-
4
- constructor (message = 'Records failed validation') {
5
- super(message)
6
- this.name = 'RecordsFailedValidationError'
7
- }
3
+ name = 'RecordsFailedValidationError'
8
4
  }
9
5
 
10
6
  export class UnsupportedMultibasePrefixError extends Error {
11
7
  static name = 'UnsupportedMultibasePrefixError'
12
-
13
- constructor (message = 'Unsupported multibase prefix') {
14
- super(message)
15
- this.name = 'UnsupportedMultibasePrefixError'
16
- }
8
+ name = 'UnsupportedMultibasePrefixError'
17
9
  }
18
10
 
19
11
  export class UnsupportedMultihashCodecError extends Error {
20
12
  static name = 'UnsupportedMultihashCodecError'
21
-
22
- constructor (message = 'Unsupported multihash codec') {
23
- super(message)
24
- this.name = 'UnsupportedMultihashCodecError'
25
- }
13
+ name = 'UnsupportedMultihashCodecError'
26
14
  }
27
15
 
28
16
  export class InvalidValueError extends Error {
29
17
  static name = 'InvalidValueError'
30
-
31
- constructor (message = 'Invalid value') {
32
- super(message)
33
- this.name = 'InvalidValueError'
34
- }
18
+ name = 'InvalidValueError'
35
19
  }
36
20
 
37
21
  export class InvalidTopicError extends Error {
38
22
  static name = 'InvalidTopicError'
39
-
40
- constructor (message = 'Invalid topic') {
41
- super(message)
42
- this.name = 'InvalidTopicError'
43
- }
23
+ name = 'InvalidTopicError'
44
24
  }
45
25
 
46
26
  export class RecordNotFoundError extends Error {
47
27
  static name = 'RecordNotFoundError'
48
28
  name = 'RecordNotFoundError'
49
29
  }
30
+
31
+ export class SignatureCreationError extends Error {
32
+ static name = 'SignatureCreationError'
33
+ name = 'SignatureCreationError'
34
+ }
35
+
36
+ export class SignatureVerificationError extends Error {
37
+ static name = 'SignatureVerificationError'
38
+ name = 'SignatureVerificationError'
39
+ }
40
+
41
+ export class RecordExpiredError extends Error {
42
+ static name = 'RecordExpiredError'
43
+ name = 'RecordExpiredError'
44
+ }
45
+
46
+ export class UnsupportedValidityError extends Error {
47
+ static name = 'UnsupportedValidityError'
48
+ name = 'UnsupportedValidityError'
49
+ }
50
+
51
+ export class RecordTooLargeError extends Error {
52
+ static name = 'RecordTooLargeError'
53
+ name = 'RecordTooLargeError'
54
+ }
55
+
56
+ export class InvalidRecordDataError extends Error {
57
+ static name = 'InvalidRecordDataError'
58
+ name = 'InvalidRecordDataError'
59
+ }
60
+
61
+ export class InvalidEmbeddedPublicKeyError extends Error {
62
+ static name = 'InvalidEmbeddedPublicKeyError'
63
+ name = 'InvalidEmbeddedPublicKeyError'
64
+ }
package/src/index.ts CHANGED
@@ -23,9 +23,9 @@
23
23
  * const { publicKey } = await name.publish('key-1', cid)
24
24
  *
25
25
  * // resolve the name
26
- * const result = await name.resolve(publicKey)
27
- *
28
- * console.info(result.cid, result.path)
26
+ * for await (const result of name.resolve(publicKey)) {
27
+ * console.info(result.record.value) // /ipfs/QmFoo
28
+ * }
29
29
  * ```
30
30
  *
31
31
  * @example Publishing a recursive record
@@ -53,8 +53,9 @@
53
53
  * const { publicKey: recursivePublicKey } = await name.publish('key-2', publicKey)
54
54
  *
55
55
  * // resolve the name recursively - it resolves until a CID is found
56
- * const result = await name.resolve(recursivePublicKey)
57
- * console.info(result.cid.toString() === cid.toString()) // true
56
+ * for await (const result of name.resolve(recursivePublicKey)) {
57
+ * console.info(result.record.value) // /ipfs/QmFoo../foo.txt
58
+ * }
58
59
  * ```
59
60
  *
60
61
  * @example Publishing a record with a path
@@ -82,9 +83,9 @@
82
83
  * const { publicKey } = await name.publish('key-1', `/ipfs/${finalDirCid}/foo.txt`)
83
84
  *
84
85
  * // resolve the name
85
- * const result = await name.resolve(publicKey)
86
- *
87
- * console.info(result.cid, result.path) // QmFoo.. 'foo.txt'
86
+ * for await (const result of name.resolve(publicKey)) {
87
+ * console.info(result.record.value) // /ipfs/QmFoo../foo.txt
88
+ * }
88
89
  * ```
89
90
  *
90
91
  * @example Using custom PubSub router
@@ -104,29 +105,30 @@
104
105
  * may fail to be published with "Insufficient peers" errors.
105
106
  *
106
107
  * ```TypeScript
107
- * import { createHelia, libp2pDefaults } from 'helia'
108
108
  * import { ipns } from '@helia/ipns'
109
109
  * import { pubsub } from '@helia/ipns/routing'
110
+ * import { withLibp2p, libp2pDefaults } from '@helia/libp2p'
110
111
  * import { unixfs } from '@helia/unixfs'
111
- * import { floodsub } from '@libp2p/floodsub'
112
112
  * import { generateKeyPair } from '@libp2p/crypto/keys'
113
+ * import { floodsub } from '@libp2p/floodsub'
114
+ * import { createHelia } from 'helia'
115
+ * import type { Helia } from '@helia/interface'
113
116
  * import type { PubSub } from '@helia/ipns/routing'
117
+ * import type { DefaultLibp2pServices } from '@helia/libp2p'
118
+ * import type { FloodSub } from '@libp2p/floodsub'
114
119
  * import type { Libp2p } from '@libp2p/interface'
115
- * import type { DefaultLibp2pServices } from 'helia'
116
120
  *
117
- * const libp2pOptions = libp2pDefaults()
121
+ * const libp2pOptions = libp2pDefaults() as any
118
122
  * libp2pOptions.services.pubsub = floodsub()
119
123
  *
120
- * const helia = await createHelia<Libp2p<DefaultLibp2pServices & { pubsub: PubSub }>>({
121
- * libp2p: libp2pOptions
122
- * })
124
+ * const helia = await withLibp2p<Helia, { pubsub: FloodSub }>(createHelia(), libp2pOptions).start()
125
+ *
123
126
  * const name = ipns(helia, {
124
127
  * routers: [
125
128
  * pubsub(helia)
126
129
  * ]
127
130
  * })
128
131
  *
129
- *
130
132
  * // store some data to publish
131
133
  * const fs = unixfs(helia)
132
134
  * const cid = await fs.addBytes(Uint8Array.from([0, 1, 2, 3, 4]))
@@ -135,51 +137,12 @@
135
137
  * const { publicKey } = await name.publish('key-1', cid)
136
138
  *
137
139
  * // resolve the name
138
- * const result = await name.resolve(publicKey)
139
- * ```
140
- *
141
- * @example Republishing an existing IPNS record
142
- *
143
- * It is sometimes useful to be able to republish an existing IPNS record
144
- * without needing the private key. This allows you to extend the availability
145
- * of a record that was created elsewhere.
146
- *
147
- * ```TypeScript
148
- * import { createHelia } from 'helia'
149
- * import { ipns, ipnsValidator } from '@helia/ipns'
150
- * import { delegatedRoutingV1HttpApiClient } from '@helia/delegated-routing-v1-http-api-client'
151
- * import { CID } from 'multiformats/cid'
152
- * import { multihashToIPNSRoutingKey, marshalIPNSRecord } from 'ipns'
153
- * import { defaultLogger } from '@libp2p/logger'
154
- *
155
- * const helia = await createHelia()
156
- * const name = ipns(helia)
157
- *
158
- * const ipnsName = 'k51qzi5uqu5dktsyfv7xz8h631pri4ct7osmb43nibxiojpttxzoft6hdyyzg4'
159
- * const parsedCid: CID<unknown, 114, 0 | 18, 1> = CID.parse(ipnsName)
160
- * const delegatedClient = delegatedRoutingV1HttpApiClient({
161
- * url: 'https://delegated-ipfs.dev'
162
- * })({
163
- * logger: defaultLogger()
164
- * })
165
- * const record = await delegatedClient.getIPNS(parsedCid)
166
- *
167
- * const routingKey = multihashToIPNSRoutingKey(parsedCid.multihash)
168
- * const marshaledRecord = marshalIPNSRecord(record)
169
- *
170
- * // validate that they key corresponds to the record
171
- * await ipnsValidator(routingKey, marshaledRecord)
172
- *
173
- * // publish record to routing
174
- * await Promise.all(
175
- * name.routers.map(async r => {
176
- * await r.put(routingKey, marshaledRecord)
177
- * })
178
- * )
140
+ * for await (const result of name.resolve(publicKey)) {
141
+ * console.info(result.record.value)
142
+ * }
179
143
  * ```
180
144
  */
181
145
 
182
- import { ipnsValidator } from 'ipns/validator'
183
146
  import { CID } from 'multiformats/cid'
184
147
  import { IPNSResolver as IPNSResolverClass } from './ipns/resolver.ts'
185
148
  import { IPNS as IPNSClass } from './ipns.ts'
@@ -187,12 +150,12 @@ import { localStore } from './local-store.ts'
187
150
  import { helia } from './routing/index.ts'
188
151
  import { localStoreRouting } from './routing/local-store.ts'
189
152
  import type { IPNSResolverComponents } from './ipns/resolver.ts'
153
+ import type { IPNSRecord } from './records.ts'
190
154
  import type { IPNSRouting, IPNSRoutingProgressEvents } from './routing/index.ts'
191
- import type { Routing, HeliaEvents } from '@helia/interface'
192
- import type { AbortOptions, ComponentLogger, Libp2p, PeerId, PublicKey, TypedEventEmitter } from '@libp2p/interface'
193
- import type { Keychain } from '@libp2p/keychain'
155
+ import type { Routing, HeliaEvents, Keychain, PublicKey } from '@helia/interface'
156
+ import type { ComponentLogger, TypedEventEmitter } from '@libp2p/interface'
157
+ import type { AbortOptions } from 'abort-error'
194
158
  import type { Datastore } from 'interface-datastore'
195
- import type { IPNSRecord } from 'ipns'
196
159
  import type { MultihashDigest } from 'multiformats/hashes/interface'
197
160
  import type { ProgressEvent, ProgressOptions } from 'progress-events'
198
161
 
@@ -214,23 +177,31 @@ export type DatastoreProgressEvents =
214
177
 
215
178
  export interface PublishOptions extends AbortOptions, ProgressOptions<PublishProgressEvents | IPNSRoutingProgressEvents> {
216
179
  /**
217
- * Time duration of the signature validity in ms (default: 48hrs)
180
+ * Time duration of the signature validity in ms
181
+ *
182
+ * @default 172_800_000
218
183
  */
219
184
  lifetime?: number
220
185
 
221
186
  /**
222
- * Only publish to a local datastore (default: false)
187
+ * Only publish to a local datastore
188
+ *
189
+ * @default false
223
190
  */
224
191
  offline?: boolean
225
192
 
226
193
  /**
227
194
  * By default a IPNS V1 and a V2 signature is added to every record. Pass
228
- * false here to only add a V2 signature. (default: true)
195
+ * false here to only add a V2 signature.
196
+ *
197
+ * @default true
229
198
  */
230
199
  v1Compatible?: boolean
231
200
 
232
201
  /**
233
- * The TTL of the record in ms (default: 5 minutes)
202
+ * The TTL of the record in ms
203
+ *
204
+ * @default 300_000
234
205
  */
235
206
  ttl?: number
236
207
  }
@@ -257,32 +228,25 @@ export interface ResolveOptions extends AbortOptions, ProgressOptions<ResolvePro
257
228
  }
258
229
 
259
230
  export interface ResolveResult {
260
- /**
261
- * The CID that was resolved
262
- */
263
- cid: CID
264
-
265
- /**
266
- * Any path component that was part of the resolved record
267
- */
268
- path?: string
269
- }
270
-
271
- export interface IPNSResolveResult extends ResolveResult {
272
231
  /**
273
232
  * The resolved record
274
233
  */
275
234
  record: IPNSRecord
276
235
  }
277
236
 
278
- export interface IPNSPublishResult {
237
+ export interface PublishResult {
279
238
  /**
280
239
  * The published record
281
240
  */
282
241
  record: IPNSRecord
283
242
 
284
243
  /**
285
- * The public key that was used to publish the record
244
+ * The IPNS name that can be used to resolve this record
245
+ */
246
+ name: string
247
+
248
+ /**
249
+ * The public key that was used to sign and publish the record
286
250
  */
287
251
  publicKey: PublicKey
288
252
  }
@@ -295,7 +259,7 @@ export interface IPNSResolver {
295
259
  * Ed25519, secp256k1 or RSA PeerId and recursively resolves the IPNS record
296
260
  * corresponding to that key until a value is found.
297
261
  */
298
- resolve(key: CID<unknown, 0x72, 0x00 | 0x12, 1> | PublicKey | MultihashDigest<0x00 | 0x12> | PeerId, options?: ResolveOptions): Promise<IPNSResolveResult>
262
+ resolve(key: CID<unknown, 0x72> | MultihashDigest, options?: ResolveOptions): AsyncGenerator<ResolveResult>
299
263
  }
300
264
 
301
265
  export interface IPNS {
@@ -308,12 +272,14 @@ export interface IPNS {
308
272
  * Creates and publishes an IPNS record that will resolve the passed value
309
273
  * signed by a key stored in the libp2p keychain under the passed key name.
310
274
  *
275
+ * If the key does not exist, a new Ed25519 key will be created. To use a
276
+ * different key types, ensure the key is created and stored in the keychain
277
+ * before invoking this method.
278
+ *
311
279
  * It is possible to create a recursive IPNS record by passing:
312
280
  *
313
- * - A PeerId,
314
- * - A PublicKey
315
- * - A CID with the libp2p-key codec and Identity or SHA256 hash algorithms
316
- * - A Multihash with the Identity or SHA256 hash algorithms
281
+ * - A CID with the libp2p-key codec
282
+ * - A Multihash
317
283
  * - A string IPNS key (e.g. `/ipns/Qmfoo`)
318
284
  *
319
285
  * @example
@@ -332,38 +298,36 @@ export interface IPNS {
332
298
  * console.info(result) // { answer: ... }
333
299
  * ```
334
300
  */
335
- publish(keyName: string, value: CID | PublicKey | MultihashDigest<0x00 | 0x12> | PeerId | string, options?: PublishOptions): Promise<IPNSPublishResult>
301
+ publish(keyName: string, value: CID | PublicKey | MultihashDigest | string, options?: PublishOptions): Promise<PublishResult>
336
302
 
337
303
  /**
338
- * Accepts a libp2p public key, a CID with the libp2p-key codec and either the
339
- * identity hash (for Ed25519 and secp256k1 public keys) or a SHA256 hash (for
340
- * RSA public keys), or the multihash of a libp2p-key encoded CID, or a
341
- * Ed25519, secp256k1 or RSA PeerId and recursively resolves the IPNS record
342
- * corresponding to that key until a value is found.
304
+ * Accepts a multihash of a public key, a libp2p-key CID containing the
305
+ * multihash of a public key, or an IPNS name in it's string representation
306
+ * and recursively resolves IPNS records until a non-recursive record is found
307
+ * (e.g. the value can be parsed as a string that does not start with
308
+ * `/ipns/`).
343
309
  */
344
- resolve(key: CID<unknown, 0x72, 0x00 | 0x12, 1> | PublicKey | MultihashDigest<0x00 | 0x12> | PeerId, options?: ResolveOptions): Promise<IPNSResolveResult>
310
+ resolve(name: CID<unknown, 0x72> | PublicKey | MultihashDigest | string, options?: ResolveOptions): AsyncGenerator<ResolveResult>
345
311
 
346
312
  /**
347
313
  * Stop republishing of an IPNS record
348
314
  *
349
- * This will delete the last signed IPNS record from the datastore, but the
350
- * key will remain in the keychain.
315
+ * This will delete the last signed IPNS record from the datastore.
351
316
  *
352
317
  * Note that the record may still be resolved by other peers until it expires
353
- * or is no longer valid.
318
+ * or is otherwise no longer valid.
354
319
  */
355
320
  unpublish(keyName: string, options?: AbortOptions): Promise<void>
356
321
  }
357
322
 
358
323
  export type { IPNSRouting } from './routing/index.ts'
359
-
360
- export type { IPNSRecord } from 'ipns'
324
+ export type { IPNSRecord } from './records.ts'
361
325
 
362
326
  export interface IPNSComponents {
363
327
  datastore: Datastore
364
328
  routing: Routing
365
329
  logger: ComponentLogger
366
- libp2p: Libp2p<{ keychain: Keychain }>
330
+ keychain: Keychain
367
331
  events: TypedEventEmitter<HeliaEvents> // Helia event bus
368
332
  }
369
333
 
@@ -414,5 +378,4 @@ export function ipnsResolver (components: IPNSResolverComponents, options: IPNSR
414
378
  })
415
379
  }
416
380
 
417
- export { ipnsValidator, type IPNSRoutingProgressEvents }
418
- export { ipnsSelector } from 'ipns/selector'
381
+ export type { IPNSRoutingProgressEvents }