diff --git a/async/exercises/ex1/README.md b/async/exercises/ex1/README.md
new file mode 100755
index 0000000..1208cfc
--- /dev/null
+++ b/async/exercises/ex1/README.md
@@ -0,0 +1,9 @@
+# Instructions
+
+1. This exercise calls for you to write some async flow-control code. To start off with, you'll use callbacks only.
+
+2. Expected behavior:
+ - Request all 3 files at the same time (in "parallel").
+ - Render them ASAP (don't just blindly wait for all to finish loading)
+ - BUT, render them in proper (obvious) order: "file1", "file2", "file3".
+ - After all 3 are done, output "Complete!".
diff --git a/async/exercises/ex1/ex1.html b/async/exercises/ex1/ex1.html
new file mode 100755
index 0000000..63c0e5f
--- /dev/null
+++ b/async/exercises/ex1/ex1.html
@@ -0,0 +1,13 @@
+
+
+
+
+Exercise 1
+
+
+Exercise 1
+
+
+
+
+
diff --git a/async/exercises/ex1/ex1.js b/async/exercises/ex1/ex1.js
new file mode 100755
index 0000000..ff964f5
--- /dev/null
+++ b/async/exercises/ex1/ex1.js
@@ -0,0 +1,65 @@
+function fakeAjax(url,cb) {
+ var fake_responses = {
+ "file1": "The first text",
+ "file2": "The middle text",
+ "file3": "The last text"
+ };
+ var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000;
+
+ console.log("Requesting: " + url);
+
+ setTimeout(function(){
+ cb(fake_responses[url]);
+ },randomDelay);
+}
+
+function output(text) {
+ console.log(text);
+}
+
+// **************************************
+// The old-n-busted callback way
+//this is called each time we getFile
+function getFile(file) {
+ fakeAjax(file,function(text){
+ //calls a function to handle the response from the AJAX
+ handleResponse(file,text);
+ });
+}
+//an object to hold information to see what has returned already
+var responses = {};
+
+function handleResponse(file,cont) {
+ //Checks to see if the file exists in the holding object
+ if (!(file in responses)) {
+ //if it doesn't exist add it to the object
+ responses[file] = cont;
+ }
+ //holds the order of the ways we want the files to display
+ var fileOrder = ["file1","file2","file3"];
+ //itterates over the array to check if all files are been retrieved
+ for (var i = 0; i < fileOrder.length; i++) {
+ //checks if the file has been added to response
+ console.log(responses);
+ if (fileOrder[i] in responses) {
+ //makes sure to only display items that haven't already been displayed
+ if (typeof responses[fileOrder[i]] == "string") {
+ //function that just logs the argument
+ output(responses[fileOrder[i]]);
+ responses[fileOrder[i]] = false;
+ }
+ }
+ else {
+ return;
+ }
+ }
+ //function that just logs the argument
+ output("Complete");
+}
+
+
+
+// request all files at once in "parallel"
+getFile("file1");
+getFile("file2");
+getFile("file3");
diff --git a/async/exercises/ex2/README.md b/async/exercises/ex2/README.md
new file mode 100755
index 0000000..626c49b
--- /dev/null
+++ b/async/exercises/ex2/README.md
@@ -0,0 +1,9 @@
+# Instructions
+
+1. You'll do the same thing as the previous exercise(s), but now you should use thunks.
+
+2. Expected behavior:
+ - Request all 3 files at the same time (in "parallel").
+ - Render them ASAP (don't just blindly wait for all to finish loading)
+ - BUT, render them in proper (obvious) order: "file1", "file2", "file3".
+ - After all 3 are done, output "Complete!".
diff --git a/async/exercises/ex2/ex2.html b/async/exercises/ex2/ex2.html
new file mode 100755
index 0000000..f858f4c
--- /dev/null
+++ b/async/exercises/ex2/ex2.html
@@ -0,0 +1,13 @@
+
+
+
+
+Exercise 2
+
+
+Exercise 2
+
+
+
+
+
diff --git a/async/exercises/ex2/ex2.js b/async/exercises/ex2/ex2.js
new file mode 100755
index 0000000..1797c87
--- /dev/null
+++ b/async/exercises/ex2/ex2.js
@@ -0,0 +1,61 @@
+function fakeAjax(url,cb) {
+ var fake_responses = {
+ "file1": "The first text",
+ "file2": "The middle text",
+ "file3": "The last text"
+ };
+ var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000;
+
+ console.log("Requesting: " + url);
+
+ setTimeout(function(){
+ cb(fake_responses[url]);
+ },randomDelay);
+}
+
+function output(text) {
+ console.log(text);
+}
+
+// **************************************
+//active thunk generator
+function getFile(file) {
+ var text;
+ var fn;
+
+ fakeAjax(file,function(res){
+ if (fn) {
+ fn(res)
+ }else {
+ text = res;
+ }
+ });
+
+ //return this callback for the thunks
+ return function(cb) {
+ //if the information has arrived return the cb function
+ if (text) {
+ cb(text)
+ //if not then set fn to cb I think it is undefined
+ }else {
+ fn = cb;
+ }
+ };
+}
+
+// generate the thunks before you need to display them
+var thunk1 = getFile("file1")
+var thunk2 = getFile("file2")
+var thunk3 = getFile("file3")
+
+//won't display the inner nest until the outer nest gets the neccessary arguments
+thunk1(function(text1) {
+ output(text1);
+ thunk2(function(text2) {
+ output(text2);
+ thunk3(function(text3){
+ output(text3);
+ output("completed");
+ })
+ })
+})
diff --git a/async/exercises/ex3/README.md b/async/exercises/ex3/README.md
new file mode 100755
index 0000000..3565e50
--- /dev/null
+++ b/async/exercises/ex3/README.md
@@ -0,0 +1,9 @@
+# Instructions
+
+1. You'll do the same thing as the previous exercise(s), but now you should use promises.
+
+2. Expected behavior:
+ - Request all 3 files at the same time (in "parallel").
+ - Render them ASAP (don't just blindly wait for all to finish loading)
+ - BUT, render them in proper (obvious) order: "file1", "file2", "file3".
+ - After all 3 are done, output "Complete!".
diff --git a/async/exercises/ex3/ex3.html b/async/exercises/ex3/ex3.html
new file mode 100755
index 0000000..33e5265
--- /dev/null
+++ b/async/exercises/ex3/ex3.html
@@ -0,0 +1,14 @@
+
+
+
+
+Exercise 3
+
+
+Exercise 3
+
+
+
+
+
+
diff --git a/async/exercises/ex3/ex3.js b/async/exercises/ex3/ex3.js
new file mode 100755
index 0000000..f65d35a
--- /dev/null
+++ b/async/exercises/ex3/ex3.js
@@ -0,0 +1,50 @@
+function fakeAjax(url,cb) {
+ var fake_responses = {
+ "file1": "The first text",
+ "file2": "The middle text",
+ "file3": "The last text"
+ };
+ var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000;
+
+ console.log("Requesting: " + url);
+
+ setTimeout(function(){
+ cb(fake_responses[url]);
+ },randomDelay);
+}
+
+function output(text) {
+ console.log(text);
+}
+
+// **************************************
+
+function getFile(file) {
+ // creates a new promise
+ return new Promise(function(resolve){
+ fakeAjax(file,resolve);
+ });
+}
+
+//set the variable to the retrieved promise object
+var prom1 = getFile("file1");
+var prom2 = getFile("file2");
+var prom3 = getFile("file3");
+
+//call the information one after another in order
+prom1
+.then(output)
+.then(function(){
+ return prom2;
+})
+.then(output)
+.then(function(){
+ return prom3;
+})
+.then(output)
+.then(function(){
+ output("Complete")
+})
+.catch(function(err){
+ output(err)
+})
diff --git a/async/exercises/ex3/npo.js b/async/exercises/ex3/npo.js
new file mode 100755
index 0000000..c363ed4
--- /dev/null
+++ b/async/exercises/ex3/npo.js
@@ -0,0 +1,5 @@
+/*! Native Promise Only
+ v0.8.1 (c) Kyle Simpson
+ MIT License: http://getify.mit-license.org
+*/
+!function(t,n,e){n[t]=n[t]||e(),"undefined"!=typeof module&&module.exports?module.exports=n[t]:"function"==typeof define&&define.amd&&define(function(){return n[t]})}("Promise","undefined"!=typeof global?global:this,function(){"use strict";function t(t,n){l.add(t,n),h||(h=y(l.drain))}function n(t){var n,e=typeof t;return null==t||"object"!=e&&"function"!=e||(n=t.then),"function"==typeof n?n:!1}function e(){for(var t=0;t0&&t(e,u))}catch(a){i.call(new f(u),a)}}}function i(n){var o=this;o.triggered||(o.triggered=!0,o.def&&(o=o.def),o.msg=n,o.state=2,o.chain.length>0&&t(e,o))}function c(t,n,e,o){for(var r=0;r
+
+
+
+Exercise 4
+
+
+Exercise 4
+
+
+
+
+
diff --git a/async/exercises/ex4/ex4.js b/async/exercises/ex4/ex4.js
new file mode 100755
index 0000000..07cc701
--- /dev/null
+++ b/async/exercises/ex4/ex4.js
@@ -0,0 +1,39 @@
+function fakeAjax(url,cb) {
+ var fake_responses = {
+ "file1": "The first text",
+ "file2": "The middle text",
+ "file3": "The last text"
+ };
+ var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000;
+
+ console.log("Requesting: " + url);
+
+ setTimeout(function(){
+ cb(fake_responses[url]);
+ },randomDelay);
+}
+
+function output(text) {
+ console.log(text);
+}
+
+// **************************************
+// The old-n-busted callback way
+
+function getFile(file) {
+ return new Promise(function(resolve){
+ fakeAjax(file,resolve);
+ });
+}
+
+["file1","file2","file3"]
+//go over the array
+.map(getFile)
+// transform the file array to an array of promise objects
+.reduce(function combine(chain,promise) {
+ return chain.then(function () {
+ return promise;
+ }).then(output)
+}, Promise.resolve()).then(function() {
+ output("complete")
+})
diff --git a/async/exercises/ex4/npo.js b/async/exercises/ex4/npo.js
new file mode 100755
index 0000000..c363ed4
--- /dev/null
+++ b/async/exercises/ex4/npo.js
@@ -0,0 +1,5 @@
+/*! Native Promise Only
+ v0.8.1 (c) Kyle Simpson
+ MIT License: http://getify.mit-license.org
+*/
+!function(t,n,e){n[t]=n[t]||e(),"undefined"!=typeof module&&module.exports?module.exports=n[t]:"function"==typeof define&&define.amd&&define(function(){return n[t]})}("Promise","undefined"!=typeof global?global:this,function(){"use strict";function t(t,n){l.add(t,n),h||(h=y(l.drain))}function n(t){var n,e=typeof t;return null==t||"object"!=e&&"function"!=e||(n=t.then),"function"==typeof n?n:!1}function e(){for(var t=0;t0&&t(e,u))}catch(a){i.call(new f(u),a)}}}function i(n){var o=this;o.triggered||(o.triggered=!0,o.def&&(o=o.def),o.msg=n,o.state=2,o.chain.length>0&&t(e,o))}function c(t,n,e,o){for(var r=0;r0){u=!1,a=s.shift(),c=g.slice(),g.length=0,c.unshift(createStepCompletion());try{a.apply(h,c)}catch(i){l(i)?$=$.concat(i):$.push(i),n=!0,scheduleSequenceTick()}}}function createStepCompletion(){function done(){n||r||u||(u=!0,g.push.apply(g,arguments),$.length=0,scheduleSequenceTick())}return done.fail=function $$step$fail(){n||r||u||(n=!0,g.length=0,$.push.apply($,arguments),scheduleSequenceTick())},done.abort=function $$step$abort(){n||r||(u=!1,r=!0,g.length=$.length=0,scheduleSequenceTick())},done.errfcb=function $$step$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},done}function createGate(e,t,u){function resetGate(){clearTimeout(s),s=d=m=o=null}function scheduleGateTick(){return g?gateTick():void(s||(s=schedule(gateTick)))}function gateTick(){if(!(n||r||$)){var t=[];s=null,p?(e.fail.apply(h,o),resetGate()):g?(e.abort(),resetGate()):checkGate()&&($=!0,d.forEach(function $$each(e,n){t.push(m["s"+n])}),e.apply(h,t),resetGate())}}function checkGate(){if(0!==d.length){var e=!0;return d.some(function $$some(n){return null===n?(e=!1,!0):void 0}),e}}function createSegmentCompletion(){function done(){if(!(n||r||p||g||$||d[e])){var t=c.apply(h,arguments);m["s"+e]=t.length>1?t:t[0],d[e]=!0,scheduleGateTick()}}var e=d.length;return done.fail=function $$segment$fail(){n||r||p||g||$||d[e]||(p=!0,o=f.call(arguments),scheduleGateTick())},done.abort=function $$segment$abort(){n||r||p||g||$||(g=!0,gateTick())},done.errfcb=function $$segment$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},d[e]=null,done}var a,i,o,s,p=!1,g=!1,$=!1,d=[],m={};t.some(function $$some(e){if(p||g)return!0;a=u.slice(),a.unshift(createSegmentCompletion());try{e.apply(h,a)}catch(n){return i=n,p=!0,!0}}),i&&(l(i)?e.fail.apply(h,i):e.fail(i))}function then(){return n||r||0===arguments.length?d:(wrapArgs(arguments,thenWrapper).forEach(function $$each(e){i(e)?seq(e):s.push(e)}),scheduleSequenceTick(),d)}function or(){return r||0===arguments.length?d:(p.push.apply(p,arguments),scheduleSequenceTick(),d)}function gate(){if(n||r||0===arguments.length)return d;var e=f.call(arguments).map(function $$map(e){var n;return i(e)?(n={seq:e},tapSequence(n),function $$segment(e){n.seq.pipe(e)}):e});return then(function $$then(n){var t=f.call(arguments,1);createGate(n,e,t)}),d}function pipe(){return r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){e.apply(h,f.call(arguments,1)),n()}).or(e.fail)}),d)}function seq(){return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){var n={seq:e};i(e)&&tapSequence(n),then(function $$then(e){var t=n.seq;i(t)||(t=n.seq.apply(h,f.call(arguments,1))),t.pipe(e)})}),d)}function val(){return n||r||0===arguments.length?d:(f.call(wrapArgs(arguments,valWrapper)).forEach(function $$each(e){then(function $$then(n){var t=e.apply(h,f.call(arguments,1));l(t)||(t=c(t)),n.apply(h,t)})}),d)}function promise(){function wrap(e){return function $$fn(){e.apply(h,l(arguments[0])?arguments[0]:arguments)}}return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){var t=e;"function"==typeof e&&"function"!=typeof e.then&&(t=e.apply(h,f.call(arguments,1))),t.then(wrap(n),wrap(n.fail))})}),d)}function fork(){var e;return val(function $$val(){return e?e.apply(h,arguments):e=createSequence.apply(h,arguments).defer(),c.apply(h,arguments)}),or(function $$or(){if(e)e.fail.apply(h,arguments);else{var n=f.call(arguments);e=createSequence().then(function $$then(e){e.fail.apply(h,n)}).defer()}}),createSequence().then(function $$then(n){e?e.pipe(n):e=n}).defer()}function abort(){return n?d:(r=!0,sequenceTick(),d)}function duplicate(){var e;return a={then_queue:s.slice(),or_queue:p.slice()},e=createSequence(),a=null,e}function unpause(){g.push.apply(g,arguments),e===!0&&(e=null),scheduleSequenceTick()}function defer(){return p.push(function ignored(){}),d}function internals(e,t){var a=arguments.length>1;switch(e){case"seq_error":if(!a)return n;n=t;break;case"seq_aborted":if(!a)return r;r=t;break;case"then_ready":if(!a)return u;u=t;break;case"then_queue":return s;case"or_queue":return p;case"sequence_messages":return g;case"sequence_errors":return $}}function includeExtensions(){Object.keys(o).forEach(function $$each(e){d[e]=o[e](d,internals)})}var e,n=!1,t=!1,r=!1,u=!0,s=[],p=[],g=[],$=[],d=brandIt({then:then,or:or,onerror:or,gate:gate,all:gate,pipe:pipe,seq:seq,val:val,promise:promise,fork:fork,abort:abort,duplicate:duplicate,defer:defer});return includeExtensions(),a&&(s=a.then_queue.slice(),p=a.or_queue.slice(),d.unpause=unpause,e=!0),d.then.apply(h,arguments),d}function brandIt(e){return Object.defineProperty(e,p,{enumerable:!1,value:!0})}function checkBranding(e){return!(null==e||"object"!=typeof e||!e[p])}function valWrapper(e){return c.apply(h,f.call(arguments).slice(1,e+1))}function thenWrapper(e){arguments[e+1].apply(h,f.call(arguments).slice(1,e+1))}function wrapArgs(e,n){var t,r;for(e=f.call(e),t=0;t 1 ?
+ ARRAY_SLICE.call(arguments,1) :
+ void 0
+ ;
+ num = +num || 0;
+
+ api.then(function $$then(done){
+ var args = orig_args || ARRAY_SLICE.call(arguments,1);
+
+ setTimeout(function $$set$timeout(){
+ done.apply(ø,args);
+ },num);
+ });
+
+ return api;
+ };
+});
+
+ASQ.after = function $$after() {
+ return ASQ().after.apply(ø,arguments);
+};
+// "any"
+ASQ.extend("any",function $$extend(api,internals){
+ return function $$any() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ function reset() {
+ finished = true;
+ error_messages.length = 0;
+ success_messages.length = 0;
+ }
+
+ function complete(trigger) {
+ if (success_messages.length > 0) {
+ // any successful segment's message(s) sent
+ // to main sequence to proceed as success
+ success_messages.length = fns.length;
+ trigger.apply(ø,success_messages);
+ }
+ else {
+ // send errors into main sequence
+ error_messages.length = fns.length;
+ trigger.fail.apply(ø,error_messages);
+ }
+
+ reset();
+ }
+
+ function success(trigger,idx,args) {
+ if (!finished) {
+ completed++;
+ success_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+
+ // all segments complete?
+ if (completed === fns.length) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+ }
+
+ function failure(trigger,idx,args) {
+ if (!finished &&
+ !(idx in error_messages)
+ ) {
+ completed++;
+ error_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+ }
+
+ // all segments complete?
+ if (!finished &&
+ completed === fns.length
+ ) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+
+ var completed = 0, error_messages = [], finished = false,
+ success_messages = [],
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1))
+ ;
+
+ wrapGate(sq,fns,success,failure,reset);
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "errfcb"
+ASQ.extend("errfcb",function $$extend(api,internals){
+ return function $$errfcb() {
+ // create a fake sequence to extract the callbacks
+ var sq = {
+ val: function $$then(cb){ sq.val_cb = cb; return sq; },
+ or: function $$or(cb){ sq.or_cb = cb; return sq; }
+ };
+
+ // trick `seq(..)`s checks for a sequence
+ sq[brand] = true;
+
+ // immediately register our fake sequence on the
+ // main sequence
+ api.seq(sq);
+
+ // provide the "error-first" callback
+ return function $$errorfirst$callback(err) {
+ if (err) {
+ sq.or_cb(err);
+ }
+ else {
+ sq.val_cb.apply(ø,ARRAY_SLICE.call(arguments,1));
+ }
+ };
+ };
+});
+// "failAfter"
+ASQ.extend("failAfter",function $$extend(api,internals){
+ return function $$failAfter(num) {
+ var args = arguments.length > 1 ?
+ ARRAY_SLICE.call(arguments,1) :
+ void 0
+ ;
+ num = +num || 0;
+
+ api.then(function $$then(done){
+ setTimeout(function $$set$timeout(){
+ done.fail.apply(ø,args);
+ },num);
+ });
+
+ return api;
+ };
+});
+
+ASQ.failAfter = function $$fail$after() {
+ return ASQ().failAfter.apply(ø,arguments);
+};
+// "first"
+ASQ.extend("first",function $$extend(api,internals){
+ return function $$first() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ function reset() {
+ error_messages.length = 0;
+ }
+
+ function success(trigger,idx,args) {
+ if (!finished) {
+ finished = true;
+
+ // first successful segment triggers
+ // main sequence to proceed as success
+ trigger(
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ );
+
+ reset();
+ }
+ }
+
+ function failure(trigger,idx,args) {
+ if (!finished &&
+ !(idx in error_messages)
+ ) {
+ completed++;
+ error_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+
+ // all segments complete without success?
+ if (completed === fns.length) {
+ finished = true;
+
+ // send errors into main sequence
+ error_messages.length = fns.length;
+ trigger.fail.apply(ø,error_messages);
+
+ reset();
+ }
+ }
+ }
+
+ var completed = 0, error_messages = [], finished = false,
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1))
+ ;
+
+ wrapGate(sq,fns,success,failure,reset);
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "go-style CSP"
+(function IIFE(){
+
+ // filter out already-resolved queue entries
+ function filterResolved(queue) {
+ return queue.filter(function $$filter(entry){
+ return !entry.resolved;
+ });
+ }
+
+ function closeQueue(queue,finalValue) {
+ queue.forEach(function $$each(iter){
+ if (!iter.resolved) {
+ iter.next();
+ iter.next(finalValue);
+ }
+ });
+ queue.length = 0;
+ }
+
+ function channel(bufSize) {
+ var ch = {
+ close: function $$close(){
+ ch.closed = true;
+ closeQueue(ch.put_queue,false);
+ closeQueue(ch.take_queue,ASQ.csp.CLOSED);
+ },
+ closed: false,
+ messages: [],
+ put_queue: [],
+ take_queue: [],
+ buffer_size: +bufSize || 0
+ };
+ return ch;
+ }
+
+ function unblock(iter) {
+ if (iter && !iter.resolved) {
+ iter.next(iter.next().value);
+ }
+ }
+
+ function put(channel,value) {
+ var ret;
+
+ if (channel.closed) {
+ return false;
+ }
+
+ // remove already-resolved entries
+ channel.put_queue = filterResolved(channel.put_queue);
+ channel.take_queue = filterResolved(channel.take_queue);
+
+ // immediate put?
+ if (channel.messages.length < channel.buffer_size) {
+ channel.messages.push(value);
+ unblock(channel.take_queue.shift());
+ return true;
+ }
+ // queued put
+ else {
+ channel.put_queue.push(
+ // make a notifiable iterable for 'put' blocking
+ ASQ.iterable()
+ .then(function $$then(){
+ if (!channel.closed) {
+ channel.messages.push(value);
+ return true;
+ }
+ else {
+ return false;
+ }
+ })
+ );
+
+ // wrap a sequence/promise around the iterable
+ ret = ASQ(
+ channel.put_queue[channel.put_queue.length - 1]
+ );
+
+ // take waiting on this queued put?
+ if (channel.take_queue.length > 0) {
+ unblock(channel.put_queue.shift());
+ unblock(channel.take_queue.shift());
+ }
+
+ return ret;
+ }
+ }
+
+ function putAsync(channel,value,cb) {
+ var ret = ASQ(put(channel,value));
+
+ if (cb && typeof cb == "function") {
+ ret.val(cb);
+ }
+ else {
+ return ret;
+ }
+ }
+
+ function take(channel) {
+ var ret;
+
+ try {
+ ret = takem(channel);
+ }
+ catch (err) {
+ ret = err;
+ }
+
+ if (ASQ.isSequence(ret)) {
+ ret.pCatch(function $$pcatch(err){
+ return err;
+ });
+ }
+
+ return ret;
+ }
+
+ function takeAsync(channel,cb) {
+ var ret = ASQ(take(channel));
+
+ if (cb && typeof cb == "function") {
+ ret.val(cb);
+ }
+ else {
+ return ret;
+ }
+ }
+
+ function takem(channel) {
+ var msg;
+
+ if (channel.closed) {
+ return ASQ.csp.CLOSED;
+ }
+
+ // remove already-resolved entries
+ channel.put_queue = filterResolved(channel.put_queue);
+ channel.take_queue = filterResolved(channel.take_queue);
+
+ // immediate take?
+ if (channel.messages.length > 0) {
+ msg = channel.messages.shift();
+ unblock(channel.put_queue.shift());
+ if (msg instanceof Error) {
+ throw msg;
+ }
+ return msg;
+ }
+ // queued take
+ else {
+ channel.take_queue.push(
+ // make a notifiable iterable for 'take' blocking
+ ASQ.iterable()
+ .then(function $$then(){
+ if (!channel.closed) {
+ var v = channel.messages.shift();
+ if (v instanceof Error) {
+ throw v;
+ }
+ return v;
+ }
+ else {
+ return ASQ.csp.CLOSED;
+ }
+ })
+ );
+
+ // wrap a sequence/promise around the iterable
+ msg = ASQ(
+ channel.take_queue[channel.take_queue.length - 1]
+ );
+
+ // put waiting on this take?
+ if (channel.put_queue.length > 0) {
+ unblock(channel.put_queue.shift());
+ unblock(channel.take_queue.shift());
+ }
+
+ return msg;
+ }
+ }
+
+ function takemAsync(channel,cb) {
+ var ret = ASQ(takem(channel));
+
+ if (cb && typeof cb == "function") {
+ ret.pThen(cb,cb);
+ }
+ else {
+ return ret.val(function $$val(v){
+ if (v instanceof Error) {
+ throw v;
+ }
+ return v;
+ });
+ }
+ }
+
+ function alts(actions) {
+ var closed, open, handlers, i, isq, ret, resolved = false;
+
+ // used `alts(..)` incorrectly?
+ if (!Array.isArray(actions) || actions.length == 0) {
+ throw Error("Invalid usage");
+ }
+
+ closed = [];
+ open = [];
+ handlers = [];
+
+ // separate actions by open/closed channel status
+ actions.forEach(function $$each(action){
+ var channel = Array.isArray(action) ? action[0] : action;
+
+ // remove already-resolved entries
+ channel.put_queue = filterResolved(channel.put_queue);
+ channel.take_queue = filterResolved(channel.take_queue);
+
+ if (channel.closed) {
+ closed.push(channel);
+ }
+ else {
+ open.push(action);
+ }
+ });
+
+ // if no channels are still open, we're done
+ if (open.length == 0) {
+ return { value: ASQ.csp.CLOSED, channel: closed };
+ }
+
+ // can any channel action be executed immediately?
+ for (i=0; i 0) {
+ return { value: take(open[i]), channel: open[i] };
+ }
+ }
+
+ isq = ASQ.iterable();
+ var ret = ASQ(isq);
+
+ // setup channel action handlers
+ for (i=0; i 0) {
+ schedule(function handleUnblocking(){
+ if (!resolved) {
+ unblock(channel.put_queue.shift());
+ unblock(channel.take_queue.shift());
+ }
+ },0);
+ }
+ }
+ // take action?
+ else {
+ channel = action;
+
+ // define take handler
+ handlers.push(
+ ASQ.iterable()
+ .then(function $$then(){
+ resolved = true;
+
+ // mark all handlers across this `alts(..)` as resolved now
+ handlers = handlers.filter(function $$filter(handler){
+ return !(handler.resolved = true);
+ });
+
+ // channel still open?
+ if (!channel.closed) {
+ isq.next({ value: channel.messages.shift(), channel: channel });
+ }
+ // channel already closed?
+ else {
+ isq.next({ value: ASQ.csp.CLOSED, channel: channel });
+ }
+ })
+ );
+
+ // queue up take handler
+ channel.take_queue.push(handlers[handlers.length-1]);
+
+ // put waiting on this queued take?
+ if (channel.put_queue.length > 0) {
+ schedule(function handleUnblocking(){
+ if (!resolved) {
+ unblock(channel.put_queue.shift());
+ unblock(channel.take_queue.shift());
+ }
+ });
+ }
+ }
+ })(open[i]);
+ }
+
+ return ret;
+ }
+
+ function altsAsync(chans,cb) {
+ var ret = ASQ(alts(chans));
+
+ if (cb && typeof cb == "function") {
+ ret.pThen(cb,cb);
+ }
+ else {
+ return ret;
+ }
+ }
+
+ function timeout(delay) {
+ var ch = channel();
+ setTimeout(ch.close,delay);
+ return ch;
+ }
+
+ function go(gen,args) {
+ // goroutine arguments passed?
+ if (arguments.length > 1) {
+ if (!args || !Array.isArray(args)) {
+ args = [args];
+ }
+ }
+ else {
+ args = [];
+ }
+
+ return function *$$go(token) {
+
+ // unblock the overall goroutine handling
+ function unblock() {
+ token.unblock_count++;
+
+ if (token.block && !token.block.marked) {
+ token.block.marked = true;
+ token.block.next();
+ }
+ }
+
+ var ret, msg, err, type, done = false, it;
+
+ // keep track of how many requests for unblocking
+ // have occurred
+ token.unblock_count = (token.unblock_count || 0);
+
+ // keep track of how many goroutines are running
+ // so we can infer when we're done go'ing
+ token.go_count = (token.go_count || 0) + 1;
+
+ // need to initialize a set of goroutines?
+ if (token.go_count === 1) {
+ // create a default channel for these goroutines
+ token.channel = channel();
+ token.channel.messages = token.messages;
+ token.channel.go = function $$go(){
+ // unblock the goroutine handling for this
+ // new goroutine
+ unblock();
+ // add the goroutine (called with any args) to
+ // the handling queue
+ token.add( go.apply(ø,arguments) );
+ };
+ // starting out with initial channel messages?
+ if (token.channel.messages.length > 0) {
+ // fake back-pressure blocking for each
+ token.channel.put_queue = token.channel.messages.map(function $$map(){
+ // make a notifiable iterable for 'put' blocking
+ return ASQ.iterable()
+ .then(function $$then(){
+ unblock(token.channel.take_queue.shift());
+ return !token.channel.closed;
+ });
+ });
+ }
+ }
+
+ // initialize the generator
+ it = gen.apply(ø,[token.channel].concat(args));
+
+ (function iterate(){
+
+ function next() {
+ // keep going with next step in goroutine?
+ if (!done) {
+ iterate();
+ }
+ // unblock overall goroutine handling to
+ // continue with other goroutines
+ else {
+ unblock();
+ }
+ }
+
+ // has a resumption value been achieved yet?
+ if (!ret) {
+ // try to resume the goroutine
+ try {
+ // resume with injected exception?
+ if (err) {
+ ret = it.throw(err);
+ err = null;
+ }
+ // resume normally
+ else {
+ ret = it.next(msg);
+ }
+ }
+ // resumption failed, so bail
+ catch (e) {
+ done = true;
+ err = e;
+ msg = null;
+ unblock();
+ return;
+ }
+
+ // keep track of the result of the resumption
+ done = ret.done;
+ ret = ret.value;
+ type = typeof ret;
+
+ // if this goroutine is complete, unblock the
+ // overall goroutine handling
+ if (done) {
+ unblock();
+ }
+
+ // received a thenable/promise back?
+ if (isPromise(ret)) {
+ ret = ASQ().promise(ret);
+ }
+
+ // wait for the value?
+ if (ASQ.isSequence(ret)) {
+ ret.val(function $$val(){
+ ret = null;
+ msg = arguments.length > 1 ?
+ ASQ.messages.apply(ø,arguments) :
+ arguments[0]
+ ;
+ next();
+ })
+ .or(function $$or(){
+ ret = null;
+ msg = arguments.length > 1 ?
+ ASQ.messages.apply(ø,arguments) :
+ arguments[0]
+ ;
+ if (msg instanceof Error) {
+ err = msg;
+ msg = null;
+ }
+ next();
+ });
+ }
+ // immediate value, prepare it to go right back in
+ else {
+ msg = ret;
+ ret = null;
+ next();
+ }
+ }
+ })();
+
+ // keep this goroutine alive until completion
+ while (!done) {
+ // transfer control to another goroutine
+ yield token;
+
+ // need to block overall goroutine handling
+ // while idle?
+ if (!done && !token.block && token.unblock_count === 0) {
+ // wait here while idle
+ yield (token.block = ASQ.iterable());
+
+ token.block = false;
+ }
+
+ if (token.unblock_count > 0) token.unblock_count--;
+ }
+
+ // this goroutine is done now
+ token.go_count--;
+
+ // all goroutines done?
+ if (token.go_count === 0) {
+ // any lingering blocking need to be cleaned up?
+ unblock();
+
+ // capture any untaken messages
+ msg = ASQ.messages.apply(ø,token.messages);
+
+ // need to implicitly force-close channel?
+ if (token.channel && !token.channel.closed) {
+ token.channel.closed = true;
+ token.channel.put_queue.length = token.channel.take_queue.length = 0;
+ token.channel.close = token.channel.go = token.channel.messages = null;
+ }
+ token.channel = null;
+ }
+
+ // make sure leftover error or message are
+ // passed along
+ if (err) {
+ throw err;
+ }
+ else if (token.go_count === 0) {
+ return msg;
+ }
+ else {
+ return token;
+ }
+ };
+ }
+
+ ASQ.csp = {
+ chan: channel,
+ put: put,
+ putAsync: putAsync,
+ take: take,
+ takeAsync: takeAsync,
+ takem: takem,
+ takemAsync: takemAsync,
+ alts: alts,
+ altsAsync: altsAsync,
+ timeout: timeout,
+ go: go,
+ CLOSED: {}
+ };
+
+})();
+// "ASQ.iterable()"
+(function IIFE(){
+ var template;
+
+ ASQ.iterable = function $$iterable() {
+ function throwSequenceErrors() {
+ throw (sequence_errors.length === 1 ? sequence_errors[0] : sequence_errors);
+ }
+
+ function notifyErrors() {
+ var fn;
+
+ seq_tick = null;
+
+ if (seq_error) {
+ if (or_queue.length === 0 && !error_reported) {
+ error_reported = true;
+ throwSequenceErrors();
+ }
+
+ while (or_queue.length > 0) {
+ error_reported = true;
+ fn = or_queue.shift();
+ try {
+ fn.apply(ø,sequence_errors);
+ }
+ catch (err) {
+ if (checkBranding(err)) {
+ sequence_errors = sequence_errors.concat(err);
+ }
+ else {
+ sequence_errors.push(err);
+ }
+ if (or_queue.length === 0) {
+ throwSequenceErrors();
+ }
+ }
+ }
+ }
+ }
+
+ function val() {
+ if (seq_error || seq_aborted || arguments.length === 0) {
+ return sequence_api;
+ }
+
+ var args = ARRAY_SLICE.call(arguments).map(function mapper(arg){
+ if (typeof arg != "function") return function $$val() { return arg; };
+ else return arg;
+ });
+
+ val_queue.push.apply(val_queue,args);
+
+ return sequence_api;
+ }
+
+ function or() {
+ if (seq_aborted || arguments.length === 0) {
+ return sequence_api;
+ }
+
+ or_queue.push.apply(or_queue,arguments);
+
+ if (!seq_tick) {
+ seq_tick = schedule(notifyErrors);
+ }
+
+ return sequence_api;
+ }
+
+ function pipe() {
+ if (seq_aborted || arguments.length === 0) {
+ return sequence_api;
+ }
+
+ ARRAY_SLICE.call(arguments)
+ .forEach(function $$each(fn){
+ val(fn).or(fn.fail);
+ });
+
+ return sequence_api;
+ }
+
+ function next() {
+ if (seq_error || seq_aborted || val_queue.length === 0) {
+ if (val_queue.length > 0) {
+ $throw$("Sequence cannot be iterated");
+ }
+ return { done: true };
+ }
+
+ try {
+ return { value: val_queue.shift().apply(ø,arguments) };
+ }
+ catch (err) {
+ if (ASQ.isMessageWrapper(err)) {
+ $throw$.apply(ø,err);
+ }
+ else {
+ $throw$(err);
+ }
+
+ return {};
+ }
+ }
+
+ function $throw$() {
+ if (seq_error || seq_aborted) {
+ return sequence_api;
+ }
+
+ sequence_errors.push.apply(sequence_errors,arguments);
+ seq_error = true;
+ if (!seq_tick) {
+ seq_tick = schedule(notifyErrors);
+ }
+
+ return sequence_api;
+ }
+
+ function $return$(val) {
+ if (seq_error || seq_aborted) {
+ val = void 0;
+ }
+
+ abort();
+
+ return { done: true, value: val };
+ }
+
+ function abort() {
+ if (seq_error || seq_aborted) {
+ return;
+ }
+
+ seq_aborted = true;
+
+ clearTimeout(seq_tick);
+ seq_tick = null;
+ val_queue.length = or_queue.length = sequence_errors.length = 0;
+ }
+
+ function duplicate() {
+ var isq;
+
+ template = {
+ val_queue: val_queue.slice(),
+ or_queue: or_queue.slice()
+ };
+ isq = ASQ.iterable();
+ template = null;
+
+ return isq;
+ }
+
+ // opt-out of global error reporting for this sequence
+ function defer() {
+ or_queue.push(function $$ignored(){});
+ return sequence_api;
+ }
+
+ // ***********************************************
+ // Object branding utilities
+ // ***********************************************
+ function brandIt(obj) {
+ Object.defineProperty(obj,brand,{
+ enumerable: false,
+ value: true
+ });
+
+ return obj;
+ }
+
+ var sequence_api,
+
+ seq_error = false,
+ error_reported = false,
+ seq_aborted = false,
+
+ seq_tick,
+
+ val_queue = [],
+ or_queue = [],
+
+ sequence_errors = []
+ ;
+
+ // ***********************************************
+ // Setup the ASQ.iterable() public API
+ // ***********************************************
+ sequence_api = brandIt({
+ val: val,
+ then: val,
+ or: or,
+ pipe: pipe,
+ next: next,
+ "throw": $throw$,
+ "return": $return$,
+ abort: abort,
+ duplicate: duplicate,
+ defer: defer
+ });
+
+ // useful for ES6 `for..of` loops,
+ // add `@@iterator` to simply hand back
+ // our iterable sequence itself!
+ sequence_api[(typeof Symbol == "function" && Symbol.iterator) || "@@iterator"] = function $$iter() {
+ return sequence_api;
+ };
+
+ // templating the iterable-sequence setup?
+ if (template) {
+ val_queue = template.val_queue.slice(0);
+ or_queue = template.or_queue.slice(0);
+ }
+
+ // treat ASQ.iterable() constructor parameters as having been
+ // passed to `val()`
+ sequence_api.val.apply(ø,arguments);
+
+ return sequence_api;
+ };
+
+})();
+// "last"
+ASQ.extend("last",function $$extend(api,internals){
+ return function $$last() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ function reset() {
+ finished = true;
+ error_messages.length = 0;
+ success_messages = null;
+ }
+
+ function complete(trigger) {
+ if (success_messages != null) {
+ // last successful segment's message(s) sent
+ // to main sequence to proceed as success
+ trigger(
+ success_messages.length > 1 ?
+ ASQ.messages.apply(ø,success_messages) :
+ success_messages[0]
+ );
+ }
+ else {
+ // send errors into main sequence
+ error_messages.length = fns.length;
+ trigger.fail.apply(ø,error_messages);
+ }
+
+ reset();
+ }
+
+ function success(trigger,idx,args) {
+ if (!finished) {
+ completed++;
+ success_messages = args;
+
+ // all segments complete?
+ if (completed === fns.length) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+ }
+
+ function failure(trigger,idx,args) {
+ if (!finished &&
+ !(idx in error_messages)
+ ) {
+ completed++;
+ error_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+ }
+
+ // all segments complete?
+ if (!finished &&
+ completed === fns.length
+ ) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+
+ var completed = 0, error_messages = [], finished = false,
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)),
+ success_messages
+ ;
+
+ wrapGate(sq,fns,success,failure,reset);
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "map"
+ASQ.extend("map",function $$extend(api,internals){
+ return function $$map(pArr,pEach) {
+ if (internals("seq_error") || internals("seq_aborted")) {
+ return api;
+ }
+
+ api.seq(function $$seq(){
+ var tmp, args = ARRAY_SLICE.call(arguments),
+ arr = pArr, each = pEach;
+
+ // if missing `map(..)` args, use value-messages (if any)
+ if (!each) each = args.shift();
+ if (!arr) arr = args.shift();
+
+ // if arg types in reverse order (each,arr), swap
+ if (typeof arr === "function" && Array.isArray(each)) {
+ tmp = arr;
+ arr = each;
+ each = tmp;
+ }
+
+ return ASQ.apply(ø,args)
+ .gate.apply(ø,arr.map(function $$map(item){
+ return function $$segment(){
+ each.apply(ø,[item].concat(ARRAY_SLICE.call(arguments)));
+ };
+ }));
+ })
+ .val(function $$val(){
+ // collect all gate segment output into one value-message
+ // Note: return a normal array here, not a message wrapper!
+ return ARRAY_SLICE.call(arguments);
+ });
+
+ return api;
+ };
+});
+// "none"
+ASQ.extend("none",function $$extend(api,internals){
+ return function $$none() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ function reset() {
+ finished = true;
+ error_messages.length = 0;
+ success_messages.length = 0;
+ }
+
+ function complete(trigger) {
+ if (success_messages.length > 0) {
+ // any successful segment's message(s) sent
+ // to main sequence to proceed as **error**
+ success_messages.length = fns.length;
+ trigger.fail.apply(ø,success_messages);
+ }
+ else {
+ // send errors as **success** to main sequence
+ error_messages.length = fns.length;
+ trigger.apply(ø,error_messages);
+ }
+
+ reset();
+ }
+
+ function success(trigger,idx,args) {
+ if (!finished) {
+ completed++;
+ success_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+
+ // all segments complete?
+ if (completed === fns.length) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+ }
+
+ function failure(trigger,idx,args) {
+ if (!finished &&
+ !(idx in error_messages)
+ ) {
+ completed++;
+ error_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+ }
+
+ // all segments complete?
+ if (!finished &&
+ completed === fns.length
+ ) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+
+ var completed = 0, error_messages = [], finished = false,
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)),
+ success_messages = []
+ ;
+
+ wrapGate(sq,fns,success,failure,reset);
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "pThen"
+ASQ.extend("pThen",function $$extend(api,internals){
+ return function $$pthen(success,failure) {
+ if (internals("seq_aborted")) {
+ return api;
+ }
+
+ var ignore_success_handler = false, ignore_failure_handler = false;
+
+ if (typeof success === "function") {
+ api.then(function $$then(done){
+ if (!ignore_success_handler) {
+ var ret, msgs = ASQ.messages.apply(ø,arguments);
+ msgs.shift();
+
+ if (msgs.length === 1) {
+ msgs = msgs[0];
+ }
+
+ ignore_failure_handler = true;
+
+ try {
+ ret = success(msgs);
+ }
+ catch (err) {
+ if (!ASQ.isMessageWrapper(err)) {
+ err = [err];
+ }
+ done.fail.apply(ø,err);
+ return;
+ }
+
+ // returned a sequence?
+ if (ASQ.isSequence(ret)) {
+ ret.pipe(done);
+ }
+ // returned a message wrapper?
+ else if (ASQ.isMessageWrapper(ret)) {
+ done.apply(ø,ret);
+ }
+ // returned a promise/thenable?
+ else if (isPromise(ret)) {
+ ret.then(done,done.fail);
+ }
+ // just a normal value to pass along
+ else {
+ done(ret);
+ }
+ }
+ else {
+ done.apply(ø,ARRAY_SLICE.call(arguments,1));
+ }
+ });
+ }
+ if (typeof failure === "function") {
+ api.or(function $$or(){
+ if (!ignore_failure_handler) {
+ var ret, msgs = ASQ.messages.apply(ø,arguments), smgs,
+ or_queue = ARRAY_SLICE.call(internals("or_queue"))
+ ;
+
+ if (msgs.length === 1) {
+ msgs = msgs[0];
+ }
+
+ ignore_success_handler = true;
+
+ // NOTE: if this call throws, that'll automatically
+ // be handled by core as we'd want it to be
+ ret = failure(msgs);
+
+ // if we get this far:
+ // first, inject return value (if any) as
+ // next step's sequence messages
+ smgs = internals("sequence_messages");
+ smgs.length = 0;
+ if (typeof ret !== "undefined") {
+ if (!ASQ.isMessageWrapper(ret)) {
+ ret = [ret];
+ }
+ smgs.push.apply(smgs,ret);
+ }
+
+ // reset internal error state, because we've exclusively
+ // handled any errors up to this point of the sequence
+ internals("sequence_errors").length = 0;
+ internals("seq_error",false);
+ internals("then_ready",true);
+
+ // temporarily empty the or-queue
+ internals("or_queue").length = 0;
+
+ // make sure to schedule success-procession on the chain
+ api.val(function $$val(){
+ // pass thru messages
+ return ASQ.messages.apply(ø,arguments);
+ });
+
+ // at next cycle, reinstate the or-queue (if any)
+ if (or_queue.length > 0) {
+ schedule(function $$schedule(){
+ api.or.apply(ø,or_queue);
+ });
+ }
+ }
+ });
+ }
+ return api;
+ };
+});
+
+// "pCatch"
+ASQ.extend("pCatch",function $$extend(api,internals){
+ return function $$pcatch(failure) {
+ if (internals("seq_aborted")) {
+ return api;
+ }
+
+ api.pThen(void 0,failure);
+
+ return api;
+ };
+});
+// "race"
+ASQ.extend("race",function $$extend(api,internals){
+ return function $$race() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments)
+ .map(function $$map(v){
+ var def;
+ // tap any directly-provided sequences immediately
+ if (ASQ.isSequence(v)) {
+ def = { seq: v };
+ tapSequence(def);
+ return function $$fn(done) {
+ def.seq.pipe(done);
+ };
+ }
+ else return v;
+ });
+
+ api.then(function $$then(done){
+ var args = ARRAY_SLICE.call(arguments);
+
+ fns.forEach(function $$each(fn){
+ fn.apply(ø,args);
+ });
+ });
+
+ return api;
+ };
+});
+// "react" (reactive sequences)
+ASQ.react = function $$react(reactor) {
+ function next() {
+ if (!paused) {
+ if (template) {
+ var sq = template.duplicate();
+ sq.unpause.apply(ø,arguments);
+ return sq;
+ }
+ return ASQ(function $$asq(){ throw "Disabled Sequence"; });
+ }
+ }
+
+ function registerTeardown(fn) {
+ if (template && typeof fn === "function") {
+ teardowns.push(fn);
+ }
+ }
+
+ var template = ASQ().duplicate(),
+ teardowns = [], paused = false
+ ;
+
+ // add reactive sequence kill switch
+ template.stop = function $$stop() {
+ if (template) {
+ template = null;
+ teardowns.forEach(Function.call,Function.call);
+ teardowns.length = 0;
+ }
+ };
+
+ template.pause = function $$pause() {
+ if (!paused && template) {
+ paused = true;
+ teardowns.forEach(Function.call,Function.call);
+ teardowns.length = 0;
+ }
+ };
+
+ template.resume = function $$resume() {
+ if (paused && template) {
+ paused = false;
+ reactor.call(template,next,registerTeardown);
+ }
+ };
+
+ template.push = next;
+
+ next.onStream = function $$onStream() {
+ ARRAY_SLICE.call(arguments)
+ .forEach(function $$each(stream){
+ stream.on("data",next);
+ stream.on("error",next);
+ });
+ };
+
+ next.unStream = function $$unStream() {
+ ARRAY_SLICE.call(arguments)
+ .forEach(function $$each(stream){
+ stream.removeListener("data",next);
+ stream.removeListener("error",next);
+ });
+ };
+
+ // make sure `reactor(..)` is called async
+ ASQ.__schedule(function $$schedule(){
+ reactor.call(template,next,registerTeardown);
+ });
+
+ return template;
+};
+// "react" helpers
+(function IIFE(){
+
+ var Ar = ASQ.react;
+
+ Ar.of = function $$react$of() {
+ function reactor(next) {
+ if (!started) {
+ started = true;
+ if (args.length > 0) {
+ args.shift().val(function val(){
+ next.apply(ø,arguments);
+ if (args.length > 0) {
+ args.shift().val(val);
+ }
+ });
+ }
+ }
+ }
+
+ var started, args = ARRAY_SLICE.call(arguments)
+ .map(function wrapper(arg){
+ if (!ASQ.isSequence(arg)) arg = ASQ(arg);
+ return arg;
+ });
+
+ return Ar(reactor);
+ };
+
+ Ar.all = Ar.zip = makeReactOperator(/*buffer=*/true);
+ Ar.allLatest = makeReactOperator(/*buffer=false*/);
+ Ar.latest = Ar.combineLatest = makeReactOperator(/*buffer=*/false,/*keep=*/true);
+
+ Ar.any = Ar.merge = function $$react$any(){
+ function reactor(next,registerTeardown){
+ function processSequence(def){
+ function trigger(){
+ var args = ASQ.messages.apply(ø,arguments);
+ // still observing sequence-streams?
+ if (seqs && seqs.length > 0) {
+ // fire off reactive sequence instance
+ next.apply(ø,args);
+ }
+ // keep sequence going
+ return args;
+ }
+
+ // sequence-stream event listener
+ def.seq.val(trigger);
+ }
+
+ // observe all sequence-streams
+ seqs.forEach(processSequence);
+
+ // listen for stop() of reactive sequence
+ registerTeardown(function $$teardown(){
+ seqs = null;
+ });
+ }
+
+ // observe all sequence-streams
+ var seqs = tapSequences.apply(null,arguments);
+
+ if (seqs.length == 0) return;
+
+ return Ar(reactor);
+ };
+
+ Ar.distinct = function $$react$distinct(seq){
+ return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/true));
+ };
+
+ Ar.distinctConsecutive = Ar.distinctUntilChanged = function $$react$distinct$consecutive(seq) {
+ return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/false));
+ };
+
+ Ar.filter = function $$react$filter(seq,filterer){
+ function reactor(next,registerTeardown) {
+ function trigger(){
+ var messages = ASQ.messages.apply(ø,arguments);
+
+ if (filterer && filterer.apply(ø,messages)) {
+ // fire off reactive sequence instance
+ next.apply(ø,messages);
+ }
+
+ // keep sequence going
+ return messages;
+ }
+
+ // sequence-stream event listener
+ def.seq.val(trigger);
+
+ // listen for stop() of reactive sequence
+ registerTeardown(function $$teardown(){
+ def = filterer = null;
+ });
+ }
+
+ // observe sequence-stream
+ var def = tapSequences(seq)[0];
+
+ if (!def) return;
+
+ return Ar(reactor);
+ };
+
+ Ar.fromObservable = function $$react$from$observable(obsv){
+ function reactor(next,registerTeardown){
+ // process buffer (if any)
+ buffer.forEach(next);
+ buffer.length = 0;
+
+ // start non-buffered notifications?
+ if (!buffer.complete) {
+ notify = next;
+ }
+
+ registerTeardown(function $$teardown(){
+ obsv.dispose();
+ });
+ }
+
+ function notify(v) {
+ buffer.push(v);
+ }
+
+ var buffer = [];
+
+ obsv.subscribe(
+ function $$on$next(v){
+ notify(v);
+ },
+ function $$on$error(){},
+ function $$on$complete(){
+ buffer.complete = true;
+ obsv.dispose();
+ }
+ );
+
+ return Ar(reactor);
+ };
+
+ ASQ.extend("toObservable",function $$extend(api,internals){
+ return function $$to$observable(){
+ function init(observer) {
+ function define(pair){
+ function listen(){
+ var args = ASQ.messages.apply(ø,arguments);
+ observer[pair[1]].apply(observer,
+ args.length == 1 ? [args[0]] : args
+ );
+ return args;
+ }
+
+ api[pair[0]](listen);
+ }
+
+ [["val","onNext"],["or","onError"]]
+ .forEach(define);
+ }
+
+ return Rx.Observable.create(init);
+ };
+ });
+
+ function tapSequences() {
+ function tapSequence(seq) {
+ // temporary `trigger` which, if called before being replaced
+ // below, creates replacement proxy sequence with the
+ // event message(s) re-fired
+ function trigger() {
+ var args = ARRAY_SLICE.call(arguments);
+ def.seq = Ar(function $$react(next){
+ next.apply(ø,args);
+ });
+ }
+
+ if (ASQ.isSequence(seq)) {
+ var def = { seq: seq };
+
+ // listen for events from the sequence-stream
+ seq.val(function $$val(){
+ trigger.apply(ø,arguments);
+ return ASQ.messages.apply(ø,arguments);
+ });
+
+ // make a reactive sequence to act as a proxy to the original
+ // sequence
+ def.seq = Ar(function $$react(next){
+ // replace the temporary trigger (created above)
+ // with this proxy's trigger
+ trigger = next;
+ });
+
+ return def;
+ }
+ }
+
+ return ARRAY_SLICE.call(arguments)
+ .map(tapSequence)
+ .filter(Boolean);
+ }
+
+ function makeReactOperator(buffer,keep) {
+ return function $$react$operator(){
+ function reactor(next,registerTeardown){
+ function processSequence(def) {
+ // sequence-stream event listener
+ function trigger() {
+ var args = ASQ.messages.apply(ø,arguments);
+ // still observing sequence-streams?
+ if (seqs && seqs.length > 0) {
+ // store event message(s), if any
+ seq_events[seq_id] =
+ (buffer ? seq_events[seq_id] : []).concat(
+ args.length > 0 ? (args.length > 1 ? [args] : args[0]) : undefined
+ );
+
+ // collect event message(s) across the
+ // sequence-stream sources
+ var messages = seq_events.reduce(function reducer(msgs,eventList,idx){
+ if (eventList.length > 0) msgs.push(eventList[0]);
+ return msgs;
+ },[]);
+
+ // did all sequence-streams get an event?
+ if (messages.length == seq_events.length) {
+ if (messages.length == 1) messages = messages[0];
+
+ // fire off reactive sequence instance
+ next.apply(ø,messages);
+
+ // discard stored event message(s)?
+ if (!keep) {
+ seq_events.forEach(function $$each(eventList){
+ eventList.shift();
+ });
+ }
+ }
+ }
+ // keep sequence going
+ return args;
+ }
+
+ var seq_id = seq_events.length;
+ seq_events.push([]);
+ def.seq.val(trigger);
+ }
+
+ // process all sequence-streams
+ seqs.forEach(processSequence);
+
+ // listen for stop() of reactive sequence
+ registerTeardown(function $$teardown(){
+ seqs = seq_events = null;
+ });
+ }
+
+ var seq_events = [],
+ // observe all sequence-streams
+ seqs = tapSequences.apply(null,arguments)
+ ;
+
+ if (seqs.length == 0) return;
+
+ return Ar(reactor);
+ };
+ }
+
+ function makeDistinctFilterer(keepAll) {
+ function filterer() {
+ function isDuplicate(msgSet) {
+ return (
+ msgSet.length == message_set.length &&
+ msgSet.every(function $$every(val,idx){
+ return val === message_set[idx];
+ })
+ );
+ }
+
+ var message_set = ASQ.messages.apply(ø,arguments);
+
+ // any messages in message-set to check against?
+ if (message_set.length > 0) {
+ // duplicate message-set?
+ if (msg_sets.some(isDuplicate)) {
+ return false;
+ }
+
+ // remember all message-sets for future distinct checking?
+ if (keepAll) {
+ msg_sets.push(message_set);
+ }
+ // only keep the last message-set for distinct-consecutive
+ // checking
+ else {
+ msg_sets[0] = message_set;
+ }
+ }
+
+ // allow distinct non-duplicate value through
+ return true;
+ }
+
+ var msg_sets = [];
+
+ return filterer;
+ }
+
+})();
+// "runner"
+ASQ.extend("runner",function $$extend(api,internals){
+
+ return function $$runner() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var args = ARRAY_SLICE.call(arguments);
+
+ api
+ .then(function $$then(mainDone){
+
+ function wrap(v) {
+ // function? expected to produce an iterator
+ // (like a generator) or a promise
+ if (typeof v === "function") {
+ // call function passing in the control token
+ // note: neutralize `this` in call to prevent
+ // unexpected behavior
+ v = v.call(ø,token);
+
+ // promise returned (ie, from async function)?
+ if (isPromise(v)) {
+ // wrap it in iterable sequence
+ v = ASQ.iterable(v);
+ }
+ }
+ // an iterable sequence? duplicate it (in case of multiple runs)
+ else if (ASQ.isSequence(v) && "next" in v) {
+ v = v.duplicate();
+ }
+ // wrap anything else in iterable sequence
+ else {
+ v = ASQ.iterable(v);
+ }
+
+ // a sequence to tap for errors?
+ if (ASQ.isSequence(v)) {
+ // listen for any sequence failures
+ v.or(function $$or(){
+ // signal iteration-error
+ mainDone.fail.apply(ø,arguments);
+ });
+ }
+
+ return v;
+ }
+
+ function addWrapped() {
+ iterators.push.apply(
+ iterators,
+ ARRAY_SLICE.call(arguments).map(wrap)
+ );
+ }
+
+ function iterateOrQuit(iterFn,now) {
+ // still have some co-routine runs to process?
+ if (iterators.length > 0) {
+ if (now) iterFn();
+ else schedule(iterFn);
+ }
+ // all done!
+ else {
+ // previous value message?
+ if (typeof next_val !== "undefined") {
+ // not a message wrapper array?
+ if (!ASQ.isMessageWrapper(next_val)) {
+ // wrap value for the subsequent `apply(..)`
+ next_val = [next_val];
+ }
+ }
+ else {
+ // nothing to affirmatively pass along
+ next_val = [];
+ }
+
+ // signal done with all co-routine runs
+ mainDone.apply(ø,next_val);
+ }
+ }
+
+ var iterators = args,
+ token = {
+ messages: ARRAY_SLICE.call(arguments,1),
+ add: addWrapped
+ },
+ iter, ret, next_val = token
+ ;
+
+ // map co-routines to round-robin list of iterators
+ iterators = iterators.map(wrap);
+
+ // async iteration of round-robin list
+ (function iterate(){
+ // get next co-routine in list
+ iter = iterators.shift();
+
+ // process the iteration
+ try {
+ // multiple messages to send to an iterable
+ // sequence?
+ if (ASQ.isMessageWrapper(next_val) &&
+ ASQ.isSequence(iter)
+ ) {
+ ret = iter.next.apply(iter,next_val);
+ }
+ else {
+ ret = iter.next(next_val);
+ }
+ }
+ catch (err) {
+ return mainDone.fail(err);
+ }
+
+ // bail on run in aborted sequence
+ if (internals("seq_aborted")) return;
+
+ // was the control token yielded?
+ if (ret.value === token) {
+ // round-robin: put co-routine back into the list
+ // at the end where it was so it can be processed
+ // again on next loop-iteration
+ if (!ret.done) {
+ iterators.push(iter);
+ }
+ next_val = token;
+ iterateOrQuit(iterate,/*now=*/false);
+ }
+ else {
+ // not a recognized ASQ instance returned?
+ if (!ASQ.isSequence(ret.value)) {
+ // received a thenable/promise back?
+ if (isPromise(ret.value)) {
+ // wrap in a sequence
+ ret.value = ASQ().promise(ret.value);
+ }
+ // thunk yielded?
+ else if (typeof ret.value === "function") {
+ // wrap thunk call in a sequence
+ var fn = ret.value;
+ ret.value = ASQ(function $$ASQ(done){
+ fn(done.errfcb);
+ });
+ }
+ // message wrapper returned?
+ else if (ASQ.isMessageWrapper(ret.value)) {
+ // wrap message(s) in a sequence
+ ret.value = ASQ.apply(ø,
+ // don't let `apply(..)` discard an empty message
+ // wrapper! instead, pass it along as its own value
+ // itself.
+ ret.value.length > 0 ? ret.value : ASQ.messages(undefined)
+ );
+ }
+ // non-undefined value returned?
+ else if (typeof ret.value !== "undefined") {
+ // wrap the value in a sequence
+ ret.value = ASQ(ret.value);
+ }
+ else {
+ // make an empty sequence
+ ret.value = ASQ();
+ }
+ }
+
+ ret.value
+ .val(function $$val(){
+ // bail on run in aborted sequence
+ if (internals("seq_aborted")) return;
+
+ if (arguments.length > 0) {
+ // save any return messages for input
+ // to next iteration
+ next_val = arguments.length > 1 ?
+ ASQ.messages.apply(ø,arguments) :
+ arguments[0]
+ ;
+ }
+
+ // still more to iterate?
+ if (!ret.done) {
+ // was the control token passed along?
+ if (next_val === token) {
+ // round-robin: put co-routine back into the list
+ // at the end, so that the the next iterator can be
+ // processed on next loop-iteration
+ iterators.push(iter);
+ }
+ else {
+ // put co-routine back in where it just
+ // was so it can be processed again on
+ // next loop-iteration
+ iterators.unshift(iter);
+ }
+ }
+
+ iterateOrQuit(iterate,/*now=*/true);
+ })
+ .or(function $$or(){
+ // bail on run in aborted sequence
+ if (internals("seq_aborted")) return;
+
+ try {
+ // if an error occurs in the step-continuation
+ // promise or sequence, throw it back into the
+ // generator or iterable-sequence
+ iter["throw"].apply(iter,arguments);
+ }
+ catch (err) {
+ // if an error comes back out of after the throw,
+ // pass it out to the main sequence, as iteration
+ // must now be complete
+ mainDone.fail(err);
+ }
+ });
+ }
+ })();
+ });
+
+ return api;
+ };
+});
+// "toPromise"
+ASQ.extend("toPromise",function $$extend(api,internals){
+ return function $$to$promise() {
+ return new Promise(function $$executor(resolve,reject){
+ api
+ .val(function $$val(){
+ var args = ARRAY_SLICE.call(arguments);
+ resolve.call(ø,args.length > 1 ? args : args[0]);
+ return ASQ.messages.apply(ø,args);
+ })
+ .or(function $$or(){
+ var args = ARRAY_SLICE.call(arguments);
+ reject.call(ø,args.length > 1 ? args : args[0]);
+ });
+ });
+ };
+});
+// "try"
+ASQ.extend("try",function $$extend(api,internals){
+ return function $$try() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments)
+ .map(function $$map(fn){
+ return function $$then(mainDone) {
+ var main_args = ARRAY_SLICE.call(arguments),
+ sq = ASQ.apply(ø,main_args.slice(1))
+ ;
+
+ sq
+ .then(function $$inner$then(){
+ fn.apply(ø,arguments);
+ })
+ .val(function $$val(){
+ mainDone.apply(ø,arguments);
+ })
+ .or(function $$inner$or(){
+ var msgs = ASQ.messages.apply(ø,arguments);
+ // failed, so map error(s) as `catch`
+ mainDone({
+ "catch": msgs.length > 1 ? msgs : msgs[0]
+ });
+ });
+ };
+ });
+
+ api.then.apply(ø,fns);
+
+ return api;
+ };
+});
+// "until"
+ASQ.extend("until",function $$extend(api,internals){
+ return function $$until() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments)
+ .map(function $$map(fn){
+ return function $$then(mainDone) {
+ var main_args = ARRAY_SLICE.call(arguments),
+ sq = ASQ.apply(ø,main_args.slice(1))
+ ;
+
+ sq
+ .then(function $$inner$then(){
+ var args = ARRAY_SLICE.call(arguments);
+ args[0]["break"] = function $$break(){
+ mainDone.fail.apply(ø,arguments);
+ sq.abort();
+ };
+
+ fn.apply(ø,args);
+ })
+ .val(function $$val(){
+ mainDone.apply(ø,arguments);
+ })
+ .or(function $$inner$or(){
+ // failed, retry
+ $$then.apply(ø,main_args);
+ });
+ };
+ });
+
+ api.then.apply(ø,fns);
+
+ return api;
+ };
+});
+// "waterfall"
+ASQ.extend("waterfall",function $$extend(api,internals){
+ return function $$waterfall() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ var msgs = ASQ.messages(),
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1))
+ ;
+
+ fns.forEach(function $$each(fn){
+ sq.then(fn)
+ .val(function $$val(){
+ var args = ASQ.messages.apply(ø,arguments);
+ msgs.push(args.length > 1 ? args : args[0]);
+ return msgs;
+ });
+ });
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "wrap"
+ASQ.wrap = function $$wrap(fn,opts) {
+ function checkThis(t,o) {
+ return (!t ||
+ (typeof window != "undefined" && t === window) ||
+ (typeof global != "undefined" && t === global)
+ ) ? o : t;
+ }
+
+ function paramSpread(gen) {
+ return function *paramSpread(token) {
+ yield *gen.apply(this,token.messages);
+ };
+ }
+
+ var errfcb, params_first, act, this_obj;
+
+ opts = (opts && typeof opts == "object") ? opts : {};
+
+ if (
+ (opts.errfcb && opts.splitcb) ||
+ (opts.errfcb && opts.simplecb) ||
+ (opts.splitcb && opts.simplecb) ||
+ ("errfcb" in opts && !opts.errfcb && !opts.splitcb && !opts.simplecb) ||
+ (opts.params_first && opts.params_last) ||
+ (opts.spread && !opts.gen)
+ ) {
+ throw Error("Invalid options");
+ }
+
+ // initialize default flags
+ this_obj = (opts["this"] && typeof opts["this"] == "object") ? opts["this"] : ø;
+ errfcb = opts.errfcb || !(opts.splitcb || opts.simplecb);
+ params_first = !!opts.params_first ||
+ (!opts.params_last && !("params_first" in opts || opts.params_first)) ||
+ ("params_last" in opts && !opts.params_first && !opts.params_last)
+ ;
+
+ if (params_first) {
+ act = "push";
+ }
+ else {
+ act = "unshift";
+ }
+
+ if (opts.gen) {
+ if (opts.spread) {
+ fn = paramSpread(fn);
+ }
+ return function $$wrapped$gen() {
+ return ASQ.apply(ø,arguments).runner(fn);
+ };
+ }
+ if (errfcb) {
+ return function $$wrapped$errfcb() {
+ var args = ARRAY_SLICE.call(arguments),
+ _this = checkThis(this,this_obj)
+ ;
+
+ return ASQ(function $$asq(done){
+ args[act](done.errfcb);
+ fn.apply(_this,args);
+ });
+ };
+ }
+ if (opts.splitcb) {
+ return function $$wrapped$splitcb() {
+ var args = ARRAY_SLICE.call(arguments),
+ _this = checkThis(this,this_obj)
+ ;
+
+ return ASQ(function $$asq(done){
+ args[act](done,done.fail);
+ fn.apply(_this,args);
+ });
+ };
+ }
+ if (opts.simplecb) {
+ return function $$wrapped$simplecb() {
+ var args = ARRAY_SLICE.call(arguments),
+ _this = checkThis(this,this_obj)
+ ;
+
+ return ASQ(function $$asq(done){
+ args[act](done);
+ fn.apply(_this,args);
+ });
+ };
+ }
+};
+
+
+ // just return `ASQ` itself for convenience sake
+ return ASQ;
+});
diff --git a/async/exercises/ex5/ex5.html b/async/exercises/ex5/ex5.html
new file mode 100755
index 0000000..04171dd
--- /dev/null
+++ b/async/exercises/ex5/ex5.html
@@ -0,0 +1,14 @@
+
+
+
+
+Exercise 5
+
+
+Exercise 5
+
+
+
+
+
+
diff --git a/async/exercises/ex5/ex5.js b/async/exercises/ex5/ex5.js
new file mode 100755
index 0000000..361b423
--- /dev/null
+++ b/async/exercises/ex5/ex5.js
@@ -0,0 +1,39 @@
+function fakeAjax(url,cb) {
+ var fake_responses = {
+ "file1": "The first text",
+ "file2": "The middle text",
+ "file3": "The last text"
+ };
+ var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000;
+
+ console.log("Requesting: " + url);
+
+ setTimeout(function(){
+ cb(fake_responses[url]);
+ },randomDelay);
+}
+
+function output(text) {
+ console.log(text);
+}
+
+// **************************************
+//Using ASQ for this exercise
+var getFile = ASQ.wrap(fakeAjax, { simplecb: true });
+
+function getFile(file) {
+ return ASQ(function(done){
+ fakeAjax(file,done);
+ });
+}
+
+
+getFile("file1")
+.val(output)
+.seq(getFile("file2"))
+.val(output)
+.seq(getFile("file3"))
+.val(output)
+.val(function functionName() {
+ output("complete")
+});
diff --git a/async/exercises/ex6/README.md b/async/exercises/ex6/README.md
new file mode 100755
index 0000000..476a277
--- /dev/null
+++ b/async/exercises/ex6/README.md
@@ -0,0 +1,9 @@
+# Instructions
+
+1. You'll do the same thing as the previous exercise(s), but now you should use map/reduce, asynquence, and an array of files.
+
+2. Expected behavior:
+ - Request all 3 files at the same time (in "parallel").
+ - Render them ASAP (don't just blindly wait for all to finish loading)
+ - BUT, render them in proper (obvious) order: "file1", "file2", "file3".
+ - After all 3 are done, output "Complete!".
diff --git a/async/exercises/ex6/asq.bundle.js b/async/exercises/ex6/asq.bundle.js
new file mode 100755
index 0000000..93c9ada
--- /dev/null
+++ b/async/exercises/ex6/asq.bundle.js
@@ -0,0 +1,2333 @@
+/*! asynquence
+ v0.8.2 (c) Kyle Simpson
+ MIT License: http://getify.mit-license.org
+*/
+!function UMD(e,n,t){"function"==typeof define&&define.amd?define(t):"undefined"!=typeof module&&module.exports?module.exports=t():n[e]=t(e,n)}("ASQ",this,function DEF(e,n){"use strict";function Queue(){function Item(e){this.fn=e,this.next=void 0}var e,n,r;return{add:function $$add(t){r=new Item(t),n?n.next=r:e=r,n=r,r=void 0},drain:function $$drain(){var r=e;for(e=n=t=null;r;)r.fn(),r=r.next}}}function schedule(e){r.add(e),t||(t=u(r.drain))}function tapSequence(e){function trigger(){e.seq=createSequence.apply(h,arguments).defer()}trigger.fail=function $$trigger$fail(){var n=f.call(arguments);e.seq=createSequence(function $$create$sequence(e){e.fail.apply(h,n)}).defer()},e.seq.val(function $$val(){return trigger.apply(h,arguments),c.apply(h,arguments)}).or(function $$or(){trigger.fail.apply(h,arguments)}),e.seq=createSequence(function $$create$sequence(e){trigger=e}).defer()}function createSequence(){function scheduleSequenceTick(){r?sequenceTick():e||(e=schedule(sequenceTick))}function throwSequenceErrors(){throw 1===$.length?$[0]:$}function sequenceTick(){var a,c;if(e=null,delete d.unpause,r)clearTimeout(e),e=null,s.length=p.length=g.length=$.length=0;else if(n)for(0!==p.length||t||(t=!0,throwSequenceErrors());p.length;){t=!0,a=p.shift();try{a.apply(h,$)}catch(i){l(i)?$=$.concat(i):($.push(i),i.stack&&$.push(i.stack)),0===p.length&&throwSequenceErrors()}}else if(u&&s.length>0){u=!1,a=s.shift(),c=g.slice(),g.length=0,c.unshift(createStepCompletion());try{a.apply(h,c)}catch(i){l(i)?$=$.concat(i):$.push(i),n=!0,scheduleSequenceTick()}}}function createStepCompletion(){function done(){n||r||u||(u=!0,g.push.apply(g,arguments),$.length=0,scheduleSequenceTick())}return done.fail=function $$step$fail(){n||r||u||(n=!0,g.length=0,$.push.apply($,arguments),scheduleSequenceTick())},done.abort=function $$step$abort(){n||r||(u=!1,r=!0,g.length=$.length=0,scheduleSequenceTick())},done.errfcb=function $$step$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},done}function createGate(e,t,u){function resetGate(){clearTimeout(s),s=d=m=o=null}function scheduleGateTick(){return g?gateTick():void(s||(s=schedule(gateTick)))}function gateTick(){if(!(n||r||$)){var t=[];s=null,p?(e.fail.apply(h,o),resetGate()):g?(e.abort(),resetGate()):checkGate()&&($=!0,d.forEach(function $$each(e,n){t.push(m["s"+n])}),e.apply(h,t),resetGate())}}function checkGate(){if(0!==d.length){var e=!0;return d.some(function $$some(n){return null===n?(e=!1,!0):void 0}),e}}function createSegmentCompletion(){function done(){if(!(n||r||p||g||$||d[e])){var t=c.apply(h,arguments);m["s"+e]=t.length>1?t:t[0],d[e]=!0,scheduleGateTick()}}var e=d.length;return done.fail=function $$segment$fail(){n||r||p||g||$||d[e]||(p=!0,o=f.call(arguments),scheduleGateTick())},done.abort=function $$segment$abort(){n||r||p||g||$||(g=!0,gateTick())},done.errfcb=function $$segment$errfcb(e){e?done.fail(e):done.apply(h,f.call(arguments,1))},d[e]=null,done}var a,i,o,s,p=!1,g=!1,$=!1,d=[],m={};t.some(function $$some(e){if(p||g)return!0;a=u.slice(),a.unshift(createSegmentCompletion());try{e.apply(h,a)}catch(n){return i=n,p=!0,!0}}),i&&(l(i)?e.fail.apply(h,i):e.fail(i))}function then(){return n||r||0===arguments.length?d:(wrapArgs(arguments,thenWrapper).forEach(function $$each(e){i(e)?seq(e):s.push(e)}),scheduleSequenceTick(),d)}function or(){return r||0===arguments.length?d:(p.push.apply(p,arguments),scheduleSequenceTick(),d)}function gate(){if(n||r||0===arguments.length)return d;var e=f.call(arguments).map(function $$map(e){var n;return i(e)?(n={seq:e},tapSequence(n),function $$segment(e){n.seq.pipe(e)}):e});return then(function $$then(n){var t=f.call(arguments,1);createGate(n,e,t)}),d}function pipe(){return r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){e.apply(h,f.call(arguments,1)),n()}).or(e.fail)}),d)}function seq(){return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){var n={seq:e};i(e)&&tapSequence(n),then(function $$then(e){var t=n.seq;i(t)||(t=n.seq.apply(h,f.call(arguments,1))),t.pipe(e)})}),d)}function val(){return n||r||0===arguments.length?d:(f.call(wrapArgs(arguments,valWrapper)).forEach(function $$each(e){then(function $$then(n){var t=e.apply(h,f.call(arguments,1));l(t)||(t=c(t)),n.apply(h,t)})}),d)}function promise(){function wrap(e){return function $$fn(){e.apply(h,l(arguments[0])?arguments[0]:arguments)}}return n||r||0===arguments.length?d:(f.call(arguments).forEach(function $$each(e){then(function $$then(n){var t=e;"function"==typeof e&&"function"!=typeof e.then&&(t=e.apply(h,f.call(arguments,1))),t.then(wrap(n),wrap(n.fail))})}),d)}function fork(){var e;return val(function $$val(){return e?e.apply(h,arguments):e=createSequence.apply(h,arguments).defer(),c.apply(h,arguments)}),or(function $$or(){if(e)e.fail.apply(h,arguments);else{var n=f.call(arguments);e=createSequence().then(function $$then(e){e.fail.apply(h,n)}).defer()}}),createSequence().then(function $$then(n){e?e.pipe(n):e=n}).defer()}function abort(){return n?d:(r=!0,sequenceTick(),d)}function duplicate(){var e;return a={then_queue:s.slice(),or_queue:p.slice()},e=createSequence(),a=null,e}function unpause(){g.push.apply(g,arguments),e===!0&&(e=null),scheduleSequenceTick()}function defer(){return p.push(function ignored(){}),d}function internals(e,t){var a=arguments.length>1;switch(e){case"seq_error":if(!a)return n;n=t;break;case"seq_aborted":if(!a)return r;r=t;break;case"then_ready":if(!a)return u;u=t;break;case"then_queue":return s;case"or_queue":return p;case"sequence_messages":return g;case"sequence_errors":return $}}function includeExtensions(){Object.keys(o).forEach(function $$each(e){d[e]=o[e](d,internals)})}var e,n=!1,t=!1,r=!1,u=!0,s=[],p=[],g=[],$=[],d=brandIt({then:then,or:or,onerror:or,gate:gate,all:gate,pipe:pipe,seq:seq,val:val,promise:promise,fork:fork,abort:abort,duplicate:duplicate,defer:defer});return includeExtensions(),a&&(s=a.then_queue.slice(),p=a.or_queue.slice(),d.unpause=unpause,e=!0),d.then.apply(h,arguments),d}function brandIt(e){return Object.defineProperty(e,p,{enumerable:!1,value:!0})}function checkBranding(e){return!(null==e||"object"!=typeof e||!e[p])}function valWrapper(e){return c.apply(h,f.call(arguments).slice(1,e+1))}function thenWrapper(e){arguments[e+1].apply(h,f.call(arguments).slice(1,e+1))}function wrapArgs(e,n){var t,r;for(e=f.call(e),t=0;t 1 ?
+ ARRAY_SLICE.call(arguments,1) :
+ void 0
+ ;
+ num = +num || 0;
+
+ api.then(function $$then(done){
+ var args = orig_args || ARRAY_SLICE.call(arguments,1);
+
+ setTimeout(function $$set$timeout(){
+ done.apply(ø,args);
+ },num);
+ });
+
+ return api;
+ };
+});
+
+ASQ.after = function $$after() {
+ return ASQ().after.apply(ø,arguments);
+};
+// "any"
+ASQ.extend("any",function $$extend(api,internals){
+ return function $$any() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ function reset() {
+ finished = true;
+ error_messages.length = 0;
+ success_messages.length = 0;
+ }
+
+ function complete(trigger) {
+ if (success_messages.length > 0) {
+ // any successful segment's message(s) sent
+ // to main sequence to proceed as success
+ success_messages.length = fns.length;
+ trigger.apply(ø,success_messages);
+ }
+ else {
+ // send errors into main sequence
+ error_messages.length = fns.length;
+ trigger.fail.apply(ø,error_messages);
+ }
+
+ reset();
+ }
+
+ function success(trigger,idx,args) {
+ if (!finished) {
+ completed++;
+ success_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+
+ // all segments complete?
+ if (completed === fns.length) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+ }
+
+ function failure(trigger,idx,args) {
+ if (!finished &&
+ !(idx in error_messages)
+ ) {
+ completed++;
+ error_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+ }
+
+ // all segments complete?
+ if (!finished &&
+ completed === fns.length
+ ) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+
+ var completed = 0, error_messages = [], finished = false,
+ success_messages = [],
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1))
+ ;
+
+ wrapGate(sq,fns,success,failure,reset);
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "errfcb"
+ASQ.extend("errfcb",function $$extend(api,internals){
+ return function $$errfcb() {
+ // create a fake sequence to extract the callbacks
+ var sq = {
+ val: function $$then(cb){ sq.val_cb = cb; return sq; },
+ or: function $$or(cb){ sq.or_cb = cb; return sq; }
+ };
+
+ // trick `seq(..)`s checks for a sequence
+ sq[brand] = true;
+
+ // immediately register our fake sequence on the
+ // main sequence
+ api.seq(sq);
+
+ // provide the "error-first" callback
+ return function $$errorfirst$callback(err) {
+ if (err) {
+ sq.or_cb(err);
+ }
+ else {
+ sq.val_cb.apply(ø,ARRAY_SLICE.call(arguments,1));
+ }
+ };
+ };
+});
+// "failAfter"
+ASQ.extend("failAfter",function $$extend(api,internals){
+ return function $$failAfter(num) {
+ var args = arguments.length > 1 ?
+ ARRAY_SLICE.call(arguments,1) :
+ void 0
+ ;
+ num = +num || 0;
+
+ api.then(function $$then(done){
+ setTimeout(function $$set$timeout(){
+ done.fail.apply(ø,args);
+ },num);
+ });
+
+ return api;
+ };
+});
+
+ASQ.failAfter = function $$fail$after() {
+ return ASQ().failAfter.apply(ø,arguments);
+};
+// "first"
+ASQ.extend("first",function $$extend(api,internals){
+ return function $$first() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ function reset() {
+ error_messages.length = 0;
+ }
+
+ function success(trigger,idx,args) {
+ if (!finished) {
+ finished = true;
+
+ // first successful segment triggers
+ // main sequence to proceed as success
+ trigger(
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ );
+
+ reset();
+ }
+ }
+
+ function failure(trigger,idx,args) {
+ if (!finished &&
+ !(idx in error_messages)
+ ) {
+ completed++;
+ error_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+
+ // all segments complete without success?
+ if (completed === fns.length) {
+ finished = true;
+
+ // send errors into main sequence
+ error_messages.length = fns.length;
+ trigger.fail.apply(ø,error_messages);
+
+ reset();
+ }
+ }
+ }
+
+ var completed = 0, error_messages = [], finished = false,
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1))
+ ;
+
+ wrapGate(sq,fns,success,failure,reset);
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "go-style CSP"
+(function IIFE(){
+
+ // filter out already-resolved queue entries
+ function filterResolved(queue) {
+ return queue.filter(function $$filter(entry){
+ return !entry.resolved;
+ });
+ }
+
+ function closeQueue(queue,finalValue) {
+ queue.forEach(function $$each(iter){
+ if (!iter.resolved) {
+ iter.next();
+ iter.next(finalValue);
+ }
+ });
+ queue.length = 0;
+ }
+
+ function channel(bufSize) {
+ var ch = {
+ close: function $$close(){
+ ch.closed = true;
+ closeQueue(ch.put_queue,false);
+ closeQueue(ch.take_queue,ASQ.csp.CLOSED);
+ },
+ closed: false,
+ messages: [],
+ put_queue: [],
+ take_queue: [],
+ buffer_size: +bufSize || 0
+ };
+ return ch;
+ }
+
+ function unblock(iter) {
+ if (iter && !iter.resolved) {
+ iter.next(iter.next().value);
+ }
+ }
+
+ function put(channel,value) {
+ var ret;
+
+ if (channel.closed) {
+ return false;
+ }
+
+ // remove already-resolved entries
+ channel.put_queue = filterResolved(channel.put_queue);
+ channel.take_queue = filterResolved(channel.take_queue);
+
+ // immediate put?
+ if (channel.messages.length < channel.buffer_size) {
+ channel.messages.push(value);
+ unblock(channel.take_queue.shift());
+ return true;
+ }
+ // queued put
+ else {
+ channel.put_queue.push(
+ // make a notifiable iterable for 'put' blocking
+ ASQ.iterable()
+ .then(function $$then(){
+ if (!channel.closed) {
+ channel.messages.push(value);
+ return true;
+ }
+ else {
+ return false;
+ }
+ })
+ );
+
+ // wrap a sequence/promise around the iterable
+ ret = ASQ(
+ channel.put_queue[channel.put_queue.length - 1]
+ );
+
+ // take waiting on this queued put?
+ if (channel.take_queue.length > 0) {
+ unblock(channel.put_queue.shift());
+ unblock(channel.take_queue.shift());
+ }
+
+ return ret;
+ }
+ }
+
+ function putAsync(channel,value,cb) {
+ var ret = ASQ(put(channel,value));
+
+ if (cb && typeof cb == "function") {
+ ret.val(cb);
+ }
+ else {
+ return ret;
+ }
+ }
+
+ function take(channel) {
+ var ret;
+
+ try {
+ ret = takem(channel);
+ }
+ catch (err) {
+ ret = err;
+ }
+
+ if (ASQ.isSequence(ret)) {
+ ret.pCatch(function $$pcatch(err){
+ return err;
+ });
+ }
+
+ return ret;
+ }
+
+ function takeAsync(channel,cb) {
+ var ret = ASQ(take(channel));
+
+ if (cb && typeof cb == "function") {
+ ret.val(cb);
+ }
+ else {
+ return ret;
+ }
+ }
+
+ function takem(channel) {
+ var msg;
+
+ if (channel.closed) {
+ return ASQ.csp.CLOSED;
+ }
+
+ // remove already-resolved entries
+ channel.put_queue = filterResolved(channel.put_queue);
+ channel.take_queue = filterResolved(channel.take_queue);
+
+ // immediate take?
+ if (channel.messages.length > 0) {
+ msg = channel.messages.shift();
+ unblock(channel.put_queue.shift());
+ if (msg instanceof Error) {
+ throw msg;
+ }
+ return msg;
+ }
+ // queued take
+ else {
+ channel.take_queue.push(
+ // make a notifiable iterable for 'take' blocking
+ ASQ.iterable()
+ .then(function $$then(){
+ if (!channel.closed) {
+ var v = channel.messages.shift();
+ if (v instanceof Error) {
+ throw v;
+ }
+ return v;
+ }
+ else {
+ return ASQ.csp.CLOSED;
+ }
+ })
+ );
+
+ // wrap a sequence/promise around the iterable
+ msg = ASQ(
+ channel.take_queue[channel.take_queue.length - 1]
+ );
+
+ // put waiting on this take?
+ if (channel.put_queue.length > 0) {
+ unblock(channel.put_queue.shift());
+ unblock(channel.take_queue.shift());
+ }
+
+ return msg;
+ }
+ }
+
+ function takemAsync(channel,cb) {
+ var ret = ASQ(takem(channel));
+
+ if (cb && typeof cb == "function") {
+ ret.pThen(cb,cb);
+ }
+ else {
+ return ret.val(function $$val(v){
+ if (v instanceof Error) {
+ throw v;
+ }
+ return v;
+ });
+ }
+ }
+
+ function alts(actions) {
+ var closed, open, handlers, i, isq, ret, resolved = false;
+
+ // used `alts(..)` incorrectly?
+ if (!Array.isArray(actions) || actions.length == 0) {
+ throw Error("Invalid usage");
+ }
+
+ closed = [];
+ open = [];
+ handlers = [];
+
+ // separate actions by open/closed channel status
+ actions.forEach(function $$each(action){
+ var channel = Array.isArray(action) ? action[0] : action;
+
+ // remove already-resolved entries
+ channel.put_queue = filterResolved(channel.put_queue);
+ channel.take_queue = filterResolved(channel.take_queue);
+
+ if (channel.closed) {
+ closed.push(channel);
+ }
+ else {
+ open.push(action);
+ }
+ });
+
+ // if no channels are still open, we're done
+ if (open.length == 0) {
+ return { value: ASQ.csp.CLOSED, channel: closed };
+ }
+
+ // can any channel action be executed immediately?
+ for (i=0; i 0) {
+ return { value: take(open[i]), channel: open[i] };
+ }
+ }
+
+ isq = ASQ.iterable();
+ var ret = ASQ(isq);
+
+ // setup channel action handlers
+ for (i=0; i 0) {
+ schedule(function handleUnblocking(){
+ if (!resolved) {
+ unblock(channel.put_queue.shift());
+ unblock(channel.take_queue.shift());
+ }
+ },0);
+ }
+ }
+ // take action?
+ else {
+ channel = action;
+
+ // define take handler
+ handlers.push(
+ ASQ.iterable()
+ .then(function $$then(){
+ resolved = true;
+
+ // mark all handlers across this `alts(..)` as resolved now
+ handlers = handlers.filter(function $$filter(handler){
+ return !(handler.resolved = true);
+ });
+
+ // channel still open?
+ if (!channel.closed) {
+ isq.next({ value: channel.messages.shift(), channel: channel });
+ }
+ // channel already closed?
+ else {
+ isq.next({ value: ASQ.csp.CLOSED, channel: channel });
+ }
+ })
+ );
+
+ // queue up take handler
+ channel.take_queue.push(handlers[handlers.length-1]);
+
+ // put waiting on this queued take?
+ if (channel.put_queue.length > 0) {
+ schedule(function handleUnblocking(){
+ if (!resolved) {
+ unblock(channel.put_queue.shift());
+ unblock(channel.take_queue.shift());
+ }
+ });
+ }
+ }
+ })(open[i]);
+ }
+
+ return ret;
+ }
+
+ function altsAsync(chans,cb) {
+ var ret = ASQ(alts(chans));
+
+ if (cb && typeof cb == "function") {
+ ret.pThen(cb,cb);
+ }
+ else {
+ return ret;
+ }
+ }
+
+ function timeout(delay) {
+ var ch = channel();
+ setTimeout(ch.close,delay);
+ return ch;
+ }
+
+ function go(gen,args) {
+ // goroutine arguments passed?
+ if (arguments.length > 1) {
+ if (!args || !Array.isArray(args)) {
+ args = [args];
+ }
+ }
+ else {
+ args = [];
+ }
+
+ return function *$$go(token) {
+
+ // unblock the overall goroutine handling
+ function unblock() {
+ token.unblock_count++;
+
+ if (token.block && !token.block.marked) {
+ token.block.marked = true;
+ token.block.next();
+ }
+ }
+
+ var ret, msg, err, type, done = false, it;
+
+ // keep track of how many requests for unblocking
+ // have occurred
+ token.unblock_count = (token.unblock_count || 0);
+
+ // keep track of how many goroutines are running
+ // so we can infer when we're done go'ing
+ token.go_count = (token.go_count || 0) + 1;
+
+ // need to initialize a set of goroutines?
+ if (token.go_count === 1) {
+ // create a default channel for these goroutines
+ token.channel = channel();
+ token.channel.messages = token.messages;
+ token.channel.go = function $$go(){
+ // unblock the goroutine handling for this
+ // new goroutine
+ unblock();
+ // add the goroutine (called with any args) to
+ // the handling queue
+ token.add( go.apply(ø,arguments) );
+ };
+ // starting out with initial channel messages?
+ if (token.channel.messages.length > 0) {
+ // fake back-pressure blocking for each
+ token.channel.put_queue = token.channel.messages.map(function $$map(){
+ // make a notifiable iterable for 'put' blocking
+ return ASQ.iterable()
+ .then(function $$then(){
+ unblock(token.channel.take_queue.shift());
+ return !token.channel.closed;
+ });
+ });
+ }
+ }
+
+ // initialize the generator
+ it = gen.apply(ø,[token.channel].concat(args));
+
+ (function iterate(){
+
+ function next() {
+ // keep going with next step in goroutine?
+ if (!done) {
+ iterate();
+ }
+ // unblock overall goroutine handling to
+ // continue with other goroutines
+ else {
+ unblock();
+ }
+ }
+
+ // has a resumption value been achieved yet?
+ if (!ret) {
+ // try to resume the goroutine
+ try {
+ // resume with injected exception?
+ if (err) {
+ ret = it.throw(err);
+ err = null;
+ }
+ // resume normally
+ else {
+ ret = it.next(msg);
+ }
+ }
+ // resumption failed, so bail
+ catch (e) {
+ done = true;
+ err = e;
+ msg = null;
+ unblock();
+ return;
+ }
+
+ // keep track of the result of the resumption
+ done = ret.done;
+ ret = ret.value;
+ type = typeof ret;
+
+ // if this goroutine is complete, unblock the
+ // overall goroutine handling
+ if (done) {
+ unblock();
+ }
+
+ // received a thenable/promise back?
+ if (isPromise(ret)) {
+ ret = ASQ().promise(ret);
+ }
+
+ // wait for the value?
+ if (ASQ.isSequence(ret)) {
+ ret.val(function $$val(){
+ ret = null;
+ msg = arguments.length > 1 ?
+ ASQ.messages.apply(ø,arguments) :
+ arguments[0]
+ ;
+ next();
+ })
+ .or(function $$or(){
+ ret = null;
+ msg = arguments.length > 1 ?
+ ASQ.messages.apply(ø,arguments) :
+ arguments[0]
+ ;
+ if (msg instanceof Error) {
+ err = msg;
+ msg = null;
+ }
+ next();
+ });
+ }
+ // immediate value, prepare it to go right back in
+ else {
+ msg = ret;
+ ret = null;
+ next();
+ }
+ }
+ })();
+
+ // keep this goroutine alive until completion
+ while (!done) {
+ // transfer control to another goroutine
+ yield token;
+
+ // need to block overall goroutine handling
+ // while idle?
+ if (!done && !token.block && token.unblock_count === 0) {
+ // wait here while idle
+ yield (token.block = ASQ.iterable());
+
+ token.block = false;
+ }
+
+ if (token.unblock_count > 0) token.unblock_count--;
+ }
+
+ // this goroutine is done now
+ token.go_count--;
+
+ // all goroutines done?
+ if (token.go_count === 0) {
+ // any lingering blocking need to be cleaned up?
+ unblock();
+
+ // capture any untaken messages
+ msg = ASQ.messages.apply(ø,token.messages);
+
+ // need to implicitly force-close channel?
+ if (token.channel && !token.channel.closed) {
+ token.channel.closed = true;
+ token.channel.put_queue.length = token.channel.take_queue.length = 0;
+ token.channel.close = token.channel.go = token.channel.messages = null;
+ }
+ token.channel = null;
+ }
+
+ // make sure leftover error or message are
+ // passed along
+ if (err) {
+ throw err;
+ }
+ else if (token.go_count === 0) {
+ return msg;
+ }
+ else {
+ return token;
+ }
+ };
+ }
+
+ ASQ.csp = {
+ chan: channel,
+ put: put,
+ putAsync: putAsync,
+ take: take,
+ takeAsync: takeAsync,
+ takem: takem,
+ takemAsync: takemAsync,
+ alts: alts,
+ altsAsync: altsAsync,
+ timeout: timeout,
+ go: go,
+ CLOSED: {}
+ };
+
+})();
+// "ASQ.iterable()"
+(function IIFE(){
+ var template;
+
+ ASQ.iterable = function $$iterable() {
+ function throwSequenceErrors() {
+ throw (sequence_errors.length === 1 ? sequence_errors[0] : sequence_errors);
+ }
+
+ function notifyErrors() {
+ var fn;
+
+ seq_tick = null;
+
+ if (seq_error) {
+ if (or_queue.length === 0 && !error_reported) {
+ error_reported = true;
+ throwSequenceErrors();
+ }
+
+ while (or_queue.length > 0) {
+ error_reported = true;
+ fn = or_queue.shift();
+ try {
+ fn.apply(ø,sequence_errors);
+ }
+ catch (err) {
+ if (checkBranding(err)) {
+ sequence_errors = sequence_errors.concat(err);
+ }
+ else {
+ sequence_errors.push(err);
+ }
+ if (or_queue.length === 0) {
+ throwSequenceErrors();
+ }
+ }
+ }
+ }
+ }
+
+ function val() {
+ if (seq_error || seq_aborted || arguments.length === 0) {
+ return sequence_api;
+ }
+
+ var args = ARRAY_SLICE.call(arguments).map(function mapper(arg){
+ if (typeof arg != "function") return function $$val() { return arg; };
+ else return arg;
+ });
+
+ val_queue.push.apply(val_queue,args);
+
+ return sequence_api;
+ }
+
+ function or() {
+ if (seq_aborted || arguments.length === 0) {
+ return sequence_api;
+ }
+
+ or_queue.push.apply(or_queue,arguments);
+
+ if (!seq_tick) {
+ seq_tick = schedule(notifyErrors);
+ }
+
+ return sequence_api;
+ }
+
+ function pipe() {
+ if (seq_aborted || arguments.length === 0) {
+ return sequence_api;
+ }
+
+ ARRAY_SLICE.call(arguments)
+ .forEach(function $$each(fn){
+ val(fn).or(fn.fail);
+ });
+
+ return sequence_api;
+ }
+
+ function next() {
+ if (seq_error || seq_aborted || val_queue.length === 0) {
+ if (val_queue.length > 0) {
+ $throw$("Sequence cannot be iterated");
+ }
+ return { done: true };
+ }
+
+ try {
+ return { value: val_queue.shift().apply(ø,arguments) };
+ }
+ catch (err) {
+ if (ASQ.isMessageWrapper(err)) {
+ $throw$.apply(ø,err);
+ }
+ else {
+ $throw$(err);
+ }
+
+ return {};
+ }
+ }
+
+ function $throw$() {
+ if (seq_error || seq_aborted) {
+ return sequence_api;
+ }
+
+ sequence_errors.push.apply(sequence_errors,arguments);
+ seq_error = true;
+ if (!seq_tick) {
+ seq_tick = schedule(notifyErrors);
+ }
+
+ return sequence_api;
+ }
+
+ function $return$(val) {
+ if (seq_error || seq_aborted) {
+ val = void 0;
+ }
+
+ abort();
+
+ return { done: true, value: val };
+ }
+
+ function abort() {
+ if (seq_error || seq_aborted) {
+ return;
+ }
+
+ seq_aborted = true;
+
+ clearTimeout(seq_tick);
+ seq_tick = null;
+ val_queue.length = or_queue.length = sequence_errors.length = 0;
+ }
+
+ function duplicate() {
+ var isq;
+
+ template = {
+ val_queue: val_queue.slice(),
+ or_queue: or_queue.slice()
+ };
+ isq = ASQ.iterable();
+ template = null;
+
+ return isq;
+ }
+
+ // opt-out of global error reporting for this sequence
+ function defer() {
+ or_queue.push(function $$ignored(){});
+ return sequence_api;
+ }
+
+ // ***********************************************
+ // Object branding utilities
+ // ***********************************************
+ function brandIt(obj) {
+ Object.defineProperty(obj,brand,{
+ enumerable: false,
+ value: true
+ });
+
+ return obj;
+ }
+
+ var sequence_api,
+
+ seq_error = false,
+ error_reported = false,
+ seq_aborted = false,
+
+ seq_tick,
+
+ val_queue = [],
+ or_queue = [],
+
+ sequence_errors = []
+ ;
+
+ // ***********************************************
+ // Setup the ASQ.iterable() public API
+ // ***********************************************
+ sequence_api = brandIt({
+ val: val,
+ then: val,
+ or: or,
+ pipe: pipe,
+ next: next,
+ "throw": $throw$,
+ "return": $return$,
+ abort: abort,
+ duplicate: duplicate,
+ defer: defer
+ });
+
+ // useful for ES6 `for..of` loops,
+ // add `@@iterator` to simply hand back
+ // our iterable sequence itself!
+ sequence_api[(typeof Symbol == "function" && Symbol.iterator) || "@@iterator"] = function $$iter() {
+ return sequence_api;
+ };
+
+ // templating the iterable-sequence setup?
+ if (template) {
+ val_queue = template.val_queue.slice(0);
+ or_queue = template.or_queue.slice(0);
+ }
+
+ // treat ASQ.iterable() constructor parameters as having been
+ // passed to `val()`
+ sequence_api.val.apply(ø,arguments);
+
+ return sequence_api;
+ };
+
+})();
+// "last"
+ASQ.extend("last",function $$extend(api,internals){
+ return function $$last() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ function reset() {
+ finished = true;
+ error_messages.length = 0;
+ success_messages = null;
+ }
+
+ function complete(trigger) {
+ if (success_messages != null) {
+ // last successful segment's message(s) sent
+ // to main sequence to proceed as success
+ trigger(
+ success_messages.length > 1 ?
+ ASQ.messages.apply(ø,success_messages) :
+ success_messages[0]
+ );
+ }
+ else {
+ // send errors into main sequence
+ error_messages.length = fns.length;
+ trigger.fail.apply(ø,error_messages);
+ }
+
+ reset();
+ }
+
+ function success(trigger,idx,args) {
+ if (!finished) {
+ completed++;
+ success_messages = args;
+
+ // all segments complete?
+ if (completed === fns.length) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+ }
+
+ function failure(trigger,idx,args) {
+ if (!finished &&
+ !(idx in error_messages)
+ ) {
+ completed++;
+ error_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+ }
+
+ // all segments complete?
+ if (!finished &&
+ completed === fns.length
+ ) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+
+ var completed = 0, error_messages = [], finished = false,
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)),
+ success_messages
+ ;
+
+ wrapGate(sq,fns,success,failure,reset);
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "map"
+ASQ.extend("map",function $$extend(api,internals){
+ return function $$map(pArr,pEach) {
+ if (internals("seq_error") || internals("seq_aborted")) {
+ return api;
+ }
+
+ api.seq(function $$seq(){
+ var tmp, args = ARRAY_SLICE.call(arguments),
+ arr = pArr, each = pEach;
+
+ // if missing `map(..)` args, use value-messages (if any)
+ if (!each) each = args.shift();
+ if (!arr) arr = args.shift();
+
+ // if arg types in reverse order (each,arr), swap
+ if (typeof arr === "function" && Array.isArray(each)) {
+ tmp = arr;
+ arr = each;
+ each = tmp;
+ }
+
+ return ASQ.apply(ø,args)
+ .gate.apply(ø,arr.map(function $$map(item){
+ return function $$segment(){
+ each.apply(ø,[item].concat(ARRAY_SLICE.call(arguments)));
+ };
+ }));
+ })
+ .val(function $$val(){
+ // collect all gate segment output into one value-message
+ // Note: return a normal array here, not a message wrapper!
+ return ARRAY_SLICE.call(arguments);
+ });
+
+ return api;
+ };
+});
+// "none"
+ASQ.extend("none",function $$extend(api,internals){
+ return function $$none() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ function reset() {
+ finished = true;
+ error_messages.length = 0;
+ success_messages.length = 0;
+ }
+
+ function complete(trigger) {
+ if (success_messages.length > 0) {
+ // any successful segment's message(s) sent
+ // to main sequence to proceed as **error**
+ success_messages.length = fns.length;
+ trigger.fail.apply(ø,success_messages);
+ }
+ else {
+ // send errors as **success** to main sequence
+ error_messages.length = fns.length;
+ trigger.apply(ø,error_messages);
+ }
+
+ reset();
+ }
+
+ function success(trigger,idx,args) {
+ if (!finished) {
+ completed++;
+ success_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+
+ // all segments complete?
+ if (completed === fns.length) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+ }
+
+ function failure(trigger,idx,args) {
+ if (!finished &&
+ !(idx in error_messages)
+ ) {
+ completed++;
+ error_messages[idx] =
+ args.length > 1 ?
+ ASQ.messages.apply(ø,args) :
+ args[0]
+ ;
+ }
+
+ // all segments complete?
+ if (!finished &&
+ completed === fns.length
+ ) {
+ finished = true;
+
+ complete(trigger);
+ }
+ }
+
+ var completed = 0, error_messages = [], finished = false,
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1)),
+ success_messages = []
+ ;
+
+ wrapGate(sq,fns,success,failure,reset);
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "pThen"
+ASQ.extend("pThen",function $$extend(api,internals){
+ return function $$pthen(success,failure) {
+ if (internals("seq_aborted")) {
+ return api;
+ }
+
+ var ignore_success_handler = false, ignore_failure_handler = false;
+
+ if (typeof success === "function") {
+ api.then(function $$then(done){
+ if (!ignore_success_handler) {
+ var ret, msgs = ASQ.messages.apply(ø,arguments);
+ msgs.shift();
+
+ if (msgs.length === 1) {
+ msgs = msgs[0];
+ }
+
+ ignore_failure_handler = true;
+
+ try {
+ ret = success(msgs);
+ }
+ catch (err) {
+ if (!ASQ.isMessageWrapper(err)) {
+ err = [err];
+ }
+ done.fail.apply(ø,err);
+ return;
+ }
+
+ // returned a sequence?
+ if (ASQ.isSequence(ret)) {
+ ret.pipe(done);
+ }
+ // returned a message wrapper?
+ else if (ASQ.isMessageWrapper(ret)) {
+ done.apply(ø,ret);
+ }
+ // returned a promise/thenable?
+ else if (isPromise(ret)) {
+ ret.then(done,done.fail);
+ }
+ // just a normal value to pass along
+ else {
+ done(ret);
+ }
+ }
+ else {
+ done.apply(ø,ARRAY_SLICE.call(arguments,1));
+ }
+ });
+ }
+ if (typeof failure === "function") {
+ api.or(function $$or(){
+ if (!ignore_failure_handler) {
+ var ret, msgs = ASQ.messages.apply(ø,arguments), smgs,
+ or_queue = ARRAY_SLICE.call(internals("or_queue"))
+ ;
+
+ if (msgs.length === 1) {
+ msgs = msgs[0];
+ }
+
+ ignore_success_handler = true;
+
+ // NOTE: if this call throws, that'll automatically
+ // be handled by core as we'd want it to be
+ ret = failure(msgs);
+
+ // if we get this far:
+ // first, inject return value (if any) as
+ // next step's sequence messages
+ smgs = internals("sequence_messages");
+ smgs.length = 0;
+ if (typeof ret !== "undefined") {
+ if (!ASQ.isMessageWrapper(ret)) {
+ ret = [ret];
+ }
+ smgs.push.apply(smgs,ret);
+ }
+
+ // reset internal error state, because we've exclusively
+ // handled any errors up to this point of the sequence
+ internals("sequence_errors").length = 0;
+ internals("seq_error",false);
+ internals("then_ready",true);
+
+ // temporarily empty the or-queue
+ internals("or_queue").length = 0;
+
+ // make sure to schedule success-procession on the chain
+ api.val(function $$val(){
+ // pass thru messages
+ return ASQ.messages.apply(ø,arguments);
+ });
+
+ // at next cycle, reinstate the or-queue (if any)
+ if (or_queue.length > 0) {
+ schedule(function $$schedule(){
+ api.or.apply(ø,or_queue);
+ });
+ }
+ }
+ });
+ }
+ return api;
+ };
+});
+
+// "pCatch"
+ASQ.extend("pCatch",function $$extend(api,internals){
+ return function $$pcatch(failure) {
+ if (internals("seq_aborted")) {
+ return api;
+ }
+
+ api.pThen(void 0,failure);
+
+ return api;
+ };
+});
+// "race"
+ASQ.extend("race",function $$extend(api,internals){
+ return function $$race() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments)
+ .map(function $$map(v){
+ var def;
+ // tap any directly-provided sequences immediately
+ if (ASQ.isSequence(v)) {
+ def = { seq: v };
+ tapSequence(def);
+ return function $$fn(done) {
+ def.seq.pipe(done);
+ };
+ }
+ else return v;
+ });
+
+ api.then(function $$then(done){
+ var args = ARRAY_SLICE.call(arguments);
+
+ fns.forEach(function $$each(fn){
+ fn.apply(ø,args);
+ });
+ });
+
+ return api;
+ };
+});
+// "react" (reactive sequences)
+ASQ.react = function $$react(reactor) {
+ function next() {
+ if (!paused) {
+ if (template) {
+ var sq = template.duplicate();
+ sq.unpause.apply(ø,arguments);
+ return sq;
+ }
+ return ASQ(function $$asq(){ throw "Disabled Sequence"; });
+ }
+ }
+
+ function registerTeardown(fn) {
+ if (template && typeof fn === "function") {
+ teardowns.push(fn);
+ }
+ }
+
+ var template = ASQ().duplicate(),
+ teardowns = [], paused = false
+ ;
+
+ // add reactive sequence kill switch
+ template.stop = function $$stop() {
+ if (template) {
+ template = null;
+ teardowns.forEach(Function.call,Function.call);
+ teardowns.length = 0;
+ }
+ };
+
+ template.pause = function $$pause() {
+ if (!paused && template) {
+ paused = true;
+ teardowns.forEach(Function.call,Function.call);
+ teardowns.length = 0;
+ }
+ };
+
+ template.resume = function $$resume() {
+ if (paused && template) {
+ paused = false;
+ reactor.call(template,next,registerTeardown);
+ }
+ };
+
+ template.push = next;
+
+ next.onStream = function $$onStream() {
+ ARRAY_SLICE.call(arguments)
+ .forEach(function $$each(stream){
+ stream.on("data",next);
+ stream.on("error",next);
+ });
+ };
+
+ next.unStream = function $$unStream() {
+ ARRAY_SLICE.call(arguments)
+ .forEach(function $$each(stream){
+ stream.removeListener("data",next);
+ stream.removeListener("error",next);
+ });
+ };
+
+ // make sure `reactor(..)` is called async
+ ASQ.__schedule(function $$schedule(){
+ reactor.call(template,next,registerTeardown);
+ });
+
+ return template;
+};
+// "react" helpers
+(function IIFE(){
+
+ var Ar = ASQ.react;
+
+ Ar.of = function $$react$of() {
+ function reactor(next) {
+ if (!started) {
+ started = true;
+ if (args.length > 0) {
+ args.shift().val(function val(){
+ next.apply(ø,arguments);
+ if (args.length > 0) {
+ args.shift().val(val);
+ }
+ });
+ }
+ }
+ }
+
+ var started, args = ARRAY_SLICE.call(arguments)
+ .map(function wrapper(arg){
+ if (!ASQ.isSequence(arg)) arg = ASQ(arg);
+ return arg;
+ });
+
+ return Ar(reactor);
+ };
+
+ Ar.all = Ar.zip = makeReactOperator(/*buffer=*/true);
+ Ar.allLatest = makeReactOperator(/*buffer=false*/);
+ Ar.latest = Ar.combineLatest = makeReactOperator(/*buffer=*/false,/*keep=*/true);
+
+ Ar.any = Ar.merge = function $$react$any(){
+ function reactor(next,registerTeardown){
+ function processSequence(def){
+ function trigger(){
+ var args = ASQ.messages.apply(ø,arguments);
+ // still observing sequence-streams?
+ if (seqs && seqs.length > 0) {
+ // fire off reactive sequence instance
+ next.apply(ø,args);
+ }
+ // keep sequence going
+ return args;
+ }
+
+ // sequence-stream event listener
+ def.seq.val(trigger);
+ }
+
+ // observe all sequence-streams
+ seqs.forEach(processSequence);
+
+ // listen for stop() of reactive sequence
+ registerTeardown(function $$teardown(){
+ seqs = null;
+ });
+ }
+
+ // observe all sequence-streams
+ var seqs = tapSequences.apply(null,arguments);
+
+ if (seqs.length == 0) return;
+
+ return Ar(reactor);
+ };
+
+ Ar.distinct = function $$react$distinct(seq){
+ return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/true));
+ };
+
+ Ar.distinctConsecutive = Ar.distinctUntilChanged = function $$react$distinct$consecutive(seq) {
+ return Ar.filter(seq,makeDistinctFilterer(/*keepAll=*/false));
+ };
+
+ Ar.filter = function $$react$filter(seq,filterer){
+ function reactor(next,registerTeardown) {
+ function trigger(){
+ var messages = ASQ.messages.apply(ø,arguments);
+
+ if (filterer && filterer.apply(ø,messages)) {
+ // fire off reactive sequence instance
+ next.apply(ø,messages);
+ }
+
+ // keep sequence going
+ return messages;
+ }
+
+ // sequence-stream event listener
+ def.seq.val(trigger);
+
+ // listen for stop() of reactive sequence
+ registerTeardown(function $$teardown(){
+ def = filterer = null;
+ });
+ }
+
+ // observe sequence-stream
+ var def = tapSequences(seq)[0];
+
+ if (!def) return;
+
+ return Ar(reactor);
+ };
+
+ Ar.fromObservable = function $$react$from$observable(obsv){
+ function reactor(next,registerTeardown){
+ // process buffer (if any)
+ buffer.forEach(next);
+ buffer.length = 0;
+
+ // start non-buffered notifications?
+ if (!buffer.complete) {
+ notify = next;
+ }
+
+ registerTeardown(function $$teardown(){
+ obsv.dispose();
+ });
+ }
+
+ function notify(v) {
+ buffer.push(v);
+ }
+
+ var buffer = [];
+
+ obsv.subscribe(
+ function $$on$next(v){
+ notify(v);
+ },
+ function $$on$error(){},
+ function $$on$complete(){
+ buffer.complete = true;
+ obsv.dispose();
+ }
+ );
+
+ return Ar(reactor);
+ };
+
+ ASQ.extend("toObservable",function $$extend(api,internals){
+ return function $$to$observable(){
+ function init(observer) {
+ function define(pair){
+ function listen(){
+ var args = ASQ.messages.apply(ø,arguments);
+ observer[pair[1]].apply(observer,
+ args.length == 1 ? [args[0]] : args
+ );
+ return args;
+ }
+
+ api[pair[0]](listen);
+ }
+
+ [["val","onNext"],["or","onError"]]
+ .forEach(define);
+ }
+
+ return Rx.Observable.create(init);
+ };
+ });
+
+ function tapSequences() {
+ function tapSequence(seq) {
+ // temporary `trigger` which, if called before being replaced
+ // below, creates replacement proxy sequence with the
+ // event message(s) re-fired
+ function trigger() {
+ var args = ARRAY_SLICE.call(arguments);
+ def.seq = Ar(function $$react(next){
+ next.apply(ø,args);
+ });
+ }
+
+ if (ASQ.isSequence(seq)) {
+ var def = { seq: seq };
+
+ // listen for events from the sequence-stream
+ seq.val(function $$val(){
+ trigger.apply(ø,arguments);
+ return ASQ.messages.apply(ø,arguments);
+ });
+
+ // make a reactive sequence to act as a proxy to the original
+ // sequence
+ def.seq = Ar(function $$react(next){
+ // replace the temporary trigger (created above)
+ // with this proxy's trigger
+ trigger = next;
+ });
+
+ return def;
+ }
+ }
+
+ return ARRAY_SLICE.call(arguments)
+ .map(tapSequence)
+ .filter(Boolean);
+ }
+
+ function makeReactOperator(buffer,keep) {
+ return function $$react$operator(){
+ function reactor(next,registerTeardown){
+ function processSequence(def) {
+ // sequence-stream event listener
+ function trigger() {
+ var args = ASQ.messages.apply(ø,arguments);
+ // still observing sequence-streams?
+ if (seqs && seqs.length > 0) {
+ // store event message(s), if any
+ seq_events[seq_id] =
+ (buffer ? seq_events[seq_id] : []).concat(
+ args.length > 0 ? (args.length > 1 ? [args] : args[0]) : undefined
+ );
+
+ // collect event message(s) across the
+ // sequence-stream sources
+ var messages = seq_events.reduce(function reducer(msgs,eventList,idx){
+ if (eventList.length > 0) msgs.push(eventList[0]);
+ return msgs;
+ },[]);
+
+ // did all sequence-streams get an event?
+ if (messages.length == seq_events.length) {
+ if (messages.length == 1) messages = messages[0];
+
+ // fire off reactive sequence instance
+ next.apply(ø,messages);
+
+ // discard stored event message(s)?
+ if (!keep) {
+ seq_events.forEach(function $$each(eventList){
+ eventList.shift();
+ });
+ }
+ }
+ }
+ // keep sequence going
+ return args;
+ }
+
+ var seq_id = seq_events.length;
+ seq_events.push([]);
+ def.seq.val(trigger);
+ }
+
+ // process all sequence-streams
+ seqs.forEach(processSequence);
+
+ // listen for stop() of reactive sequence
+ registerTeardown(function $$teardown(){
+ seqs = seq_events = null;
+ });
+ }
+
+ var seq_events = [],
+ // observe all sequence-streams
+ seqs = tapSequences.apply(null,arguments)
+ ;
+
+ if (seqs.length == 0) return;
+
+ return Ar(reactor);
+ };
+ }
+
+ function makeDistinctFilterer(keepAll) {
+ function filterer() {
+ function isDuplicate(msgSet) {
+ return (
+ msgSet.length == message_set.length &&
+ msgSet.every(function $$every(val,idx){
+ return val === message_set[idx];
+ })
+ );
+ }
+
+ var message_set = ASQ.messages.apply(ø,arguments);
+
+ // any messages in message-set to check against?
+ if (message_set.length > 0) {
+ // duplicate message-set?
+ if (msg_sets.some(isDuplicate)) {
+ return false;
+ }
+
+ // remember all message-sets for future distinct checking?
+ if (keepAll) {
+ msg_sets.push(message_set);
+ }
+ // only keep the last message-set for distinct-consecutive
+ // checking
+ else {
+ msg_sets[0] = message_set;
+ }
+ }
+
+ // allow distinct non-duplicate value through
+ return true;
+ }
+
+ var msg_sets = [];
+
+ return filterer;
+ }
+
+})();
+// "runner"
+ASQ.extend("runner",function $$extend(api,internals){
+
+ return function $$runner() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var args = ARRAY_SLICE.call(arguments);
+
+ api
+ .then(function $$then(mainDone){
+
+ function wrap(v) {
+ // function? expected to produce an iterator
+ // (like a generator) or a promise
+ if (typeof v === "function") {
+ // call function passing in the control token
+ // note: neutralize `this` in call to prevent
+ // unexpected behavior
+ v = v.call(ø,token);
+
+ // promise returned (ie, from async function)?
+ if (isPromise(v)) {
+ // wrap it in iterable sequence
+ v = ASQ.iterable(v);
+ }
+ }
+ // an iterable sequence? duplicate it (in case of multiple runs)
+ else if (ASQ.isSequence(v) && "next" in v) {
+ v = v.duplicate();
+ }
+ // wrap anything else in iterable sequence
+ else {
+ v = ASQ.iterable(v);
+ }
+
+ // a sequence to tap for errors?
+ if (ASQ.isSequence(v)) {
+ // listen for any sequence failures
+ v.or(function $$or(){
+ // signal iteration-error
+ mainDone.fail.apply(ø,arguments);
+ });
+ }
+
+ return v;
+ }
+
+ function addWrapped() {
+ iterators.push.apply(
+ iterators,
+ ARRAY_SLICE.call(arguments).map(wrap)
+ );
+ }
+
+ function iterateOrQuit(iterFn,now) {
+ // still have some co-routine runs to process?
+ if (iterators.length > 0) {
+ if (now) iterFn();
+ else schedule(iterFn);
+ }
+ // all done!
+ else {
+ // previous value message?
+ if (typeof next_val !== "undefined") {
+ // not a message wrapper array?
+ if (!ASQ.isMessageWrapper(next_val)) {
+ // wrap value for the subsequent `apply(..)`
+ next_val = [next_val];
+ }
+ }
+ else {
+ // nothing to affirmatively pass along
+ next_val = [];
+ }
+
+ // signal done with all co-routine runs
+ mainDone.apply(ø,next_val);
+ }
+ }
+
+ var iterators = args,
+ token = {
+ messages: ARRAY_SLICE.call(arguments,1),
+ add: addWrapped
+ },
+ iter, ret, next_val = token
+ ;
+
+ // map co-routines to round-robin list of iterators
+ iterators = iterators.map(wrap);
+
+ // async iteration of round-robin list
+ (function iterate(){
+ // get next co-routine in list
+ iter = iterators.shift();
+
+ // process the iteration
+ try {
+ // multiple messages to send to an iterable
+ // sequence?
+ if (ASQ.isMessageWrapper(next_val) &&
+ ASQ.isSequence(iter)
+ ) {
+ ret = iter.next.apply(iter,next_val);
+ }
+ else {
+ ret = iter.next(next_val);
+ }
+ }
+ catch (err) {
+ return mainDone.fail(err);
+ }
+
+ // bail on run in aborted sequence
+ if (internals("seq_aborted")) return;
+
+ // was the control token yielded?
+ if (ret.value === token) {
+ // round-robin: put co-routine back into the list
+ // at the end where it was so it can be processed
+ // again on next loop-iteration
+ if (!ret.done) {
+ iterators.push(iter);
+ }
+ next_val = token;
+ iterateOrQuit(iterate,/*now=*/false);
+ }
+ else {
+ // not a recognized ASQ instance returned?
+ if (!ASQ.isSequence(ret.value)) {
+ // received a thenable/promise back?
+ if (isPromise(ret.value)) {
+ // wrap in a sequence
+ ret.value = ASQ().promise(ret.value);
+ }
+ // thunk yielded?
+ else if (typeof ret.value === "function") {
+ // wrap thunk call in a sequence
+ var fn = ret.value;
+ ret.value = ASQ(function $$ASQ(done){
+ fn(done.errfcb);
+ });
+ }
+ // message wrapper returned?
+ else if (ASQ.isMessageWrapper(ret.value)) {
+ // wrap message(s) in a sequence
+ ret.value = ASQ.apply(ø,
+ // don't let `apply(..)` discard an empty message
+ // wrapper! instead, pass it along as its own value
+ // itself.
+ ret.value.length > 0 ? ret.value : ASQ.messages(undefined)
+ );
+ }
+ // non-undefined value returned?
+ else if (typeof ret.value !== "undefined") {
+ // wrap the value in a sequence
+ ret.value = ASQ(ret.value);
+ }
+ else {
+ // make an empty sequence
+ ret.value = ASQ();
+ }
+ }
+
+ ret.value
+ .val(function $$val(){
+ // bail on run in aborted sequence
+ if (internals("seq_aborted")) return;
+
+ if (arguments.length > 0) {
+ // save any return messages for input
+ // to next iteration
+ next_val = arguments.length > 1 ?
+ ASQ.messages.apply(ø,arguments) :
+ arguments[0]
+ ;
+ }
+
+ // still more to iterate?
+ if (!ret.done) {
+ // was the control token passed along?
+ if (next_val === token) {
+ // round-robin: put co-routine back into the list
+ // at the end, so that the the next iterator can be
+ // processed on next loop-iteration
+ iterators.push(iter);
+ }
+ else {
+ // put co-routine back in where it just
+ // was so it can be processed again on
+ // next loop-iteration
+ iterators.unshift(iter);
+ }
+ }
+
+ iterateOrQuit(iterate,/*now=*/true);
+ })
+ .or(function $$or(){
+ // bail on run in aborted sequence
+ if (internals("seq_aborted")) return;
+
+ try {
+ // if an error occurs in the step-continuation
+ // promise or sequence, throw it back into the
+ // generator or iterable-sequence
+ iter["throw"].apply(iter,arguments);
+ }
+ catch (err) {
+ // if an error comes back out of after the throw,
+ // pass it out to the main sequence, as iteration
+ // must now be complete
+ mainDone.fail(err);
+ }
+ });
+ }
+ })();
+ });
+
+ return api;
+ };
+});
+// "toPromise"
+ASQ.extend("toPromise",function $$extend(api,internals){
+ return function $$to$promise() {
+ return new Promise(function $$executor(resolve,reject){
+ api
+ .val(function $$val(){
+ var args = ARRAY_SLICE.call(arguments);
+ resolve.call(ø,args.length > 1 ? args : args[0]);
+ return ASQ.messages.apply(ø,args);
+ })
+ .or(function $$or(){
+ var args = ARRAY_SLICE.call(arguments);
+ reject.call(ø,args.length > 1 ? args : args[0]);
+ });
+ });
+ };
+});
+// "try"
+ASQ.extend("try",function $$extend(api,internals){
+ return function $$try() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments)
+ .map(function $$map(fn){
+ return function $$then(mainDone) {
+ var main_args = ARRAY_SLICE.call(arguments),
+ sq = ASQ.apply(ø,main_args.slice(1))
+ ;
+
+ sq
+ .then(function $$inner$then(){
+ fn.apply(ø,arguments);
+ })
+ .val(function $$val(){
+ mainDone.apply(ø,arguments);
+ })
+ .or(function $$inner$or(){
+ var msgs = ASQ.messages.apply(ø,arguments);
+ // failed, so map error(s) as `catch`
+ mainDone({
+ "catch": msgs.length > 1 ? msgs : msgs[0]
+ });
+ });
+ };
+ });
+
+ api.then.apply(ø,fns);
+
+ return api;
+ };
+});
+// "until"
+ASQ.extend("until",function $$extend(api,internals){
+ return function $$until() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments)
+ .map(function $$map(fn){
+ return function $$then(mainDone) {
+ var main_args = ARRAY_SLICE.call(arguments),
+ sq = ASQ.apply(ø,main_args.slice(1))
+ ;
+
+ sq
+ .then(function $$inner$then(){
+ var args = ARRAY_SLICE.call(arguments);
+ args[0]["break"] = function $$break(){
+ mainDone.fail.apply(ø,arguments);
+ sq.abort();
+ };
+
+ fn.apply(ø,args);
+ })
+ .val(function $$val(){
+ mainDone.apply(ø,arguments);
+ })
+ .or(function $$inner$or(){
+ // failed, retry
+ $$then.apply(ø,main_args);
+ });
+ };
+ });
+
+ api.then.apply(ø,fns);
+
+ return api;
+ };
+});
+// "waterfall"
+ASQ.extend("waterfall",function $$extend(api,internals){
+ return function $$waterfall() {
+ if (internals("seq_error") || internals("seq_aborted") ||
+ arguments.length === 0
+ ) {
+ return api;
+ }
+
+ var fns = ARRAY_SLICE.call(arguments);
+
+ api.then(function $$then(done){
+ var msgs = ASQ.messages(),
+ sq = ASQ.apply(ø,ARRAY_SLICE.call(arguments,1))
+ ;
+
+ fns.forEach(function $$each(fn){
+ sq.then(fn)
+ .val(function $$val(){
+ var args = ASQ.messages.apply(ø,arguments);
+ msgs.push(args.length > 1 ? args : args[0]);
+ return msgs;
+ });
+ });
+
+ sq.pipe(done);
+ });
+
+ return api;
+ };
+});
+// "wrap"
+ASQ.wrap = function $$wrap(fn,opts) {
+ function checkThis(t,o) {
+ return (!t ||
+ (typeof window != "undefined" && t === window) ||
+ (typeof global != "undefined" && t === global)
+ ) ? o : t;
+ }
+
+ function paramSpread(gen) {
+ return function *paramSpread(token) {
+ yield *gen.apply(this,token.messages);
+ };
+ }
+
+ var errfcb, params_first, act, this_obj;
+
+ opts = (opts && typeof opts == "object") ? opts : {};
+
+ if (
+ (opts.errfcb && opts.splitcb) ||
+ (opts.errfcb && opts.simplecb) ||
+ (opts.splitcb && opts.simplecb) ||
+ ("errfcb" in opts && !opts.errfcb && !opts.splitcb && !opts.simplecb) ||
+ (opts.params_first && opts.params_last) ||
+ (opts.spread && !opts.gen)
+ ) {
+ throw Error("Invalid options");
+ }
+
+ // initialize default flags
+ this_obj = (opts["this"] && typeof opts["this"] == "object") ? opts["this"] : ø;
+ errfcb = opts.errfcb || !(opts.splitcb || opts.simplecb);
+ params_first = !!opts.params_first ||
+ (!opts.params_last && !("params_first" in opts || opts.params_first)) ||
+ ("params_last" in opts && !opts.params_first && !opts.params_last)
+ ;
+
+ if (params_first) {
+ act = "push";
+ }
+ else {
+ act = "unshift";
+ }
+
+ if (opts.gen) {
+ if (opts.spread) {
+ fn = paramSpread(fn);
+ }
+ return function $$wrapped$gen() {
+ return ASQ.apply(ø,arguments).runner(fn);
+ };
+ }
+ if (errfcb) {
+ return function $$wrapped$errfcb() {
+ var args = ARRAY_SLICE.call(arguments),
+ _this = checkThis(this,this_obj)
+ ;
+
+ return ASQ(function $$asq(done){
+ args[act](done.errfcb);
+ fn.apply(_this,args);
+ });
+ };
+ }
+ if (opts.splitcb) {
+ return function $$wrapped$splitcb() {
+ var args = ARRAY_SLICE.call(arguments),
+ _this = checkThis(this,this_obj)
+ ;
+
+ return ASQ(function $$asq(done){
+ args[act](done,done.fail);
+ fn.apply(_this,args);
+ });
+ };
+ }
+ if (opts.simplecb) {
+ return function $$wrapped$simplecb() {
+ var args = ARRAY_SLICE.call(arguments),
+ _this = checkThis(this,this_obj)
+ ;
+
+ return ASQ(function $$asq(done){
+ args[act](done);
+ fn.apply(_this,args);
+ });
+ };
+ }
+};
+
+
+ // just return `ASQ` itself for convenience sake
+ return ASQ;
+});
diff --git a/async/exercises/ex6/ex6.html b/async/exercises/ex6/ex6.html
new file mode 100755
index 0000000..2b24736
--- /dev/null
+++ b/async/exercises/ex6/ex6.html
@@ -0,0 +1,14 @@
+
+
+
+
+Exercise 6
+
+
+Exercise 6
+
+
+
+
+
+
diff --git a/async/exercises/ex6/ex6.js b/async/exercises/ex6/ex6.js
new file mode 100755
index 0000000..676a0ea
--- /dev/null
+++ b/async/exercises/ex6/ex6.js
@@ -0,0 +1,40 @@
+function fakeAjax(url,cb) {
+ var fake_responses = {
+ "file1": "The first text",
+ "file2": "The middle text",
+ "file3": "The last text"
+ };
+ var randomDelay = (Math.round(Math.random() * 1E4) % 8000) + 1000;
+
+ console.log("Requesting: " + url);
+
+ setTimeout(function(){
+ cb(fake_responses[url]);
+ },randomDelay);
+}
+
+function output(text) {
+ console.log(text);
+}
+
+// **************************************
+
+function getFile(file) {
+ return ASQ(function(done){
+ fakeAjax(file,done);
+ });
+}
+
+ASQ()
+.seq(
+ ...["file1","file2","file3"]
+ .map(getFile)
+ .map(function(sq) {
+ return function () {
+ return sq.val(output);
+ }
+ })
+)
+.val(function() {
+ output("complete")
+})
diff --git a/async/slides.key b/async/slides.key
new file mode 100755
index 0000000..6e812a9
Binary files /dev/null and b/async/slides.key differ
diff --git a/async/slides.pdf b/async/slides.pdf
new file mode 100755
index 0000000..f9e0f63
Binary files /dev/null and b/async/slides.pdf differ
diff --git a/pg-promise-exercises/exercises.js b/pg-promise-exercises/exercises.js
index c154c5b..3fb4df9 100644
--- a/pg-promise-exercises/exercises.js
+++ b/pg-promise-exercises/exercises.js
@@ -5,7 +5,7 @@ const postgresConfig = {
host: 'localhost',
port: 5432,
database: 'pg-promise-exercises',
- user: '', // replace this with your username
+ user: 'alexreany', // replace this with your username
password: '' // replace this if you have set a password for your username (this is unlikely)
};
diff --git a/pg-promise-exercises/schema.sql b/pg-promise-exercises/schema.sql
index 4cdba1f..3bd96ee 100644
--- a/pg-promise-exercises/schema.sql
+++ b/pg-promise-exercises/schema.sql
@@ -19,364 +19,364 @@ CREATE TABLE "books" (
-- Name: "plpgsql_call_handler" () Type: FUNCTION Owner: postgres
--
-CREATE FUNCTION "plpgsql_call_handler" () RETURNS opaque AS '/usr/local/pgsql/lib/plpgsql.so', 'plpgsql_call_handler' LANGUAGE 'C';
-
---
--- TOC Entry ID 48 (OID 2991734)
---
--- Name: plpgsql Type: PROCEDURAL LANGUAGE Owner:
---
-
-CREATE TRUSTED PROCEDURAL LANGUAGE 'plpgsql' HANDLER "plpgsql_call_handler" LANCOMPILER 'PL/pgSQL';
-
---
--- TOC Entry ID 51 (OID 2991735)
---
--- Name: "audit_bk" (integer) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "audit_bk" (integer) RETURNS integer AS '
- DECLARE
- key ALIAS FOR $1;
- table_data inventory%ROWTYPE;
- BEGIN
- INSERT INTO inventory_audit SELECT table_data WHERE sort_key=key;
-
- IF NOT FOUND THEN
- RAISE EXCEPTION ''View'' || key || '' not found '';
- END IF;
-
- return 1;
-end;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 52 (OID 2991736)
---
--- Name: "audit" (integer) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "audit" (integer) RETURNS integer AS '
- DECLARE
- key ALIAS FOR $1;
- table_data inventory%ROWTYPE;
- BEGIN
- INSERT INTO inventory_audit SELECT table_data WHERE sort_key=key;
-
- IF NOT FOUND THEN
- RAISE EXCEPTION ''View'' || key || '' not found '';
- END IF;
-
- return 1;
-end;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 53 (OID 2991737)
---
--- Name: "auditbk" () Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "auditbk" () RETURNS integer AS '
- DECLARE
- key ALIAS FOR $1;
- table_data inventory%ROWTYPE;
- BEGIN
- INSERT INTO inventory_audit SELECT table_data WHERE sort_key=key;
-
- IF NOT FOUND THEN
- RAISE EXCEPTION ''View'' || key || '' not found '';
- END IF;
-
- return 1;
-end;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 54 (OID 2991738)
---
--- Name: "audit_bk1" () Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "audit_bk1" () RETURNS opaque AS '
- DECLARE
- key ALIAS FOR $1;
- table_data inventory%ROWTYPE;
- BEGIN
- INSERT INTO inventory_audit SELECT table_data WHERE sort_key=key;
-
- IF NOT FOUND THEN
- RAISE EXCEPTION ''View'' || key || '' not found '';
- END IF;
-
- return 1;
-end;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 73 (OID 2991835)
---
--- Name: "test_check_a_id" () Type: FUNCTION Owner: example
---
-
-CREATE FUNCTION "test_check_a_id" () RETURNS opaque AS '
- BEGIN
- -- checks to make sure the author id
- -- inserted is not left blank or less than 100
-
- IF NEW.a_id ISNULL THEN
- RAISE EXCEPTION
- ''The author id cannot be left blank!'';
- ELSE
- IF NEW.a_id < 100 THEN
- RAISE EXCEPTION
- ''Please insert a valid author id.'';
- ELSE
- RETURN NEW;
- END IF;
- END IF;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 66 (OID 2992619)
---
--- Name: "audit_test" () Type: FUNCTION Owner: example
---
-
-CREATE FUNCTION "audit_test" () RETURNS opaque AS '
- BEGIN
-
- IF TG_OP = ''INSERT'' OR TG_OP = ''UPDATE'' THEN
-
- NEW.user_aud := current_user;
- NEW.mod_time := ''NOW'';
-
- INSERT INTO inventory_audit SELECT * FROM inventory WHERE prod_id=NEW.prod_id;
-
- RETURN NEW;
-
- ELSE if TG_OP = ''DELETE'' THEN
- INSERT INTO inventory_audit SELECT *, current_user, ''NOW'' FROM inventory WHERE prod_id=OLD.prod_id;
-
- RETURN OLD;
- END IF;
- END IF;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 67 (OID 3000878)
---
--- Name: "first" () Type: FUNCTION Owner: example
---
-
-CREATE FUNCTION "first" () RETURNS integer AS '
- DecLarE
- oNe IntEgER := 1;
- bEGiN
- ReTUrn oNE;
- eNd;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 68 (OID 3000881)
---
--- Name: "test" (integer) Type: FUNCTION Owner: example
---
-
-CREATE FUNCTION "test" (integer) RETURNS integer AS '
-
- DECLARE
- -- defines the variable as ALIAS
- variable ALIAS FOR $1;
- BEGIN
- -- displays the variable after multiplying it by two
- return variable * 2.0;
- END;
- ' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 69 (OID 3000991)
---
--- Name: "you_me" (integer) Type: FUNCTION Owner: example
---
-
-CREATE FUNCTION "you_me" (integer) RETURNS integer AS '
- DECLARE
- RENAME $1 TO user_no;
- --you INTEGER := 5;
- BEGIN
- return user_no;
- END;' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 62 (OID 3001136)
---
--- Name: "count_by_two" (integer) Type: FUNCTION Owner: example
---
-
-CREATE FUNCTION "count_by_two" (integer) RETURNS integer AS '
- DECLARE
- userNum ALIAS FOR $1;
- i integer;
- BEGIN
- i := 1;
- WHILE userNum[1] < 20 LOOP
- i = i+1;
- return userNum;
- END LOOP;
-
- END;
- ' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 63 (OID 3001139)
---
--- Name: "me" () Type: FUNCTION Owner: example
+-- CREATE FUNCTION "plpgsql_call_handler" () RETURNS opaque AS '/usr/local/Cellar/postgresql/9.6.2/lib/postgresql/plpgsql.so', 'plpgsql_call_handler' LANGUAGE 'c';
+--
+-- --
+-- -- TOC Entry ID 48 (OID 2991734)
+-- --
+-- -- Name: plpgsql Type: PROCEDURAL LANGUAGE Owner:
+-- --
+--
+-- CREATE TRUSTED PROCEDURAL LANGUAGE 'plpgsql' HANDLER "plpgsql_call_handler" LANCOMPILER 'PL/pgSQL';
+--
+-- --
+-- -- TOC Entry ID 51 (OID 2991735)
+-- --
+-- -- Name: "audit_bk" (integer) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "audit_bk" (integer) RETURNS integer AS '
+-- DECLARE
+-- key ALIAS FOR $1;
+-- table_data inventory%ROWTYPE;
+-- BEGIN
+-- INSERT INTO inventory_audit SELECT table_data WHERE sort_key=key;
+--
+-- IF NOT FOUND THEN
+-- RAISE EXCEPTION ''View'' || key || '' not found '';
+-- END IF;
+--
+-- return 1;
+-- end;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 52 (OID 2991736)
+-- --
+-- -- Name: "audit" (integer) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "audit" (integer) RETURNS integer AS '
+-- DECLARE
+-- key ALIAS FOR $1;
+-- table_data inventory%ROWTYPE;
+-- BEGIN
+-- INSERT INTO inventory_audit SELECT table_data WHERE sort_key=key;
+--
+-- IF NOT FOUND THEN
+-- RAISE EXCEPTION ''View'' || key || '' not found '';
+-- END IF;
+--
+-- return 1;
+-- end;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 53 (OID 2991737)
+-- --
+-- -- Name: "auditbk" () Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "auditbk" () RETURNS integer AS '
+-- DECLARE
+-- key ALIAS FOR $1;
+-- table_data inventory%ROWTYPE;
+-- BEGIN
+-- INSERT INTO inventory_audit SELECT table_data WHERE sort_key=key;
+--
+-- IF NOT FOUND THEN
+-- RAISE EXCEPTION ''View'' || key || '' not found '';
+-- END IF;
+--
+-- return 1;
+-- end;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 54 (OID 2991738)
+-- --
+-- -- Name: "audit_bk1" () Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "audit_bk1" () RETURNS opaque AS '
+-- DECLARE
+-- key ALIAS FOR $1;
+-- table_data inventory%ROWTYPE;
+-- BEGIN
+-- INSERT INTO inventory_audit SELECT table_data WHERE sort_key=key;
+--
+-- IF NOT FOUND THEN
+-- RAISE EXCEPTION ''View'' || key || '' not found '';
+-- END IF;
+--
+-- return 1;
+-- end;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 73 (OID 2991835)
+-- --
+-- -- Name: "test_check_a_id" () Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "test_check_a_id" () RETURNS opaque AS '
+-- BEGIN
+-- -- checks to make sure the author id
+-- -- inserted is not left blank or less than 100
+--
+-- IF NEW.a_id ISNULL THEN
+-- RAISE EXCEPTION
+-- ''The author id cannot be left blank!'';
+-- ELSE
+-- IF NEW.a_id < 100 THEN
+-- RAISE EXCEPTION
+-- ''Please insert a valid author id.'';
+-- ELSE
+-- RETURN NEW;
+-- END IF;
+-- END IF;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 66 (OID 2992619)
+-- --
+-- -- Name: "audit_test" () Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "audit_test" () RETURNS opaque AS '
+-- BEGIN
+--
+-- IF TG_OP = ''INSERT'' OR TG_OP = ''UPDATE'' THEN
+--
+-- NEW.user_aud := current_user;
+-- NEW.mod_time := ''NOW'';
+--
+-- INSERT INTO inventory_audit SELECT * FROM inventory WHERE prod_id=NEW.prod_id;
+--
+-- RETURN NEW;
+--
+-- ELSE if TG_OP = ''DELETE'' THEN
+-- INSERT INTO inventory_audit SELECT *, current_user, ''NOW'' FROM inventory WHERE prod_id=OLD.prod_id;
+--
+-- RETURN OLD;
+-- END IF;
+-- END IF;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 67 (OID 3000878)
+-- --
+-- -- Name: "first" () Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "first" () RETURNS integer AS '
+-- DecLarE
+-- oNe IntEgER := 1;
+-- bEGiN
+-- ReTUrn oNE;
+-- eNd;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 68 (OID 3000881)
+-- --
+-- -- Name: "test" (integer) Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "test" (integer) RETURNS integer AS '
+--
+-- DECLARE
+-- -- defines the variable as ALIAS
+-- variable ALIAS FOR $1;
+-- BEGIN
+-- -- displays the variable after multiplying it by two
+-- return variable * 2.0;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 69 (OID 3000991)
+-- --
+-- -- Name: "you_me" (integer) Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "you_me" (integer) RETURNS integer AS '
+-- DECLARE
+-- RENAME $1 TO user_no;
+-- --you INTEGER := 5;
+-- BEGIN
+-- return user_no;
+-- END;' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 62 (OID 3001136)
+-- --
+-- -- Name: "count_by_two" (integer) Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "count_by_two" (integer) RETURNS integer AS '
+-- DECLARE
+-- userNum ALIAS FOR $1;
+-- i integer;
+-- BEGIN
+-- i := 1;
+-- WHILE userNum[1] < 20 LOOP
+-- i = i+1;
+-- return userNum;
+-- END LOOP;
+--
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 63 (OID 3001139)
+-- --
+-- -- Name: "me" () Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "me" () RETURNS text AS '
+-- DECLARE
+-- you text := ''testing'';
+-- RENAME you to me;
+-- BEGIN
+-- return me;
+-- END;' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 64 (OID 3001149)
+-- --
+-- -- Name: "display_cust" (integer) Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "display_cust" (integer) RETURNS text AS '
+-- DECLARE
+-- -- declares an alias name for input
+-- cust_num ALIAS FOR $1;
+--
+-- -- declares a row type
+-- cust_info customer%ROWTYPE;
+-- BEGIN
+-- -- puts information into the newly declared rowtype
+-- SELECT into cust_info *
+-- FROM customer
+-- WHERE cust_id=cust_num;
+--
+-- -- displays the customer lastname
+-- -- extracted from the rowtype
+-- return cust_info.lastname;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 65 (OID 3001151)
+-- --
+-- -- Name: "mixed" () Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "mixed" () RETURNS integer AS '
+-- DecLarE
+-- --assigns 1 to the oNe variable
+-- oNe IntEgER
+-- := 1;
+--
+-- bEGiN
+--
+-- --displays the value of oNe
+-- ReTUrn oNe;
+-- eNd;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 12 (OID 3117548)
+-- --
+-- -- Name: publishers Type: TABLE Owner: postgres
+-- --
--
-
-CREATE FUNCTION "me" () RETURNS text AS '
- DECLARE
- you text := ''testing'';
- RENAME you to me;
- BEGIN
- return me;
- END;' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 64 (OID 3001149)
---
--- Name: "display_cust" (integer) Type: FUNCTION Owner: example
---
-
-CREATE FUNCTION "display_cust" (integer) RETURNS text AS '
- DECLARE
- -- declares an alias name for input
- cust_num ALIAS FOR $1;
-
- -- declares a row type
- cust_info customer%ROWTYPE;
- BEGIN
- -- puts information into the newly declared rowtype
- SELECT into cust_info *
- FROM customer
- WHERE cust_id=cust_num;
-
- -- displays the customer lastname
- -- extracted from the rowtype
- return cust_info.lastname;
- END;
- ' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 65 (OID 3001151)
---
--- Name: "mixed" () Type: FUNCTION Owner: example
---
-
-CREATE FUNCTION "mixed" () RETURNS integer AS '
- DecLarE
- --assigns 1 to the oNe variable
- oNe IntEgER
- := 1;
-
- bEGiN
-
- --displays the value of oNe
- ReTUrn oNe;
- eNd;
- ' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 12 (OID 3117548)
---
--- Name: publishers Type: TABLE Owner: postgres
---
-
CREATE TABLE "publishers" (
"id" integer NOT NULL,
"name" text,
"address" text,
Constraint "publishers_pkey" Primary Key ("id")
);
-
---
--- TOC Entry ID 55 (OID 3117729)
---
--- Name: "compound_word" (text,text) Type: FUNCTION Owner: example
---
-
-CREATE FUNCTION "compound_word" (text,text) RETURNS text AS '
- DECLARE
- -- defines an alias name for the two input values
- word1 ALIAS FOR $1;
- word2 ALIAS FOR $2;
- BEGIN
- -- displays the resulting joined words
- RETURN word1 || word2;
- END;
- ' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 56 (OID 3117787)
---
--- Name: "givename" () Type: FUNCTION Owner: example
--
-
-CREATE FUNCTION "givename" () RETURNS opaque AS '
- DECLARE
- tablename text;
- BEGIN
-
- tablename = TG_RELNAME;
- INSERT INTO INVENTORY values (123, tablename);
- return old;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 14 (OID 3389594)
---
--- Name: authors Type: TABLE Owner: manager
+-- --
+-- -- TOC Entry ID 55 (OID 3117729)
+-- --
+-- -- Name: "compound_word" (text,text) Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "compound_word" (text,text) RETURNS text AS '
+-- DECLARE
+-- -- defines an alias name for the two input values
+-- word1 ALIAS FOR $1;
+-- word2 ALIAS FOR $2;
+-- BEGIN
+-- -- displays the resulting joined words
+-- RETURN word1 || word2;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 56 (OID 3117787)
+-- --
+-- -- Name: "givename" () Type: FUNCTION Owner: example
+-- --
+--
+-- CREATE FUNCTION "givename" () RETURNS opaque AS '
+-- DECLARE
+-- tablename text;
+-- BEGIN
+--
+-- tablename = TG_RELNAME;
+-- INSERT INTO INVENTORY values (123, tablename);
+-- return old;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 14 (OID 3389594)
+-- --
+-- -- Name: authors Type: TABLE Owner: manager
+-- --
--
-
CREATE TABLE "authors" (
"id" integer NOT NULL,
"last_name" text,
"first_name" text,
Constraint "authors_pkey" Primary Key ("id")
);
-
--
--- TOC Entry ID 15 (OID 3389632)
+-- --
+-- -- TOC Entry ID 15 (OID 3389632)
+-- --
+-- -- Name: states Type: TABLE Owner: postgres
+-- --
--
--- Name: states Type: TABLE Owner: postgres
---
-
CREATE TABLE "states" (
"id" integer NOT NULL,
"name" text,
"abbreviation" character(2),
Constraint "state_pkey" Primary Key ("id")
);
-
---
--- TOC Entry ID 16 (OID 3389702)
--
--- Name: my_list Type: TABLE Owner: postgres
+-- --
+-- -- TOC Entry ID 16 (OID 3389702)
+-- --
+-- -- Name: my_list Type: TABLE Owner: postgres
+-- --
--
-
CREATE TABLE "my_list" (
"todos" text
);
+-- --
+-- -- TOC Entry ID 17 (OID 3390348)
+-- --
+-- -- Name: stock Type: TABLE Owner: postgres
+-- --
--
--- TOC Entry ID 17 (OID 3390348)
---
--- Name: stock Type: TABLE Owner: postgres
---
-
CREATE TABLE "stock" (
"isbn" text NOT NULL,
"cost" numeric(5,2),
@@ -384,577 +384,577 @@ CREATE TABLE "stock" (
"stock" integer,
Constraint "stock_pkey" Primary Key ("isbn")
);
-
---
--- TOC Entry ID 4 (OID 3390416)
--
--- Name: subject_ids Type: SEQUENCE Owner: postgres
+-- --
+-- -- TOC Entry ID 4 (OID 3390416)
+-- --
+-- -- Name: subject_ids Type: SEQUENCE Owner: postgres
+-- --
--
-
CREATE SEQUENCE "subject_ids" start 0 increment 1 maxvalue 2147483647 minvalue 0 cache 1 ;
-
--
--- TOC Entry ID 19 (OID 3390653)
+-- --
+-- -- TOC Entry ID 19 (OID 3390653)
+-- --
+-- -- Name: numeric_values Type: TABLE Owner: postgres
+-- --
--
--- Name: numeric_values Type: TABLE Owner: postgres
---
-
CREATE TABLE "numeric_values" (
"num" numeric(30,6)
);
-
--
--- TOC Entry ID 20 (OID 3390866)
+-- --
+-- -- TOC Entry ID 20 (OID 3390866)
+-- --
+-- -- Name: daily_inventory Type: TABLE Owner: postgres
+-- --
--
--- Name: daily_inventory Type: TABLE Owner: postgres
---
-
CREATE TABLE "daily_inventory" (
"isbn" text,
"is_stocked" boolean
);
-
---
--- TOC Entry ID 21 (OID 3391084)
--
--- Name: money_example Type: TABLE Owner: postgres
+-- --
+-- -- TOC Entry ID 21 (OID 3391084)
+-- --
+-- -- Name: money_example Type: TABLE Owner: postgres
+-- --
--
-
CREATE TABLE "money_example" (
"money_cash" money,
"numeric_cash" numeric(6,2)
);
-
--
--- TOC Entry ID 22 (OID 3391184)
+-- --
+-- -- TOC Entry ID 22 (OID 3391184)
+-- --
+-- -- Name: shipments Type: TABLE Owner: postgres
+-- --
--
--- Name: shipments Type: TABLE Owner: postgres
---
-
CREATE TABLE "shipments" (
"id" integer DEFAULT nextval('"shipments_ship_id_seq"'::text) NOT NULL,
"customer_id" integer,
"isbn" text,
"ship_date" timestamp with time zone
);
-
--
--- TOC Entry ID 24 (OID 3391454)
+-- --
+-- -- TOC Entry ID 24 (OID 3391454)
+-- --
+-- -- Name: customers Type: TABLE Owner: manager
+-- --
--
--- Name: customers Type: TABLE Owner: manager
---
-
CREATE TABLE "customers" (
"id" integer NOT NULL,
"last_name" text,
"first_name" text,
Constraint "customers_pkey" Primary Key ("id")
);
-
---
--- TOC Entry ID 6 (OID 3574018)
--
--- Name: book_ids Type: SEQUENCE Owner: postgres
+-- --
+-- -- TOC Entry ID 6 (OID 3574018)
+-- --
+-- -- Name: book_ids Type: SEQUENCE Owner: postgres
+-- --
--
-
CREATE SEQUENCE "book_ids" start 0 increment 1 maxvalue 2147483647 minvalue 0 cache 1 ;
-
--
--- TOC Entry ID 26 (OID 3574043)
+-- --
+-- -- TOC Entry ID 26 (OID 3574043)
+-- --
+-- -- Name: book_queue Type: TABLE Owner: postgres
+-- --
--
--- Name: book_queue Type: TABLE Owner: postgres
---
-
CREATE TABLE "book_queue" (
"title" text NOT NULL,
"author_id" integer,
"subject_id" integer,
"approved" boolean
);
-
--
--- TOC Entry ID 78 (OID 3574403)
+-- --
+-- -- TOC Entry ID 78 (OID 3574403)
+-- --
+-- -- Name: "title" (integer) Type: FUNCTION Owner: postgres
+-- --
--
--- Name: "title" (integer) Type: FUNCTION Owner: postgres
+-- CREATE FUNCTION "title" (integer) RETURNS text AS 'SELECT title from books where id = $1' LANGUAGE 'sql';
--
-
-CREATE FUNCTION "title" (integer) RETURNS text AS 'SELECT title from books where id = $1' LANGUAGE 'sql';
-
+-- --
+-- -- TOC Entry ID 27 (OID 3574983)
+-- --
+-- -- Name: stock_backup Type: TABLE Owner: postgres
+-- --
--
--- TOC Entry ID 27 (OID 3574983)
---
--- Name: stock_backup Type: TABLE Owner: postgres
---
-
CREATE TABLE "stock_backup" (
"isbn" text,
"cost" numeric(5,2),
"retail" numeric(5,2),
"stock" integer
);
-
--
--- TOC Entry ID 89 (OID 3625934)
---
--- Name: "double_price" (double precision) Type: FUNCTION Owner: postgres
+-- --
+-- -- TOC Entry ID 89 (OID 3625934)
+-- --
+-- -- Name: "double_price" (double precision) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "double_price" (double precision) RETURNS double precision AS '
+-- DECLARE
+-- BEGIN
+-- return $1 * 2;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 90 (OID 3625935)
+-- --
+-- -- Name: "triple_price" (double precision) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "triple_price" (double precision) RETURNS double precision AS '
+-- DECLARE
+-- -- Declare input_price as an alias for the
+-- -- argument variable normally referenced with
+-- -- the $1 identifier.
+-- input_price ALIAS FOR $1;
+--
+-- BEGIN
+-- -- Return the input price multiplied by three.
+-- RETURN input_price * 3;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 87 (OID 3625944)
+-- --
+-- -- Name: "stock_amount" (integer,integer) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "stock_amount" (integer,integer) RETURNS integer AS '
+-- DECLARE
+-- -- Declare aliases for function arguments.
+-- b_id ALIAS FOR $1;
+-- b_edition ALIAS FOR $2;
+-- -- Declare variable to store the ISBN number.
+-- b_isbn TEXT;
+-- -- Declare variable to store the stock amount.
+-- stock_amount INTEGER;
+-- BEGIN
+-- -- This SELECT INTO statement retrieves the ISBN
+-- -- number of the row in the editions table that had
+-- -- both the book ID number and edition number that
+-- -- were provided as function arguments.
+-- SELECT INTO b_isbn isbn FROM editions WHERE
+-- book_id = b_id AND edition = b_edition;
+--
+-- -- Check to see if the ISBN number retrieved
+-- -- is NULL. This will happen if there is not an
+-- -- existing book with both the ID number and edition
+-- -- number specified in the function arguments.
+-- -- If the ISBN is null, the function returns a
+-- -- value of -1 and ends.
+-- IF b_isbn IS NULL THEN
+-- RETURN -1;
+-- END IF;
+--
+-- -- Retrieve the amount of books available from the
+-- -- stock table and record the number in the
+-- -- stock_amount variable.
+-- SELECT INTO stock_amount stock FROM stock WHERE isbn = b_isbn;
+--
+-- -- Return the amount of books available.
+-- RETURN stock_amount;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 86 (OID 3625946)
+-- --
+-- -- Name: "in_stock" (integer,integer) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "in_stock" (integer,integer) RETURNS boolean AS '
+-- DECLARE
+-- b_id ALIAS FOR $1;
+-- b_edition ALIAS FOR $2;
+-- b_isbn TEXT;
+-- stock_amount INTEGER;
+-- BEGIN
+-- -- This SELECT INTO statement retrieves the ISBN
+-- -- number of the row in the editions table that had
+-- -- both the book ID number and edition number that
+-- -- were provided as function arguments.
+-- SELECT INTO b_isbn isbn FROM editions WHERE
+-- book_id = b_id AND edition = b_edition;
+--
+-- -- Check to see if the ISBN number retrieved
+-- -- is NULL. This will happen if there is not an
+-- -- existing book with both the ID number and edition
+-- -- number specified in the function arguments.
+-- -- If the ISBN is null, the function returns a
+-- -- FALSE value and ends.
+-- IF b_isbn IS NULL THEN
+-- RETURN FALSE;
+-- END IF;
+--
+-- -- Retrieve the amount of books available from the
+-- -- stock table and record the number in the
+-- -- stock_amount variable.
+-- SELECT INTO stock_amount stock FROM stock WHERE isbn = b_isbn;
+--
+-- -- Use an IF/THEN/ELSE check to see if the amount
+-- -- of books available is less than, or equal to 0.
+-- -- If so, return FALSE. If not, return TRUE.
+-- IF stock_amount <= 0 THEN
+-- RETURN FALSE;
+-- ELSE
+-- RETURN TRUE;
+-- END IF;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 82 (OID 3626013)
+-- --
+-- -- Name: "extract_all_titles" () Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "extract_all_titles" () RETURNS text AS '
+-- DECLARE
+-- sub_id INTEGER;
+-- text_output TEXT = '' '';
+-- sub_title TEXT;
+-- row_data books%ROWTYPE;
+-- BEGIN
+-- FOR i IN 0..15 LOOP
+-- SELECT INTO sub_title subject FROM subjects WHERE id = i;
+-- text_output = text_output || ''
+-- '' || sub_title || '':
+-- '';
+--
+-- FOR row_data IN SELECT * FROM books
+-- WHERE subject_id = i LOOP
+--
+-- IF NOT FOUND THEN
+-- text_output := text_output || ''None.
+-- '';
+-- ELSE
+-- text_output := text_output || row_data.title || ''
+-- '';
+-- END IF;
+--
+-- END LOOP;
+-- END LOOP;
+-- RETURN text_output;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 79 (OID 3626052)
+-- --
+-- -- Name: "books_by_subject" (text) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "books_by_subject" (text) RETURNS text AS '
+-- DECLARE
+-- sub_title ALIAS FOR $1;
+-- sub_id INTEGER;
+-- found_text TEXT :='''';
+-- BEGIN
+-- SELECT INTO sub_id id FROM subjects WHERE subject = sub_title;
+-- RAISE NOTICE ''sub_id = %'',sub_id;
+-- IF sub_title = ''all'' THEN
+-- found_text := extract_all_titles();
+-- RETURN found_text;
+-- ELSE IF sub_id >= 0 THEN
+-- found_text := extract_title(sub_id);
+-- RETURN ''
+-- '' || sub_title || '':
+-- '' || found_text;
+-- END IF;
+-- END IF;
+-- RETURN ''Subject not found.'';
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 81 (OID 3626590)
+-- --
+-- -- Name: "add_two_loop" (integer,integer) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "add_two_loop" (integer,integer) RETURNS integer AS '
+-- DECLARE
+--
+-- -- Declare aliases for function arguments.
+--
+-- low_number ALIAS FOR $1;
+-- high_number ALIAS FOR $2;
+--
+-- -- Declare a variable to hold the result.
+--
+-- result INTEGER = 0;
+--
+-- BEGIN
+--
+-- WHILE result != high_number LOOP
+-- result := result + 1;
+-- END LOOP;
+--
+-- RETURN result;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 92 (OID 3627916)
+-- --
+-- -- Name: "extract_all_titles2" () Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "extract_all_titles2" () RETURNS text AS '
+-- DECLARE
+-- sub_id INTEGER;
+-- text_output TEXT = '' '';
+-- sub_title TEXT;
+-- row_data books%ROWTYPE;
+-- BEGIN
+-- FOR i IN 0..15 LOOP
+-- SELECT INTO sub_title subject FROM subjects WHERE id = i;
+-- text_output = text_output || ''
+-- '' || sub_title || '':
+-- '';
+--
+-- FOR row_data IN SELECT * FROM books
+-- WHERE subject_id = i LOOP
+--
+-- text_output := text_output || row_data.title || ''
+-- '';
+--
+-- END LOOP;
+-- END LOOP;
+-- RETURN text_output;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 94 (OID 3627974)
+-- --
+-- -- Name: "extract_title" (integer) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "extract_title" (integer) RETURNS text AS '
+-- DECLARE
+-- sub_id ALIAS FOR $1;
+-- text_output TEXT :=''
+-- '';
+-- row_data RECORD;
+-- BEGIN
+-- FOR row_data IN SELECT * FROM books
+-- WHERE subject_id = sub_id ORDER BY title LOOP
+-- text_output := text_output || row_data.title || ''
+-- '';
+-- END LOOP;
+-- RETURN text_output;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 95 (OID 3628021)
+-- --
+-- -- Name: "raise_test" () Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "raise_test" () RETURNS integer AS '
+-- DECLARE
+--
+-- -- Declare an integer variable for testing.
+--
+-- an_integer INTEGER = 1;
+--
+-- BEGIN
+--
+-- -- Raise a debug level message.
+--
+-- RAISE DEBUG ''The raise_test() function began.'';
+--
+-- an_integer = an_integer + 1;
+--
+-- -- Raise a notice stating that the an_integer
+-- -- variable was changed, then raise another notice
+-- -- stating its new value.
+--
+-- RAISE NOTICE ''Variable an_integer was changed.'';
+-- RAISE NOTICE ''Variable an_integer value is now %.'',an_integer;
+--
+-- -- Raise an exception.
+--
+-- RAISE EXCEPTION ''Variable % changed. Aborting transaction.'',an_integer;
+--
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 93 (OID 3628069)
+-- --
+-- -- Name: "add_shipment" (integer,text) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "add_shipment" (integer,text) RETURNS timestamp with time zone AS '
+-- DECLARE
+-- customer_id ALIAS FOR $1;
+-- isbn ALIAS FOR $2;
+-- shipment_id INTEGER;
+-- right_now timestamp;
+-- BEGIN
+-- right_now := ''now'';
+-- SELECT INTO shipment_id id FROM shipments ORDER BY id DESC;
+-- shipment_id := shipment_id + 1;
+-- INSERT INTO shipments VALUES ( shipment_id, customer_id, isbn, right_now );
+-- RETURN right_now;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 102 (OID 3628076)
+-- --
+-- -- Name: "ship_item" (text,text,text) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "ship_item" (text,text,text) RETURNS integer AS '
+-- DECLARE
+-- l_name ALIAS FOR $1;
+-- f_name ALIAS FOR $2;
+-- book_isbn ALIAS FOR $3;
+-- book_id INTEGER;
+-- customer_id INTEGER;
+--
+-- BEGIN
+--
+-- SELECT INTO customer_id get_customer_id(l_name,f_name);
+--
+-- IF customer_id = -1 THEN
+-- RETURN -1;
+-- END IF;
+--
+-- SELECT INTO book_id book_id FROM editions WHERE isbn = book_isbn;
+--
+-- IF NOT FOUND THEN
+-- RETURN -1;
+-- END IF;
--
-
-CREATE FUNCTION "double_price" (double precision) RETURNS double precision AS '
- DECLARE
- BEGIN
- return $1 * 2;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 90 (OID 3625935)
---
--- Name: "triple_price" (double precision) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "triple_price" (double precision) RETURNS double precision AS '
- DECLARE
- -- Declare input_price as an alias for the
- -- argument variable normally referenced with
- -- the $1 identifier.
- input_price ALIAS FOR $1;
-
- BEGIN
- -- Return the input price multiplied by three.
- RETURN input_price * 3;
- END;
- ' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 87 (OID 3625944)
---
--- Name: "stock_amount" (integer,integer) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "stock_amount" (integer,integer) RETURNS integer AS '
- DECLARE
- -- Declare aliases for function arguments.
- b_id ALIAS FOR $1;
- b_edition ALIAS FOR $2;
- -- Declare variable to store the ISBN number.
- b_isbn TEXT;
- -- Declare variable to store the stock amount.
- stock_amount INTEGER;
- BEGIN
- -- This SELECT INTO statement retrieves the ISBN
- -- number of the row in the editions table that had
- -- both the book ID number and edition number that
- -- were provided as function arguments.
- SELECT INTO b_isbn isbn FROM editions WHERE
- book_id = b_id AND edition = b_edition;
-
- -- Check to see if the ISBN number retrieved
- -- is NULL. This will happen if there is not an
- -- existing book with both the ID number and edition
- -- number specified in the function arguments.
- -- If the ISBN is null, the function returns a
- -- value of -1 and ends.
- IF b_isbn IS NULL THEN
- RETURN -1;
- END IF;
-
- -- Retrieve the amount of books available from the
- -- stock table and record the number in the
- -- stock_amount variable.
- SELECT INTO stock_amount stock FROM stock WHERE isbn = b_isbn;
-
- -- Return the amount of books available.
- RETURN stock_amount;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 86 (OID 3625946)
---
--- Name: "in_stock" (integer,integer) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "in_stock" (integer,integer) RETURNS boolean AS '
- DECLARE
- b_id ALIAS FOR $1;
- b_edition ALIAS FOR $2;
- b_isbn TEXT;
- stock_amount INTEGER;
- BEGIN
- -- This SELECT INTO statement retrieves the ISBN
- -- number of the row in the editions table that had
- -- both the book ID number and edition number that
- -- were provided as function arguments.
- SELECT INTO b_isbn isbn FROM editions WHERE
- book_id = b_id AND edition = b_edition;
-
- -- Check to see if the ISBN number retrieved
- -- is NULL. This will happen if there is not an
- -- existing book with both the ID number and edition
- -- number specified in the function arguments.
- -- If the ISBN is null, the function returns a
- -- FALSE value and ends.
- IF b_isbn IS NULL THEN
- RETURN FALSE;
- END IF;
-
- -- Retrieve the amount of books available from the
- -- stock table and record the number in the
- -- stock_amount variable.
- SELECT INTO stock_amount stock FROM stock WHERE isbn = b_isbn;
-
- -- Use an IF/THEN/ELSE check to see if the amount
- -- of books available is less than, or equal to 0.
- -- If so, return FALSE. If not, return TRUE.
- IF stock_amount <= 0 THEN
- RETURN FALSE;
- ELSE
- RETURN TRUE;
- END IF;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 82 (OID 3626013)
---
--- Name: "extract_all_titles" () Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "extract_all_titles" () RETURNS text AS '
- DECLARE
- sub_id INTEGER;
- text_output TEXT = '' '';
- sub_title TEXT;
- row_data books%ROWTYPE;
- BEGIN
- FOR i IN 0..15 LOOP
- SELECT INTO sub_title subject FROM subjects WHERE id = i;
- text_output = text_output || ''
-'' || sub_title || '':
-'';
-
- FOR row_data IN SELECT * FROM books
- WHERE subject_id = i LOOP
-
- IF NOT FOUND THEN
- text_output := text_output || ''None.
-'';
- ELSE
- text_output := text_output || row_data.title || ''
-'';
- END IF;
-
- END LOOP;
- END LOOP;
- RETURN text_output;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 79 (OID 3626052)
---
--- Name: "books_by_subject" (text) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "books_by_subject" (text) RETURNS text AS '
- DECLARE
- sub_title ALIAS FOR $1;
- sub_id INTEGER;
- found_text TEXT :='''';
- BEGIN
- SELECT INTO sub_id id FROM subjects WHERE subject = sub_title;
- RAISE NOTICE ''sub_id = %'',sub_id;
- IF sub_title = ''all'' THEN
- found_text := extract_all_titles();
- RETURN found_text;
- ELSE IF sub_id >= 0 THEN
- found_text := extract_title(sub_id);
- RETURN ''
-'' || sub_title || '':
-'' || found_text;
- END IF;
- END IF;
- RETURN ''Subject not found.'';
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 81 (OID 3626590)
---
--- Name: "add_two_loop" (integer,integer) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "add_two_loop" (integer,integer) RETURNS integer AS '
- DECLARE
-
- -- Declare aliases for function arguments.
-
- low_number ALIAS FOR $1;
- high_number ALIAS FOR $2;
-
- -- Declare a variable to hold the result.
-
- result INTEGER = 0;
-
- BEGIN
-
- WHILE result != high_number LOOP
- result := result + 1;
- END LOOP;
-
- RETURN result;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 92 (OID 3627916)
---
--- Name: "extract_all_titles2" () Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "extract_all_titles2" () RETURNS text AS '
- DECLARE
- sub_id INTEGER;
- text_output TEXT = '' '';
- sub_title TEXT;
- row_data books%ROWTYPE;
- BEGIN
- FOR i IN 0..15 LOOP
- SELECT INTO sub_title subject FROM subjects WHERE id = i;
- text_output = text_output || ''
-'' || sub_title || '':
-'';
-
- FOR row_data IN SELECT * FROM books
- WHERE subject_id = i LOOP
-
- text_output := text_output || row_data.title || ''
-'';
-
- END LOOP;
- END LOOP;
- RETURN text_output;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 94 (OID 3627974)
---
--- Name: "extract_title" (integer) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "extract_title" (integer) RETURNS text AS '
- DECLARE
- sub_id ALIAS FOR $1;
- text_output TEXT :=''
-'';
- row_data RECORD;
- BEGIN
- FOR row_data IN SELECT * FROM books
- WHERE subject_id = sub_id ORDER BY title LOOP
- text_output := text_output || row_data.title || ''
-'';
- END LOOP;
- RETURN text_output;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 95 (OID 3628021)
---
--- Name: "raise_test" () Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "raise_test" () RETURNS integer AS '
- DECLARE
-
- -- Declare an integer variable for testing.
-
- an_integer INTEGER = 1;
-
- BEGIN
-
- -- Raise a debug level message.
-
- RAISE DEBUG ''The raise_test() function began.'';
-
- an_integer = an_integer + 1;
-
- -- Raise a notice stating that the an_integer
- -- variable was changed, then raise another notice
- -- stating its new value.
-
- RAISE NOTICE ''Variable an_integer was changed.'';
- RAISE NOTICE ''Variable an_integer value is now %.'',an_integer;
-
- -- Raise an exception.
-
- RAISE EXCEPTION ''Variable % changed. Aborting transaction.'',an_integer;
-
- END;
-' LANGUAGE 'plpgsql';
-
+-- PERFORM add_shipment(customer_id,book_isbn);
+--
+-- RETURN 1;
+-- END;
+-- ' LANGUAGE 'plpgsql';
--
--- TOC Entry ID 93 (OID 3628069)
+-- --
+-- -- TOC Entry ID 103 (OID 3628114)
+-- --
+-- -- Name: "check_book_addition" () Type: FUNCTION Owner: postgres
+-- --
--
--- Name: "add_shipment" (integer,text) Type: FUNCTION Owner: postgres
+-- CREATE FUNCTION "check_book_addition" () RETURNS opaque AS '
+-- DECLARE
+-- id_number INTEGER;
+-- book_isbn TEXT;
+-- BEGIN
--
-
-CREATE FUNCTION "add_shipment" (integer,text) RETURNS timestamp with time zone AS '
- DECLARE
- customer_id ALIAS FOR $1;
- isbn ALIAS FOR $2;
- shipment_id INTEGER;
- right_now timestamp;
- BEGIN
- right_now := ''now'';
- SELECT INTO shipment_id id FROM shipments ORDER BY id DESC;
- shipment_id := shipment_id + 1;
- INSERT INTO shipments VALUES ( shipment_id, customer_id, isbn, right_now );
- RETURN right_now;
- END;
-' LANGUAGE 'plpgsql';
-
+-- SELECT INTO id_number id FROM customers WHERE id = NEW.customer_id;
--
--- TOC Entry ID 102 (OID 3628076)
+-- IF NOT FOUND THEN
+-- RAISE EXCEPTION ''Invalid customer ID number.'';
+-- END IF;
--
--- Name: "ship_item" (text,text,text) Type: FUNCTION Owner: postgres
+-- SELECT INTO book_isbn isbn FROM editions WHERE isbn = NEW.isbn;
--
-
-CREATE FUNCTION "ship_item" (text,text,text) RETURNS integer AS '
- DECLARE
- l_name ALIAS FOR $1;
- f_name ALIAS FOR $2;
- book_isbn ALIAS FOR $3;
- book_id INTEGER;
- customer_id INTEGER;
-
- BEGIN
-
- SELECT INTO customer_id get_customer_id(l_name,f_name);
-
- IF customer_id = -1 THEN
- RETURN -1;
- END IF;
-
- SELECT INTO book_id book_id FROM editions WHERE isbn = book_isbn;
-
- IF NOT FOUND THEN
- RETURN -1;
- END IF;
-
- PERFORM add_shipment(customer_id,book_isbn);
-
- RETURN 1;
- END;
-' LANGUAGE 'plpgsql';
-
+-- IF NOT FOUND THEN
+-- RAISE EXCEPTION ''Invalid ISBN.'';
+-- END IF;
--
--- TOC Entry ID 103 (OID 3628114)
+-- UPDATE stock SET stock = stock -1 WHERE isbn = NEW.isbn;
--
--- Name: "check_book_addition" () Type: FUNCTION Owner: postgres
+-- RETURN NEW;
+-- END;
+-- ' LANGUAGE 'plpgsql';
--
-
-CREATE FUNCTION "check_book_addition" () RETURNS opaque AS '
- DECLARE
- id_number INTEGER;
- book_isbn TEXT;
- BEGIN
-
- SELECT INTO id_number id FROM customers WHERE id = NEW.customer_id;
-
- IF NOT FOUND THEN
- RAISE EXCEPTION ''Invalid customer ID number.'';
- END IF;
-
- SELECT INTO book_isbn isbn FROM editions WHERE isbn = NEW.isbn;
-
- IF NOT FOUND THEN
- RAISE EXCEPTION ''Invalid ISBN.'';
- END IF;
-
- UPDATE stock SET stock = stock -1 WHERE isbn = NEW.isbn;
-
- RETURN NEW;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 28 (OID 3628246)
---
--- Name: stock_view Type: VIEW Owner: postgres
+-- --
+-- -- TOC Entry ID 28 (OID 3628246)
+-- --
+-- -- Name: stock_view Type: VIEW Owner: postgres
+-- --
+--
+-- CREATE VIEW "stock_view" as SELECT stock.isbn, stock.retail, stock.stock FROM stock;
--
-
-CREATE VIEW "stock_view" as SELECT stock.isbn, stock.retail, stock.stock FROM stock;
-
---
--- TOC Entry ID 30 (OID 3628247)
+-- --
+-- -- TOC Entry ID 30 (OID 3628247)
+-- --
+-- -- Name: favorite_books Type: TABLE Owner: manager
+-- --
--
--- Name: favorite_books Type: TABLE Owner: manager
---
-
CREATE TABLE "favorite_books" (
"employee_id" integer,
"books" text[]
);
-
---
--- TOC Entry ID 8 (OID 3628626)
--
--- Name: shipments_ship_id_seq Type: SEQUENCE Owner: manager
+-- --
+-- -- TOC Entry ID 8 (OID 3628626)
+-- --
+-- -- Name: shipments_ship_id_seq Type: SEQUENCE Owner: manager
+-- --
--
-
CREATE SEQUENCE "shipments_ship_id_seq" start 0 increment 1 maxvalue 2147483647 minvalue 0 cache 1 ;
+-- --
+-- -- TOC Entry ID 74 (OID 3628648)
+-- --
+-- -- Name: "check_shipment_addition" () Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "check_shipment_addition" () RETURNS opaque AS '
+-- DECLARE
+-- -- Declare a variable to hold the customer ID.
+-- id_number INTEGER;
+--
+-- -- Declare a variable to hold the ISBN.
+-- book_isbn TEXT;
+-- BEGIN
+--
+-- -- If there is an ID number that matches the customer ID in
+-- -- the new table, retrieve it from the customers table.
+-- SELECT INTO id_number id FROM customers WHERE id = NEW.customer_id;
+--
+-- -- If there was no matching ID number, raise an exception.
+-- IF NOT FOUND THEN
+-- RAISE EXCEPTION ''Invalid customer ID number.'';
+-- END IF;
+--
+-- -- If there is an ISBN that matches the ISBN specified in the
+-- -- new table, retrieve it from the editions table.
+-- SELECT INTO book_isbn isbn FROM editions WHERE isbn = NEW.isbn;
+--
+-- -- If there is no matching ISBN, raise an exception.
+-- IF NOT FOUND THEN
+-- RAISE EXCEPTION ''Invalid ISBN.'';
+-- END IF;
+--
+-- -- If the previous checks succeeded, update the stock amount
+-- -- for INSERT commands.
+-- IF TG_OP = ''INSERT'' THEN
+-- UPDATE stock SET stock = stock -1 WHERE isbn = NEW.isbn;
+-- END IF;
+--
+-- RETURN NEW;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 31 (OID 3628899)
+-- --
+-- -- Name: employees Type: TABLE Owner: postgres
+-- --
--
--- TOC Entry ID 74 (OID 3628648)
---
--- Name: "check_shipment_addition" () Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "check_shipment_addition" () RETURNS opaque AS '
- DECLARE
- -- Declare a variable to hold the customer ID.
- id_number INTEGER;
-
- -- Declare a variable to hold the ISBN.
- book_isbn TEXT;
- BEGIN
-
- -- If there is an ID number that matches the customer ID in
- -- the new table, retrieve it from the customers table.
- SELECT INTO id_number id FROM customers WHERE id = NEW.customer_id;
-
- -- If there was no matching ID number, raise an exception.
- IF NOT FOUND THEN
- RAISE EXCEPTION ''Invalid customer ID number.'';
- END IF;
-
- -- If there is an ISBN that matches the ISBN specified in the
- -- new table, retrieve it from the editions table.
- SELECT INTO book_isbn isbn FROM editions WHERE isbn = NEW.isbn;
-
- -- If there is no matching ISBN, raise an exception.
- IF NOT FOUND THEN
- RAISE EXCEPTION ''Invalid ISBN.'';
- END IF;
-
- -- If the previous checks succeeded, update the stock amount
- -- for INSERT commands.
- IF TG_OP = ''INSERT'' THEN
- UPDATE stock SET stock = stock -1 WHERE isbn = NEW.isbn;
- END IF;
-
- RETURN NEW;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 31 (OID 3628899)
---
--- Name: employees Type: TABLE Owner: postgres
---
-
CREATE TABLE "employees" (
"id" integer NOT NULL,
"last_name" text NOT NULL,
@@ -962,13 +962,13 @@ CREATE TABLE "employees" (
CONSTRAINT "employees_id" CHECK ((id > 100)),
Constraint "employees_pkey" Primary Key ("id")
);
-
--
--- TOC Entry ID 32 (OID 3629174)
+-- --
+-- -- TOC Entry ID 32 (OID 3629174)
+-- --
+-- -- Name: editions Type: TABLE Owner: manager
+-- --
--
--- Name: editions Type: TABLE Owner: manager
---
-
CREATE TABLE "editions" (
"isbn" text NOT NULL,
"book_id" integer,
@@ -979,188 +979,188 @@ CREATE TABLE "editions" (
CONSTRAINT "integrity" CHECK (((book_id NOTNULL) AND (edition NOTNULL))),
Constraint "pkey" Primary Key ("isbn")
);
-
---
--- TOC Entry ID 10 (OID 3629402)
--
--- Name: author_ids Type: SEQUENCE Owner: manager
+-- --
+-- -- TOC Entry ID 10 (OID 3629402)
+-- --
+-- -- Name: author_ids Type: SEQUENCE Owner: manager
+-- --
--
-
CREATE SEQUENCE "author_ids" start 0 increment 1 maxvalue 2147483647 minvalue 0 cache 1 ;
-
---
--- TOC Entry ID 35 (OID 3629424)
--
--- Name: distinguished_authors Type: TABLE Owner: manager
+-- --
+-- -- TOC Entry ID 35 (OID 3629424)
+-- --
+-- -- Name: distinguished_authors Type: TABLE Owner: manager
+-- --
--
-
CREATE TABLE "distinguished_authors" (
"award" text
)
INHERITS ("authors");
-
--
--- TOC Entry ID 107 (OID 3726476)
---
--- Name: "isbn_to_title" (text) Type: FUNCTION Owner: manager
---
-
-CREATE FUNCTION "isbn_to_title" (text) RETURNS text AS 'SELECT title FROM books
- JOIN editions AS e (isbn, id)
- USING (id)
- WHERE isbn = $1' LANGUAGE 'sql';
-
+-- --
+-- -- TOC Entry ID 107 (OID 3726476)
+-- --
+-- -- Name: "isbn_to_title" (text) Type: FUNCTION Owner: manager
+-- --
--
--- TOC Entry ID 36 (OID 3727889)
+-- CREATE FUNCTION "isbn_to_title" (text) RETURNS text AS 'SELECT title FROM books
+-- JOIN editions AS e (isbn, id)
+-- USING (id)
+-- WHERE isbn = $1' LANGUAGE 'sql';
--
--- Name: favorite_authors Type: TABLE Owner: manager
+-- --
+-- -- TOC Entry ID 36 (OID 3727889)
+-- --
+-- -- Name: favorite_authors Type: TABLE Owner: manager
+-- --
--
-
CREATE TABLE "favorite_authors" (
"employee_id" integer,
"authors_and_titles" text[]
);
+-- --
+-- -- TOC Entry ID 99 (OID 3728728)
+-- --
+-- -- Name: "get_customer_name" (integer) Type: FUNCTION Owner: postgres
+-- --
--
--- TOC Entry ID 99 (OID 3728728)
---
--- Name: "get_customer_name" (integer) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "get_customer_name" (integer) RETURNS text AS '
- DECLARE
-
- -- Declare aliases for user input.
- customer_id ALIAS FOR $1;
-
- -- Declare variables to hold the customer name.
- customer_fname TEXT;
- customer_lname TEXT;
-
- BEGIN
-
- -- Retrieve the customer first and last name for the customer whose
- -- ID matches the value supplied as a function argument.
- SELECT INTO customer_fname, customer_lname
- first_name, last_name FROM customers
- WHERE id = customer_id;
-
- -- Return the name.
- RETURN customer_fname || '' '' || customer_lname;
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 100 (OID 3728729)
---
--- Name: "get_customer_id" (text,text) Type: FUNCTION Owner: postgres
+-- CREATE FUNCTION "get_customer_name" (integer) RETURNS text AS '
+-- DECLARE
--
-
-CREATE FUNCTION "get_customer_id" (text,text) RETURNS integer AS '
- DECLARE
-
- -- Declare aliases for user input.
- l_name ALIAS FOR $1;
- f_name ALIAS FOR $2;
-
- -- Declare a variable to hold the customer ID number.
- customer_id INTEGER;
-
- BEGIN
-
- -- Retrieve the customer ID number of the customer whose first and last
- -- name match the values supplied as function arguments.
- SELECT INTO customer_id id FROM customers
- WHERE last_name = l_name AND first_name = f_name;
-
- -- Return the ID number.
- RETURN customer_id;
- END;
-' LANGUAGE 'plpgsql';
-
+-- -- Declare aliases for user input.
+-- customer_id ALIAS FOR $1;
--
--- TOC Entry ID 101 (OID 3728730)
+-- -- Declare variables to hold the customer name.
+-- customer_fname TEXT;
+-- customer_lname TEXT;
--
--- Name: "get_author" (text) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "get_author" (text) RETURNS text AS '
- DECLARE
-
- -- Declare an alias for the function argument,
- -- which should be the first name of an author.
- f_name ALIAS FOR $1;
-
- -- Declare a variable with the same type as
- -- the last_name field of the authors table.
- l_name authors.last_name%TYPE;
-
- BEGIN
-
- -- Retrieve the last name of an author from the
- -- authors table whose first name matches the
- -- argument received by the function, and
- -- insert it into the l_name variable.
- SELECT INTO l_name last_name FROM authors WHERE first_name = f_name;
-
- -- Return the first name and last name, separated
- -- by a space.
- return f_name || '' '' || l_name;
-
- END;
-' LANGUAGE 'plpgsql';
-
+-- BEGIN
--
--- TOC Entry ID 97 (OID 3728759)
+-- -- Retrieve the customer first and last name for the customer whose
+-- -- ID matches the value supplied as a function argument.
+-- SELECT INTO customer_fname, customer_lname
+-- first_name, last_name FROM customers
+-- WHERE id = customer_id;
--
--- Name: "get_author" (integer) Type: FUNCTION Owner: postgres
+-- -- Return the name.
+-- RETURN customer_fname || '' '' || customer_lname;
+-- END;
+-- ' LANGUAGE 'plpgsql';
--
-
-CREATE FUNCTION "get_author" (integer) RETURNS text AS '
- DECLARE
-
- -- Declare an alias for the function argument,
- -- which should be the id of the author.
- author_id ALIAS FOR $1;
-
- -- Declare a variable that uses the structure of
- -- the authors table.
- found_author authors%ROWTYPE;
-
- BEGIN
-
- -- Retrieve a row of author information for
- -- the author whose id number matches
- -- the argument received by the function.
- SELECT INTO found_author * FROM authors WHERE id = author_id;
-
- -- Return the first
- RETURN found_author.first_name || '' '' || found_author.last_name;
-
- END;
-' LANGUAGE 'plpgsql';
-
---
--- TOC Entry ID 70 (OID 3743412)
---
--- Name: "html_linebreaks" (text) Type: FUNCTION Owner: postgres
---
-
-CREATE FUNCTION "html_linebreaks" (text) RETURNS text AS '
- DECLARE
- formatted_string text := '''';
- BEGIN
- FOR i IN 0 .. length($1) LOOP
- IF substr($1, i, 1) = ''
-'' THEN
- formatted_string := formatted_string || ''
'';
- ELSE
- formatted_string := formatted_string || substr($1, i, 1);
- END IF;
- END LOOP;
- RETURN formatted_string;
- END;
-' LANGUAGE 'plpgsql';
+-- --
+-- -- TOC Entry ID 100 (OID 3728729)
+-- --
+-- -- Name: "get_customer_id" (text,text) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "get_customer_id" (text,text) RETURNS integer AS '
+-- DECLARE
+--
+-- -- Declare aliases for user input.
+-- l_name ALIAS FOR $1;
+-- f_name ALIAS FOR $2;
+--
+-- -- Declare a variable to hold the customer ID number.
+-- customer_id INTEGER;
+--
+-- BEGIN
+--
+-- -- Retrieve the customer ID number of the customer whose first and last
+-- -- name match the values supplied as function arguments.
+-- SELECT INTO customer_id id FROM customers
+-- WHERE last_name = l_name AND first_name = f_name;
+--
+-- -- Return the ID number.
+-- RETURN customer_id;
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 101 (OID 3728730)
+-- --
+-- -- Name: "get_author" (text) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "get_author" (text) RETURNS text AS '
+-- DECLARE
+--
+-- -- Declare an alias for the function argument,
+-- -- which should be the first name of an author.
+-- f_name ALIAS FOR $1;
+--
+-- -- Declare a variable with the same type as
+-- -- the last_name field of the authors table.
+-- l_name authors.last_name%TYPE;
+--
+-- BEGIN
+--
+-- -- Retrieve the last name of an author from the
+-- -- authors table whose first name matches the
+-- -- argument received by the function, and
+-- -- insert it into the l_name variable.
+-- SELECT INTO l_name last_name FROM authors WHERE first_name = f_name;
+--
+-- -- Return the first name and last name, separated
+-- -- by a space.
+-- return f_name || '' '' || l_name;
+--
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 97 (OID 3728759)
+-- --
+-- -- Name: "get_author" (integer) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "get_author" (integer) RETURNS text AS '
+-- DECLARE
+--
+-- -- Declare an alias for the function argument,
+-- -- which should be the id of the author.
+-- author_id ALIAS FOR $1;
+--
+-- -- Declare a variable that uses the structure of
+-- -- the authors table.
+-- found_author authors%ROWTYPE;
+--
+-- BEGIN
+--
+-- -- Retrieve a row of author information for
+-- -- the author whose id number matches
+-- -- the argument received by the function.
+-- SELECT INTO found_author * FROM authors WHERE id = author_id;
+--
+-- -- Return the first
+-- RETURN found_author.first_name || '' '' || found_author.last_name;
+--
+-- END;
+-- ' LANGUAGE 'plpgsql';
+--
+-- --
+-- -- TOC Entry ID 70 (OID 3743412)
+-- --
+-- -- Name: "html_linebreaks" (text) Type: FUNCTION Owner: postgres
+-- --
+--
+-- CREATE FUNCTION "html_linebreaks" (text) RETURNS text AS '
+-- DECLARE
+-- formatted_string text := '''';
+-- BEGIN
+-- FOR i IN 0 .. length($1) LOOP
+-- IF substr($1, i, 1) = ''
+-- '' THEN
+-- formatted_string := formatted_string || ''
'';
+-- ELSE
+-- formatted_string := formatted_string || substr($1, i, 1);
+-- END IF;
+-- END LOOP;
+-- RETURN formatted_string;
+-- END;
+-- ' LANGUAGE 'plpgsql';
--
-- TOC Entry ID 37 (OID 3751599)
@@ -1191,7 +1191,7 @@ CREATE TABLE "subjects" (
-- Name: sum(text) Type: AGGREGATE Owner: postgres
--
-CREATE AGGREGATE sum ( BASETYPE = text, SFUNC = textcat, STYPE = text, INITCOND = '' );
+-- CREATE AGGREGATE sum ( BASETYPE = text, SFUNC = textcat, STYPE = text, INITCOND = '' );
--
-- TOC Entry ID 39 (OID 3751975)
@@ -1225,14 +1225,14 @@ CREATE TABLE "book_backup" (
-- Name: "sync_authors_and_books" () Type: FUNCTION Owner: postgres
--
-CREATE FUNCTION "sync_authors_and_books" () RETURNS opaque AS '
- BEGIN
- IF TG_OP = ''UPDATE'' THEN
- UPDATE books SET author_id = new.id WHERE author_id = old.id;
- END IF;
- RETURN new;
- END;
-' LANGUAGE 'plpgsql';
+-- CREATE FUNCTION "sync_authors_and_books" () RETURNS opaque AS '
+-- BEGIN
+-- IF TG_OP = ''UPDATE'' THEN
+-- UPDATE books SET author_id = new.id WHERE author_id = old.id;
+-- END IF;
+-- RETURN new;
+-- END;
+-- ' LANGUAGE 'plpgsql';
--
-- TOC Entry ID 41 (OID 4063343)
@@ -1251,8 +1251,8 @@ CREATE TABLE "schedules" (
--
-- Name: recent_shipments Type: VIEW Owner: postgres
--
-
-CREATE VIEW "recent_shipments" as SELECT count(*) AS num_shipped, max(shipments.ship_date) AS max, b.title FROM ((shipments JOIN editions USING (isbn)) NATURAL JOIN books b(book_id)) GROUP BY b.title ORDER BY count(*) DESC;
+--
+-- CREATE VIEW "recent_shipments" as SELECT count(*) AS num_shipped, max(shipments.ship_date) AS max, b.title FROM ((shipments JOIN editions USING (isbn)) NATURAL JOIN books b(book_id)) GROUP BY b.title ORDER BY count(*) DESC;
--
-- Data for TOC Entry ID 112 (OID 3117548)
@@ -1774,7 +1774,7 @@ CREATE INDEX "text_idx" on "text_sorting" using btree ( "letter" "bpchar_ops" )
-- Name: check_shipment Type: TRIGGER Owner: postgres
--
-CREATE TRIGGER "check_shipment" BEFORE INSERT OR UPDATE ON "shipments" FOR EACH ROW EXECUTE PROCEDURE "check_shipment_addition" ();
+-- CREATE TRIGGER "check_shipment" BEFORE INSERT OR UPDATE ON "shipments" FOR EACH ROW EXECUTE PROCEDURE "check_shipment_addition" ();
--
-- TOC Entry ID 135 (OID 3752103)
@@ -1782,15 +1782,15 @@ CREATE TRIGGER "check_shipment" BEFORE INSERT OR UPDATE ON "shipments" FOR EACH
-- Name: sync_authors_books Type: TRIGGER Owner: manager
--
-CREATE TRIGGER "sync_authors_books" BEFORE UPDATE ON "authors" FOR EACH ROW EXECUTE PROCEDURE "sync_authors_and_books" ();
+-- CREATE TRIGGER "sync_authors_books" BEFORE UPDATE ON "authors" FOR EACH ROW EXECUTE PROCEDURE "sync_authors_and_books" ();
--
-- TOC Entry ID 139 (OID 4063374)
--
-- Name: "RI_ConstraintTrigger_4063373" Type: TRIGGER Owner: postgres
--
-
-CREATE CONSTRAINT TRIGGER "valid_employee" AFTER INSERT OR UPDATE ON "schedules" FROM "employees" NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_check_ins" ('valid_employee', 'schedules', 'employees', 'FULL', 'employee_id', 'id');
+--
+-- CREATE CONSTRAINT TRIGGER "valid_employee" AFTER INSERT OR UPDATE ON "schedules" FROM "employees" NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_check_ins" ('valid_employee', 'schedules', 'employees', 'FULL', 'employee_id', 'id');
--
-- TOC Entry ID 137 (OID 4063376)
@@ -1798,7 +1798,7 @@ CREATE CONSTRAINT TRIGGER "valid_employee" AFTER INSERT OR UPDATE ON "schedules"
-- Name: "RI_ConstraintTrigger_4063375" Type: TRIGGER Owner: postgres
--
-CREATE CONSTRAINT TRIGGER "valid_employee" AFTER DELETE ON "employees" FROM "schedules" NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_noaction_del" ('valid_employee', 'schedules', 'employees', 'FULL', 'employee_id', 'id');
+-- CREATE CONSTRAINT TRIGGER "valid_employee" AFTER DELETE ON "employees" FROM "schedules" NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_noaction_del" ('valid_employee', 'schedules', 'employees', 'FULL', 'employee_id', 'id');
--
-- TOC Entry ID 138 (OID 4063378)
@@ -1806,7 +1806,7 @@ CREATE CONSTRAINT TRIGGER "valid_employee" AFTER DELETE ON "employees" FROM "sc
-- Name: "RI_ConstraintTrigger_4063377" Type: TRIGGER Owner: postgres
--
-CREATE CONSTRAINT TRIGGER "valid_employee" AFTER UPDATE ON "employees" FROM "schedules" NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_noaction_upd" ('valid_employee', 'schedules', 'employees', 'FULL', 'employee_id', 'id');
+-- CREATE CONSTRAINT TRIGGER "valid_employee" AFTER UPDATE ON "employees" FROM "schedules" NOT DEFERRABLE INITIALLY IMMEDIATE FOR EACH ROW EXECUTE PROCEDURE "RI_FKey_noaction_upd" ('valid_employee', 'schedules', 'employees', 'FULL', 'employee_id', 'id');
--
-- TOC Entry ID 140 (OID 3752079)
@@ -1821,15 +1821,15 @@ CREATE RULE sync_stock_with_editions AS ON UPDATE TO editions DO UPDATE stock SE
-- Name: subject_ids Type: SEQUENCE SET Owner:
--
-SELECT setval ('"subject_ids"', 15, 't');
+-- SELECT setval ('"subject_ids"', 15, 't');
--
-- TOC Entry ID 7 (OID 3574018)
--
-- Name: book_ids Type: SEQUENCE SET Owner:
--
-
-SELECT setval ('"book_ids"', 41478, 't');
+--
+-- SELECT setval ('"book_ids"', 41478, 't');
--
-- TOC Entry ID 9 (OID 3628626)