[
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules\njspm_packages\n\n# Optional npm cache directory\n.npm\n\n# Optional REPL history\n.node_repl_history\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"6\"\n  - \"6.1\"\n  - \"5.11\"\n"
  },
  {
    "path": "README.md",
    "content": "# PQ: Human Readable Promise Chain Query Compiler\n\nPromises are awesome. But when it comes to write promise chains, it becomes kind of hard to write.\nPQ solves this issue and allows you to create **human readable promise chains**\n\n[![npm version](https://badge.fury.io/js/pquery.svg)](https://badge.fury.io/js/pquery)\n[![Build Status](https://travis-ci.org/f/pq.svg?branch=master)](https://travis-ci.org/f/pq)\n\n- Make your Promises more human-readable.\n- Allows to **create your own DSL**.\n- Zero-dependency.\n\n> `pq.debug()` gives you a cool debugger to debug your queries\n\n## Install\n\nYou can simply use NPM/Bower to download **pq**.\n\n```\n# Using NPM\nnpm install pquery --save\n\n# Using Bower\nbower install pquery --save\n```\n\n## Overview\n\n**What you write:**\n```js\npq(\"(name, surname) of users of @json of #fetch('/users')\").then(...)\n\n// or more functional\npq(fetch(\"/users\"), \"(name, surname) of users of @json\").then(...)\n\n// or Unix way\npq(\"#fetch('/users') | @json | users | (name, surname)\").then(...)\n\n// or reverse pipeline\npq(\"(name, surname) <| users <| @json <| #fetch('/users')\").then(...)\n```\n\n**This is actually what you run:**\n```js\nfetch(\"/users\").\n  then(function (response) {\n    return response.json()\n  }).\n  then(function (response) {\n    return response.users\n  }).\n  then(function (response) {\n    return response.map(function (object) { return {\n      name: object.name,\n      surname: object.surname\n  }})\n})\n```\n\n## Why?\n\nI use promises in many cases in my daily work. And **calling a promise chain** is a bit *boring* to write. I used to write `then` keyword *again and again* to create a chain and this drive me crazy, **they seem ugly**.\n\nSo, I created **pq** to make this chains **easier to write and easier to read**.\n\nLet's checkout a real-world promise example:\n```js\nvar foo = fetch(\"/hello\")\n\nfoo.then(function (response) {\n  return response.json()\n}).then(function (response) {\n  return response.data\n}) // this then's may go to the sky, or the hell!\n```\n\nThis is how to write this using **pq**:\n```js\npq(foo, \"data of @json\")\n```\n\n### Queries are Powerful Strings\n\nSince **pq** is just a string, you can create queries anywhere you want and these **may be handy to write your own DSL**. Here is a real-world example:\n\n**Instead of** writing this promise chain:\n```js\nfastfood().\nthen(function (response) {\n  return response.menus\n}).\nthen(function (response) {\n  return response.find({name: 'hamburger'})\n}).\nthen(function (response) {\n  return response.items()\n}).\nthen(function (response) {\n  return response.map(function (res) {\n    return {\n      name: res.name,\n      price: res.price\n    }\n  })\n}).\nthen(function (response) {\n  $(\"ul\").append($(\"<li/>\").html(`${response.name} ${response.price}`))\n})\n```\n\n**Just write this**:\n```html\n<ul data-pq=\"(name, price) of @items of find({name: 'hamburger'}) of menus\">\n  {% $data.forEach(function (item) { %}\n  <li> {{ item.name }} costs {{ item.price }} </li>\n  {% }) %}\n</ul>\n```\n\n## How to Write Queries\n\nThere are few simple rules to write a readable query:\n\n### Promise Chain Keywords\n\n**`then` and `of` are main keywords** to generate promise chains. `foo then bar` is actually `foo.then(function (r) { return r.bar })`. Since they are chained, the left part of chain must have the right of the chain.\n\n**`of` (reverse promise keyword) makes the query more readable. Just like the *SQL*, you define what you want at first.** `bar of foo` is `foo.then(function (r) { return r.bar })`, too.\n\nKeyword | Description | Example\n--- | --- | ---\n`.. then ` or `.. -> ..` or `|>` or ` | ` | Simple promise chain | `@json then data`, `@json -> data`\n`.. of ..` or `.. <- ..` or `<|` | Simple promise chain, reversed | `data of @json`, `data <- @json`\n\n> You can use `of` and `then` together: `full_name of user then last_letter of first_name`.\n> This will be run like: `(full_name of user) then (last_letter of first_name)`,\n> which is actually `user then full_name then first_name then last_letter`.\n\n> **If it becomes confusing to you, do not use them together**\n\n### Meta Characters (Optional)\n\nMeta characters are optional. But they want to make your query easier to read/write. If you want to call a function, you can just put a `@` character beginning of it. `@json` will be converted to `json()`.\n\nThe most useful meta character is `%{number}`. It allows you to pass arguments to the `pq`. `(\"a of %1\", \"b\")` will be `a of b`.\n\nCharacter | Description | Example | Equivalent\n--- | --- | --- | ---\n`@` | Method Calling | `@methodName` | `methodName()`\n`%{number}` | Simple Parameters | `pq(promise, \"%1 of @json\", \"hello\")` | `pq(promise, \"hello of @json\")`\n`&` | This Object | `&.length of users of @json` | `this.length of users of json()`\n`#` | Single Call | `@json of #fetch(...)` |\n`!` | Promisify | `response of !functionWithCallback` |\n\n### Tutorial\n\nThis is a simple, delayed Promised function:\n```js\nfunction sauces(id) {\n  return function () {\n    return new Promise(function (resolve) {\n      return resolve({\n        items: id == 1 ? [\n          {name: \"Ketchup\"},\n          {name: \"Mustard\"}\n        ] : [\n          {name: \"BBQ\"},\n          {name: \"Mayonnaise\"}\n        ]\n      })\n    })\n  }\n}\n\nfunction burgers() {\n  return new Promise(function (resolve) {\n    setTimeout(function () {\n      return resolve({\n        items: [\n          {name: \"McChicken\", price: \"$10\", sauces: sauces(1)},\n          {name: \"Big Mac\", price: \"$15\", sauces: sauces(2)},\n        ]\n      })\n    }, 1000)\n  })\n}\n```\n\nLet's query this using **pq**:\n\n```js\npq(burgers(), \"(price) of items\").then(function (prices) {\n  console.log(prices) // [{price: \"$10\", price: \"$15\"}]\n})\n```\n\nLet's make it more complex:\n```js\npq(burgers(), \"(name) of items of @sauces of items[0]\").then(function (sauce) {\n  console.log(sauce) // [{name: \"Ketchup\"}, {name: \"Mustard\"}]\n})\n```\n\n## How to Write Custom Parsers\n\nIt's too easy to add custom parsers using `pq.parse` command:\n\n```js\npq.parse(function (query) {\n  return query.replace(/^gh\\:([^\\s]+)/, \"#fetch('https://api.github.com/$1?page=1&per_page=100')\")\n})\n\npq.parse(function (query) {\n  return query.replace(/([^\\s]+)\\s*~=\\s*([^\\s]+)/, \"filter(function (n) {return n.$1 == '$2'})\")\n})\n```\n\nThen you'll be able to use your custom parsers.\n```js\npq(\"name~=delorean of @json of gh:users/f/repos\").then(function (result) {\n  console.log(result)\n})\n```\n\n## Query Reducers\n\nQuery reducers helps you to manage your data flow easier.\n\n### `pq.before`\n\n`pq.before` will give you the raw query so you can make changes on it on-the-fly.\n\n```js\npq.before(function (query) {\n  // You can change query before compilation\n  return query\n})\n```\n\n### `pq.after`\n\n`pq.after` will give you compiled promise fragments.\n\n```js\npq.after(function (queries) {\n  // You can change queries after it's compiled\n  return queries.push(pq.compile_fragment(\"@json\"))\n})\n```\n\n## License\n\nMIT Licensed - Copyright &copy; 2016 by Fatih Kadir Akın\n"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"pquery\",\n  \"version\": \"0.3.4\",\n  \"description\": \"Promise Queries\",\n  \"main\": \"build/pquery.js\",\n  \"authors\": [\n    \"Fatih Kadir Akın <fatihkadirakin@gmail.com>\"\n  ],\n  \"license\": \"MIT\",\n  \"keywords\": [\n    \"promise\",\n    \"query\"\n  ],\n  \"homepage\": \"https://github.com/f/pq\",\n  \"ignore\": [\n    \"**/.*\",\n    \"node_modules\",\n    \"bower_components\",\n    \"test\",\n    \"tests\"\n  ]\n}\n"
  },
  {
    "path": "build/pquery.js",
    "content": "(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.pq = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n'use strict';\n\nvar processFn = function (fn, P, opts) {\n\treturn function () {\n\t\tvar that = this;\n\t\tvar args = new Array(arguments.length);\n\n\t\tfor (var i = 0; i < arguments.length; i++) {\n\t\t\targs[i] = arguments[i];\n\t\t}\n\n\t\treturn new P(function (resolve, reject) {\n\t\t\targs.push(function (err, result) {\n\t\t\t\tif (err) {\n\t\t\t\t\treject(err);\n\t\t\t\t} else if (opts.multiArgs) {\n\t\t\t\t\tvar results = new Array(arguments.length - 1);\n\n\t\t\t\t\tfor (var i = 1; i < arguments.length; i++) {\n\t\t\t\t\t\tresults[i - 1] = arguments[i];\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve(results);\n\t\t\t\t} else {\n\t\t\t\t\tresolve(result);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tfn.apply(that, args);\n\t\t});\n\t};\n};\n\nvar pify = module.exports = function (obj, P, opts) {\n\tif (typeof P !== 'function') {\n\t\topts = P;\n\t\tP = Promise;\n\t}\n\n\topts = opts || {};\n\topts.exclude = opts.exclude || [/.+Sync$/];\n\n\tvar filter = function (key) {\n\t\tvar match = function (pattern) {\n\t\t\treturn typeof pattern === 'string' ? key === pattern : pattern.test(key);\n\t\t};\n\n\t\treturn opts.include ? opts.include.some(match) : !opts.exclude.some(match);\n\t};\n\n\tvar ret = typeof obj === 'function' ? function () {\n\t\tif (opts.excludeMain) {\n\t\t\treturn obj.apply(this, arguments);\n\t\t}\n\n\t\treturn processFn(obj, P, opts).apply(this, arguments);\n\t} : {};\n\n\treturn Object.keys(obj).reduce(function (ret, key) {\n\t\tvar x = obj[key];\n\n\t\tret[key] = typeof x === 'function' && filter(key) ? processFn(x, P, opts) : x;\n\n\t\treturn ret;\n\t}, ret);\n};\n\npify.all = pify;\n\n},{}],2:[function(require,module,exports){\nmodule.exports = function (pq) {\n  return function () {\n    pq.before(function (query) {\n      for (var i = 0; i < 50; i++) { console.groupEnd() }\n      console.group(\"%cPQ: \" + query, \"\\\n                      padding: 2px 5px;\\\n                      font-weight: normal;\\\n                      background-color:#222;\\\n                      display: inline-block;\\\n                      border-radius:3px;\\\n                      font-size:16px;\\\n                      color:#fff;\\\n                      \")\n        /*\n        */\n      return query\n    })\n    pq.after(function (query) {\n      console.group('Promise Chain')\n      query.forEach(function (q) {\n        console.log(q\n                    .replace(/^then\\(function \\(response\\) \\{ return/, ' ... ')\n                    .replace(/\\}\\)$/, ' ... '))\n      })\n      console.groupEnd()\n      return query\n    })\n    pq.middleware(function (r) {\n      if (typeof r === \"string\" || typeof r === \"number\") {\n        console.log(r)\n      } else if (r instanceof Array) {\n        r.forEach(function (i) { console.log(i) })\n      } else {\n        for (var key in r) {\n          if (r.hasOwnProperty(key)) {\n            console.log(key + \":\", r[key])\n          }\n        }\n      }\n      console.groupEnd()\n      return r\n    })\n  }\n}\n\n},{}],3:[function(require,module,exports){\nvar PARSE_FLOW = require(\"./parsers\")\nvar AFTER_FLOW = []\nvar BEFORE_FLOW = []\nvar RESPONSE_FLOW = []\nvar ERROR_FLOW = []\n\nvar REVERSE_PROMISE_SEPERATOR = /\\sof\\s|\\<\\-|\\<\\|/g\nvar PROMISE_SEPERATOR = /\\sthen\\s|\\-\\>|\\|\\>|\\s\\|\\s/g\n\nfunction flatten(array) {\n  return array.reduce(function (a, b) {\n    return a.concat(b)\n  }, [])\n}\n\nfunction addCustomParser(fn, toEnd) {\n  if (toEnd === true) {\n    PARSE_FLOW.push(fn)\n  } else {\n    PARSE_FLOW.unshift(fn)\n  }\n  return pq\n}\n\nfunction addBeforeHandler(fn) {\n  BEFORE_FLOW.push(fn)\n  return pq\n}\n\nfunction addAfterHandler(fn) {\n  AFTER_FLOW.push(fn)\n  return pq\n}\n\nfunction addResponseHandler(fn) {\n  RESPONSE_FLOW.push(fn)\n  return pq\n}\n\nfunction compileFragments(fragments, params, query) {\n  return fragments.map(function (fragment) {\n      return PARSE_FLOW.reduce(function (_query, parser) {\n        return parser(_query, params, fragment, query)\n      }, fragment)\n  }).map(function (unit) {\n    var body = \"response.\" + unit\n    if (unit[0] == \"#\") {\n      body = unit.substr(1)\n    }\n    return \"then(function (response) { return \" + body + \" })\"\n  })\n}\n\nfunction orderQuery(query) {\n  var promises = query.split(PROMISE_SEPERATOR)\n  return flatten(promises.map(function (sub) {\n    return sub.split(REVERSE_PROMISE_SEPERATOR).reverse()\n  })).map(function (query) {\n    return query.trim()\n  })\n}\n\nfunction compile(query) {\n  var params = Array.prototype.slice.call(arguments, 1)\n  query = BEFORE_FLOW.reduce(function (query, handler) {\n    return handler(query, params)\n  }, query)\n  var promisedUnits = compileFragments(orderQuery(query), params, query)\n\n  promisedUnits = AFTER_FLOW.reduce(function (query, handler) {\n    return handler(query, params)\n  }, promisedUnits).join(\".\")\n\n  try {\n    return new Function(\"promise\", \"return Promise.resolve(promise).\" + promisedUnits)\n  } catch (e) {\n    throw new e.constructor(\"Problem with running pq: \" + e.message)\n  }\n}\n\nfunction pq(promise, query) {\n  var params = Array.prototype.slice.call(arguments, 2)\n  if (typeof promise === \"string\") {\n    params.unshift(query)\n    query = promise\n  }\n  return compile.apply(null, [query].concat(params))(promise).then(function (response) {\n    return RESPONSE_FLOW.reduce(function (response, handler) {\n      return handler(response)\n    }, response)\n  })\n}\n\npq.promisify = require('pify')\npq.compile = compile\npq.compileFragments = compileFragments\npq.orderQuery = orderQuery\npq.parse = addCustomParser\npq.before = addBeforeHandler\npq.after = addAfterHandler\npq.middleware = addResponseHandler\npq.debug = require('./debugger')(pq)\nmodule.exports = pq\n\nPromise.prototype.query = function (query) {\n  return this.then(function (response) {\n    return pq(response, query)\n  })\n}\n\n},{\"./debugger\":2,\"./parsers\":4,\"pify\":1}],4:[function(require,module,exports){\nfunction parseEachKey(query) {\n  var KEY_GETTER = /^\\(([\\w+\\,\\s\\.]+)\\)$/gi\n  if (KEY_GETTER.test(query)) {\n    var keys = query.replace(KEY_GETTER, function (m, keys) {\n      return keys.split(\",\").map(function (key) {\n        return key.trim()\n      }).map(function (key) {\n        return key.split('.').pop() + \": o.\" + key\n      }).join(\", \")\n    })\n    return \".map(function (o) { return { \" + keys + \" }})\"\n  }\n  return query\n}\n\nfunction parseParam(query, params) {\n  return query.replace(/(^\\s*|[^\\%])\\%(\\d+)/g, function (_, e, r) {\n    return (e=='%'?'':e) + params[parseInt(r)-1]\n  }).replace(/\\%{2}(\\d+)/g, \"%$1\")\n}\n\nfunction parseThis(query) {\n  return query\n    .replace(/^\\&\\./g, \"response.\")\n    .replace(/^this$/g, \"response\")\n}\n\nfunction parseMethodCall(query) {\n  return query.replace(/^\\@([\\w\\.\\_]+)/g, \"$1()\")\n}\n\nfunction parsePify(query) {\n  return query.replace(/^\\!([\\w\\.\\_]+)(.*)/, \"#pq.promisify($1)$2\")\n}\n\n// Parser Flow\nmodule.exports = [\n  parseEachKey,\n  parseThis,\n  parseMethodCall,\n  parseParam,\n  parsePify\n]\n\n},{}]},{},[3])(3)\n});"
  },
  {
    "path": "example/index.html",
    "content": "<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <script src=\"http://code.jquery.com/jquery-latest.js\"></script>\n    <script src=\"http://underscorejs.org/underscore-min.js\"></script>\n    <script src=\"../build/pquery.js\"></script>\n  </head>\n  <body>\n  <script>\n      pq.debug()\n      pq.after(function (query) {\n        return query\n      })\n      pq.parse(function (query) {\n        return query.replace(/^gh\\:([^\\s]+)/, \"#$.get('https://api.github.com/$1?page=1&per_page=100')\")\n      })\n\n      pq.parse(function (query) {\n        return query.replace(/([^\\s]+)\\s*~=\\s*([^\\s]+)/, \"filter(function (n) {return n.$1 == '$2'})\")\n      })\n\n      pq(\"name~=delorean of gh:users/f/repos\").then(function (result) {\n        console.log(\"RESPONSE\", result)\n      })\n\n      function hello(num, callback) {\n        setTimeout(function () {\n          callback(null, {a: num}, 1)\n        })\n      }\n\n      pq(\"a of !hello(1)\").then(function (a) {\n        console.log(a)\n      })\n    </script>\n  </body>\n</html>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"pquery\",\n  \"version\": \"0.3.4\",\n  \"description\": \"Promise Queries\",\n  \"main\": \"src/index.js\",\n  \"scripts\": {\n    \"test\": \"node test/test.js\",\n    \"build\": \"./node_modules/.bin/browserify src/index.js --standalone pq > ./build/pquery.js\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/f/pq.git\"\n  },\n  \"keywords\": [\n    \"promise\",\n    \"query\"\n  ],\n  \"author\": \"Fatih Kadir Akın <fatihkadirakin@gmail.com>\",\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/f/pq/issues\"\n  },\n  \"homepage\": \"https://github.com/f/pq#readme\",\n  \"devDependencies\": {\n    \"babelify\": \"^7.3.0\",\n    \"browserify\": \"^13.0.1\"\n  },\n  \"dependencies\": {\n    \"pify\": \"^2.3.0\"\n  }\n}\n"
  },
  {
    "path": "src/debugger.js",
    "content": "module.exports = function (pq) {\n  return function () {\n    pq.before(function (query) {\n      for (var i = 0; i < 50; i++) { console.groupEnd() }\n      console.group(\"%cPQ: \" + query, \"\\\n                      padding: 2px 5px;\\\n                      font-weight: normal;\\\n                      background-color:#222;\\\n                      display: inline-block;\\\n                      border-radius:3px;\\\n                      font-size:16px;\\\n                      color:#fff;\\\n                      \")\n        /*\n        */\n      return query\n    })\n    pq.after(function (query) {\n      console.group('Promise Chain')\n      query.forEach(function (q) {\n        console.log(q\n                    .replace(/^then\\(function \\(response\\) \\{ return/, ' ... ')\n                    .replace(/\\}\\)$/, ' ... '))\n      })\n      console.groupEnd()\n      return query\n    })\n    pq.middleware(function (r) {\n      if (typeof r === \"string\" || typeof r === \"number\") {\n        console.log(r)\n      } else if (r instanceof Array) {\n        r.forEach(function (i) { console.log(i) })\n      } else {\n        for (var key in r) {\n          if (r.hasOwnProperty(key)) {\n            console.log(key + \":\", r[key])\n          }\n        }\n      }\n      console.groupEnd()\n      return r\n    })\n  }\n}\n"
  },
  {
    "path": "src/index.js",
    "content": "var PARSE_FLOW = require(\"./parsers\")\nvar AFTER_FLOW = []\nvar BEFORE_FLOW = []\nvar RESPONSE_FLOW = []\nvar ERROR_FLOW = []\n\nvar REVERSE_PROMISE_SEPERATOR = /\\sof\\s|\\<\\-|\\<\\|/g\nvar PROMISE_SEPERATOR = /\\sthen\\s|\\-\\>|\\|\\>|\\s\\|\\s/g\n\nfunction flatten(array) {\n  return array.reduce(function (a, b) {\n    return a.concat(b)\n  }, [])\n}\n\nfunction addCustomParser(fn, toEnd) {\n  if (toEnd === true) {\n    PARSE_FLOW.push(fn)\n  } else {\n    PARSE_FLOW.unshift(fn)\n  }\n  return pq\n}\n\nfunction addBeforeHandler(fn) {\n  BEFORE_FLOW.push(fn)\n  return pq\n}\n\nfunction addAfterHandler(fn) {\n  AFTER_FLOW.push(fn)\n  return pq\n}\n\nfunction addResponseHandler(fn) {\n  RESPONSE_FLOW.push(fn)\n  return pq\n}\n\nfunction compileFragments(fragments, params, query) {\n  return fragments.map(function (fragment) {\n      return PARSE_FLOW.reduce(function (_query, parser) {\n        return parser(_query, params, fragment, query)\n      }, fragment)\n  }).map(function (unit) {\n    var body = \"response.\" + unit\n    if (unit[0] == \"#\") {\n      body = unit.substr(1)\n    }\n    return \"then(function (response) { return \" + body + \" })\"\n  })\n}\n\nfunction orderQuery(query) {\n  var promises = query.split(PROMISE_SEPERATOR)\n  return flatten(promises.map(function (sub) {\n    return sub.split(REVERSE_PROMISE_SEPERATOR).reverse()\n  })).map(function (query) {\n    return query.trim()\n  })\n}\n\nfunction compile(query) {\n  var params = Array.prototype.slice.call(arguments, 1)\n  query = BEFORE_FLOW.reduce(function (query, handler) {\n    return handler(query, params)\n  }, query)\n  var promisedUnits = compileFragments(orderQuery(query), params, query)\n\n  promisedUnits = AFTER_FLOW.reduce(function (query, handler) {\n    return handler(query, params)\n  }, promisedUnits).join(\".\")\n\n  try {\n    return new Function(\"promise\", \"return Promise.resolve(promise).\" + promisedUnits)\n  } catch (e) {\n    throw new e.constructor(\"Problem with running pq: \" + e.message)\n  }\n}\n\nfunction pq(promise, query) {\n  var params = Array.prototype.slice.call(arguments, 2)\n  if (typeof promise === \"string\") {\n    params.unshift(query)\n    query = promise\n  }\n  return compile.apply(null, [query].concat(params))(promise).then(function (response) {\n    return RESPONSE_FLOW.reduce(function (response, handler) {\n      return handler(response)\n    }, response)\n  })\n}\n\npq.promisify = require('pify')\npq.compile = compile\npq.compileFragments = compileFragments\npq.orderQuery = orderQuery\npq.parse = addCustomParser\npq.before = addBeforeHandler\npq.after = addAfterHandler\npq.middleware = addResponseHandler\npq.debug = require('./debugger')(pq)\nmodule.exports = pq\n\nPromise.prototype.query = function (query) {\n  return this.then(function (response) {\n    return pq(response, query)\n  })\n}\n"
  },
  {
    "path": "src/parsers.js",
    "content": "function parseEachKey(query) {\n  var KEY_GETTER = /^\\(([\\w+\\,\\s\\.]+)\\)$/gi\n  if (KEY_GETTER.test(query)) {\n    var keys = query.replace(KEY_GETTER, function (m, keys) {\n      return keys.split(\",\").map(function (key) {\n        return key.trim()\n      }).map(function (key) {\n        return key.split('.').pop() + \": o.\" + key\n      }).join(\", \")\n    })\n    return \".map(function (o) { return { \" + keys + \" }})\"\n  }\n  return query\n}\n\nfunction parseParam(query, params) {\n  return query.replace(/(^\\s*|[^\\%])\\%(\\d+)/g, function (_, e, r) {\n    return (e=='%'?'':e) + params[parseInt(r)-1]\n  }).replace(/\\%{2}(\\d+)/g, \"%$1\")\n}\n\nfunction parseThis(query) {\n  return query\n    .replace(/^\\&\\./g, \"response.\")\n    .replace(/^this$/g, \"response\")\n}\n\nfunction parseMethodCall(query) {\n  return query.replace(/^\\@([\\w\\.\\_]+)/g, \"$1()\")\n}\n\nfunction parsePify(query) {\n  return query.replace(/^\\!([\\w\\.\\_]+)(.*)/, \"#pq.promisify($1)$2\")\n}\n\n// Parser Flow\nmodule.exports = [\n  parseEachKey,\n  parseThis,\n  parseMethodCall,\n  parseParam,\n  parsePify\n]\n"
  },
  {
    "path": "test/test.js",
    "content": "var assert = require('assert')\nvar compile = require(\"../\").compile\n\nfunction getCompiledCode(code, param) {\n  return compile(code, param).toString().split(/\\n/)[2]\n}\n\nassert.equal(getCompiledCode(\"a of b\"), \"return Promise.resolve(promise).then(function (response) { return response.b }).then(function (response) { return response.a })\")\nassert.equal(getCompiledCode(\"a of b of c\"), \"return Promise.resolve(promise).then(function (response) { return response.c }).then(function (response) { return response.b }).then(function (response) { return response.a })\")\nassert.equal(getCompiledCode(\"b then a\"), \"return Promise.resolve(promise).then(function (response) { return response.b }).then(function (response) { return response.a })\")\nassert.equal(getCompiledCode(\"a of b\"), getCompiledCode(\"a <- b\"))\nassert.equal(getCompiledCode(\"a then b\"), getCompiledCode(\"a -> b\"))\nassert.equal(getCompiledCode(\"a then b\"), getCompiledCode(\"b of a\"))\nassert.equal(getCompiledCode(\"a of b\"), getCompiledCode(\"b then a\"))\nassert.equal(getCompiledCode(\"a <- b\"), getCompiledCode(\"b then a\"))\nassert.equal(getCompiledCode(\"a of b\"), getCompiledCode(\"b -> a\"))\nassert.equal(getCompiledCode(\"a of b of c\"), getCompiledCode(\"c then b then a\"))\nassert.equal(getCompiledCode(\"a -> b -> c\"), getCompiledCode(\"c <- b <- a\"))\nassert.equal(getCompiledCode(\"a -> b -> c\"), getCompiledCode(\"a | b | c\"))\nassert.equal(getCompiledCode(\"a |> b |> c\"), getCompiledCode(\"a | b | c\"))\nassert.equal(getCompiledCode(\"a <| b <| c\"), getCompiledCode(\"c | b | a\"))\n\nassert.equal(getCompiledCode(\"a of @b\"), \"return Promise.resolve(promise).then(function (response) { return response.b() }).then(function (response) { return response.a })\")\nassert.equal(getCompiledCode(\"a of @b of c()\"), \"return Promise.resolve(promise).then(function (response) { return response.c() }).then(function (response) { return response.b() }).then(function (response) { return response.a })\")\nassert.equal(getCompiledCode(\"b then @a\"), \"return Promise.resolve(promise).then(function (response) { return response.b }).then(function (response) { return response.a() })\")\nassert.equal(getCompiledCode(\"@a of b\"), getCompiledCode(\"@a <- b\"))\nassert.equal(getCompiledCode(\"a then @b\"), getCompiledCode(\"a -> @b\"))\nassert.equal(getCompiledCode(\"a then b()\"), getCompiledCode(\"@b of a\"))\nassert.equal(getCompiledCode(\"a() of b\"), getCompiledCode(\"b then @a\"))\nassert.equal(getCompiledCode(\"a <- @b\"), getCompiledCode(\"b() then a\"))\nassert.equal(getCompiledCode(\"@a of b\"), getCompiledCode(\"b -> a()\"))\nassert.equal(getCompiledCode(\"@a of @b of @c\"), getCompiledCode(\"c() then b() then a()\"))\nassert.equal(getCompiledCode(\"a() -> b() -> c()\"), getCompiledCode(\"@c <- @b <- @a\"))\n\nassert.equal(getCompiledCode(\"a() -> b('%1') -> c()\", \"hey\"), getCompiledCode(\"@c <- b('hey') <- @a\"))\n"
  }
]