Skip to content
This repository was archived by the owner on Sep 3, 2021. It is now read-only.
This repository was archived by the owner on Sep 3, 2021. It is now read-only.

Proposal: Let's introduce asCID static method #111

Open
@Gozala

Description

@Gozala

This idea first was proposed in #109 and later came up in #110. I thought it would be best to factor it out into separate thread and discuss it here.

Problem

At the moment CID.isCID(v) is used all over the place as a glorified v instanceof CID check. However it does not check if v is instanceof CID instead it checks presence of special symbol. That addresses problem with having multiple different versions of CID implementations, however it does overlook the fact that two different version may in fact be incompatible e.g. new version may change behavior of specific method e.g. toString I think that is already happening (per #109 (comment))

In the new CID you can use .toString() with no arguments and it will give you a base32 multibase encoded string for CIDv1 and the bare base58btc encoding for CIDv0.

Even if above is backwards compatible change, incompatible change may come sooner or later.

This is a symptom of more general issue with validation pattern.
If you're inclined I would invite to read excellent parse don't validate primer that explains hazzards of that problem (in the context of typed language, but it applies to this just as well)

Proposal

Changing behavior of CID.isCID(v) to do component validation (if I interperent @hugomrdias suggestion moxystudio/js-class-is#25 (comment)) is going to be too disruptive to be worth it. Furthermore it would not address the problem stated above. Instead I would like to propose an alternative in form of asCID static method to which existing code base could be gradually migrated and future code base should default.

Implementation could be something along these lines:

class CID {
  /**
   * If passed value is a CID or compatible JSON representation, CID instance for it is returned
   * otherwise `null` is returned.
   * returns `null`.
   * @param {any} value
   * @returns {CID|null}
   */
  asCID(value) {
    // If is CID nothing to do here
     if (value instanceof CID) {
       return value
     }
     // If CID components validate it's CID from other realm or another version of CID
     // In that case CID of this class is assembled from the components.
     else if (CIDUtil.checkCIDComponents(other) == null) {
       return new CID(value.version, value.codec, value.multihash, value.multibaseName)
     }
     // Otherwise it's not valid / compatible CID so return `null`
     else {
       return null
     }
  }
}

With such method in place existing pattern of

if (CID.isCID(cid)) {
  // use cid
}

Could gradually be transitioned to following pattern instead:

const cid = CID.asCID(value)
if (cid) {
   // use cid
}

It is a bit more verbose, but it would avoid issues that may arise from version incompatibilities. It will also preserve CID-ness when things are structured cloned.

Metadata

Metadata

Assignees

Labels

explorationkind/enhancementA net-new feature or improvement to an existing feature

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions