Example #1
0
export function listMigrations(directory: string): Promise<Migration[]> {
  return fs.readdirAsync(directory)
    .map(R.match(MIGRATION_FILE_REGEXP))
    .filter(R.identity)
    .then(R.groupBy(R.nth<string>(1)))
    .then(R.mapObj(R.partial(matchesToMigration, directory)))
    .then(R.values)
    .then(R.sortBy((migration: Migration) => migration.id));
}
Example #2
0
export function readDownSQL(migration: Migration): Promise<string> {
  if (migration.split) {
    return fs.readFileAsync(migration.downPath, {encoding: 'utf8'})
      .then(R.trim);
  }
  return fs.readFileAsync(migration.path, {encoding: 'utf8'})
    .then(R.split(MIGRATION_SQL_SPLIT_REGEXP))
    .tap(R.partial(assertSQLSections, migration))
    .then(R.nth(1))
    .then(R.trim);
}
Example #3
0
export const create = config => {
  // combine the user's defaults with ours
  const headers = merge(DEFAULT_HEADERS, config.headers || {})
  const combinedConfig = merge(DEFAULT_CONFIG, dissoc('headers', config))

  // create the axios instance
  const instance = axios.create(combinedConfig)

  const monitors = []
  const addMonitor = monitor => {
    monitors.push(monitor)
  }

  const requestTransforms = []
  const asyncRequestTransforms = []
  const responseTransforms = []

  const addRequestTransform = transform => requestTransforms.push(transform)
  const addAsyncRequestTransform = transform => asyncRequestTransforms.push(transform)
  const addResponseTransform = transform => responseTransforms.push(transform)

  // convenience for setting new request headers
  const setHeader = (name, value) => {
    headers[name] = value
    return instance
  }

  // sets headers in bulk
  const setHeaders = headers => {
    forEach(header => setHeader(header, headers[header]), keys(headers))
    return instance
  }

  // remove header
  const deleteHeader = name => {
    delete headers[name]
    return instance
  }

  /**
   * Sets a new base URL.
   */
  const setBaseURL = newURL => {
    instance.defaults.baseURL = newURL
    return instance
  }

  /**
   * Gets the current base URL used by axios.
   */
  const getBaseURL = () => {
    return instance.defaults.baseURL
  }

  /**
   * Make the request for GET, HEAD, DELETE
   */
  const doRequestWithoutBody = (method, url, params = {}, axiosConfig = {}) => {
    return doRequest(merge({ url, params, method }, axiosConfig))
  }

  /**
   * Make the request for POST, PUT, PATCH
   */
  const doRequestWithBody = (method, url, data = null, axiosConfig = {}) => {
    return doRequest(merge({ url, method, data }, axiosConfig))
  }

  /**
   * Make the request with this config!
   */
  const doRequest = async axiosRequestConfig => {
    axiosRequestConfig.headers = {
      ...headers,
      ...axiosRequestConfig.headers,
    }

    // add the request transforms
    if (requestTransforms.length > 0) {
      // overwrite our axios request with whatever our object looks like now
      // axiosRequestConfig = doRequestTransforms(requestTransforms, axiosRequestConfig)
      forEach(transform => transform(axiosRequestConfig), requestTransforms)
    }

    // add the async request transforms
    if (asyncRequestTransforms.length > 0) {
      for (let index = 0; index < asyncRequestTransforms.length; index++) {
        const transform = asyncRequestTransforms[index](axiosRequestConfig)
        if (isPromise(transform)) {
          await transform
        } else {
          await transform(axiosRequestConfig)
        }
      }
    }

    // after the call, convert the axios response, then execute our monitors
    const chain = pipe(
      convertResponse(toNumber(new Date())),
      // partial(convertResponse, [toNumber(new Date())]),
      runMonitors,
    )

    return instance
      .request(axiosRequestConfig)
      .then(chain)
      .catch(chain)
  }

  /**
   * Fires after we convert from axios' response into our response.  Exceptions
   * raised for each monitor will be ignored.
   */
  const runMonitors = ourResponse => {
    monitors.forEach(monitor => {
      try {
        monitor(ourResponse)
      } catch (error) {
        // all monitor complaints will be ignored
      }
    })
    return ourResponse
  }

  /**
   * Converts an axios response/error into our response.
   */
  const convertResponse = curry((startedAt: number, axiosResult: AxiosResponse | AxiosError) => {
    const end: number = toNumber(new Date())
    const duration: number = end - startedAt

    // new in Axios 0.13 -- some data could be buried 1 level now
    const isError = axiosResult instanceof Error || axios.isCancel(axiosResult)
    const axiosResponse = axiosResult as AxiosResponse
    const axiosError = axiosResult as AxiosError
    const response = isError ? axiosError.response : axiosResponse
    const status = (response && response.status) || null
    const problem = isError ? getProblemFromError(axiosResult) : getProblemFromStatus(status)
    const originalError = isError ? axiosError : null
    const ok = in200s(status)
    const config = axiosResult.config || null
    const headers = (response && response.headers) || null
    let data = (response && response.data) || null

    // give an opportunity for anything to the response transforms to change stuff along the way
    let transformedResponse = {
      duration,
      problem,
      originalError,
      ok,
      status,
      headers,
      config,
      data,
    }
    if (responseTransforms.length > 0) {
      forEach(transform => transform(transformedResponse), responseTransforms)
    }

    return transformedResponse
  })

  // create the base object
  const sauce = {
    axiosInstance: instance,
    monitors,
    addMonitor,
    requestTransforms,
    asyncRequestTransforms,
    responseTransforms,
    addRequestTransform,
    addAsyncRequestTransform,
    addResponseTransform,
    setHeader,
    setHeaders,
    deleteHeader,
    headers,
    setBaseURL,
    getBaseURL,
    get: partial(doRequestWithoutBody, ['get']),
    delete: partial(doRequestWithoutBody, ['delete']),
    head: partial(doRequestWithoutBody, ['head']),
    post: partial(doRequestWithBody, ['post']),
    put: partial(doRequestWithBody, ['put']),
    patch: partial(doRequestWithBody, ['patch']),
    link: partial(doRequestWithoutBody, ['link']),
    unlink: partial(doRequestWithoutBody, ['unlink']),
  }
  // send back the sauce
  return sauce
}
Example #4
0
import { findApp } from './util'
import { FoundBrowser, Browser } from '../types'
import * as linuxHelper from '../linux'
import { log } from '../log'
import { merge, partial } from 'ramda'

