All files / src/fs/protocol/public index.ts

0% Statements 0/49
0% Branches 0/24
0% Functions 0/8
0% Lines 0/46

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129                                                                                                                                                                                                                                                                 
/** @internal */
 
/** @internal */
import { Links } from '../../types'
import { TreeInfo, FileInfo, Skeleton, PutDetails } from './types'
import { Metadata } from '../../metadata'
import { isString } from '../../../common/type-checks'
import * as check from '../../types/check'
 
import { isValue, Maybe } from '../../../common'
import * as ipfs from '../../../ipfs'
import { CID, FileContent } from '../../../ipfs'
import * as link from '../../link'
 
import * as basic from '../basic'
 
export const putTree = async (
    links: Links,
    skeletonVal: Skeleton,
    metadataVal: Metadata,
    previousCID: Maybe<CID>
  ): Promise<PutDetails> => {
  const userlandInfo = await basic.putLinks(links)
  const userland = link.make('userland', userlandInfo.cid, true, userlandInfo.size)
  const [metadata, skeleton] = await Promise.all([
    putAndMakeLink('metadata', metadataVal),
    putAndMakeLink('skeleton', skeletonVal),
  ])
  const previous = previousCID != null
    ? link.make('previous', previousCID, false, await ipfs.size(previousCID))
    : undefined
 
  const internalLinks = { metadata, skeleton, userland, previous } as Links
  const { cid, size } = await basic.putLinks(internalLinks)
  return {
    cid,
    userland: userland.cid,
    metadata: metadata.cid,
    size,
    isFile: false,
    skeleton: skeletonVal
  }
}
 
export const putFile = async (
    content: FileContent,
    metadataVal: Metadata,
    previousCID: Maybe<CID>
  ): Promise<PutDetails> => {
  const userlandInfo = await basic.putFile(content)
  const userland = link.make('userland', userlandInfo.cid, true, userlandInfo.size)
  const metadata = await putAndMakeLink('metadata', metadataVal)
  const previous = previousCID != null
    ? link.make('previous', previousCID, false, await ipfs.size(previousCID))
    : undefined
 
  const internalLinks = { metadata, userland, previous } as Links
  const { cid, size } = await basic.putLinks(internalLinks)
  return {
    cid,
    userland: userland.cid,
    metadata: metadata.cid,
    size,
    isFile: true,
    skeleton: {}
  }
}
 
export const putAndMakeLink = async (name: string, val: FileContent) => {
  const { cid, size } = await ipfs.encoded.add(val, null)
  return link.make(name, cid, true, size)
}
 
export const get = async (cid: CID): Promise<TreeInfo | FileInfo> => {
  const links = await basic.getLinks(cid)
  const metadata = await getAndCheckValue(links, 'metadata', check.isMetadata)
  const skeleton = metadata.isFile
    ? undefined
    : await getAndCheckValue(links, 'skeleton', check.isSkeleton)
 
  const userland = links['userland']?.cid || null
  if (!check.isCID(userland)) throw new Error("Could not find userland")
 
  const previous = links['previous']?.cid || undefined
  return { userland, metadata, previous, skeleton }
}
 
export const getValue = async (
  linksOrCID: Links | CID,
  name: string,
): Promise<unknown> => {
  if (isString(linksOrCID)) {
    const links = await basic.getLinks(linksOrCID)
    return getValueFromLinks(links, name)
  }
 
  return getValueFromLinks(linksOrCID, name)
}
 
export const getValueFromLinks = async (
  links: Links,
  name: string,
): Promise<unknown> => {
  const linkCID = links[name]?.cid
  if (!linkCID) return null
 
  return ipfs.encoded.catAndDecode(linkCID, null)
}
export const getAndCheckValue = async <T>(
  linksOrCid: Links | CID,
  name: string,
  checkFn: (val: any) => val is T,
  canBeNull = false
): Promise<T> => {
  const val = await getValue(linksOrCid, name)
  return checkValue(val, name, checkFn, canBeNull)
}
 
export const checkValue = <T>(val: any, name: string, checkFn: (val: any) => val is T, canBeNull = false): T => {
  if(!isValue(val)){
    if(canBeNull) return val
    throw new Error(`Could not find header value: ${name}`)
  }
  if(checkFn(val)){
    return val
  }
  throw new Error(`Improperly formatted header value: ${name}`)
}