bock.worker.js

Summary

Maintainability
A
1 hr
Test Coverage
'use strict'

var store = []

function removeById(id) {
  for (var i = 0, l = store.length; i < l; i += 1) {
    if (store[i].id === id) {
      store.splice(i, 1)
      break
    }
  }
}

self.addEventListener('message', function (event) {
  var data = event.data
  if (data) {
    switch (data.topic) {
      case 'bock.append':
        store.push({ id: data.id, config: data.config })
        break
      case 'bock.remove':
        removeById(data.id)
        break
      case 'bock.sync':
        store = data.config
        break
      case 'bock.flush':
        store = []
        break
    }
  }
})

self.addEventListener('fetch', function (event) {
  var match = matchRequest(event.request)
  if (match) {
    event.respondWith(injectResponse(match.config))
  }
})

function injectResponse(config) {
  if (config.proxy) {
    return proxyRequest(config)
  } else {
    return buildMockResponse(config)
  }
}

function buildMockResponse(config) {
  var response = mockResponse(config)
  if (config.delay) {
    response = delayResponse(config, response)
  }
  return response
}

function mockResponse(config) {
  return new Response(config.responseBody || '', {
    status: config.responseCode,
    headers: config.headers
  })
}

function proxyRequest(config) {
  var proxy = forwardProxyRequest(config)
  if (config.delay) {
    proxy = delayResponse(config, proxy)
  }
  return proxy
}

function forwardProxyRequest(config) {
  return fetch(config.proxy, {
    method: config.proxyMethod || config.method,
    body: config.proxyBody || config.body,
    headers: config.headers || config.proxyHeaders,
    credentials: config.credentials
  })
}

function delayResponse(config, response) {
  return new Promise(function (resolve) {
    setTimeout(function () {
      resolve(response)
    }, config.delay)
  })
}

function matchRequest(request) {
  return store
    .filter(matchURL(request))
    .filter(matchHeaders(request))
    .shift()
}

function matchURL(request) {
  var requestUrl = new URL(request.url)
  return function (mock) {
    var mockUrl = new URL(mock.config.url)
    return mock.config.method === request.method
      && mockUrl.origin === requestUrl.origin
      && mockUrl.password === requestUrl.password
      && mockUrl.username === requestUrl.username
      && mockUrl.pathname === requestUrl.pathname
  }
}

function matchHeaders(request) {
  return function (mock) {
    var headers = mock.headers
    var requestHeaders = request.headers
    if (headers) for (var prop in headers) {
      if (matchHeader(requestHeaders, headers, prop)) return false
    }
    return true
  }
}

function matchHeader(requestHeaders, headers, prop) {
  return requestHeaders.has(prop)
    && !requestHeaders.get(prop).match(new RegExp(headers[prop], 'i'))
}