├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── binding.gyp ├── build.cljs ├── native ├── Cargo.lock ├── Cargo.toml ├── build.rs └── src │ └── lib.rs ├── package-lock.json ├── package.json └── src ├── dais.js ├── daisneon ├── bridge.cljs ├── dais.cljs └── example.cljs ├── index.js └── lib.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | # Project related 2 | 3 | # Java related 4 | pom.xml 5 | pom.xml.asc 6 | *jar 7 | *.class 8 | 9 | # Leiningen 10 | classes/ 11 | lib/ 12 | checkouts/ 13 | target/ 14 | .lein-* 15 | repl-port 16 | .nrepl-port 17 | .repl 18 | 19 | # Node / Neon 20 | native/target 21 | native/index.node 22 | native/artifacts.json 23 | node_modules/ 24 | 25 | # Temp Files 26 | *.orig 27 | *~ 28 | .*.swp 29 | .*.swo 30 | *.tmp 31 | *.bak 32 | 33 | # OS X 34 | .DS_Store 35 | 36 | # Logging 37 | *.log 38 | /logs/ 39 | 40 | # Builds 41 | out/ 42 | build/ 43 | 44 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2017, Paul deGrandis All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is furnished to do 11 | so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | SHELL := /usr/bin/env bash 3 | 4 | # This path is only accurate when calling with `make -f` directly 5 | # In a shell-wrap situation it resolves to the temp file descriptor 6 | MAKEFILE_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) 7 | 8 | RUN_ARGS := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS)) 9 | 10 | # Tools/Executables 11 | LUMO ?=lumo 12 | LUMO_BUILD_FILE ?=build.cljs 13 | NEON ?=neon 14 | NODE_GYP ?=node-gyp 15 | NPM ?=npm 16 | 17 | # Auxiliary Functions 18 | quiet = $(if $V, $1, @echo " $2"; $1) 19 | very-quiet = $(if $V, $1, @$1) 20 | 21 | #define cljscompilefn 22 | #$(shell $(LUMO) -c $1 $(LUMO_BUILD_FILE) $2) 23 | #endef 24 | 25 | ## TODO: Use vars/alias/functions from above for all build steps 26 | 27 | .DEFAULT_GOAL := local-install 28 | 29 | .PHONY : all 30 | all: local-install 31 | 32 | .PHONY : cljs-repl 33 | cljs-repl: 34 | npm run cljs-socketrepl 35 | 36 | .PHONY : cljs 37 | cljs: 38 | npm run compile-cljs 39 | 40 | .PHONY : rust 41 | rust: 42 | npm run compile-rust 43 | 44 | .PHONY : cpp 45 | cpp: 46 | npm run compile-cpp 47 | 48 | .PHONY : local-install 49 | local-install: 50 | npm install 51 | 52 | .PHONY : clean 53 | clean: 54 | rm -r ./build ./target ./native/target ./native/index.node 55 | 56 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Dais-Neon 3 | =========== 4 | 5 | Dais interceptor chain in Rust+Node.js with ClojureScript support. 6 | 7 | There is also C++ support via node-gyp and [Native Abstractions for Node.js](https://github.com/nodejs/nan). 8 | 9 | The Dais Interceptor Chain is a simple, synchronous-only interceptor chain, 10 | inspired by [Pedestal](https://github.com/pedestal/pedestal). 11 | [Dais](https://github.com/ohpauleez/dais) was first written in Java and 12 | designed to be used in Java and Clojure. 13 | 14 | 15 | ### Getting Started 16 | 17 | You can compile the Rust, C++, and ClojureScript with `npm install`. 18 | 19 | From there you can enter Node.js REPL with `node`: 20 | 21 | ``` 22 | $ node 23 | > const dais = require('.') 24 | > dais.hello() 25 | 'hello node - from JavaScript' 26 | > dais.hellorust() 27 | 'hello node - from Rust' 28 | > dais.hellocljs() 29 | 'hello node - from ClojureScript' 30 | > dais.hellocpp() 31 | 'hello node - from C++' 32 | ``` 33 | 34 | And you can also use the ClojureScript/Lumo REPL (without access to index.js) 35 | 36 | ``` 37 | $ make cljs-repl 38 | cljs.user=> (require '[daisneon.bridge :as bridge]) 39 | nil 40 | cljs.user=> (.hello bridge/rust) 41 | "hello node - from Rust" 42 | cljs.user=> (.Hello bridge/cpp) 43 | "hello node - from C++" 44 | ``` 45 | 46 | 47 | ### Hacking 48 | 49 | * This project uses `npm` for build tasks. 50 | For convenience, these are plumbed into a Makefile 51 | * The ClojureScript REPL has socketrepl support, all via Lumo 52 | * You may want to modify `target/main.js` and add `goog.require("daisneon.example");` 53 | if you're working at the node shell via index.js 54 | * You can directly require JS files from the CLJS REPL 55 | eg: `(require '[dais :as dais])` for JavaScript Dais chain 56 | 57 | 58 | ### Basic benchmarks 59 | 60 | This project is mostly about exploring the integration possibilities and 61 | understanding runtime overhead. The native code never migrates to typed arrays, 62 | it only does interop and works directly in the v8 types. 63 | 64 | "The machine code that V8 emits for your JS code can specialize and take 65 | shortcuts but every element Get/Set call in your [native] code goes through 66 | a lot of layers to implement the proper JS semantics." [see issue](https://github.com/nodejs/nan/issues/640) 67 | 68 | To see the general numbers, modify `target/main.js` and add `goog.require("daisneon.example");` 69 | Then you can examine chain executions: 70 | 71 | ``` 72 | $ node 73 | > const dais = require('.') 74 | > dais.testChains() 75 | ``` 76 | 77 | * rust: 0.073ms 78 | * Static processing only (no dynamic chains, and no error handling) 79 | * cpp: 0.042ms 80 | * Static processing only (no dynamic chains, and no error handling) 81 | * js: 0.051ms 82 | * cljs-static: 0.287ms 83 | * cljs: 0.346ms 84 | * cljs-js-interop: 1.737ms 85 | * Involves converting JS objects to maps and then back to objects at the end 86 | 87 | For reference, the Java Dais chain runs between 0.02ms - 0.20ms. 88 | The Pedestal Chain runs between 1-3ms. The Pedestal chain includes logging, 89 | runtime metrics, is thread-safe, and has full async capabilities 90 | (ie: it includes extra signaling and thread-pool migration) 91 | 92 | 93 | ### TODO 94 | 95 | * Consider adding Nan::TryCatch and tc.HasCaught() to the C++ code 96 | 97 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "include_dirs": [ 5 | ""] 5 | license = "MIT" 6 | build = "build.rs" 7 | 8 | [lib] 9 | name = "daisneon" 10 | crate-type = ["dylib"] 11 | 12 | [build-dependencies] 13 | neon-build = "0.1.20" 14 | 15 | [dependencies] 16 | neon = "0.1.20" 17 | itertools = "0.6.5" 18 | -------------------------------------------------------------------------------- /native/build.rs: -------------------------------------------------------------------------------- 1 | extern crate neon_build; 2 | 3 | fn main() { 4 | neon_build::setup(); // must be called in build.rs 5 | 6 | // add project-specific build logic here... 7 | } 8 | -------------------------------------------------------------------------------- /native/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate neon; 3 | extern crate itertools; 4 | 5 | use std::collections::VecDeque; 6 | use itertools::Itertools; 7 | use itertools::FoldWhile::{Continue, Done}; 8 | 9 | use neon::vm::{Call, JsResult}; 10 | use neon::js::{JsFunction, JsString, JsNumber, JsBoolean, JsNull, JsArray, JsObject, JsValue, Object}; 11 | use neon::mem::Handle; 12 | 13 | fn hello(call: Call) -> JsResult { 14 | let scope = call.scope; 15 | Ok(JsString::new(scope, "hello node - from Rust").unwrap()) 16 | } 17 | 18 | fn ret_obj(call: Call) -> JsResult { 19 | let scope = call.scope; 20 | let obj: Handle = JsObject::new(scope); 21 | obj.set("one", JsNumber::new(scope, 1_f64))?; 22 | Ok(obj) 23 | } 24 | 25 | fn basic_execute(call: Call) -> JsResult { 26 | let scope = call.scope; 27 | let context = call.arguments.require(scope, 0)?.check::()?; 28 | let mut stack : VecDeque> = VecDeque::new(); 29 | let mut did_terminate = false; 30 | let interceptors: Vec> = call.arguments.require(scope, 1)?.check::()?.to_vec(scope)?; 31 | let ectx = interceptors.iter() 32 | .fold_while(context, |ctx, interceptor| { 33 | let i: Handle = interceptor.downcast::().unwrap(); 34 | stack.push_front(i); 35 | // TODO: We need to do a `match` on enter_f in case the interceptor 36 | // doesn't have it 37 | let enter_f: Handle = i.get(scope, "enter").unwrap().downcast::().unwrap(); 38 | let new_ctx: Handle = enter_f.call(scope, JsNull::new(), vec![ctx]).unwrap().check::().unwrap(); 39 | let terminators: Vec> = ctx.get(scope, "dais.terminators").unwrap().check::().unwrap().to_vec(scope).unwrap(); 40 | let should_terminate = terminators.iter() 41 | .any(|term_val| { 42 | let terminator: Handle = term_val.downcast::().unwrap(); 43 | let term_res: Handle = terminator.call(scope, JsNull::new(), vec![ctx]).unwrap().check::().unwrap(); 44 | term_res.value()}); 45 | if should_terminate { did_terminate = true; Done(new_ctx) } else { Continue(new_ctx) }}).into_inner(); 46 | 47 | let final_ctx = if did_terminate { 48 | stack.iter() 49 | .fold(ectx, |ctx, interceptor| { 50 | let maybe_leave = interceptor.get(scope, "leave").unwrap().downcast::(); 51 | match maybe_leave { 52 | Some(leave_f) => leave_f.call(scope, JsNull::new(), vec![ctx]).unwrap().check::().unwrap(), 53 | None => ctx, 54 | }}) 55 | } else { ectx }; 56 | Ok(final_ctx) 57 | //Ok(if did_terminate { handle_leave(&call, &mut ctx, &stack) } else { ctx }) 58 | } 59 | 60 | register_module!(m, { 61 | m.export("hello", hello)?; 62 | m.export("returnObj", ret_obj)?; 63 | m.export("basicExecute", basic_execute)?; 64 | Ok(()) 65 | }); 66 | 67 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "daisneon", 3 | "version": "0.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "abbrev": { 8 | "version": "1.1.1", 9 | "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", 10 | "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" 11 | }, 12 | "ajv": { 13 | "version": "4.11.8", 14 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", 15 | "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", 16 | "requires": { 17 | "co": "4.6.0", 18 | "json-stable-stringify": "1.0.1" 19 | } 20 | }, 21 | "align-text": { 22 | "version": "0.1.4", 23 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 24 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 25 | "requires": { 26 | "kind-of": "3.2.2", 27 | "longest": "1.0.1", 28 | "repeat-string": "1.6.1" 29 | } 30 | }, 31 | "amdefine": { 32 | "version": "1.0.1", 33 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 34 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" 35 | }, 36 | "ansi-escape-sequences": { 37 | "version": "4.0.0", 38 | "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.0.0.tgz", 39 | "integrity": "sha512-v+0wW9Wezwsyb0uF4aBVCjmSqit3Ru7PZFziGF0o2KwTvN2zWfTi3BRLq9EkJFdg3eBbyERXGTntVpBxH1J68Q==", 40 | "requires": { 41 | "array-back": "2.0.0" 42 | } 43 | }, 44 | "ansi-escapes": { 45 | "version": "3.0.0", 46 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", 47 | "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==" 48 | }, 49 | "ansi-regex": { 50 | "version": "2.1.1", 51 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 52 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 53 | }, 54 | "ansi-styles": { 55 | "version": "2.2.1", 56 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 57 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 58 | }, 59 | "aproba": { 60 | "version": "1.2.0", 61 | "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", 62 | "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" 63 | }, 64 | "are-we-there-yet": { 65 | "version": "1.1.4", 66 | "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", 67 | "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", 68 | "requires": { 69 | "delegates": "1.0.0", 70 | "readable-stream": "2.3.3" 71 | } 72 | }, 73 | "array-back": { 74 | "version": "2.0.0", 75 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", 76 | "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", 77 | "requires": { 78 | "typical": "2.6.1" 79 | } 80 | }, 81 | "asn1": { 82 | "version": "0.2.3", 83 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", 84 | "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" 85 | }, 86 | "assert-plus": { 87 | "version": "0.2.0", 88 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", 89 | "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=" 90 | }, 91 | "async": { 92 | "version": "1.5.2", 93 | "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", 94 | "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" 95 | }, 96 | "asynckit": { 97 | "version": "0.4.0", 98 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 99 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 100 | }, 101 | "aws-sign2": { 102 | "version": "0.6.0", 103 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", 104 | "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=" 105 | }, 106 | "aws4": { 107 | "version": "1.6.0", 108 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", 109 | "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" 110 | }, 111 | "balanced-match": { 112 | "version": "1.0.0", 113 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 114 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 115 | }, 116 | "bcrypt-pbkdf": { 117 | "version": "1.0.1", 118 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", 119 | "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", 120 | "optional": true, 121 | "requires": { 122 | "tweetnacl": "0.14.5" 123 | } 124 | }, 125 | "block-stream": { 126 | "version": "0.0.9", 127 | "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", 128 | "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", 129 | "requires": { 130 | "inherits": "2.0.3" 131 | } 132 | }, 133 | "boom": { 134 | "version": "2.10.1", 135 | "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", 136 | "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", 137 | "requires": { 138 | "hoek": "2.16.3" 139 | } 140 | }, 141 | "brace-expansion": { 142 | "version": "1.1.8", 143 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 144 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 145 | "requires": { 146 | "balanced-match": "1.0.0", 147 | "concat-map": "0.0.1" 148 | } 149 | }, 150 | "builtins": { 151 | "version": "0.0.7", 152 | "resolved": "https://registry.npmjs.org/builtins/-/builtins-0.0.7.tgz", 153 | "integrity": "sha1-NVIZzWzxjb58Acx/0tznZc/cVJo=" 154 | }, 155 | "camelcase": { 156 | "version": "1.2.1", 157 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 158 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", 159 | "optional": true 160 | }, 161 | "caseless": { 162 | "version": "0.12.0", 163 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 164 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 165 | }, 166 | "center-align": { 167 | "version": "0.1.3", 168 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 169 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 170 | "optional": true, 171 | "requires": { 172 | "align-text": "0.1.4", 173 | "lazy-cache": "1.0.4" 174 | } 175 | }, 176 | "chalk": { 177 | "version": "1.1.3", 178 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 179 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 180 | "requires": { 181 | "ansi-styles": "2.2.1", 182 | "escape-string-regexp": "1.0.5", 183 | "has-ansi": "2.0.0", 184 | "strip-ansi": "3.0.1", 185 | "supports-color": "2.0.0" 186 | } 187 | }, 188 | "cli-cursor": { 189 | "version": "2.1.0", 190 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 191 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 192 | "requires": { 193 | "restore-cursor": "2.0.0" 194 | } 195 | }, 196 | "cli-width": { 197 | "version": "2.2.0", 198 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 199 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" 200 | }, 201 | "cliui": { 202 | "version": "2.1.0", 203 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 204 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 205 | "optional": true, 206 | "requires": { 207 | "center-align": "0.1.3", 208 | "right-align": "0.1.3", 209 | "wordwrap": "0.0.2" 210 | }, 211 | "dependencies": { 212 | "wordwrap": { 213 | "version": "0.0.2", 214 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 215 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", 216 | "optional": true 217 | } 218 | } 219 | }, 220 | "co": { 221 | "version": "4.6.0", 222 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 223 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" 224 | }, 225 | "code-point-at": { 226 | "version": "1.1.0", 227 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 228 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" 229 | }, 230 | "color-convert": { 231 | "version": "1.9.0", 232 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", 233 | "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", 234 | "requires": { 235 | "color-name": "1.1.3" 236 | } 237 | }, 238 | "color-name": { 239 | "version": "1.1.3", 240 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 241 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 242 | }, 243 | "combined-stream": { 244 | "version": "1.0.5", 245 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", 246 | "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", 247 | "requires": { 248 | "delayed-stream": "1.0.0" 249 | } 250 | }, 251 | "command-line-args": { 252 | "version": "4.0.7", 253 | "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-4.0.7.tgz", 254 | "integrity": "sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA==", 255 | "requires": { 256 | "array-back": "2.0.0", 257 | "find-replace": "1.0.3", 258 | "typical": "2.6.1" 259 | } 260 | }, 261 | "command-line-commands": { 262 | "version": "2.0.1", 263 | "resolved": "https://registry.npmjs.org/command-line-commands/-/command-line-commands-2.0.1.tgz", 264 | "integrity": "sha512-m8c2p1DrNd2ruIAggxd/y6DgygQayf6r8RHwchhXryaLF8I6koYjoYroVP+emeROE9DXN5b9sP1Gh+WtvTTdtQ==", 265 | "requires": { 266 | "array-back": "2.0.0" 267 | } 268 | }, 269 | "command-line-usage": { 270 | "version": "4.0.1", 271 | "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.0.1.tgz", 272 | "integrity": "sha512-IqYzZuXizukrdhnbdUj2hh4iceycow+Jn10mER4lwU4IapYvl5ZzoRPsj5Yraew5oRk4yfFKMuULGvAfb5o29w==", 273 | "requires": { 274 | "ansi-escape-sequences": "4.0.0", 275 | "array-back": "2.0.0", 276 | "table-layout": "0.4.2", 277 | "typical": "2.6.1" 278 | } 279 | }, 280 | "concat-map": { 281 | "version": "0.0.1", 282 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 283 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 284 | }, 285 | "console-control-strings": { 286 | "version": "1.1.0", 287 | "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", 288 | "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" 289 | }, 290 | "core-util-is": { 291 | "version": "1.0.2", 292 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 293 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 294 | }, 295 | "cryptiles": { 296 | "version": "2.0.5", 297 | "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", 298 | "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", 299 | "requires": { 300 | "boom": "2.10.1" 301 | } 302 | }, 303 | "dashdash": { 304 | "version": "1.14.1", 305 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 306 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 307 | "requires": { 308 | "assert-plus": "1.0.0" 309 | }, 310 | "dependencies": { 311 | "assert-plus": { 312 | "version": "1.0.0", 313 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 314 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 315 | } 316 | } 317 | }, 318 | "decamelize": { 319 | "version": "1.2.0", 320 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 321 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 322 | "optional": true 323 | }, 324 | "deep-extend": { 325 | "version": "0.5.0", 326 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.0.tgz", 327 | "integrity": "sha1-bvSgmwX5iw41jW2T1Mo8rsZnKAM=" 328 | }, 329 | "delayed-stream": { 330 | "version": "1.0.0", 331 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 332 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 333 | }, 334 | "delegates": { 335 | "version": "1.0.0", 336 | "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", 337 | "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" 338 | }, 339 | "ecc-jsbn": { 340 | "version": "0.1.1", 341 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", 342 | "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", 343 | "optional": true, 344 | "requires": { 345 | "jsbn": "0.1.1" 346 | } 347 | }, 348 | "escape-string-regexp": { 349 | "version": "1.0.5", 350 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 351 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 352 | }, 353 | "extend": { 354 | "version": "3.0.1", 355 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", 356 | "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" 357 | }, 358 | "external-editor": { 359 | "version": "2.0.5", 360 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.5.tgz", 361 | "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==", 362 | "requires": { 363 | "iconv-lite": "0.4.19", 364 | "jschardet": "1.5.1", 365 | "tmp": "0.0.33" 366 | } 367 | }, 368 | "extsprintf": { 369 | "version": "1.3.0", 370 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 371 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 372 | }, 373 | "figures": { 374 | "version": "2.0.0", 375 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 376 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 377 | "requires": { 378 | "escape-string-regexp": "1.0.5" 379 | } 380 | }, 381 | "find-replace": { 382 | "version": "1.0.3", 383 | "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-1.0.3.tgz", 384 | "integrity": "sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A=", 385 | "requires": { 386 | "array-back": "1.0.4", 387 | "test-value": "2.1.0" 388 | }, 389 | "dependencies": { 390 | "array-back": { 391 | "version": "1.0.4", 392 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", 393 | "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", 394 | "requires": { 395 | "typical": "2.6.1" 396 | } 397 | } 398 | } 399 | }, 400 | "forever-agent": { 401 | "version": "0.6.1", 402 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 403 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 404 | }, 405 | "form-data": { 406 | "version": "2.1.4", 407 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", 408 | "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", 409 | "requires": { 410 | "asynckit": "0.4.0", 411 | "combined-stream": "1.0.5", 412 | "mime-types": "2.1.17" 413 | } 414 | }, 415 | "fs.realpath": { 416 | "version": "1.0.0", 417 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 418 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 419 | }, 420 | "fstream": { 421 | "version": "1.0.11", 422 | "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", 423 | "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", 424 | "requires": { 425 | "graceful-fs": "4.1.11", 426 | "inherits": "2.0.3", 427 | "mkdirp": "0.5.1", 428 | "rimraf": "2.6.2" 429 | } 430 | }, 431 | "gauge": { 432 | "version": "2.7.4", 433 | "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", 434 | "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", 435 | "requires": { 436 | "aproba": "1.2.0", 437 | "console-control-strings": "1.1.0", 438 | "has-unicode": "2.0.1", 439 | "object-assign": "4.1.1", 440 | "signal-exit": "3.0.2", 441 | "string-width": "1.0.2", 442 | "strip-ansi": "3.0.1", 443 | "wide-align": "1.1.2" 444 | }, 445 | "dependencies": { 446 | "is-fullwidth-code-point": { 447 | "version": "1.0.0", 448 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 449 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 450 | "requires": { 451 | "number-is-nan": "1.0.1" 452 | } 453 | }, 454 | "string-width": { 455 | "version": "1.0.2", 456 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 457 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 458 | "requires": { 459 | "code-point-at": "1.1.0", 460 | "is-fullwidth-code-point": "1.0.0", 461 | "strip-ansi": "3.0.1" 462 | } 463 | } 464 | } 465 | }, 466 | "getpass": { 467 | "version": "0.1.7", 468 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 469 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 470 | "requires": { 471 | "assert-plus": "1.0.0" 472 | }, 473 | "dependencies": { 474 | "assert-plus": { 475 | "version": "1.0.0", 476 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 477 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 478 | } 479 | } 480 | }, 481 | "git-config": { 482 | "version": "0.0.7", 483 | "resolved": "https://registry.npmjs.org/git-config/-/git-config-0.0.7.tgz", 484 | "integrity": "sha1-qcij7wendsPXImE1bYtye2IgKyg=", 485 | "requires": { 486 | "iniparser": "1.0.5" 487 | } 488 | }, 489 | "glob": { 490 | "version": "7.1.2", 491 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 492 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 493 | "requires": { 494 | "fs.realpath": "1.0.0", 495 | "inflight": "1.0.6", 496 | "inherits": "2.0.3", 497 | "minimatch": "3.0.4", 498 | "once": "1.4.0", 499 | "path-is-absolute": "1.0.1" 500 | } 501 | }, 502 | "graceful-fs": { 503 | "version": "4.1.11", 504 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 505 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" 506 | }, 507 | "handlebars": { 508 | "version": "4.0.10", 509 | "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", 510 | "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", 511 | "requires": { 512 | "async": "1.5.2", 513 | "optimist": "0.6.1", 514 | "source-map": "0.4.4", 515 | "uglify-js": "2.8.29" 516 | } 517 | }, 518 | "har-schema": { 519 | "version": "1.0.5", 520 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", 521 | "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=" 522 | }, 523 | "har-validator": { 524 | "version": "4.2.1", 525 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", 526 | "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", 527 | "requires": { 528 | "ajv": "4.11.8", 529 | "har-schema": "1.0.5" 530 | } 531 | }, 532 | "has-ansi": { 533 | "version": "2.0.0", 534 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 535 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 536 | "requires": { 537 | "ansi-regex": "2.1.1" 538 | } 539 | }, 540 | "has-flag": { 541 | "version": "2.0.0", 542 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", 543 | "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" 544 | }, 545 | "has-unicode": { 546 | "version": "2.0.1", 547 | "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", 548 | "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" 549 | }, 550 | "hawk": { 551 | "version": "3.1.3", 552 | "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", 553 | "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", 554 | "requires": { 555 | "boom": "2.10.1", 556 | "cryptiles": "2.0.5", 557 | "hoek": "2.16.3", 558 | "sntp": "1.0.9" 559 | } 560 | }, 561 | "hoek": { 562 | "version": "2.16.3", 563 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", 564 | "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" 565 | }, 566 | "http-signature": { 567 | "version": "1.1.1", 568 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", 569 | "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", 570 | "requires": { 571 | "assert-plus": "0.2.0", 572 | "jsprim": "1.4.1", 573 | "sshpk": "1.13.1" 574 | } 575 | }, 576 | "iconv-lite": { 577 | "version": "0.4.19", 578 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 579 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 580 | }, 581 | "in-publish": { 582 | "version": "2.0.0", 583 | "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", 584 | "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=" 585 | }, 586 | "inflight": { 587 | "version": "1.0.6", 588 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 589 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 590 | "requires": { 591 | "once": "1.4.0", 592 | "wrappy": "1.0.2" 593 | } 594 | }, 595 | "inherits": { 596 | "version": "2.0.3", 597 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 598 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 599 | }, 600 | "iniparser": { 601 | "version": "1.0.5", 602 | "resolved": "https://registry.npmjs.org/iniparser/-/iniparser-1.0.5.tgz", 603 | "integrity": "sha1-g21r7+bfv87gvM8c+fKsxwJ/eD0=" 604 | }, 605 | "inquirer": { 606 | "version": "3.3.0", 607 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", 608 | "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", 609 | "requires": { 610 | "ansi-escapes": "3.0.0", 611 | "chalk": "2.1.0", 612 | "cli-cursor": "2.1.0", 613 | "cli-width": "2.2.0", 614 | "external-editor": "2.0.5", 615 | "figures": "2.0.0", 616 | "lodash": "4.17.4", 617 | "mute-stream": "0.0.7", 618 | "run-async": "2.3.0", 619 | "rx-lite": "4.0.8", 620 | "rx-lite-aggregates": "4.0.8", 621 | "string-width": "2.1.1", 622 | "strip-ansi": "4.0.0", 623 | "through": "2.3.8" 624 | }, 625 | "dependencies": { 626 | "ansi-regex": { 627 | "version": "3.0.0", 628 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 629 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 630 | }, 631 | "ansi-styles": { 632 | "version": "3.2.0", 633 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", 634 | "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", 635 | "requires": { 636 | "color-convert": "1.9.0" 637 | } 638 | }, 639 | "chalk": { 640 | "version": "2.1.0", 641 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", 642 | "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", 643 | "requires": { 644 | "ansi-styles": "3.2.0", 645 | "escape-string-regexp": "1.0.5", 646 | "supports-color": "4.4.0" 647 | } 648 | }, 649 | "strip-ansi": { 650 | "version": "4.0.0", 651 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 652 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 653 | "requires": { 654 | "ansi-regex": "3.0.0" 655 | } 656 | }, 657 | "supports-color": { 658 | "version": "4.4.0", 659 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", 660 | "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", 661 | "requires": { 662 | "has-flag": "2.0.0" 663 | } 664 | } 665 | } 666 | }, 667 | "is-buffer": { 668 | "version": "1.1.5", 669 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", 670 | "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" 671 | }, 672 | "is-fullwidth-code-point": { 673 | "version": "2.0.0", 674 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 675 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 676 | }, 677 | "is-promise": { 678 | "version": "2.1.0", 679 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 680 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 681 | }, 682 | "is-typedarray": { 683 | "version": "1.0.0", 684 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 685 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 686 | }, 687 | "isarray": { 688 | "version": "1.0.0", 689 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 690 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 691 | }, 692 | "isexe": { 693 | "version": "2.0.0", 694 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 695 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" 696 | }, 697 | "isstream": { 698 | "version": "0.1.2", 699 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 700 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 701 | }, 702 | "jsbn": { 703 | "version": "0.1.1", 704 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 705 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", 706 | "optional": true 707 | }, 708 | "jschardet": { 709 | "version": "1.5.1", 710 | "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.5.1.tgz", 711 | "integrity": "sha512-vE2hT1D0HLZCLLclfBSfkfTTedhVj0fubHpJBHKwwUWX0nSbhPAfk+SG9rTX95BYNmau8rGFfCeaT6T5OW1C2A==" 712 | }, 713 | "json-schema": { 714 | "version": "0.2.3", 715 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 716 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 717 | }, 718 | "json-stable-stringify": { 719 | "version": "1.0.1", 720 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", 721 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", 722 | "requires": { 723 | "jsonify": "0.0.0" 724 | } 725 | }, 726 | "json-stringify-safe": { 727 | "version": "5.0.1", 728 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 729 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 730 | }, 731 | "jsonify": { 732 | "version": "0.0.0", 733 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 734 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" 735 | }, 736 | "jsprim": { 737 | "version": "1.4.1", 738 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 739 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 740 | "requires": { 741 | "assert-plus": "1.0.0", 742 | "extsprintf": "1.3.0", 743 | "json-schema": "0.2.3", 744 | "verror": "1.10.0" 745 | }, 746 | "dependencies": { 747 | "assert-plus": { 748 | "version": "1.0.0", 749 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 750 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 751 | } 752 | } 753 | }, 754 | "jszip": { 755 | "version": "2.6.1", 756 | "resolved": "https://registry.npmjs.org/jszip/-/jszip-2.6.1.tgz", 757 | "integrity": "sha1-uI86ey5noqBIFSmCx6N1bZxIKPA=", 758 | "requires": { 759 | "pako": "1.0.6" 760 | } 761 | }, 762 | "kind-of": { 763 | "version": "3.2.2", 764 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 765 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 766 | "requires": { 767 | "is-buffer": "1.1.5" 768 | } 769 | }, 770 | "lazy-cache": { 771 | "version": "1.0.4", 772 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 773 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", 774 | "optional": true 775 | }, 776 | "lodash": { 777 | "version": "4.17.4", 778 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 779 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" 780 | }, 781 | "lodash.padend": { 782 | "version": "4.6.1", 783 | "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", 784 | "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" 785 | }, 786 | "longest": { 787 | "version": "1.0.1", 788 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 789 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" 790 | }, 791 | "lumo-cljs": { 792 | "version": "1.8.0-beta", 793 | "resolved": "https://registry.npmjs.org/lumo-cljs/-/lumo-cljs-1.8.0-beta.tgz", 794 | "integrity": "sha512-Boq/ht7lt5M44wsXXzqegyp11qKf+3gzGRacO3BR2RY5ciTp2FWrSXIHgybzGiGNxXnPLpM2EANhBgsK29TyUQ==", 795 | "requires": { 796 | "jszip": "2.6.1", 797 | "progress": "2.0.0", 798 | "request": "2.81.0" 799 | } 800 | }, 801 | "mime-db": { 802 | "version": "1.30.0", 803 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", 804 | "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" 805 | }, 806 | "mime-types": { 807 | "version": "2.1.17", 808 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", 809 | "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", 810 | "requires": { 811 | "mime-db": "1.30.0" 812 | } 813 | }, 814 | "mimic-fn": { 815 | "version": "1.1.0", 816 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", 817 | "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=" 818 | }, 819 | "minimatch": { 820 | "version": "3.0.4", 821 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 822 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 823 | "requires": { 824 | "brace-expansion": "1.1.8" 825 | } 826 | }, 827 | "minimist": { 828 | "version": "0.0.10", 829 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", 830 | "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=" 831 | }, 832 | "mkdirp": { 833 | "version": "0.5.1", 834 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 835 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 836 | "requires": { 837 | "minimist": "0.0.8" 838 | }, 839 | "dependencies": { 840 | "minimist": { 841 | "version": "0.0.8", 842 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 843 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 844 | } 845 | } 846 | }, 847 | "mute-stream": { 848 | "version": "0.0.7", 849 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 850 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" 851 | }, 852 | "nan": { 853 | "version": "2.7.0", 854 | "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", 855 | "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" 856 | }, 857 | "neon-cli": { 858 | "version": "0.1.20", 859 | "resolved": "https://registry.npmjs.org/neon-cli/-/neon-cli-0.1.20.tgz", 860 | "integrity": "sha512-ecQlBX/Ozv2xu8y/GQNpDOfB2lEHpAJYilcQG8U2H2aqGGVrf/AnoyYLadXyXoFx+hdDpaGpAQIio465+Xklqg==", 861 | "requires": { 862 | "chalk": "1.1.3", 863 | "command-line-args": "4.0.7", 864 | "command-line-commands": "2.0.1", 865 | "command-line-usage": "4.0.1", 866 | "git-config": "0.0.7", 867 | "handlebars": "4.0.10", 868 | "in-publish": "2.0.0", 869 | "inquirer": "3.3.0", 870 | "mkdirp": "0.5.1", 871 | "quickly-copy-file": "1.0.0", 872 | "rimraf": "2.6.2", 873 | "rsvp": "3.6.2", 874 | "semver": "5.4.1", 875 | "toml": "2.3.3", 876 | "ts-typed-json": "0.2.2", 877 | "validate-npm-package-license": "3.0.1", 878 | "validate-npm-package-name": "2.2.2" 879 | } 880 | }, 881 | "node-gyp": { 882 | "version": "3.6.2", 883 | "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", 884 | "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", 885 | "requires": { 886 | "fstream": "1.0.11", 887 | "glob": "7.1.2", 888 | "graceful-fs": "4.1.11", 889 | "minimatch": "3.0.4", 890 | "mkdirp": "0.5.1", 891 | "nopt": "3.0.6", 892 | "npmlog": "4.1.2", 893 | "osenv": "0.1.4", 894 | "request": "2.81.0", 895 | "rimraf": "2.6.2", 896 | "semver": "5.3.0", 897 | "tar": "2.2.1", 898 | "which": "1.3.0" 899 | }, 900 | "dependencies": { 901 | "semver": { 902 | "version": "5.3.0", 903 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", 904 | "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" 905 | } 906 | } 907 | }, 908 | "nopt": { 909 | "version": "3.0.6", 910 | "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", 911 | "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", 912 | "requires": { 913 | "abbrev": "1.1.1" 914 | } 915 | }, 916 | "npmlog": { 917 | "version": "4.1.2", 918 | "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", 919 | "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", 920 | "requires": { 921 | "are-we-there-yet": "1.1.4", 922 | "console-control-strings": "1.1.0", 923 | "gauge": "2.7.4", 924 | "set-blocking": "2.0.0" 925 | } 926 | }, 927 | "number-is-nan": { 928 | "version": "1.0.1", 929 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 930 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" 931 | }, 932 | "oauth-sign": { 933 | "version": "0.8.2", 934 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", 935 | "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" 936 | }, 937 | "object-assign": { 938 | "version": "4.1.1", 939 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 940 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 941 | }, 942 | "once": { 943 | "version": "1.4.0", 944 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 945 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 946 | "requires": { 947 | "wrappy": "1.0.2" 948 | } 949 | }, 950 | "onetime": { 951 | "version": "2.0.1", 952 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 953 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 954 | "requires": { 955 | "mimic-fn": "1.1.0" 956 | } 957 | }, 958 | "optimist": { 959 | "version": "0.6.1", 960 | "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", 961 | "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", 962 | "requires": { 963 | "minimist": "0.0.10", 964 | "wordwrap": "0.0.3" 965 | } 966 | }, 967 | "os-homedir": { 968 | "version": "1.0.2", 969 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 970 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" 971 | }, 972 | "os-tmpdir": { 973 | "version": "1.0.2", 974 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 975 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 976 | }, 977 | "osenv": { 978 | "version": "0.1.4", 979 | "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", 980 | "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", 981 | "requires": { 982 | "os-homedir": "1.0.2", 983 | "os-tmpdir": "1.0.2" 984 | } 985 | }, 986 | "pako": { 987 | "version": "1.0.6", 988 | "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", 989 | "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" 990 | }, 991 | "path-is-absolute": { 992 | "version": "1.0.1", 993 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 994 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 995 | }, 996 | "performance-now": { 997 | "version": "0.2.0", 998 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", 999 | "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=" 1000 | }, 1001 | "process-nextick-args": { 1002 | "version": "1.0.7", 1003 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 1004 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 1005 | }, 1006 | "progress": { 1007 | "version": "2.0.0", 1008 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", 1009 | "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=" 1010 | }, 1011 | "punycode": { 1012 | "version": "1.4.1", 1013 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1014 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1015 | }, 1016 | "qs": { 1017 | "version": "6.4.0", 1018 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", 1019 | "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" 1020 | }, 1021 | "quickly-copy-file": { 1022 | "version": "1.0.0", 1023 | "resolved": "https://registry.npmjs.org/quickly-copy-file/-/quickly-copy-file-1.0.0.tgz", 1024 | "integrity": "sha1-n4/wZiMFEO50IrASFHKwk6hpCFk=", 1025 | "requires": { 1026 | "mkdirp": "0.5.1" 1027 | } 1028 | }, 1029 | "readable-stream": { 1030 | "version": "2.3.3", 1031 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", 1032 | "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", 1033 | "requires": { 1034 | "core-util-is": "1.0.2", 1035 | "inherits": "2.0.3", 1036 | "isarray": "1.0.0", 1037 | "process-nextick-args": "1.0.7", 1038 | "safe-buffer": "5.1.1", 1039 | "string_decoder": "1.0.3", 1040 | "util-deprecate": "1.0.2" 1041 | } 1042 | }, 1043 | "reduce-flatten": { 1044 | "version": "1.0.1", 1045 | "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", 1046 | "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=" 1047 | }, 1048 | "repeat-string": { 1049 | "version": "1.6.1", 1050 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 1051 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" 1052 | }, 1053 | "request": { 1054 | "version": "2.81.0", 1055 | "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", 1056 | "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", 1057 | "requires": { 1058 | "aws-sign2": "0.6.0", 1059 | "aws4": "1.6.0", 1060 | "caseless": "0.12.0", 1061 | "combined-stream": "1.0.5", 1062 | "extend": "3.0.1", 1063 | "forever-agent": "0.6.1", 1064 | "form-data": "2.1.4", 1065 | "har-validator": "4.2.1", 1066 | "hawk": "3.1.3", 1067 | "http-signature": "1.1.1", 1068 | "is-typedarray": "1.0.0", 1069 | "isstream": "0.1.2", 1070 | "json-stringify-safe": "5.0.1", 1071 | "mime-types": "2.1.17", 1072 | "oauth-sign": "0.8.2", 1073 | "performance-now": "0.2.0", 1074 | "qs": "6.4.0", 1075 | "safe-buffer": "5.1.1", 1076 | "stringstream": "0.0.5", 1077 | "tough-cookie": "2.3.3", 1078 | "tunnel-agent": "0.6.0", 1079 | "uuid": "3.1.0" 1080 | } 1081 | }, 1082 | "restore-cursor": { 1083 | "version": "2.0.0", 1084 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 1085 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 1086 | "requires": { 1087 | "onetime": "2.0.1", 1088 | "signal-exit": "3.0.2" 1089 | } 1090 | }, 1091 | "right-align": { 1092 | "version": "0.1.3", 1093 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 1094 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 1095 | "optional": true, 1096 | "requires": { 1097 | "align-text": "0.1.4" 1098 | } 1099 | }, 1100 | "rimraf": { 1101 | "version": "2.6.2", 1102 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", 1103 | "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", 1104 | "requires": { 1105 | "glob": "7.1.2" 1106 | } 1107 | }, 1108 | "rsvp": { 1109 | "version": "3.6.2", 1110 | "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz", 1111 | "integrity": "sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw==" 1112 | }, 1113 | "run-async": { 1114 | "version": "2.3.0", 1115 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 1116 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 1117 | "requires": { 1118 | "is-promise": "2.1.0" 1119 | } 1120 | }, 1121 | "rx-lite": { 1122 | "version": "4.0.8", 1123 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", 1124 | "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=" 1125 | }, 1126 | "rx-lite-aggregates": { 1127 | "version": "4.0.8", 1128 | "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", 1129 | "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", 1130 | "requires": { 1131 | "rx-lite": "4.0.8" 1132 | } 1133 | }, 1134 | "safe-buffer": { 1135 | "version": "5.1.1", 1136 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 1137 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" 1138 | }, 1139 | "semver": { 1140 | "version": "5.4.1", 1141 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", 1142 | "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" 1143 | }, 1144 | "set-blocking": { 1145 | "version": "2.0.0", 1146 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1147 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" 1148 | }, 1149 | "signal-exit": { 1150 | "version": "3.0.2", 1151 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1152 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 1153 | }, 1154 | "sntp": { 1155 | "version": "1.0.9", 1156 | "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", 1157 | "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", 1158 | "requires": { 1159 | "hoek": "2.16.3" 1160 | } 1161 | }, 1162 | "source-map": { 1163 | "version": "0.4.4", 1164 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", 1165 | "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", 1166 | "requires": { 1167 | "amdefine": "1.0.1" 1168 | } 1169 | }, 1170 | "source-map-support": { 1171 | "version": "0.4.18", 1172 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", 1173 | "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", 1174 | "requires": { 1175 | "source-map": "0.5.7" 1176 | }, 1177 | "dependencies": { 1178 | "source-map": { 1179 | "version": "0.5.7", 1180 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1181 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 1182 | } 1183 | } 1184 | }, 1185 | "spdx-correct": { 1186 | "version": "1.0.2", 1187 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", 1188 | "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", 1189 | "requires": { 1190 | "spdx-license-ids": "1.2.2" 1191 | } 1192 | }, 1193 | "spdx-expression-parse": { 1194 | "version": "1.0.4", 1195 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", 1196 | "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" 1197 | }, 1198 | "spdx-license-ids": { 1199 | "version": "1.2.2", 1200 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", 1201 | "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" 1202 | }, 1203 | "sshpk": { 1204 | "version": "1.13.1", 1205 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", 1206 | "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", 1207 | "requires": { 1208 | "asn1": "0.2.3", 1209 | "assert-plus": "1.0.0", 1210 | "bcrypt-pbkdf": "1.0.1", 1211 | "dashdash": "1.14.1", 1212 | "ecc-jsbn": "0.1.1", 1213 | "getpass": "0.1.7", 1214 | "jsbn": "0.1.1", 1215 | "tweetnacl": "0.14.5" 1216 | }, 1217 | "dependencies": { 1218 | "assert-plus": { 1219 | "version": "1.0.0", 1220 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 1221 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 1222 | } 1223 | } 1224 | }, 1225 | "string_decoder": { 1226 | "version": "1.0.3", 1227 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 1228 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 1229 | "requires": { 1230 | "safe-buffer": "5.1.1" 1231 | } 1232 | }, 1233 | "string-width": { 1234 | "version": "2.1.1", 1235 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1236 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1237 | "requires": { 1238 | "is-fullwidth-code-point": "2.0.0", 1239 | "strip-ansi": "4.0.0" 1240 | }, 1241 | "dependencies": { 1242 | "ansi-regex": { 1243 | "version": "3.0.0", 1244 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 1245 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 1246 | }, 1247 | "strip-ansi": { 1248 | "version": "4.0.0", 1249 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1250 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1251 | "requires": { 1252 | "ansi-regex": "3.0.0" 1253 | } 1254 | } 1255 | } 1256 | }, 1257 | "stringstream": { 1258 | "version": "0.0.5", 1259 | "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", 1260 | "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" 1261 | }, 1262 | "strip-ansi": { 1263 | "version": "3.0.1", 1264 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1265 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1266 | "requires": { 1267 | "ansi-regex": "2.1.1" 1268 | } 1269 | }, 1270 | "supports-color": { 1271 | "version": "2.0.0", 1272 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1273 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 1274 | }, 1275 | "table-layout": { 1276 | "version": "0.4.2", 1277 | "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.2.tgz", 1278 | "integrity": "sha512-tygyl5+eSHj4chpq5Zfy6cpc7MOUBClAW9ozghFH7hg9bAUzShOYn+/vUzTRkKOSLJWKfgYtP2tAU2c0oAD8eg==", 1279 | "requires": { 1280 | "array-back": "2.0.0", 1281 | "deep-extend": "0.5.0", 1282 | "lodash.padend": "4.6.1", 1283 | "typical": "2.6.1", 1284 | "wordwrapjs": "3.0.0" 1285 | } 1286 | }, 1287 | "tar": { 1288 | "version": "2.2.1", 1289 | "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", 1290 | "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", 1291 | "requires": { 1292 | "block-stream": "0.0.9", 1293 | "fstream": "1.0.11", 1294 | "inherits": "2.0.3" 1295 | } 1296 | }, 1297 | "test-value": { 1298 | "version": "2.1.0", 1299 | "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", 1300 | "integrity": "sha1-Edpv9nDzRxpztiXKTz/c97t0gpE=", 1301 | "requires": { 1302 | "array-back": "1.0.4", 1303 | "typical": "2.6.1" 1304 | }, 1305 | "dependencies": { 1306 | "array-back": { 1307 | "version": "1.0.4", 1308 | "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", 1309 | "integrity": "sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs=", 1310 | "requires": { 1311 | "typical": "2.6.1" 1312 | } 1313 | } 1314 | } 1315 | }, 1316 | "through": { 1317 | "version": "2.3.8", 1318 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1319 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 1320 | }, 1321 | "tmp": { 1322 | "version": "0.0.33", 1323 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1324 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1325 | "requires": { 1326 | "os-tmpdir": "1.0.2" 1327 | } 1328 | }, 1329 | "toml": { 1330 | "version": "2.3.3", 1331 | "resolved": "https://registry.npmjs.org/toml/-/toml-2.3.3.tgz", 1332 | "integrity": "sha512-O7L5hhSQHxuufWUdcTRPfuTh3phKfAZ/dqfxZFoxPCj2RYmpaSGLEIs016FCXItQwNr08yefUB5TSjzRYnajTA==" 1333 | }, 1334 | "tough-cookie": { 1335 | "version": "2.3.3", 1336 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", 1337 | "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", 1338 | "requires": { 1339 | "punycode": "1.4.1" 1340 | } 1341 | }, 1342 | "ts-typed-json": { 1343 | "version": "0.2.2", 1344 | "resolved": "https://registry.npmjs.org/ts-typed-json/-/ts-typed-json-0.2.2.tgz", 1345 | "integrity": "sha1-UxhL7ok+RZkbc8jEY6OLWeJ81H4=", 1346 | "requires": { 1347 | "rsvp": "3.6.2" 1348 | } 1349 | }, 1350 | "tunnel-agent": { 1351 | "version": "0.6.0", 1352 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1353 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1354 | "requires": { 1355 | "safe-buffer": "5.1.1" 1356 | } 1357 | }, 1358 | "tweetnacl": { 1359 | "version": "0.14.5", 1360 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1361 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", 1362 | "optional": true 1363 | }, 1364 | "typical": { 1365 | "version": "2.6.1", 1366 | "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", 1367 | "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" 1368 | }, 1369 | "uglify-js": { 1370 | "version": "2.8.29", 1371 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 1372 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 1373 | "optional": true, 1374 | "requires": { 1375 | "source-map": "0.5.7", 1376 | "uglify-to-browserify": "1.0.2", 1377 | "yargs": "3.10.0" 1378 | }, 1379 | "dependencies": { 1380 | "source-map": { 1381 | "version": "0.5.7", 1382 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1383 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 1384 | "optional": true 1385 | } 1386 | } 1387 | }, 1388 | "uglify-to-browserify": { 1389 | "version": "1.0.2", 1390 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 1391 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 1392 | "optional": true 1393 | }, 1394 | "util-deprecate": { 1395 | "version": "1.0.2", 1396 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1397 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1398 | }, 1399 | "uuid": { 1400 | "version": "3.1.0", 1401 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", 1402 | "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" 1403 | }, 1404 | "validate-npm-package-license": { 1405 | "version": "3.0.1", 1406 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", 1407 | "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", 1408 | "requires": { 1409 | "spdx-correct": "1.0.2", 1410 | "spdx-expression-parse": "1.0.4" 1411 | } 1412 | }, 1413 | "validate-npm-package-name": { 1414 | "version": "2.2.2", 1415 | "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-2.2.2.tgz", 1416 | "integrity": "sha1-9laVsi9zJEQgGaPH+jmm5/0pkIU=", 1417 | "requires": { 1418 | "builtins": "0.0.7" 1419 | } 1420 | }, 1421 | "verror": { 1422 | "version": "1.10.0", 1423 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1424 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1425 | "requires": { 1426 | "assert-plus": "1.0.0", 1427 | "core-util-is": "1.0.2", 1428 | "extsprintf": "1.3.0" 1429 | }, 1430 | "dependencies": { 1431 | "assert-plus": { 1432 | "version": "1.0.0", 1433 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 1434 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 1435 | } 1436 | } 1437 | }, 1438 | "which": { 1439 | "version": "1.3.0", 1440 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", 1441 | "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", 1442 | "requires": { 1443 | "isexe": "2.0.0" 1444 | } 1445 | }, 1446 | "wide-align": { 1447 | "version": "1.1.2", 1448 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", 1449 | "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", 1450 | "requires": { 1451 | "string-width": "1.0.2" 1452 | }, 1453 | "dependencies": { 1454 | "is-fullwidth-code-point": { 1455 | "version": "1.0.0", 1456 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 1457 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 1458 | "requires": { 1459 | "number-is-nan": "1.0.1" 1460 | } 1461 | }, 1462 | "string-width": { 1463 | "version": "1.0.2", 1464 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1465 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1466 | "requires": { 1467 | "code-point-at": "1.1.0", 1468 | "is-fullwidth-code-point": "1.0.0", 1469 | "strip-ansi": "3.0.1" 1470 | } 1471 | } 1472 | } 1473 | }, 1474 | "window-size": { 1475 | "version": "0.1.0", 1476 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 1477 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", 1478 | "optional": true 1479 | }, 1480 | "wordwrap": { 1481 | "version": "0.0.3", 1482 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", 1483 | "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" 1484 | }, 1485 | "wordwrapjs": { 1486 | "version": "3.0.0", 1487 | "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", 1488 | "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", 1489 | "requires": { 1490 | "reduce-flatten": "1.0.1", 1491 | "typical": "2.6.1" 1492 | } 1493 | }, 1494 | "wrappy": { 1495 | "version": "1.0.2", 1496 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1497 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1498 | }, 1499 | "yargs": { 1500 | "version": "3.10.0", 1501 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 1502 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 1503 | "optional": true, 1504 | "requires": { 1505 | "camelcase": "1.2.1", 1506 | "cliui": "2.1.0", 1507 | "decamelize": "1.2.0", 1508 | "window-size": "0.1.0" 1509 | } 1510 | } 1511 | } 1512 | } 1513 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "daisneon", 3 | "version": "0.1.0", 4 | "description": "Dais interceptor chain in Rust+Node.js", 5 | "main": "src/index.js", 6 | "author": "Paul deGrandis ", 7 | "license": "MIT", 8 | "repository": "https://github.com/ohpauleez/daisneon", 9 | "dependencies": { 10 | "neon-cli": "^0.1.20", 11 | "lumo-cljs": "1.8.0-beta", 12 | "source-map-support": "0.4.18", 13 | "nan": "^2.7.0", 14 | "node-gyp": "^3.6.2" 15 | }, 16 | "scripts": { 17 | "cljs-repl": "lumo -c src:native:build:target:. --repl", 18 | "cljs-socketrepl": "lumo -c src:native:build:target:. --socket-repl 5555", 19 | "compile-cljs": "lumo -c src build.cljs dev", 20 | "compile-rust": "neon build", 21 | "compile-cpp": "node-gyp rebuild", 22 | "install": "node-gyp rebuild && neon build && lumo -c src build.cljs" 23 | }, 24 | "gypfile": true 25 | } 26 | -------------------------------------------------------------------------------- /src/dais.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict' 3 | 4 | // The Dais interceptor chain in pure, naive JavaScript (using mutable data types) 5 | 6 | function handleLeave(context) { 7 | let stack = context["dais.stack"]; 8 | let stackLen = stack.length; 9 | for(let i = 0; i < stackLen; i++) { 10 | let interceptor = stack.pop(); 11 | try { 12 | if (interceptor.leave !== undefined) { 13 | context = interceptor.leave(context); 14 | } 15 | if (context.error !== undefined) { 16 | return handleError(context); 17 | } 18 | } catch (e) { 19 | context["error"] = e; 20 | return handleError(context); 21 | } 22 | } 23 | return context; 24 | } 25 | 26 | function handleError(context) { 27 | let stack = context["dais.stack"]; 28 | let stackLen = stack.length; 29 | for(let i = 0; i < stackLen; i++) { 30 | let error = context.error; 31 | if (error === undefined) { 32 | return handleLeave(context) 33 | } 34 | 35 | let interceptor = stack.pop(); 36 | if (interceptor.error !== undefined) { 37 | context = interceptor.error(context); 38 | } 39 | } 40 | return context; 41 | } 42 | 43 | function handleEnter(context) { 44 | let queue = context["dais.queue"]; 45 | let stack = context["dais.stack"]; 46 | let terminators = context["dais.terminators"]; 47 | while (queue.length > 0) { 48 | let interceptor = queue[0]; 49 | if (interceptor === undefined) { 50 | delete context["dais.queue"]; 51 | return handleLeave(context); 52 | } 53 | 54 | queue.shift(); 55 | stack.push(interceptor); 56 | 57 | try { 58 | if (interceptor.enter !== undefined) { 59 | context = interceptor.enter(context); 60 | } 61 | if (context.error !== undefined) { 62 | return handleError(context); 63 | } 64 | } catch (e) { 65 | context["error"] = e; 66 | return handleError(context); 67 | } 68 | if (terminators !== undefined) { 69 | if (terminators.some((elem, i, array) => elem.call(this, context))) { 70 | delete context["dais.queue"]; 71 | return handleLeave(context); 72 | } 73 | } 74 | } 75 | return context; 76 | } 77 | 78 | function execute(context, interceptors) { 79 | if (interceptors !== undefined) { 80 | context["dais.queue"] = interceptors; 81 | } 82 | context["dais.stack"] = context["dais.stack"] || []; 83 | return handleEnter(context); 84 | } 85 | 86 | module.exports.execute = execute; 87 | module.exports.handleEnter = handleEnter; 88 | module.exports.handleLeave = handleLeave; 89 | module.exports.handleError = handleError; 90 | 91 | -------------------------------------------------------------------------------- /src/daisneon/bridge.cljs: -------------------------------------------------------------------------------- 1 | (ns daisneon.bridge) 2 | 3 | (def rust (js/require "./native/index.node")) 4 | (def cpp (js/require "./build/Release/cppaddon.node")) 5 | 6 | -------------------------------------------------------------------------------- /src/daisneon/dais.cljs: -------------------------------------------------------------------------------- 1 | (ns daisneon.dais) 2 | 3 | ;; ---------- 4 | ;; This is an implementation of the Dais Interceptor Chain 5 | ;; written in ClojureScript and using ClojureScript data types (Records, keywords, persistent collections) 6 | ;; 7 | ;; There is support for static chain execution using JavaScript Arrays 8 | ;; -------------------------------------------------------------------- 9 | 10 | (enable-console-print!) 11 | 12 | (defrecord Interceptor [name enter leave error]) 13 | 14 | (extend-protocol IPrintWithWriter 15 | Interceptor 16 | (-pr-writer [i writer _] 17 | (write-all writer (str "#Interceptor{:name " (.-name i) "}")))) 18 | 19 | (defprotocol IntoInterceptor 20 | (-interceptor [t] "Given a value, produce an Interceptor Record.")) 21 | 22 | (extend-protocol IntoInterceptor 23 | PersistentHashMap 24 | (-interceptor [t] (map->Interceptor t)) 25 | PersistentArrayMap 26 | (-interceptor [t] (map->Interceptor t)) 27 | 28 | Interceptor 29 | (-interceptor [t] t) 30 | 31 | object 32 | (-interceptor [t] 33 | (->Interceptor (.-name t) (.-enter t) (.-leave t) (.-error t)))) 34 | 35 | (defn interceptor-name 36 | [n] 37 | (if-not (or (nil? n) (keyword? n)) 38 | (throw (ex-info (str "Name must be keyword or nil; Got: " (pr-str n)) {:name n})) 39 | n)) 40 | 41 | (defn interceptor? 42 | [o] 43 | (= (type o) Interceptor)) 44 | 45 | (defn valid-interceptor? 46 | [o] 47 | (if-let [int-vals (and (interceptor? o) 48 | (vals (select-keys o [:enter :leave :error])))] 49 | (and (some identity int-vals) 50 | (every? fn? (remove nil? int-vals)) 51 | (or (interceptor-name (:name o)) true) ;; Could return `nil` 52 | true) 53 | false)) 54 | 55 | (defn interceptor 56 | "Given a value, produces and returns an Interceptor (Record)." 57 | [t] 58 | {:pre [(if-not (satisfies? IntoInterceptor t) 59 | (throw (ex-info "You're trying to use something as an interceptor that isn't supported by the protocol; Perhaps you need to extend it?" 60 | {:t t 61 | :type (type t)})) 62 | true)] 63 | :post [(valid-interceptor? %)]} 64 | (-interceptor t)) 65 | 66 | (declare handle-leave) 67 | (declare handle-error) 68 | 69 | (defn handle-enter [context] 70 | (loop [ctx context] 71 | (if (empty? (:dais/queue ctx)) 72 | ctx 73 | (let [{queue :dais/queue 74 | stack :dais/stack} ctx 75 | interceptor (peek queue) 76 | old-context ctx 77 | new-queue (pop queue) 78 | ;; conj on nil returns a list, acts like a stack: 79 | new-stack (conj stack interceptor) 80 | partial-ctx (assoc ctx 81 | :dais/queue new-queue 82 | :dais/stack new-stack) 83 | enter-fn (:enter interceptor) 84 | new-context (if (fn? enter-fn) 85 | (try 86 | (enter-fn partial-ctx) 87 | (catch :default e 88 | (assoc (dissoc partial-ctx :dais/queue) 89 | :error e))) 90 | partial-ctx)] 91 | 92 | (if (:error new-context) 93 | (handle-error new-context) 94 | (recur (if (some #(% new-context) (:dais/terminators new-context)) 95 | (handle-leave (dissoc new-context :dais/queue)) 96 | new-context))))))) 97 | 98 | (defn handle-array-enter [context] 99 | (reduce 100 | (fn [ctx interceptor] 101 | (let [partial-ctx (update-in ctx [:dais/stack] conj interceptor) 102 | enter-fn (:enter interceptor) 103 | new-context (if (fn? enter-fn) 104 | (try 105 | (enter-fn partial-ctx) 106 | (catch :default e 107 | (assoc (dissoc partial-ctx :dais/queue) 108 | :error e))) 109 | partial-ctx)] 110 | (if (:error new-context) 111 | (reduced (handle-error new-context)) 112 | (if (some #(% new-context) (:dais/terminators new-context)) 113 | (reduced (handle-leave (dissoc new-context :dais/queue))) 114 | new-context)))) 115 | context 116 | (:dais/queue context))) 117 | 118 | (defn handle-leave [context] 119 | (loop [ctx context] 120 | (if (empty? (:dais/stack ctx)) 121 | (dissoc ctx 122 | :dais/stack 123 | "dais.stack") 124 | (let [stack (:dais/stack ctx) 125 | interceptor (peek stack) 126 | old-context ctx 127 | new-stack (pop stack) 128 | partial-ctx (assoc ctx 129 | :dais/stack new-stack) 130 | leave-fn (:leave interceptor) 131 | new-context (if (fn? leave-fn) 132 | (try 133 | (leave-fn partial-ctx) 134 | (catch :default e 135 | (assoc (dissoc partial-ctx :dais/queue) 136 | :error e))) 137 | partial-ctx)] 138 | 139 | (if (:error new-context) 140 | (handle-error new-context) 141 | (recur new-context)))))) 142 | 143 | (defn handle-error [context] 144 | (loop [ctx context] 145 | (if (empty? (:dais/stack ctx)) 146 | ctx 147 | (let [stack (:dais/stack ctx) 148 | interceptor (peek stack) 149 | old-context ctx 150 | new-stack (pop stack) 151 | partial-ctx (assoc ctx 152 | :dais/stack new-stack) 153 | error-fn (:error interceptor) 154 | new-context (if (fn? error-fn) 155 | (error-fn partial-ctx) 156 | partial-ctx)] 157 | 158 | (if (:error new-context) 159 | (recur new-context) 160 | (handle-leave new-context)))))) 161 | 162 | (defn ^:export execute 163 | ([context] 164 | {:pre [(map? context)]} 165 | (let [{q :dais/queue 166 | stack :dais/stack 167 | terminators :dais/terminators 168 | :or {stack '() 169 | terminators []}} context 170 | ;; Check for interop'd stack and terminators 171 | terminators (get context "dais.terminators" terminators) 172 | stack (get context "dais.stack" stack)] 173 | (cond 174 | (array? q) (handle-array-enter context) 175 | (seq q) (handle-enter (assoc context 176 | :dais/queue (if (instance? cljs.core/PersistentQueue q) 177 | q 178 | (into cljs.core/PersistentQueue.EMPTY q)) 179 | ;; Defend against stack types and interop 180 | :dais/stack (into '() (reverse stack)) 181 | :dais/terminators terminators)) 182 | :else context))) 183 | ([context interceptors] 184 | (let [final-ctx (execute (assoc (js->clj context) 185 | :dais/queue (into cljs.core/PersistentQueue.EMPTY 186 | (map interceptor interceptors))))] 187 | (if (object? context) 188 | (clj->js final-ctx) 189 | final-ctx)))) 190 | 191 | (defn ^:export hello [& args] 192 | "hello node - from ClojureScript") 193 | 194 | ;(println (main)) 195 | 196 | -------------------------------------------------------------------------------- /src/daisneon/example.cljs: -------------------------------------------------------------------------------- 1 | (ns daisneon.example 2 | (:require ;[dais :as js-dais] 3 | [daisneon.dais :as dais])) 4 | 5 | ;; Note: `js-dais` is not currently used in this file, 6 | ;; but is written to correctly configure the build/compiler map, 7 | ;; so that the pattern of integrating JS sources into the CLJS compile/build 8 | ;; is established and exercised 9 | 10 | (def inter-a (dais/interceptor {:enter #(assoc % :a 1) 11 | :leave #(assoc % :leave-a 11)})) 12 | (def inter-b (dais/interceptor {:enter #(assoc % :b 2)})) 13 | (def inter-c (dais/interceptor {:enter #(assoc % :c 3)})) 14 | 15 | (def queue-chain (into cljs.core/PersistentQueue.EMPTY [inter-a 16 | inter-b 17 | inter-c])) 18 | (def array-chain #js[inter-a inter-b inter-c]) 19 | 20 | ;; For the most part, 21 | ;; these are all 0.08 - 0.3 msecs 22 | ;; Mean is probably around 0.2 msecs 23 | ;; -------------------------------- 24 | 25 | ;; 0.1 - 0.31 msecs 26 | (defn ^:export example [] 27 | (let [context {:dais/terminators [#(:b %)] 28 | :dais/queue [{:enter #(assoc % :a 1) 29 | :leave #(assoc % :leave-a 11)} 30 | {:enter #(assoc % :b 2)} 31 | {:enter #(assoc % :c 3)}]}] 32 | (dais/execute context))) 33 | 34 | ;; 0.1 - 0.30 msecs 35 | (defn ^:export example1 [] 36 | (let [context {:dais/terminators [#(:b %)] 37 | :dais/queue [inter-a 38 | inter-b 39 | inter-c]}] 40 | (dais/execute context))) 41 | 42 | ;; 0.09 - 0.29 msecs 43 | (defn ^:export example1b [] 44 | (let [context {:dais/terminators [#(:b %)] 45 | :dais/queue queue-chain}] 46 | (dais/execute context))) 47 | 48 | ;; 0.07 - 0.30 msecs 49 | (defn ^:export exampleStatic [] 50 | (let [context {:dais/terminators [#(:b %)] 51 | :dais/queue #js[{:enter #(assoc % :a 1) 52 | :leave #(assoc % :leave-a 11)} 53 | {:enter #(assoc % :b 2)} 54 | {:enter #(assoc % :c 3)}]}] 55 | (dais/execute context))) 56 | 57 | ;; 0.06 - 0.28 msecs 58 | (defn ^:export exampleStatic1 [] 59 | (let [context {:dais/terminators [#(:b %)] 60 | :dais/queue #js[inter-a 61 | inter-b 62 | inter-c]}] 63 | (dais/execute context))) 64 | 65 | ;; 0.06 - 0.26 msecs 66 | (defn ^:export exampleStatic1b [] 67 | (let [context {:dais/terminators [#(:b %)] 68 | :dais/queue array-chain}] 69 | (dais/execute context))) 70 | 71 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // All of these require `npm install` to work 4 | const addon = require('../native'); 5 | const cppaddon = require('../build/Release/cppaddon'); 6 | const daiscljs = require('../target/main.js'); 7 | const daisjs = require('./dais.js'); 8 | 9 | function hello() { 10 | return 'hello node - from JavaScript'; 11 | } 12 | 13 | function testChains() { 14 | console.time("rust"); 15 | let rustRes = addon.basicExecute({"dais.terminators": [ctx => ctx.b !== undefined]}, 16 | [{enter: ctx => {ctx.a = 1; return ctx}, 17 | leave: ctx => {ctx["leave-a"] = 11; return ctx}}, 18 | {enter: ctx => {ctx.b = 2; return ctx}}, 19 | {enter: ctx => {ctx.c = 3; return ctx}}]); 20 | console.timeEnd("rust"); 21 | console.time("cpp"); 22 | let cppRes = cppaddon.BasicExecute({"dais.terminators": [ctx => ctx.b !== undefined]}, 23 | [{enter: ctx => {ctx.a = 1; return ctx}, 24 | leave: ctx => {ctx["leave-a"] = 11; return ctx}}, 25 | {enter: ctx => {ctx.b = 2; return ctx}}, 26 | {enter: ctx => {ctx.c = 3; return ctx}}]); 27 | console.timeEnd("cpp"); 28 | console.time("js"); 29 | let jsRes = daisjs.execute({"dais.terminators": [ctx => ctx.b !== undefined]}, 30 | [{enter: ctx => {ctx.a = 1; return ctx}, 31 | leave: ctx => {ctx["leave-a"] = 11; return ctx}}, 32 | {enter: ctx => {ctx.b = 2; return ctx}}, 33 | {enter: ctx => {ctx.c = 3; return ctx}}]); 34 | console.timeEnd("js"); 35 | console.time("cljs-js-interop"); 36 | let cljsInterRes = daisneon.dais.execute({"dais.terminators": [ctx => cljs.core.get(ctx, "b")]}, 37 | [{enter: ctx => cljs.core.assoc(ctx, "a", 1), 38 | leave: ctx => cljs.core.assoc(ctx, "leave-a", 11)}, 39 | {enter: ctx => cljs.core.assoc(ctx, "b", 2)}, 40 | {enter: ctx => cljs.core.assoc(ctx, "c", 3)}]); 41 | console.timeEnd("cljs-js-interop"); 42 | console.time("cljs-static"); 43 | let cljsStaticRes = daisneon.example.exampleStatic1b(); 44 | console.timeEnd("cljs-static"); 45 | console.time("cljs"); 46 | let cljsRes = daisneon.example.example1b(); 47 | console.timeEnd("cljs"); 48 | let res = {"rustResult": rustRes, 49 | "cppResult": cppRes, 50 | "jsResult": jsRes, 51 | "cljsInterResult": cljsInterRes, 52 | "cljsStaticResult": cljs.core.clj__GT_js(cljsStaticRes), 53 | "cljsResult": cljs.core.clj__GT_js(cljsRes), 54 | }; 55 | return res; 56 | } 57 | 58 | function testA (x) { 59 | return x+1; 60 | } 61 | 62 | const testB = (x) => {return x+1}; 63 | 64 | function testFns() { 65 | let x = 1; 66 | console.time("funct"); 67 | testA(x); 68 | console.timeEnd("funct"); 69 | console.time("const"); 70 | testB(x); 71 | console.timeEnd("const"); 72 | console.time("funct2"); 73 | for (let i = 0; i < 10000; i++) { 74 | testA(x); 75 | } 76 | console.timeEnd("funct2"); 77 | console.time("const2"); 78 | for (let i = 0; i < 10000; i++) { 79 | testB(x); 80 | } 81 | console.timeEnd("const2"); 82 | } 83 | 84 | module.exports.hello = hello; 85 | module.exports.hellorust = addon.hello; 86 | module.exports.hellocljs = daisneon.dais.hello; 87 | module.exports.hellocpp = cppaddon.Hello; 88 | 89 | module.exports.executeChain = addon.executeChain; 90 | module.exports.testChains = testChains; 91 | 92 | module.exports.testFns = testFns; 93 | 94 | -------------------------------------------------------------------------------- /src/lib.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace v8; 8 | 9 | // NAN_METHOD is a Nan macro enabling convenient way of creating native node functions. 10 | // It takes a method's name as a param. By C++ convention, I used the Capital cased name. 11 | NAN_METHOD(Hello) { 12 | // Create an instance of V8's String type 13 | auto message = Nan::New("hello node - from C++").ToLocalChecked(); 14 | // 'info' is a macro's "implicit" parameter - it's a bridge object between C++ and JavaScript runtimes 15 | // You would use info to both extract the parameters passed to a function as well as set the return value. 16 | info.GetReturnValue().Set(message); 17 | } 18 | 19 | NAN_METHOD(BasicExecute) { 20 | auto global_js_context = Nan::GetCurrentContext()->Global(); 21 | auto context = info[0]->ToObject(); 22 | auto interceptors = info[1].As(); 23 | auto terminators_key = Nan::New("dais.terminators").ToLocalChecked(); 24 | auto js_terminators = Nan::Has(context, terminators_key).FromJust() ? Nan::Get(context, terminators_key).ToLocalChecked().As() : Nan::New(); 25 | std::vector> terminators; 26 | std::list> stack; 27 | 28 | auto enter_key = Nan::New("enter").ToLocalChecked(); 29 | auto leave_key = Nan::New("leave").ToLocalChecked(); 30 | auto should_process_leave = false; // A flag to signal if leave leave handlers should be processed 31 | 32 | //Prepare our terminators so we can iterate over them 33 | unsigned int term_len = 0; 34 | if (js_terminators->IsArray()) { 35 | term_len = js_terminators->Length(); 36 | } 37 | for (unsigned int i = 0; i < term_len; i++) { 38 | if (Nan::Has(js_terminators, i).FromJust()) { 39 | auto terminator = Nan::Get(js_terminators, i).ToLocalChecked().As(); 40 | terminators.push_back(terminator); 41 | } 42 | } 43 | 44 | // Start processing interceptors 45 | unsigned int len = 0; 46 | if (interceptors->IsArray()) { 47 | len = interceptors->Length(); 48 | } 49 | for (unsigned int i = 0; i < len; i++) { 50 | if (Nan::Has(interceptors, i).FromJust()) { 51 | // Get the interceptor object 52 | auto interceptor = Nan::Get(interceptors, i).ToLocalChecked().As(); 53 | // If the interceptor has a `leave`, add it to the stack 54 | if (Nan::Has(interceptor, leave_key).FromJust()) { 55 | stack.push_front(Nan::Get(interceptor, leave_key).ToLocalChecked().As()); 56 | } 57 | // If the interceptor has an `enter`, call it. Otherwise, move on to the next interceptor 58 | if (Nan::Has(interceptor, enter_key).FromJust()) { 59 | auto enter_fn = Nan::Get(interceptor, enter_key).ToLocalChecked().As(); 60 | v8::Local args[] = {context.As()}; 61 | context = Nan::Call(enter_fn, global_js_context, 1, args).ToLocalChecked().As(); 62 | // Check terminators 63 | if (std::any_of(terminators.cbegin(), terminators.cend(), 64 | [&](const Local& terminator) { 65 | return Nan::To(Nan::Call(terminator, global_js_context, 1, args).ToLocalChecked()).FromJust(); 66 | })) { 67 | should_process_leave = true; 68 | break; 69 | } 70 | } 71 | } 72 | } 73 | // Process Leave 74 | if (should_process_leave) { 75 | for (auto const &leave_fn : stack) { 76 | v8::Local args[] = {context.As()}; 77 | context = Nan::Call(leave_fn, global_js_context, 1, args).ToLocalChecked().As(); 78 | } 79 | } 80 | info.GetReturnValue().Set(context); 81 | } 82 | 83 | // Module initialization logic 84 | NAN_MODULE_INIT(Initialize) { 85 | // Export the `Hello` function (equivalent to `export function Hello (...)` in JS) 86 | NAN_EXPORT(target, Hello); 87 | NAN_EXPORT(target, BasicExecute); 88 | } 89 | 90 | // Create the module called "addon" and initialize it with `Initialize` function (created with NAN_MODULE_INIT macro) 91 | NODE_MODULE(cppaddon, Initialize); 92 | 93 | --------------------------------------------------------------------------------