1
1
import * as bytes from 'multiformats/bytes.js'
2
- import withIs from 'class-is'
3
2
4
3
const readonly = ( object , key , value ) => {
5
4
Object . defineProperty ( object , key , {
@@ -9,6 +8,36 @@ const readonly = (object, key, value) => {
9
8
} )
10
9
}
11
10
11
+ // ESM does not support importing package.json where this version info
12
+ // should come from. To workaround it version is copied here.
13
+ const version = '0.0.0-dev'
14
+ // Start throwing exceptions on major version bump
15
+ const deprecate = ( range , message ) => {
16
+ if ( range . test ( version ) ) {
17
+ console . warn ( message )
18
+ /* c8 ignore next 3 */
19
+ } else {
20
+ throw new Error ( message )
21
+ }
22
+ }
23
+
24
+ const IS_CID_DEPRECATION =
25
+ `CID.isCID(v) is deprecated and will be removed in the next major release.
26
+ Following code pattern:
27
+
28
+ if (CID.isCID(value)) {
29
+ doSomethingWithCID(value)
30
+ }
31
+
32
+ Is replaced with:
33
+
34
+ const cid = CID.asCID(value)
35
+ if (cid) {
36
+ // Make sure to use cid instead of value
37
+ doSomethingWithCID(cid)
38
+ }
39
+ `
40
+
12
41
export default multiformats => {
13
42
const { multibase, varint, multihash } = multiformats
14
43
const parse = buff => {
@@ -22,6 +51,9 @@ export default multiformats => {
22
51
...multihash
23
52
] )
24
53
}
54
+
55
+ const cidSymbol = Symbol . for ( '@ipld/js-cid/CID' )
56
+
25
57
class CID {
26
58
constructor ( cid , ...args ) {
27
59
Object . defineProperty ( this , '_baseCache' , {
@@ -30,7 +62,7 @@ export default multiformats => {
30
62
enumerable : false
31
63
} )
32
64
readonly ( this , 'asCID' , this )
33
- if ( _CID . isCID ( cid ) ) {
65
+ if ( cid != null && cid [ cidSymbol ] === true ) {
34
66
readonly ( this , 'version' , cid . version )
35
67
readonly ( this , 'multihash' , bytes . coerce ( cid . multihash ) )
36
68
readonly ( this , 'buffer' , bytes . coerce ( cid . buffer ) )
@@ -104,11 +136,11 @@ export default multiformats => {
104
136
throw new Error ( 'Cannot convert non sha2-256 multihash CID to CIDv0' )
105
137
}
106
138
107
- return new _CID ( 0 , this . code , this . multihash )
139
+ return new CID ( 0 , this . code , this . multihash )
108
140
}
109
141
110
142
toV1 ( ) {
111
- return new _CID ( 1 , this . code , this . multihash )
143
+ return new CID ( 1 , this . code , this . multihash )
112
144
}
113
145
114
146
get toBaseEncodedString ( ) {
@@ -146,11 +178,56 @@ export default multiformats => {
146
178
this . version === other . version &&
147
179
bytes . equals ( this . multihash , other . multihash )
148
180
}
181
+
182
+ get [ Symbol . toStringTag ] ( ) {
183
+ return 'CID'
184
+ }
185
+
186
+ get [ cidSymbol ] ( ) {
187
+ return true
188
+ }
189
+
190
+ /**
191
+ * Takes any input `value` and returns a `CID` instance if it was
192
+ * a `CID` otherwise returns `null`. If `value` is instanceof `CID`
193
+ * it will return value back. If `value` is not instance of this CID
194
+ * class, but is compatible CID it will return new instance of this
195
+ * `CID` class. Otherwise returs null.
196
+ *
197
+ * This allows two different incompatible versions of CID library to
198
+ * co-exist and interop as long as binary interface is compatible.
199
+ * @param {any } value
200
+ * @returns {CID|null }
201
+ */
202
+ static asCID ( value ) {
203
+ // If value is instance of CID then we're all set.
204
+ if ( value instanceof CID ) {
205
+ return value
206
+ // If value isn't instance of this CID class but `this.asCID === this` is
207
+ // true it is CID instance coming from a different implemnetation (diff
208
+ // version or duplicate). In that case we rebase it to this `CID`
209
+ // implemnetation so caller is guaranteed to get instance with expected
210
+ // API.
211
+ } else if ( value != null && value . asCID === value ) {
212
+ const { version, code, multihash } = value
213
+ return new CID ( version , code , multihash )
214
+ // If value is a CID from older implementation that used to be tagged via
215
+ // symbol we still rebase it to the this `CID` implementation by
216
+ // delegating that to a constructor.
217
+ } else if ( value != null && value [ cidSymbol ] === true ) {
218
+ return new CID ( value )
219
+ // Otherwise value is not a CID (or an incompatible version of it) in
220
+ // which case we return `null`.
221
+ } else {
222
+ return null
223
+ }
224
+ }
225
+
226
+ static isCID ( value ) {
227
+ deprecate ( / ^ 0 \. 0 / , IS_CID_DEPRECATION )
228
+ return ! ! ( value && value [ cidSymbol ] )
229
+ }
149
230
}
150
231
151
- const _CID = withIs ( CID , {
152
- className : 'CID' ,
153
- symbolName : '@ipld/js-cid/CID'
154
- } )
155
- return _CID
232
+ return CID
156
233
}
0 commit comments