Repository: f/pq
Branch: master
Commit: 441c51074116
Files: 11
Total size: 24.5 KB
Directory structure:
gitextract_cw6h13nz/
├── .gitignore
├── .travis.yml
├── README.md
├── bower.json
├── build/
│ └── pquery.js
├── example/
│ └── index.html
├── package.json
├── src/
│ ├── debugger.js
│ ├── index.js
│ └── parsers.js
└── test/
└── test.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "6"
- "6.1"
- "5.11"
================================================
FILE: README.md
================================================
# PQ: Human Readable Promise Chain Query Compiler
Promises are awesome. But when it comes to write promise chains, it becomes kind of hard to write.
PQ solves this issue and allows you to create **human readable promise chains**
[](https://badge.fury.io/js/pquery)
[](https://travis-ci.org/f/pq)
- Make your Promises more human-readable.
- Allows to **create your own DSL**.
- Zero-dependency.
> `pq.debug()` gives you a cool debugger to debug your queries
## Install
You can simply use NPM/Bower to download **pq**.
```
# Using NPM
npm install pquery --save
# Using Bower
bower install pquery --save
```
## Overview
**What you write:**
```js
pq("(name, surname) of users of @json of #fetch('/users')").then(...)
// or more functional
pq(fetch("/users"), "(name, surname) of users of @json").then(...)
// or Unix way
pq("#fetch('/users') | @json | users | (name, surname)").then(...)
// or reverse pipeline
pq("(name, surname) <| users <| @json <| #fetch('/users')").then(...)
```
**This is actually what you run:**
```js
fetch("/users").
then(function (response) {
return response.json()
}).
then(function (response) {
return response.users
}).
then(function (response) {
return response.map(function (object) { return {
name: object.name,
surname: object.surname
}})
})
```
## Why?
I 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**.
So, I created **pq** to make this chains **easier to write and easier to read**.
Let's checkout a real-world promise example:
```js
var foo = fetch("/hello")
foo.then(function (response) {
return response.json()
}).then(function (response) {
return response.data
}) // this then's may go to the sky, or the hell!
```
This is how to write this using **pq**:
```js
pq(foo, "data of @json")
```
### Queries are Powerful Strings
Since **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:
**Instead of** writing this promise chain:
```js
fastfood().
then(function (response) {
return response.menus
}).
then(function (response) {
return response.find({name: 'hamburger'})
}).
then(function (response) {
return response.items()
}).
then(function (response) {
return response.map(function (res) {
return {
name: res.name,
price: res.price
}
})
}).
then(function (response) {
$("ul").append($("<li/>").html(`${response.name} ${response.price}`))
})
```
**Just write this**:
```html
<ul data-pq="(name, price) of @items of find({name: 'hamburger'}) of menus">
{% $data.forEach(function (item) { %}
<li> {{ item.name }} costs {{ item.price }} </li>
{% }) %}
</ul>
```
## How to Write Queries
There are few simple rules to write a readable query:
### Promise Chain Keywords
**`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.
**`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.
Keyword | Description | Example
--- | --- | ---
`.. then ` or `.. -> ..` or `|>` or ` | ` | Simple promise chain | `@json then data`, `@json -> data`
`.. of ..` or `.. <- ..` or `<|` | Simple promise chain, reversed | `data of @json`, `data <- @json`
> You can use `of` and `then` together: `full_name of user then last_letter of first_name`.
> This will be run like: `(full_name of user) then (last_letter of first_name)`,
> which is actually `user then full_name then first_name then last_letter`.
> **If it becomes confusing to you, do not use them together**
### Meta Characters (Optional)
Meta 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()`.
The most useful meta character is `%{number}`. It allows you to pass arguments to the `pq`. `("a of %1", "b")` will be `a of b`.
Character | Description | Example | Equivalent
--- | --- | --- | ---
`@` | Method Calling | `@methodName` | `methodName()`
`%{number}` | Simple Parameters | `pq(promise, "%1 of @json", "hello")` | `pq(promise, "hello of @json")`
`&` | This Object | `&.length of users of @json` | `this.length of users of json()`
`#` | Single Call | `@json of #fetch(...)` |
`!` | Promisify | `response of !functionWithCallback` |
### Tutorial
This is a simple, delayed Promised function:
```js
function sauces(id) {
return function () {
return new Promise(function (resolve) {
return resolve({
items: id == 1 ? [
{name: "Ketchup"},
{name: "Mustard"}
] : [
{name: "BBQ"},
{name: "Mayonnaise"}
]
})
})
}
}
function burgers() {
return new Promise(function (resolve) {
setTimeout(function () {
return resolve({
items: [
{name: "McChicken", price: "$10", sauces: sauces(1)},
{name: "Big Mac", price: "$15", sauces: sauces(2)},
]
})
}, 1000)
})
}
```
Let's query this using **pq**:
```js
pq(burgers(), "(price) of items").then(function (prices) {
console.log(prices) // [{price: "$10", price: "$15"}]
})
```
Let's make it more complex:
```js
pq(burgers(), "(name) of items of @sauces of items[0]").then(function (sauce) {
console.log(sauce) // [{name: "Ketchup"}, {name: "Mustard"}]
})
```
## How to Write Custom Parsers
It's too easy to add custom parsers using `pq.parse` command:
```js
pq.parse(function (query) {
return query.replace(/^gh\:([^\s]+)/, "#fetch('https://api.github.com/$1?page=1&per_page=100')")
})
pq.parse(function (query) {
return query.replace(/([^\s]+)\s*~=\s*([^\s]+)/, "filter(function (n) {return n.$1 == '$2'})")
})
```
Then you'll be able to use your custom parsers.
```js
pq("name~=delorean of @json of gh:users/f/repos").then(function (result) {
console.log(result)
})
```
## Query Reducers
Query reducers helps you to manage your data flow easier.
### `pq.before`
`pq.before` will give you the raw query so you can make changes on it on-the-fly.
```js
pq.before(function (query) {
// You can change query before compilation
return query
})
```
### `pq.after`
`pq.after` will give you compiled promise fragments.
```js
pq.after(function (queries) {
// You can change queries after it's compiled
return queries.push(pq.compile_fragment("@json"))
})
```
## License
MIT Licensed - Copyright © 2016 by Fatih Kadir Akın
================================================
FILE: bower.json
================================================
{
"name": "pquery",
"version": "0.3.4",
"description": "Promise Queries",
"main": "build/pquery.js",
"authors": [
"Fatih Kadir Akın <fatihkadirakin@gmail.com>"
],
"license": "MIT",
"keywords": [
"promise",
"query"
],
"homepage": "https://github.com/f/pq",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
================================================
FILE: build/pquery.js
================================================
(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){
'use strict';
var processFn = function (fn, P, opts) {
return function () {
var that = this;
var args = new Array(arguments.length);
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
return new P(function (resolve, reject) {
args.push(function (err, result) {
if (err) {
reject(err);
} else if (opts.multiArgs) {
var results = new Array(arguments.length - 1);
for (var i = 1; i < arguments.length; i++) {
results[i - 1] = arguments[i];
}
resolve(results);
} else {
resolve(result);
}
});
fn.apply(that, args);
});
};
};
var pify = module.exports = function (obj, P, opts) {
if (typeof P !== 'function') {
opts = P;
P = Promise;
}
opts = opts || {};
opts.exclude = opts.exclude || [/.+Sync$/];
var filter = function (key) {
var match = function (pattern) {
return typeof pattern === 'string' ? key === pattern : pattern.test(key);
};
return opts.include ? opts.include.some(match) : !opts.exclude.some(match);
};
var ret = typeof obj === 'function' ? function () {
if (opts.excludeMain) {
return obj.apply(this, arguments);
}
return processFn(obj, P, opts).apply(this, arguments);
} : {};
return Object.keys(obj).reduce(function (ret, key) {
var x = obj[key];
ret[key] = typeof x === 'function' && filter(key) ? processFn(x, P, opts) : x;
return ret;
}, ret);
};
pify.all = pify;
},{}],2:[function(require,module,exports){
module.exports = function (pq) {
return function () {
pq.before(function (query) {
for (var i = 0; i < 50; i++) { console.groupEnd() }
console.group("%cPQ: " + query, "\
padding: 2px 5px;\
font-weight: normal;\
background-color:#222;\
display: inline-block;\
border-radius:3px;\
font-size:16px;\
color:#fff;\
")
/*
*/
return query
})
pq.after(function (query) {
console.group('Promise Chain')
query.forEach(function (q) {
console.log(q
.replace(/^then\(function \(response\) \{ return/, ' ... ')
.replace(/\}\)$/, ' ... '))
})
console.groupEnd()
return query
})
pq.middleware(function (r) {
if (typeof r === "string" || typeof r === "number") {
console.log(r)
} else if (r instanceof Array) {
r.forEach(function (i) { console.log(i) })
} else {
for (var key in r) {
if (r.hasOwnProperty(key)) {
console.log(key + ":", r[key])
}
}
}
console.groupEnd()
return r
})
}
}
},{}],3:[function(require,module,exports){
var PARSE_FLOW = require("./parsers")
var AFTER_FLOW = []
var BEFORE_FLOW = []
var RESPONSE_FLOW = []
var ERROR_FLOW = []
var REVERSE_PROMISE_SEPERATOR = /\sof\s|\<\-|\<\|/g
var PROMISE_SEPERATOR = /\sthen\s|\-\>|\|\>|\s\|\s/g
function flatten(array) {
return array.reduce(function (a, b) {
return a.concat(b)
}, [])
}
function addCustomParser(fn, toEnd) {
if (toEnd === true) {
PARSE_FLOW.push(fn)
} else {
PARSE_FLOW.unshift(fn)
}
return pq
}
function addBeforeHandler(fn) {
BEFORE_FLOW.push(fn)
return pq
}
function addAfterHandler(fn) {
AFTER_FLOW.push(fn)
return pq
}
function addResponseHandler(fn) {
RESPONSE_FLOW.push(fn)
return pq
}
function compileFragments(fragments, params, query) {
return fragments.map(function (fragment) {
return PARSE_FLOW.reduce(function (_query, parser) {
return parser(_query, params, fragment, query)
}, fragment)
}).map(function (unit) {
var body = "response." + unit
if (unit[0] == "#") {
body = unit.substr(1)
}
return "then(function (response) { return " + body + " })"
})
}
function orderQuery(query) {
var promises = query.split(PROMISE_SEPERATOR)
return flatten(promises.map(function (sub) {
return sub.split(REVERSE_PROMISE_SEPERATOR).reverse()
})).map(function (query) {
return query.trim()
})
}
function compile(query) {
var params = Array.prototype.slice.call(arguments, 1)
query = BEFORE_FLOW.reduce(function (query, handler) {
return handler(query, params)
}, query)
var promisedUnits = compileFragments(orderQuery(query), params, query)
promisedUnits = AFTER_FLOW.reduce(function (query, handler) {
return handler(query, params)
}, promisedUnits).join(".")
try {
return new Function("promise", "return Promise.resolve(promise)." + promisedUnits)
} catch (e) {
throw new e.constructor("Problem with running pq: " + e.message)
}
}
function pq(promise, query) {
var params = Array.prototype.slice.call(arguments, 2)
if (typeof promise === "string") {
params.unshift(query)
query = promise
}
return compile.apply(null, [query].concat(params))(promise).then(function (response) {
return RESPONSE_FLOW.reduce(function (response, handler) {
return handler(response)
}, response)
})
}
pq.promisify = require('pify')
pq.compile = compile
pq.compileFragments = compileFragments
pq.orderQuery = orderQuery
pq.parse = addCustomParser
pq.before = addBeforeHandler
pq.after = addAfterHandler
pq.middleware = addResponseHandler
pq.debug = require('./debugger')(pq)
module.exports = pq
Promise.prototype.query = function (query) {
return this.then(function (response) {
return pq(response, query)
})
}
},{"./debugger":2,"./parsers":4,"pify":1}],4:[function(require,module,exports){
function parseEachKey(query) {
var KEY_GETTER = /^\(([\w+\,\s\.]+)\)$/gi
if (KEY_GETTER.test(query)) {
var keys = query.replace(KEY_GETTER, function (m, keys) {
return keys.split(",").map(function (key) {
return key.trim()
}).map(function (key) {
return key.split('.').pop() + ": o." + key
}).join(", ")
})
return ".map(function (o) { return { " + keys + " }})"
}
return query
}
function parseParam(query, params) {
return query.replace(/(^\s*|[^\%])\%(\d+)/g, function (_, e, r) {
return (e=='%'?'':e) + params[parseInt(r)-1]
}).replace(/\%{2}(\d+)/g, "%$1")
}
function parseThis(query) {
return query
.replace(/^\&\./g, "response.")
.replace(/^this$/g, "response")
}
function parseMethodCall(query) {
return query.replace(/^\@([\w\.\_]+)/g, "$1()")
}
function parsePify(query) {
return query.replace(/^\!([\w\.\_]+)(.*)/, "#pq.promisify($1)$2")
}
// Parser Flow
module.exports = [
parseEachKey,
parseThis,
parseMethodCall,
parseParam,
parsePify
]
},{}]},{},[3])(3)
});
================================================
FILE: example/index.html
================================================
<html>
<head>
<meta charset="utf-8">
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<script src="../build/pquery.js"></script>
</head>
<body>
<script>
pq.debug()
pq.after(function (query) {
return query
})
pq.parse(function (query) {
return query.replace(/^gh\:([^\s]+)/, "#$.get('https://api.github.com/$1?page=1&per_page=100')")
})
pq.parse(function (query) {
return query.replace(/([^\s]+)\s*~=\s*([^\s]+)/, "filter(function (n) {return n.$1 == '$2'})")
})
pq("name~=delorean of gh:users/f/repos").then(function (result) {
console.log("RESPONSE", result)
})
function hello(num, callback) {
setTimeout(function () {
callback(null, {a: num}, 1)
})
}
pq("a of !hello(1)").then(function (a) {
console.log(a)
})
</script>
</body>
</html>
================================================
FILE: package.json
================================================
{
"name": "pquery",
"version": "0.3.4",
"description": "Promise Queries",
"main": "src/index.js",
"scripts": {
"test": "node test/test.js",
"build": "./node_modules/.bin/browserify src/index.js --standalone pq > ./build/pquery.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/f/pq.git"
},
"keywords": [
"promise",
"query"
],
"author": "Fatih Kadir Akın <fatihkadirakin@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/f/pq/issues"
},
"homepage": "https://github.com/f/pq#readme",
"devDependencies": {
"babelify": "^7.3.0",
"browserify": "^13.0.1"
},
"dependencies": {
"pify": "^2.3.0"
}
}
================================================
FILE: src/debugger.js
================================================
module.exports = function (pq) {
return function () {
pq.before(function (query) {
for (var i = 0; i < 50; i++) { console.groupEnd() }
console.group("%cPQ: " + query, "\
padding: 2px 5px;\
font-weight: normal;\
background-color:#222;\
display: inline-block;\
border-radius:3px;\
font-size:16px;\
color:#fff;\
")
/*
*/
return query
})
pq.after(function (query) {
console.group('Promise Chain')
query.forEach(function (q) {
console.log(q
.replace(/^then\(function \(response\) \{ return/, ' ... ')
.replace(/\}\)$/, ' ... '))
})
console.groupEnd()
return query
})
pq.middleware(function (r) {
if (typeof r === "string" || typeof r === "number") {
console.log(r)
} else if (r instanceof Array) {
r.forEach(function (i) { console.log(i) })
} else {
for (var key in r) {
if (r.hasOwnProperty(key)) {
console.log(key + ":", r[key])
}
}
}
console.groupEnd()
return r
})
}
}
================================================
FILE: src/index.js
================================================
var PARSE_FLOW = require("./parsers")
var AFTER_FLOW = []
var BEFORE_FLOW = []
var RESPONSE_FLOW = []
var ERROR_FLOW = []
var REVERSE_PROMISE_SEPERATOR = /\sof\s|\<\-|\<\|/g
var PROMISE_SEPERATOR = /\sthen\s|\-\>|\|\>|\s\|\s/g
function flatten(array) {
return array.reduce(function (a, b) {
return a.concat(b)
}, [])
}
function addCustomParser(fn, toEnd) {
if (toEnd === true) {
PARSE_FLOW.push(fn)
} else {
PARSE_FLOW.unshift(fn)
}
return pq
}
function addBeforeHandler(fn) {
BEFORE_FLOW.push(fn)
return pq
}
function addAfterHandler(fn) {
AFTER_FLOW.push(fn)
return pq
}
function addResponseHandler(fn) {
RESPONSE_FLOW.push(fn)
return pq
}
function compileFragments(fragments, params, query) {
return fragments.map(function (fragment) {
return PARSE_FLOW.reduce(function (_query, parser) {
return parser(_query, params, fragment, query)
}, fragment)
}).map(function (unit) {
var body = "response." + unit
if (unit[0] == "#") {
body = unit.substr(1)
}
return "then(function (response) { return " + body + " })"
})
}
function orderQuery(query) {
var promises = query.split(PROMISE_SEPERATOR)
return flatten(promises.map(function (sub) {
return sub.split(REVERSE_PROMISE_SEPERATOR).reverse()
})).map(function (query) {
return query.trim()
})
}
function compile(query) {
var params = Array.prototype.slice.call(arguments, 1)
query = BEFORE_FLOW.reduce(function (query, handler) {
return handler(query, params)
}, query)
var promisedUnits = compileFragments(orderQuery(query), params, query)
promisedUnits = AFTER_FLOW.reduce(function (query, handler) {
return handler(query, params)
}, promisedUnits).join(".")
try {
return new Function("promise", "return Promise.resolve(promise)." + promisedUnits)
} catch (e) {
throw new e.constructor("Problem with running pq: " + e.message)
}
}
function pq(promise, query) {
var params = Array.prototype.slice.call(arguments, 2)
if (typeof promise === "string") {
params.unshift(query)
query = promise
}
return compile.apply(null, [query].concat(params))(promise).then(function (response) {
return RESPONSE_FLOW.reduce(function (response, handler) {
return handler(response)
}, response)
})
}
pq.promisify = require('pify')
pq.compile = compile
pq.compileFragments = compileFragments
pq.orderQuery = orderQuery
pq.parse = addCustomParser
pq.before = addBeforeHandler
pq.after = addAfterHandler
pq.middleware = addResponseHandler
pq.debug = require('./debugger')(pq)
module.exports = pq
Promise.prototype.query = function (query) {
return this.then(function (response) {
return pq(response, query)
})
}
================================================
FILE: src/parsers.js
================================================
function parseEachKey(query) {
var KEY_GETTER = /^\(([\w+\,\s\.]+)\)$/gi
if (KEY_GETTER.test(query)) {
var keys = query.replace(KEY_GETTER, function (m, keys) {
return keys.split(",").map(function (key) {
return key.trim()
}).map(function (key) {
return key.split('.').pop() + ": o." + key
}).join(", ")
})
return ".map(function (o) { return { " + keys + " }})"
}
return query
}
function parseParam(query, params) {
return query.replace(/(^\s*|[^\%])\%(\d+)/g, function (_, e, r) {
return (e=='%'?'':e) + params[parseInt(r)-1]
}).replace(/\%{2}(\d+)/g, "%$1")
}
function parseThis(query) {
return query
.replace(/^\&\./g, "response.")
.replace(/^this$/g, "response")
}
function parseMethodCall(query) {
return query.replace(/^\@([\w\.\_]+)/g, "$1()")
}
function parsePify(query) {
return query.replace(/^\!([\w\.\_]+)(.*)/, "#pq.promisify($1)$2")
}
// Parser Flow
module.exports = [
parseEachKey,
parseThis,
parseMethodCall,
parseParam,
parsePify
]
================================================
FILE: test/test.js
================================================
var assert = require('assert')
var compile = require("../").compile
function getCompiledCode(code, param) {
return compile(code, param).toString().split(/\n/)[2]
}
assert.equal(getCompiledCode("a of b"), "return Promise.resolve(promise).then(function (response) { return response.b }).then(function (response) { return response.a })")
assert.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 })")
assert.equal(getCompiledCode("b then a"), "return Promise.resolve(promise).then(function (response) { return response.b }).then(function (response) { return response.a })")
assert.equal(getCompiledCode("a of b"), getCompiledCode("a <- b"))
assert.equal(getCompiledCode("a then b"), getCompiledCode("a -> b"))
assert.equal(getCompiledCode("a then b"), getCompiledCode("b of a"))
assert.equal(getCompiledCode("a of b"), getCompiledCode("b then a"))
assert.equal(getCompiledCode("a <- b"), getCompiledCode("b then a"))
assert.equal(getCompiledCode("a of b"), getCompiledCode("b -> a"))
assert.equal(getCompiledCode("a of b of c"), getCompiledCode("c then b then a"))
assert.equal(getCompiledCode("a -> b -> c"), getCompiledCode("c <- b <- a"))
assert.equal(getCompiledCode("a -> b -> c"), getCompiledCode("a | b | c"))
assert.equal(getCompiledCode("a |> b |> c"), getCompiledCode("a | b | c"))
assert.equal(getCompiledCode("a <| b <| c"), getCompiledCode("c | b | a"))
assert.equal(getCompiledCode("a of @b"), "return Promise.resolve(promise).then(function (response) { return response.b() }).then(function (response) { return response.a })")
assert.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 })")
assert.equal(getCompiledCode("b then @a"), "return Promise.resolve(promise).then(function (response) { return response.b }).then(function (response) { return response.a() })")
assert.equal(getCompiledCode("@a of b"), getCompiledCode("@a <- b"))
assert.equal(getCompiledCode("a then @b"), getCompiledCode("a -> @b"))
assert.equal(getCompiledCode("a then b()"), getCompiledCode("@b of a"))
assert.equal(getCompiledCode("a() of b"), getCompiledCode("b then @a"))
assert.equal(getCompiledCode("a <- @b"), getCompiledCode("b() then a"))
assert.equal(getCompiledCode("@a of b"), getCompiledCode("b -> a()"))
assert.equal(getCompiledCode("@a of @b of @c"), getCompiledCode("c() then b() then a()"))
assert.equal(getCompiledCode("a() -> b() -> c()"), getCompiledCode("@c <- @b <- @a"))
assert.equal(getCompiledCode("a() -> b('%1') -> c()", "hey"), getCompiledCode("@c <- b('hey') <- @a"))
gitextract_cw6h13nz/
├── .gitignore
├── .travis.yml
├── README.md
├── bower.json
├── build/
│ └── pquery.js
├── example/
│ └── index.html
├── package.json
├── src/
│ ├── debugger.js
│ ├── index.js
│ └── parsers.js
└── test/
└── test.js
SYMBOL INDEX (30 symbols across 4 files)
FILE: build/pquery.js
function s (line 1) | function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&re...
function flatten (line 127) | function flatten(array) {
function addCustomParser (line 133) | function addCustomParser(fn, toEnd) {
function addBeforeHandler (line 142) | function addBeforeHandler(fn) {
function addAfterHandler (line 147) | function addAfterHandler(fn) {
function addResponseHandler (line 152) | function addResponseHandler(fn) {
function compileFragments (line 157) | function compileFragments(fragments, params, query) {
function orderQuery (line 171) | function orderQuery(query) {
function compile (line 180) | function compile(query) {
function pq (line 198) | function pq(promise, query) {
function parseEachKey (line 229) | function parseEachKey(query) {
function parseParam (line 244) | function parseParam(query, params) {
function parseThis (line 250) | function parseThis(query) {
function parseMethodCall (line 256) | function parseMethodCall(query) {
function parsePify (line 260) | function parsePify(query) {
FILE: src/index.js
function flatten (line 10) | function flatten(array) {
function addCustomParser (line 16) | function addCustomParser(fn, toEnd) {
function addBeforeHandler (line 25) | function addBeforeHandler(fn) {
function addAfterHandler (line 30) | function addAfterHandler(fn) {
function addResponseHandler (line 35) | function addResponseHandler(fn) {
function compileFragments (line 40) | function compileFragments(fragments, params, query) {
function orderQuery (line 54) | function orderQuery(query) {
function compile (line 63) | function compile(query) {
function pq (line 81) | function pq(promise, query) {
FILE: src/parsers.js
function parseEachKey (line 1) | function parseEachKey(query) {
function parseParam (line 16) | function parseParam(query, params) {
function parseThis (line 22) | function parseThis(query) {
function parseMethodCall (line 28) | function parseMethodCall(query) {
function parsePify (line 32) | function parsePify(query) {
FILE: test/test.js
function getCompiledCode (line 4) | function getCompiledCode(code, param) {
Condensed preview — 11 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (27K chars).
[
{
"path": ".gitignore",
"chars": 578,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n\n# Directory for instrumented libs generated by jscov"
},
{
"path": ".travis.yml",
"chars": 56,
"preview": "language: node_js\nnode_js:\n - \"6\"\n - \"6.1\"\n - \"5.11\"\n"
},
{
"path": "README.md",
"chars": 6932,
"preview": "# PQ: Human Readable Promise Chain Query Compiler\n\nPromises are awesome. But when it comes to write promise chains, it b"
},
{
"path": "bower.json",
"chars": 389,
"preview": "{\n \"name\": \"pquery\",\n \"version\": \"0.3.4\",\n \"description\": \"Promise Queries\",\n \"main\": \"build/pquery.js\",\n \"authors\""
},
{
"path": "build/pquery.js",
"chars": 7515,
"preview": "(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"func"
},
{
"path": "example/index.html",
"chars": 997,
"preview": "<html>\n <head>\n <meta charset=\"utf-8\">\n <script src=\"http://code.jquery.com/jquery-latest.js\"></script>\n <scri"
},
{
"path": "package.json",
"chars": 706,
"preview": "{\n \"name\": \"pquery\",\n \"version\": \"0.3.4\",\n \"description\": \"Promise Queries\",\n \"main\": \"src/index.js\",\n \"scripts\": {"
},
{
"path": "src/debugger.js",
"chars": 1283,
"preview": "module.exports = function (pq) {\n return function () {\n pq.before(function (query) {\n for (var i = 0; i < 50; i"
},
{
"path": "src/index.js",
"chars": 2726,
"preview": "var PARSE_FLOW = require(\"./parsers\")\nvar AFTER_FLOW = []\nvar BEFORE_FLOW = []\nvar RESPONSE_FLOW = []\nvar ERROR_FLOW = ["
},
{
"path": "src/parsers.js",
"chars": 1040,
"preview": "function parseEachKey(query) {\n var KEY_GETTER = /^\\(([\\w+\\,\\s\\.]+)\\)$/gi\n if (KEY_GETTER.test(query)) {\n var keys "
},
{
"path": "test/test.js",
"chars": 2817,
"preview": "var assert = require('assert')\nvar compile = require(\"../\").compile\n\nfunction getCompiledCode(code, param) {\n return co"
}
]
About this extraction
This page contains the full source code of the f/pq GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 11 files (24.5 KB), approximately 7.0k tokens, and a symbol index with 30 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.