digitalfabrik/integreat-app

View on GitHub
native/src/utils/helpers.ts

Summary

Maintainability
A
0 mins
Test Coverage
C
78%
import { last } from 'lodash'
import BlobUtil from 'react-native-blob-util'
import Url from 'url-parse'

import buildConfig from '../constants/buildConfig'
import appSettings from './AppSettings'
import { log } from './sentry'

// Android throws an error if attempting to delete non existing directories/files
// https://github.com/joltup/rn-fetch-blob/issues/333
export const deleteIfExists = async (path: string): Promise<void> => {
  if (await BlobUtil.fs.exists(path)) {
    await BlobUtil.fs.unlink(path)
  } else {
    log(`File or directory ${path} does not exist and was therefore not deleted.`, 'warning')
  }
}

export const determineApiUrl = async (): Promise<string> => {
  const { apiUrlOverride } = await appSettings.loadSettings()
  return apiUrlOverride || buildConfig().cmsUrl
}

/**
 * Iterates through a tree until depth is reached. A depth of 0 means only the root is visited.
 * A depth of 1 means the root and the children of it are visited. Please note that for each children of the root
 * nodeAction is called once with the category and null for the children as parameters.
 *
 * @param root The root to start iterating from
 * @param resolveChildren The function which is used to resolve children
 * @param depth The depth
 * @param nodeAction The action to trigger for each node and children
 */
export const forEachTreeNode = <T>(
  root: T,
  resolveChildren: (arg0: T) => Array<T>,
  depth: number,
  nodeAction: (arg0: T, arg1: Array<T> | null | undefined) => void,
): void => {
  if (depth === 0) {
    nodeAction(root, null)
  } else {
    const children = resolveChildren(root)
    nodeAction(root, children)
    children.forEach(child => forEachTreeNode(child, resolveChildren, depth - 1, nodeAction))
  }
}

// This code is adopted from: https://github.com/react-navigation/react-navigation-core/blob/c85a22d78a50e853632a11036ce562e4e1ecb523/src/routers/KeyGenerator.ts
const uniqueBaseId = `route-id-${Date.now()}`
let uuidCount = 0
export const generateRouteKey = (): string => {
  uuidCount += 1
  return `${uniqueBaseId}-${uuidCount}`
}

/**
 * @throws {Error} If urlString is invalid or it is not possible to get an extension from it
 */

export const getExtension = (urlString: string): string => {
  const url = new Url(urlString)

  if (!url.protocol) {
    throw new Error('Invalid URL! Missing protocol.')
  }

  const { pathname } = url
  const lastPath = last(pathname.split('/'))

  if (lastPath === undefined) {
    throw new Error('The URL does not have a pathname!')
  }

  const index = lastPath.lastIndexOf('.')

  if (index === -1) {
    return ''
  }

  return lastPath.substring(index + 1)
}

export const getErrorMessage = (error: unknown): string =>
  error instanceof Error ? error.message : 'No error message available'