const detectCanary = partial(findApp, [
  'Contents/MacOS/Google Chrome Canary',
  'com.google.Chrome.canary',
  'KSVersion'
])
const detectChrome = partial(findApp, [
  'Contents/MacOS/Google Chrome',
  'com.google.Chrome',
  'KSVersion'
])
const detectChromium = partial(findApp, [
  'Contents/MacOS/Chromium',
  'org.chromium.Chromium',
  'CFBundleShortVersionString'
])

type Detectors = {
  [index: string]: Function
}

const browsers: Detectors = {
  chrome: detectChrome,
  canary: detectCanary,
  chromium: detectChromium
}
Example #5
0
 * @param secure - True if sanitization is required
 * @param data - Object representing a user model
 */
const respond = (secure: boolean, data: User.UserData): User.UserData =>
    secure ? dissoc('password', data) : data;

/**
 * Prepares a user object for database insertion
 */
export const cleanUserData = formatter(format);

/**
 * Returns a sanitised object representing a user, removing private properties
 * @param data - A database record representing a user
 */
export const sanitizedResponse = partial(respond, [true]);

/**
 * Returns a clone of an object representing a user
 * @param data - A database record representing a user
 */
export const unsanitizedResponse = partial(respond, [false]);

/**
 * Get a list of active users
 * @param limit - The number of records to fetch
 * @param offset - The number of records to skip
 */
export const get = async (limit: number = 10, offset: number = 0): Promise<User.UserData[]> => {
    const users = await db.getActiveUsers(limit, offset);
    return users.map(sanitizedResponse);