[
  {
    "path": ".github/workflows/build.yml",
    "content": "name: Node CI\n\n# Push tests commits; pull_request tests PR merges\non: [ push, pull_request ]\n\ndefaults:\n  run:\n    shell: bash\n\njobs:\n\n  # Test the build\n  build:\n    # Setup\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        node-version: [ 12.x, 14.x, 16.x, 18.x ]\n        os: [ windows-latest, ubuntu-latest, macOS-latest ]\n\n    # Go\n    steps:\n      - name: Check out repo\n        uses: actions/checkout@v3\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v3\n        with:\n          node-version: ${{ matrix.node-version }}\n\n      - name: Env\n        run: |\n          echo \"Event name: ${{ github.event_name }}\"\n          echo \"Git ref:    ${{ github.ref }}\"\n          echo \"GH actor:   ${{ github.actor }}\"\n          echo \"SHA:        ${{ github.sha }}\"\n          VER=`node --version`; echo \"Node ver:   $VER\"\n          VER=`npm --version`; echo \"npm ver:    $VER\"\n\n      - name: Install\n        run: npm install\n\n      - name: Build\n        run: npm run build\n\n      - name: Test\n        run: npm test\n        env:\n          CI: true\n\n  # Publish to package registries\n  publish:\n    # Setup\n    needs: build\n    if: startsWith(github.ref, 'refs/tags/v')\n    runs-on: ubuntu-latest\n\n    # Go\n    steps:\n      - name: Check out repo\n        uses: actions/checkout@v3\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v3\n        with:\n          node-version: lts/*\n          registry-url: https://registry.npmjs.org/\n\n      - name: Install\n        run: npm install\n\n      - name: Build\n        run: npm run build\n\n      - name: Publish @latest to npm\n        if: contains(github.ref, 'RC') == false #'!contains()'' doesn't work lol\n        run: npm publish\n        env:\n          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "bundle.js\ndist.js\nnode_modules/\npackage-lock.json\n"
  },
  {
    "path": ".npmignore",
    "content": ".*\ntest-*.js\nindex.js\n_read.js\n_write.js\nnode_modules\n"
  },
  {
    "path": ".npmrc",
    "content": "package-lock=false\n"
  },
  {
    "path": "_read.js",
    "content": "var http = require('http')\nvar https = require('https')\nvar url = require('url')\nvar qs = require('querystring')\n\nmodule.exports = function _read(httpMethod, options, callback) {\n\n  // deep copy options\n  options = JSON.parse(JSON.stringify(options))\n\n  // alias body = data\n  if (options.body && !options.data) {\n    options.data = options.body\n  }\n\n  // require options.url or fail noisily\n  if (!options.url) {\n    throw Error('options.url required')\n  }\n\n  // setup promise if there is no callback\n  var promise\n  if (!callback) {\n    promise = new Promise(function(res, rej) {\n      callback = function(err, result) {\n        err ? rej(err) : res(result)\n      }\n    })\n  }\n\n  // parse out the options from options.url\n  var opts = url.parse(options.url)\n  var method = opts.protocol === 'https:' ? https.request : http.request\n  var defaultContentType = 'application/json; charset=utf-8'\n\n  // check for additional query params\n  if (options.data) {\n    var isSearch = !!opts.search\n    options.url += (isSearch? '&' : '?') + qs.stringify(options.data)\n    opts = url.parse(options.url)\n  }\n\n  // add timeout if it exists\n  if (options.timeout) {\n    opts.timeout = options.timeout\n  }\n\n  // wrangle defaults\n  opts.method = httpMethod\n  opts.headers = options.headers || {}\n  opts.headers['user-agent'] = opts.headers['user-agent'] || opts.headers['User-Agent'] || 'tiny-http'\n  opts.headers['content-type'] = opts.headers['content-type'] || opts.headers['Content-Type'] || defaultContentType\n\n  // make a request\n  var req = method(opts, function _res(res) {\n    var raw = [] // keep our buffers here\n    var ok = res.statusCode >= 200 && res.statusCode < 303\n\n    res.on('data', function _data(chunk) {\n      raw.push(chunk)\n    })\n\n    res.on('end', function _end() {\n      var err = null\n      var result = null\n      var isJSON = res.headers['content-type'] &&\n                  (res.headers['content-type'].startsWith('application/json') ||\n                   res.headers['content-type'].match(/^application\\/.*json/))\n      try {\n        result = Buffer.concat(raw)\n\n        if (!options.buffer) {\n          var strRes = result.toString()\n          result = strRes && isJSON ? JSON.parse(strRes) : strRes\n        }\n      }\n      catch(e) {\n        err = e\n      }\n\n      if (!ok) {\n        err = Error('GET failed with: ' + res.statusCode)\n        err.raw = res\n        err.body = isJSON? JSON.stringify(result) : result.toString()\n        err.statusCode = res.statusCode\n        callback(err)\n      }\n      else {\n        callback(err, {body:result, headers:res.headers})\n      }\n    })\n  })\n\n  req.on('error', callback)\n  req.end()\n\n  return promise\n}\n"
  },
  {
    "path": "_write.js",
    "content": "var qs = require('querystring')\nvar http = require('http')\nvar https = require('https')\nvar FormData = require('@brianleroux/form-data')\nvar url = require('url')\n\nmodule.exports = function _write(httpMethod, options, callback) {\n\n  // deep copy options if no buffers being passed in\n  let formopts = options.data || options.body\n  let notplain = k => typeof formopts[k] != 'string'\n  let basic = formopts && Object.keys(formopts).some(notplain) === false\n  if (basic) {\n    options = JSON.parse(JSON.stringify(options))\n  }\n\n  // alias body = data\n  if (options.body && !options.data) {\n    options.data = options.body\n  }\n\n  // require options.url or fail noisily\n  if (!options.url) {\n    throw Error('options.url required')\n  }\n\n  // setup promise if there is no callback\n  var promise\n  if (!callback) {\n    promise = new Promise(function(res, rej) {\n      callback = function(err, result) {\n        err ? rej(err) : res(result)\n      }\n    })\n  }\n\n  // parse out the options from options.url\n  var opts = url.parse(options.url)\n  var method = opts.protocol === 'https:'? https.request : http.request\n  var defaultContentType = 'application/json; charset=utf-8'\n\n  // add timeout\n  if (options.timeout) {\n    opts.timeout = timeout\n  }\n\n  // wrangle defaults\n  opts.method = httpMethod\n  opts.headers = options.headers || {}\n  opts.headers['user-agent'] = opts.headers['user-agent'] || opts.headers['User-Agent'] || 'tiny-http'\n  opts.headers['content-type'] = opts.headers['content-type'] || opts.headers['Content-Type'] || defaultContentType\n\n  // default to regular POST body (url enc)\n  var postData = qs.stringify(options.data || {})\n\n  function is(headers, type) {\n    var regex = type instanceof RegExp\n    var upper = headers['Content-Type']\n    var lower = headers['content-type']\n    var isU = upper && (regex ? upper.match(type) : upper.startsWith(type))\n    var isL = lower && (regex ? lower.match(type) : lower.startsWith(type))\n    return isU || isL\n  }\n\n  // if we're posting JSON stringify options.data\n  var isJSON = is(opts.headers, /^application\\/.*json/)\n  if (isJSON) {\n    postData = JSON.stringify(options.data || {})\n  }\n\n    // if we're doing a application/x-www-form-urlencoded to upload files\n  // we'll overload `method` and use the custom form-data submit instead of http.request\n  var isUrlEncoded = is(opts.headers, 'application/x-www-form-urlencoded')\n  if (isUrlEncoded) {\n    postData = Object.keys(options.data)\n      .map(k => `${encodeURI(k)}=${encodeURI(options.data[k])}`)\n      .join('&')\n  }\n\n  // ensure we know the len ~after~ we set the postData\n  opts.headers['Content-Length'] = Buffer.byteLength(postData)\n\n  // if we're doing a mutipart/form-data to upload files\n  // we'll overload `method` and use the custom form-data submit instead of http.request\n  var isMultipart = is(opts.headers, 'multipart/form-data')\n  if (isMultipart) {\n    method = function _multiPartFormDataPost(params, streamback) {\n      var form = new FormData\n      Object.keys(options.data).forEach(k=> {\n        form.append(k, options.data[k])\n      })\n      // remove stuff generated by form.submit\n      delete opts.headers['Content-Type']\n      delete opts.headers['content-type']\n      delete opts.headers['Content-Length']\n      delete opts.headers['content-length']\n      // perform a multipart/form-data POST request\n      form.submit(opts, function _submit(err, res) {\n        if (err) callback(err)\n        else streamback(res)\n      })\n    }\n  }\n\n  // make a request\n  var req = method(opts, function(res) {\n    var raw = [] // keep our buffers here\n    var ok = res.statusCode >= 200 && res.statusCode < 303\n\n    res.on('data', function _data(chunk) {\n      raw.push(chunk)\n    })\n\n    res.on('end', function _end() {\n      var err = null\n      var result = null\n\n      try {\n        result = Buffer.concat(raw)\n\n        if (!options.buffer) {\n          var isJSON = is(res.headers, /^application\\/.*json/)\n          var strRes = result.toString()\n          result = strRes && isJSON ? JSON.parse(strRes) : strRes\n        }\n      }\n      catch (e) {\n        err = e\n      }\n\n      if (!ok) {\n        err = Error(httpMethod + ' failed with: ' + res.statusCode)\n        err.raw = res\n        err.body = result\n        err.statusCode = res.statusCode\n        callback(err)\n      }\n      else {\n        callback(err, {body:result, headers:res.headers})\n      }\n    })\n  })\n\n  if (!isMultipart) {\n    req.on('error', callback)\n    req.write(postData)\n    req.end()\n  }\n\n  return promise\n}\n"
  },
  {
    "path": "index.js",
    "content": "var _read = require('./_read')\nvar _write = require('./_write')\n\nmodule.exports = {\n  get: _read.bind({}, 'GET'),\n  head: _read.bind({}, 'HEAD'),\n  options: _read.bind({}, 'OPTIONS'),\n  post: _write.bind({}, 'POST'),\n  put: _write.bind({}, 'PUT'),\n  patch: _write.bind({}, 'PATCH'),\n  del: _write.bind({}, 'DELETE'),\n  delete: _write.bind({}, 'DELETE'),\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"tiny-json-http\",\n  \"version\": \"7.5.1\",\n  \"main\": \"dist.js\",\n  \"scripts\": {\n    \"test\": \"npm run build && tape test-* | tap-spec\",\n    \"build\": \"esbuild index.js --bundle --outfile=dist.js --platform=node\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/brianleroux/tiny-json-http.git\"\n  },\n  \"author\": \"Brian LeRoux <b@brian.io>\",\n  \"license\": \"Apache-2.0\",\n  \"devDependencies\": {\n    \"@brianleroux/form-data\": \"^1.0.3\",\n    \"body-parser\": \"^1.20.2\",\n    \"esbuild\": \"^0.17.10\",\n    \"express\": \"^4.18.2\",\n    \"tap-spec\": \"^5.0.0\",\n    \"tape\": \"^5.6.3\",\n    \"uglify-es\": \"^3.3.7\"\n  }\n}\n"
  },
  {
    "path": "readme.md",
    "content": "# tiny-json-http\n\nMinimalist `HTTP` client for `GET`, `POST`, `PUT`, `PATCH` and `DELETE` `JSON` payloads\n\n- Zero dependencies: perfect for AWS Lambda\n- Sensible default: assumes buffered JSON responses\n- System symmetry: Node style errback API, or Promises for use with Async/Await\n\n```bash\nnpm i tiny-json-http --save\n```\n\n### API\n\n#### Read methods\n- `tiny.get(options[, callback])`\n- `tiny.head(options[, callback])`\n- `tiny.options(options[, callback])`\n\n#### Write methods\n- `tiny.post(options[, callback])`\n- `tiny.put(options[, callback])`\n- `tiny.patch(options[, callback])`\n- `tiny.del(options[, callback)]`\n\n_*callback is optional, tiny methods will return a promise if no callback is provided_\n\n### Options\n\n- `url` *required*\n- `data` form vars for `tiny.post`, `tiny.put`, `tiny.patch`, and `tiny.delete` otherwise querystring vars for `tiny.get`\n- `headers` key/value map used for headers (including support for uploading files with `multipart/form-data`)\n- `buffer` if set to `true` the response body is returned as a buffer\n\n### Callback values\n\n- `err` a real javascript `Error` if there was one\n- `data` an object with `headers` and `body` keys\n\n### Promises\n\n- if no `callback` is provided to the tiny-json-http methods, a promise is returned\n- perfect for use of async/await\n\n## Examples\n\n#### With Async / Await\n\n```javascript\nvar tiny = require('tiny-json-http')\nvar url = 'http://www.randomkittengenerator.com'\n\n;(async function _iife() {\n  try {\n    console.log(await tiny.get({url}))\n  } catch (err) {\n    console.log('ruh roh!', err)\n  }\n})();\n```\n\n#### With Callback\n\n```javascript\nvar tiny = require('tiny-json-http')\nvar url = 'http://www.randomkittengenerator.com'\n\ntiny.get({url}, function _get(err, result) {\n  if (err) {\n    console.log('ruh roh!', err)\n  }\n  else {\n    console.log(result)\n  }\n})\n```\n\nCheck out the tests for more examples! :heart_decoration:\n"
  },
  {
    "path": "test-form-urlencoded.js",
    "content": "var test = require('tape')\nvar tiny = require('./dist.js')\nvar http = require('http')\nvar server\nlet body = ''\n\ntest('startup', t=> {\n  t.plan(1)\n  server = http.createServer((req, res) => {\n    req.on('data', chunk => body += chunk)\n    req.on('end', () => {\n      res.writeHead(200, { 'Content-Type': 'application/json' });\n      res.end(JSON.stringify({\n        body: body.concat(),\n        gotPost:true,\n        ok:true\n      }))\n    })\n  })\n  server.listen(3000)\n  t.pass('started server')\n})\n\ntest('supports form-urlencoded bodies', t=> {\n  t.plan(3)\n  var url = 'http://localhost:3000'\n  var data = { foo: 'bar', this: 'is form url encoded!' }\n  var headers = { 'content-type': 'application/x-www-form-urlencoded' }\n  tiny.post({url, data, headers}, function __posted(err, result) {\n    if (err) {\n      t.fail(err)\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.ok(result.body.gotPost, 'got a post')\n      t.equal(result.body.body, 'foo=bar&this=is%20form%20url%20encoded!', 'got form-urlencoded response')\n      console.log(result)\n    }\n  })\n})\n\ntest('shutdown', t=> {\n  t.plan(1)\n  server.close()\n  t.ok(true, 'closed server')\n})\n"
  },
  {
    "path": "test-get.js",
    "content": "var test = require('tape')\nvar express = require('express')\nvar bodyParser = require('body-parser')\nvar app = express()\nvar tiny = require('./dist.js')\nvar server\n\napp.use(bodyParser.json())\napp.use(bodyParser.urlencoded({extended:true}))\n\napp.get('/json', (req, res)=> {\n  res.json({hello: 'there'})\n})\n\napp.get('/void', (req, res)=> {\n  res.json('')\n})\n\napp.options('/opts', (req, res) => {\n  res.setHeader('allow', 'OPTIONS, GET')\n  res.json('')\n})\n\napp.get('/goaway', (req, res) => {\n  res.setHeader('location', '/')\n  res.statusCode = 302\n  res.send()\n})\n\ntest('startup', t=> {\n  t.plan(1)\n  server = app.listen(3001, x=> {\n    t.ok(true, 'started server')\n  })\n})\n\ntest('can get a url', t=> {\n  t.plan(3)\n  var url = 'https://brian.io'\n  tiny.get({url}, function __got(err, result) {\n    if (err) {\n      t.fail(err.statusCode, 'failed to get')\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.ok(result.headers, 'got headers')\n      t.ok(result.body, 'got body')\n      console.log(result)\n    }\n  })\n})\n\ntest('can get json', t=> {\n  t.plan(2)\n  var url = 'http://localhost:3001/json'\n  tiny.get({url}, function __json(err, result) {\n    if (err) {\n      t.fail(err)\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.equal(result.body.hello, 'there', 'body is an object')\n      console.log(err, result)\n    }\n  })\n})\n\ntest('can get and handle \"no content\"', t=> {\n  t.plan(2)\n  var url = 'http://localhost:3001/void'\n  tiny.get({url}, function __void(err, result) {\n    if (err) {\n      t.fail(err)\n    }\n    else {\n      t.ok(result, 'got a result (empty tho)')\n      t.is(result.body, '')\n      console.log(result)\n    }\n  })\n})\n\n\ntest('get fails gracefully', t=> {\n  t.plan(1)\n  var url = 'http://nop333.ca'\n  tiny.get({url}, function __ruhroh(err, result) {\n    if (err) {\n      t.ok(err, 'got err as expected')\n      console.log(err)\n    }\n    else {\n      t.fail(result, 'should not succeed')\n    }\n  })\n})\n\ntest('can head a url', t=> {\n  t.plan(2)\n  var url = 'https://www.google.com'\n  tiny.head({url}, function __got(err, result) {\n    if (err) {\n      t.fail(err.statusCode, 'failed to head')\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.ok(result.headers, 'got headers')\n      console.log(JSON.stringify(result, null, 2).substring(0,75), '...')\n    }\n  })\n})\n\ntest('can options a url', t=> {\n  t.plan(2)\n  var url = 'http://localhost:3001/opts'\n  tiny.options({url}, function __got(err, result) {\n    if (err) {\n      t.fail(err.statusCode, 'failed to options')\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.ok(result.headers.allow, 'got headers')\n      console.log(result)\n    }\n  })\n})\n\ntest('can handles redirect', t=> {\n  t.plan(2)\n  var url = 'http://localhost:3001/goaway'\n  tiny.get({url}, function __got(err, result) {\n    if (err) {\n      t.fail(err.statusCode, 'failed to handle redirect')\n    } else {\n      t.ok(result, 'got a result')\n      t.ok(result.headers.location, 'got a location header')\n      console.log(result)\n    }\n  })\n})\n\ntest('shutdown', t=> {\n  t.plan(1)\n  server.close()\n  t.ok(true, 'closed server')\n})\n"
  },
  {
    "path": "test-post.js",
    "content": "var test = require('tape')\nvar express = require('express')\nvar bodyParser = require('body-parser')\nvar app = express()\nvar tiny = require('./dist.js')\nvar server\n\napp.use(bodyParser.json())\napp.use(bodyParser.urlencoded({extended:true}))\n\napp.post('/', (req, res)=> {\n  res.json(Object.assign(req.body, {gotPost:true, ok:true}))\n})\n\napp.post('/void', (req, res)=> {\n  res.json('')\n})\n\napp.put('/', (req, res)=> {\n  res.json(Object.assign(req.body, {gotPut:true, ok:true}))\n})\n\napp.patch('/', (req, res)=> {\n  res.json(Object.assign(req.body, {gotPatch:true, ok:true}))\n})\n\napp.delete('/', (req, res)=> {\n  res.json(Object.assign(req.body, {gotDel:true, ok:true}))\n})\n\napp.post('/goaway', (req, res) => {\n  res.setHeader('location', '/')\n  res.statusCode = 302\n  res.send()\n})\n\napp.post('/boom', (req, res)=> {\n  res.setHeader('test-header', 'foo')\n  res.statusCode = 400\n  res.json({calls:3})\n})\n\ntest('startup', t=> {\n  t.plan(1)\n  server = app.listen(3000, x=> {\n    t.ok(true, 'started server')\n  })\n})\n\ntest('can post', t=> {\n  t.plan(2)\n  var url = 'http://localhost:3000/'\n  var data = {a:1, b:new Date(Date.now()).toISOString()}\n  tiny.post({url, data}, function __posted(err, result) {\n    if (err) {\n      t.fail(err)\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.ok(result.body.gotPost, 'got a post')\n      console.log(result)\n    }\n  })\n})\n\ntest('can post and handle \"no content\"', t=> {\n  t.plan(2)\n  var url = 'http://localhost:3000/void'\n  var data = {a:1, b:new Date(Date.now()).toISOString()}\n  tiny.post({url, data}, function __posted(err, result) {\n    if (err) {\n      t.fail(err)\n    }\n    else {\n      t.ok(result, 'got a result (empty tho)')\n      t.is(result.body, '')\n      console.log(result)\n    }\n  })\n})\n\ntest('can put', t=> {\n  t.plan(2)\n  var url = 'http://localhost:3000/'\n  var data = {a:1, b:new Date(Date.now()).toISOString()}\n  tiny.put({url, data}, function __posted(err, result) {\n    if (err) {\n      t.fail(err)\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.ok(result.body.gotPut, 'got a put')\n      console.log(result)\n    }\n  })\n})\n\ntest('can patch', t=> {\n  t.plan(2)\n  var url = 'http://localhost:3000/'\n  var data = {a:1, b:new Date(Date.now()).toISOString()}\n  tiny.patch({url, data}, function __posted(err, result) {\n    if (err) {\n      t.fail(err)\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.ok(result.body.gotPatch, 'got a patch')\n      console.log(result)\n    }\n  })\n})\n\ntest('can del', t=> {\n  t.plan(3)\n  var url = 'http://localhost:3000/'\n  var data = {a:1, b:new Date(Date.now()).toISOString()}\n  tiny.del({url, data}, function __posted(err, result) {\n    if (err) {\n      t.fail(err)\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.ok(result.body.gotDel, 'got a del')\n      t.ok(result.body.a, 'passed params via query I guess')\n      console.log(result)\n    }\n  })\n})\n\ntest('can delete (aliased to del)', t=> {\n  t.plan(3)\n  var url = 'http://localhost:3000/'\n  var data = {a:1, b:new Date(Date.now()).toISOString()}\n  tiny.delete({url, data}, function __posted(err, result) {\n    if (err) {\n      t.fail(err)\n    }\n    else {\n      t.ok(result, 'got a result')\n      t.ok(result.body.gotDel, 'got a del')\n      t.ok(result.body.a, 'passed params via query I guess')\n      console.log(result)\n    }\n  })\n})\n\ntest('can access response on errors', t=> {\n  t.plan(5)\n  var url = 'http://localhost:3000/boom'\n  var data = {};\n  tiny.post({url, data}, function __posted(err, result) {\n    t.ok(err, 'got an error')\n    t.ok(err.raw, 'has raw response')\n    t.equal(err.raw.statusCode, 400)\n    t.equal(err.raw.headers['test-header'], 'foo')\n    t.deepEqual(err.body, {calls: 3})\n  })\n})\n\ntest('can handle redirects', t=> {\n  t.plan(2)\n  var url = 'http://localhost:3000/goaway'\n  var data = {}\n  tiny.post({url, data}, function __posted(err, result) {\n    if (err) {\n      t.fail(err)\n      t.end()\n    } else {\n      t.ok(result, 'got a result')\n      t.ok(result.headers.location, 'got a location header')\n      console.log(result)\n    }\n  })\n})\n\ntest('shutdown', t=> {\n  t.plan(1)\n  server.close()\n  t.ok(true, 'closed server')\n})\n"
  },
  {
    "path": "test-promise.js",
    "content": "var test = require('tape')\nvar tiny = require('./dist.js')\n\ntest('env', t=> {\n  t.plan(7)\n  t.ok(tiny, 'got a tiny')\n  t.ok(tiny.get, 'got a tiny.get')\n  t.ok(tiny.post, 'got a tiny.post')\n  t.ok(tiny.put, 'got a tiny.put')\n  t.ok(tiny.patch, 'got a tiny.patch')\n  t.ok(tiny.del, 'got a tiny.delete')\n  t.ok(tiny.delete, 'got a tiny.delete')\n  console.log(tiny)\n})\n\ntest('can get a url', async t=> {\n  t.plan(3)\n  var url = 'https://brian.io'\n  try {\n    var result = await tiny.get({url})\n    t.ok(result, 'got a result')\n    t.ok(result.headers, 'got headers')\n    t.ok(result.body, 'got body')\n    console.log(result)\n  }\n  catch(e) {\n    t.fail(err.statusCode, 'failed to get')\n    console.log(err)\n  }\n})\n\ntest('get fails gracefully', t=> {\n  t.plan(1)\n  var url = 'http://nop333.ca'\n  tiny.get({url}, function __ruhroh(err, result) {\n    if (err) {\n      t.ok(err, 'got err as expected')\n      console.log(err)\n    }\n    else {\n      t.fail(result, 'should not succeed')\n    }\n  })\n})\n\ntest('bad url gives a acually useful error with a fucking line number holy shit', async t=> {\n  t.plan(1)\n  try {\n    var res = await tiny.get('')\n    t.fail(res)\n    console.log(res)\n  }\n  catch(e) {\n    t.ok(e, 'res')\n    console.log(e)\n  }\n})\n"
  },
  {
    "path": "test-qq-multipart.js",
    "content": "let test = require('tape')\nlet fs = require('fs')\nlet path = require('path')\nlet tiny = require('./dist.js')\nlet http = require('http')\nlet port = 3000\nlet host = 'localhost'\nlet server\n\ntest('make a multipart post', t=> {\n  t.plan(1)\n  t.ok(tiny, 'got env')\n})\n\ntest('start a fake server', t=> {\n  t.plan(1)\n  // somebody thought this was intuitive\n  server = http.createServer((req, res)=> {\n    let body = []\n    req.on('data', chunk => body.push(chunk))\n    req.on('end', function _end() {\n      body = Buffer.concat(body).toString()\n      res.end(body)\n    })\n  })\n  server.listen({port, host}, err=> {\n    if (err) t.fail(err)\n    else t.pass(`Started server`)\n  })\n})\n\ntest('can multipart/form-data post', t=> {\n  t.plan(1)\n  let file = fs.readFileSync(path.join(__dirname, 'readme.md'))\n  tiny.post({\n    url: `http://${host}:${port}`,\n    headers: {\n      'content-type': 'multipart/form-data'\n    },\n    data: {\n      one: 1,\n      file\n    }\n  },\n  function _post(err, data) {\n    if (err) {\n      t.fail(err, err)\n      console.log(err)\n    }\n    else {\n      t.ok(data.body.includes(file.toString()), 'posted')\n      console.log(data)\n    }\n  })\n})\n\ntest('close fake server', t=> {\n  t.plan(1)\n  server.close()\n  t.ok(true, 'server closed')\n})\n"
  }
]